From c43c678df881eef5a7a42a812bcb496dd25ea7c5 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sun, 28 Oct 2018 18:12:17 +0100
Subject: [PATCH] pong now uses ipc_application_loop() in interactive mode
---
core/communication.c | 118 ++++++++++++++++++++++++++++++++++++++++++-
core/communication.h | 3 ++
core/event.h | 1 +
pong/app/pong.c | 90 +++++++++++++++++----------------
4 files changed, 166 insertions(+), 46 deletions(-)
diff --git a/core/communication.c b/core/communication.c
index 6e6eaa4..46ab0cb 100644
--- a/core/communication.c
+++ b/core/communication.c
@@ -2,6 +2,7 @@
#include "utils.h"
#include "error.h"
#include "event.h"
+#include
#include
#include
@@ -109,7 +110,7 @@ int ipc_application_connection (char **env
return 0;
}
-// send a CLOSE message then close the socket
+// close the socket
int ipc_application_close (struct ipc_service *srv)
{
return usock_close (srv->service_fd);
@@ -408,7 +409,120 @@ int ipc_service_loop (struct ipc_clients *clients, struct ipc_service *srv
return 0;
}
-int ipc_application_loop (struct ipc_services *services)
+int ipc_application_loop_ (struct ipc_services *services, struct ipc_event *event, int interactive)
{
+ assert (services != NULL);
+
+ IPC_EVENT_CLEAN(event);
+
+ int i, j;
+ /* master file descriptor list */
+ fd_set master;
+ fd_set readf;
+
+ /* maximum file descriptor number */
+ int fdmax;
+
+ /* clear the master and temp sets */
+ FD_ZERO(&master);
+ FD_ZERO(&readf);
+
+ if (interactive) {
+ FD_SET(0, &master);
+ }
+
+ for (i=0; i < services->size; i++) {
+ FD_SET(services->services[i]->service_fd, &master);
+ }
+
+ /* keep track of the biggest file descriptor */
+ fdmax = get_max_fd_from_ipc_services_ (services);
+
+ // printf ("loop ipc_server_select main_loop\n");
+ readf = master;
+ if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
+ perror("select");
+ return -1;
+ }
+
+ /*run through the existing connections looking for data to be read*/
+ for (i = 0; i <= fdmax; i++) {
+ // printf ("loop ipc_server_select inner loop\n");
+ if (FD_ISSET(i, &readf)) {
+
+ // interactive: input on stdin
+ if (i == 0) {
+ // XXX: by default, message type is 0
+ struct ipc_message *m = malloc (sizeof (struct ipc_message));
+ if (m == NULL) {
+ return IPC_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ memset (m, 0, sizeof (struct ipc_message));
+ m->payload = malloc (IPC_MAX_MESSAGE_SIZE);
+
+ m->length = read(0, m->payload , IPC_MAX_MESSAGE_SIZE);
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_STDIN, m, NULL);
+ return 0;
+ }
+
+ for(j = 0; j < services->size; j++) {
+ // printf ("loop ipc_server_select inner inner loop\n");
+ if(i == services->services[j]->service_fd ) {
+ // listen to what they have to say (disconnection or message)
+ // then add a client to `event`, the ipc_event structure
+ int ret = 0;
+ struct ipc_message *m = NULL;
+ m = malloc (sizeof(struct ipc_message));
+ if (m == NULL) {
+ return IPC_ERROR_NOT_ENOUGH_MEMORY;
+ }
+ memset (m, 0, sizeof (struct ipc_message));
+
+ // current talking client
+ struct ipc_service *ps = services->services[j];
+ ret = ipc_application_read (ps, m);
+ if (ret < 0) {
+ handle_err ("ipc_application_loop", "ipc_application_read < 0");
+ ipc_message_empty (m);
+ free (m);
+
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_ERROR, NULL, ps);
+ return IPC_ERROR_READ;
+ }
+
+ // disconnection: close the service
+ if (ret == 1) {
+ if (ipc_application_close (ps) < 0) {
+ handle_err( "ipc_application_loop", "ipc_application_close < 0");
+ }
+ if (ipc_service_del (services, ps) < 0) {
+ handle_err( "ipc_application_loop", "ipc_service_del < 0");
+ }
+ ipc_message_empty (m);
+ free (m);
+
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_DISCONNECTION, NULL, ps);
+
+ // warning: do not forget to free the ipc_client structure
+ return 0;
+ }
+
+ // we received a new message from a client
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, m, ps);
+ return 0;
+
+ }
+ }
+ }
+ }
+
return 0;
}
+
+int ipc_application_loop (struct ipc_services *services, struct ipc_event *event) {
+ return ipc_application_loop_ (services, event, 0);
+}
+
+int ipc_application_loop_interactive (struct ipc_services *services, struct ipc_event *event) {
+ return ipc_application_loop_ (services, event, 1);
+}
diff --git a/core/communication.h b/core/communication.h
index 6c614e0..7e12fd0 100644
--- a/core/communication.h
+++ b/core/communication.h
@@ -51,4 +51,7 @@ int ipc_application_write (struct ipc_service *, const struct ipc_message *m);
int ipc_application_select (struct ipc_services *services, struct ipc_services *active_services);
+int ipc_application_loop (struct ipc_services *services, struct ipc_event *event);
+int ipc_application_loop_interactive (struct ipc_services *services, struct ipc_event *event);
+
#endif
diff --git a/core/event.h b/core/event.h
index e12d95b..9ce46eb 100644
--- a/core/event.h
+++ b/core/event.h
@@ -6,6 +6,7 @@
enum ipc_event_type {
IPC_EVENT_TYPE_NOT_SET
, IPC_EVENT_TYPE_ERROR
+ , IPC_EVENT_TYPE_STDIN
, IPC_EVENT_TYPE_CONNECTION
, IPC_EVENT_TYPE_DISCONNECTION
, IPC_EVENT_TYPE_MESSAGE
diff --git a/pong/app/pong.c b/pong/app/pong.c
index 76b27e1..9900fea 100644
--- a/pong/app/pong.c
+++ b/pong/app/pong.c
@@ -3,9 +3,7 @@
#include
#include
-#include "../../core/message.h"
-#include "../../core/error.h"
-#include "../../core/communication.h"
+#include "../../core/ipc.h"
#define MSG "coucou"
#define SERVICE_NAME "pongd"
@@ -53,17 +51,10 @@ void non_interactive (char *env[])
void interactive (char *env[])
{
- struct ipc_message m;
- memset (&m, 0, sizeof (struct ipc_message));
+ int ret = 0;
struct ipc_service srv;
memset (&srv, 0, sizeof (struct ipc_service));
- char buf[IPC_MAX_MESSAGE_SIZE];
- memset (buf, 0, IPC_MAX_MESSAGE_SIZE);
- int n;
-
- int ask_server_to_quit = 0;
-
// index and version should be filled
srv.index = 0;
srv.version = 0;
@@ -74,50 +65,61 @@ void interactive (char *env[])
exit (EXIT_FAILURE);
}
+ struct ipc_event event;
+ memset (&event, 0, sizeof (struct ipc_event));
+
+ struct ipc_services services;
+ memset (&services, 0, sizeof (struct ipc_services));
+ ipc_service_add (&services, &srv);
+
while (1) {
printf ("msg to send: ");
fflush (stdout);
- n = read (0, buf, IPC_MAX_MESSAGE_SIZE);
+ ret = ipc_application_loop_interactive (&services, &event);
- if (n == 0 || strncmp (buf, "exit", 4) == 0)
- break;
-
- if (strncmp(buf, "close server", 12) == 0) {
- ask_server_to_quit = 1;
- break;
+ if (ret != 0) {
+ handle_error("ipc_application_loop != 0");
+ exit (EXIT_FAILURE);
}
- ipc_message_format_data (&m, buf, strlen(buf) +1);
- memset (buf, 0, IPC_MAX_MESSAGE_SIZE);
+ switch (event.type) {
+ case IPC_EVENT_TYPE_STDIN:
+ {
+ struct ipc_message *m = event.m;
+ if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
- // print_msg (&m);
+ ipc_message_empty (m);
+ free (m);
- if (ipc_application_write (&srv, &m) < 0) {
- handle_err("main", "application_write < 0");
- exit (EXIT_FAILURE);
- }
- ipc_message_empty (&m);
+ ipc_services_free (&services);
- if (ipc_application_read (&srv, &m) < 0) {
- handle_err("main", "application_read < 0");
- exit (EXIT_FAILURE);
- }
+ if (ipc_application_close (&srv) < 0) {
+ handle_err("main", "application_close < 0");
+ exit (EXIT_FAILURE);
+ }
- printf ("msg recv: %s", m.payload);
- ipc_message_empty (&m);
- }
+ exit (EXIT_SUCCESS);
+ }
- if (ask_server_to_quit) {
- ipc_message_format_server_close (&m);
-
- if (ipc_application_write (&srv, &m) < 0) {
- handle_err("main", "application_write < 0");
- exit (EXIT_FAILURE);
- }
- ipc_message_empty (&m);
- } else if (ipc_application_close (&srv) < 0) {
- handle_err("main", "application_close < 0");
- exit (EXIT_FAILURE);
+ if (ipc_application_write (&srv, m) < 0) {
+ handle_err("main", "application_write < 0");
+ exit (EXIT_FAILURE);
+ }
+ }
+ break;
+ case IPC_EVENT_TYPE_MESSAGE:
+ {
+ struct ipc_message *m = event.m;
+ printf ("msg recv: %.*s", m->length, m->payload);
+ };
+ break;
+ case IPC_EVENT_TYPE_DISCONNECTION:
+ case IPC_EVENT_TYPE_NOT_SET:
+ case IPC_EVENT_TYPE_CONNECTION:
+ case IPC_EVENT_TYPE_ERROR:
+ default :
+ fprintf (stderr, "should not happen, event type %d\n", event.type);
+ }
}
}