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); + } } }