diff --git a/core/communication.c b/core/communication.c index b754b1f..e458c0c 100644 --- a/core/communication.c +++ b/core/communication.c @@ -69,6 +69,14 @@ int srv_close (struct service *srv) int srv_close_proc (struct process *p) { + // struct msg m_ack_dis; + // memset (&m_ack_dis, 0, sizeof (struct msg)); + // m_ack_dis.type = MSG_TYPE_ACK_DIS; + + // if (msg_write (p->proc_fd, &m_ack_dis) < 0) { + // handle_err ("srv_close_proc", "msg_write < 0"); + // } + return usock_close (p->proc_fd); } @@ -128,6 +136,7 @@ int app_connection (int argc, char **argv, char **env return 0; } +// send a DIS message then close the socket int app_close (struct service *srv) { struct msg m; @@ -137,6 +146,14 @@ int app_close (struct service *srv) handle_err ("app_close", "msg_write < 0"); } + // if (msg_read (srv->service_fd, &m) < 0) { + // handle_err ("app_close", "msg_read < 0"); + // } + + // if (m.type != MSG_TYPE_ACK) { + // handle_err ("app_close", "msg received != ACK"); + // } + return usock_close (srv->service_fd); } @@ -165,8 +182,14 @@ int app_write (struct service *srv, const struct msg *m) */ int srv_select (struct array_proc *ap, struct service *srv - , struct process **proc) + , struct array_proc *proc) { + assert (ap != NULL); + assert (proc != NULL); + + // delete previous read process array + array_proc_free (proc); + int i, j; /* master file descriptor list */ fd_set master; @@ -183,14 +206,17 @@ int srv_select (struct array_proc *ap, struct service *srv /* add the listener to the master set */ FD_SET(listener, &master); - for(i=0; i < ap->size; i++) { + for (i=0; i < ap->size; i++) { FD_SET(ap->tab_proc[i]->proc_fd, &master); } /* keep track of the biggest file descriptor */ fdmax = getMaxFd(ap) > srv->service_fd ? getMaxFd(ap) : srv->service_fd; - while (1) { + int is_listener = 0; + + do { + // printf ("loop srv_select main_loop\n"); readf = master; if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) { perror("select"); @@ -199,20 +225,27 @@ int srv_select (struct array_proc *ap, struct service *srv /*run through the existing connections looking for data to be read*/ for (i = 0; i <= fdmax; i++) { + // printf ("loop srv_select inner loop\n"); if (FD_ISSET(i, &readf)) { if (i == listener) { - return CONNECTION; + is_listener = 1; } else { for(j = 0; j < ap->size; j++) { + // printf ("loop srv_select inner inner loop\n"); if(i == ap->tab_proc[j]->proc_fd ) { - *proc = ap->tab_proc[j]; - return APPLICATION; + add_proc (proc, ap->tab_proc[j]); } } } } } - } + } while (0); + + if (proc->size > 0 && is_listener) + return CON_APP; + if (proc->size > 0) + return APPLICATION; + return CONNECTION; } /*calculer le max filedescriptor*/ diff --git a/core/communication.h b/core/communication.h index 5a7bb82..ad10601 100644 --- a/core/communication.h +++ b/core/communication.h @@ -18,8 +18,9 @@ #define PATH_MAX BUFSIZ -#define CONNECTION 0 +#define CONNECTION 0 #define APPLICATION 1 +#define CON_APP 2 struct service { unsigned int version; @@ -42,7 +43,7 @@ int srv_accept (struct service *srv, struct process *p); int srv_read (const struct process *, struct msg *m); int srv_write (const struct process *, const struct msg *m); -int srv_select(struct array_proc *, struct service *, struct process **); +int srv_select (struct array_proc *, struct service *, struct array_proc *); int getMaxFd(struct array_proc *); diff --git a/core/msg.h b/core/msg.h index c2c904b..70cd632 100644 --- a/core/msg.h +++ b/core/msg.h @@ -5,11 +5,12 @@ #include #include -#define MSG_TYPE_CON 1 -#define MSG_TYPE_DIS 2 -#define MSG_TYPE_ERR 3 -#define MSG_TYPE_ACK 4 -#define MSG_TYPE_DATA 5 +#define MSG_TYPE_CON 1 +#define MSG_TYPE_DIS 2 +#define MSG_TYPE_ERR 3 +#define MSG_TYPE_ACK 4 +#define MSG_TYPE_DATA 5 +#define MSG_TYPE_ACK_DIS 6 struct msg { char type; diff --git a/core/process.c b/core/process.c index 507a3ac..4e2f7df 100644 --- a/core/process.c +++ b/core/process.c @@ -52,25 +52,36 @@ int add_proc (struct array_proc *aproc, struct process *p) int del_proc (struct array_proc *aproc, struct process *p) { assert(aproc != NULL); + assert(aproc->tab_proc != NULL); assert(p != NULL); + if (aproc->tab_proc == NULL) { + return -1; + } + int i; for (i = 0; i < aproc->size; i++) { if (aproc->tab_proc[i] == p) { aproc->tab_proc[i] = aproc->tab_proc[aproc->size-1]; aproc->size--; - aproc->tab_proc = realloc(aproc->tab_proc - , sizeof(struct process) * aproc->size); - - if (aproc->tab_proc == NULL) { - return -1; + if (aproc->size == 0) { + array_proc_free (aproc); } + else { + aproc->tab_proc = realloc(aproc->tab_proc + , sizeof(struct process) * aproc->size); + + if (aproc->tab_proc == NULL) { + return -2; + } + } + return 0; } } - return -2; + return -3; } void process_print (struct process *p) @@ -91,6 +102,9 @@ void array_proc_print (struct array_proc *ap) void array_proc_free (struct array_proc *ap) { - if (ap->tab_proc != NULL) - free (ap->tab_proc), ap->tab_proc = NULL; + if (ap->tab_proc != NULL) { + free (ap->tab_proc); + ap->tab_proc = NULL; + } + ap->size = 0; } diff --git a/core/process.h b/core/process.h index f6ed0fe..cf65f45 100644 --- a/core/process.h +++ b/core/process.h @@ -12,11 +12,9 @@ struct array_proc { int size; }; -// TODO -// tout revoir -int add_proc(struct array_proc *, struct process *); +int add_proc (struct array_proc *, struct process *); -int del_proc(struct array_proc *, struct process *); +int del_proc (struct array_proc *aproc, struct process *p); void array_proc_print (struct array_proc *); void array_proc_free (struct array_proc *); diff --git a/core/usocket.c b/core/usocket.c index 4a6a12b..908d79e 100644 --- a/core/usocket.c +++ b/core/usocket.c @@ -10,8 +10,8 @@ int usock_send (const int fd, const char *buf, const int msize) { - print_hexa ("msg send", (unsigned char *)buf, msize); - fflush(stdout); + // print_hexa ("msg send", (unsigned char *)buf, msize); + // fflush(stdout); int ret = 0; //printf ("%ld bytes to write\n", msize); @@ -53,8 +53,8 @@ int usock_recv (const int fd, char **buf, size_t *msize) return ret; } *msize = (size_t) ret; - print_hexa ("msg recv", (unsigned char *)*buf, *msize); - fflush(stdout); + // print_hexa ("msg recv", (unsigned char *)*buf, *msize); + // fflush(stdout); return ret; } diff --git a/pong/app/Makefile b/pong/app/Makefile index 6972c25..239c6f7 100644 --- a/pong/app/Makefile +++ b/pong/app/Makefile @@ -9,6 +9,10 @@ TESTS=$(addsuffix .test, $(EXEC)) all: $(SOURCES) $(EXEC) +test: + rm /tmp/ipc/pongd-0-0 + ./pongd.bin + $(EXEC): $(OBJECTS) $(CFILES) $(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $@.c -lcbor -o $@.bin diff --git a/pong/app/pingpong.c b/pong/app/pingpong.c deleted file mode 100644 index f795018..0000000 --- a/pong/app/pingpong.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "../../core/communication.h" -#include -#include -#include "../../core/process.h" -#include - -#define PONGD_SERVICE_NAME "pongd" -#define handle_error(msg) \ - do { perror(msg); exit(EXIT_FAILURE); } while (0) - - - -/* - * main loop - * - * opens the application pipes, - * reads then writes the same message, - * then closes the pipes - */ - -void main_loop (struct service *srv) -{ - - size_t msize = BUFSIZ; - char *buf = NULL; - if ( (buf = malloc (BUFSIZ)) == NULL) { - handle_error ("malloc"); - } - memset (buf, 0, BUFSIZ); - - int i,ret, cpt = 0; - - struct array_proc ap; - memset(&ap, 0, sizeof(struct array_proc)); - - struct process *p2 = malloc(sizeof(struct process)); - - while(cpt < 5) { - ret = srv_select(&ap, srv, &p2); - - if (ret == CONNECTION) { - struct process *p = malloc(sizeof(struct process)); - memset(p, 0, sizeof(struct process)); - if (srv_accept (srv, p) < 0) { - handle_error("srv_accept < 0"); - }else { - printf("new connection\n"); - } - - if (add_proc(&ap, p) < 0) { - handle_error("add_proc < 0"); - } - cpt++; - } else { - if (srv_read(p2, &buf, &msize) < 0) { - handle_error("srv_read < 0"); - } - - if (srv_write (p2, buf, msize) < 0) { - handle_error("srv_write < 0"); - } - } - } - - for (i = 0; i < ap.size; i++) { - if (srv_close_proc (ap.tab_proc[i]) < 0) { - handle_error( "srv_close_proc < 0"); - } - } -} - - -/* - * service ping-pong - * - * 1. creates the named pipe /tmp/, then listens - * 2. opens the named pipes in & out - * 3. talks with the (test) program - * 4. closes the test program named pipes - * 5. removes the named pipe /tmp/ - */ - -int main(int argc, char * argv[], char **env) -{ - struct service srv; - memset (&srv, 0, sizeof (struct service)); - srv.index = 0; - srv.version = 0; - unlink("/tmp/ipc/pongd-0-0"); - if (srv_init (argc, argv, env, &srv, PONGD_SERVICE_NAME) < 0) { - handle_error("srv_init < 0"); - return EXIT_FAILURE; - } - printf ("Listening on %s.\n", srv.spath); - - printf("MAIN: server created\n" ); - - // the service will loop until the end of time, a specific message, a signal - main_loop (&srv); - - // the application will shut down, and remove the service named pipe - if (srv_close (&srv) < 0) { - handle_error("srv_close < 0"); - - } - - return EXIT_SUCCESS; -} diff --git a/pong/app/pong.c b/pong/app/pong.c new file mode 100644 index 0000000..966c91c --- /dev/null +++ b/pong/app/pong.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +#include "../../core/msg.h" +#include "../../core/error.h" +#include "../../core/communication.h" + +#define MSG "coucou" +#define SERVICE_NAME "pongd" + +void non_interactive (int argc, char *argv[], char *env[]) +{ + struct msg m; + memset (&m, 0, sizeof (struct msg)); + struct service srv; + memset (&srv, 0, sizeof (struct service)); + + // index and version should be filled + srv.index = 0; + srv.version = 0; + + // init service + if (app_connection (argc, argv, env, &srv, SERVICE_NAME, NULL, 0) < 0) { + handle_err("main", "srv_init < 0"); + exit (EXIT_FAILURE); + } + + printf ("msg to send: %s\n", MSG); + msg_format_data (&m, MSG, strlen(MSG) +1); + printf ("msg to send in the client: "); + print_msg (&m); + if (app_write (&srv, &m) < 0) { + handle_err("main", "app_write < 0"); + exit (EXIT_FAILURE); + } + msg_free (&m); + + if (app_read (&srv, &m) < 0) { + handle_err("main", "app_read < 0"); + exit (EXIT_FAILURE); + } + + printf ("msg recv: %s\n", m.val); + msg_free (&m); + + if (app_close (&srv) < 0) { + handle_err("main", "app_close < 0"); + exit (EXIT_FAILURE); + } +} + +void interactive (int argc, char *argv[], char *env[]) +{ + struct msg m; + memset (&m, 0, sizeof (struct msg)); + struct service srv; + memset (&srv, 0, sizeof (struct service)); + + char buf[BUFSIZ]; + memset (buf, 0, BUFSIZ); + int n; + + // index and version should be filled + srv.index = 0; + srv.version = 0; + + // init service + if (app_connection (argc, argv, env, &srv, SERVICE_NAME, NULL, 0) < 0) { + handle_err ("main", "srv_init < 0"); + exit (EXIT_FAILURE); + } + + while (1) { + printf ("msg to send: "); + fflush (stdout); + n = read (0, buf, BUFSIZ); + + if (n == 0 || strncmp (buf, "exit", 4) == 0) + break; + + msg_format_data (&m, buf, strlen(buf) +1); + memset (buf, 0, BUFSIZ); + + // print_msg (&m); + + if (app_write (&srv, &m) < 0) { + handle_err("main", "app_write < 0"); + exit (EXIT_FAILURE); + } + msg_free (&m); + + if (app_read (&srv, &m) < 0) { + handle_err("main", "app_read < 0"); + exit (EXIT_FAILURE); + } + + printf ("msg recv: %s", m.val); + msg_free (&m); + } + + if (app_close (&srv) < 0) { + handle_err("main", "app_close < 0"); + exit (EXIT_FAILURE); + } +} + +int main (int argc, char *argv[], char *env[]) +{ + if (argc == 1) + non_interactive (argc, argv, env); + else + interactive (argc, argv, env); + + return EXIT_SUCCESS; +} diff --git a/pong/app/pongd.c b/pong/app/pongd.c new file mode 100644 index 0000000..de9adcf --- /dev/null +++ b/pong/app/pongd.c @@ -0,0 +1,144 @@ +#include "../../core/communication.h" +#include "../../core/process.h" +#include "../../core/error.h" + +#include +#include +#include + +#define PONGD_SERVICE_NAME "pongd" + +int cpt = 0; + +void handle_new_connection (struct service *srv, struct array_proc *ap) +{ + struct process *p = malloc(sizeof(struct process)); + memset(p, 0, sizeof(struct process)); + + if (srv_accept (srv, p) < 0) { + handle_error("srv_accept < 0"); + } else { + printf("new connection\n"); + } + + if (add_proc (ap, p) < 0) { + handle_error("add_proc < 0"); + } + + cpt++; + printf ("%d client(s)\n", cpt); +} + +void handle_new_msg (struct array_proc *ap, struct array_proc *proc_to_read) +{ + struct msg m; + memset (&m, 0, sizeof (struct msg)); + int i; + for (i = 0; i < proc_to_read->size; i++) { + // printf ("loop handle_new_msg\n"); + if (srv_read (proc_to_read->tab_proc[i], &m) < 0) { + handle_error("srv_read < 0"); + } + + // close the process then delete it from the process array + if (m.type == MSG_TYPE_DIS) { + cpt--; + printf ("disconnection => %d client(s) remaining\n", cpt); + + if (srv_close_proc (proc_to_read->tab_proc[i]) < 0) + handle_error( "srv_close_proc < 0"); + if (del_proc (ap, proc_to_read->tab_proc[i]) < 0) + handle_error( "del_proc < 0"); + if (del_proc (proc_to_read, proc_to_read->tab_proc[i]) < 0) + handle_err( "handle_new_msg", "del_proc < 0"); + i--; + continue; + } + + printf ("new message : %s", m.val); + if (srv_write (proc_to_read->tab_proc[i], &m) < 0) { + handle_error("srv_write < 0"); + } + } +} + +/* + * main loop + * + * accept new application connections + * read a message and send it back + * close a connection if MSG_TYPE_DIS received + */ + +void main_loop (struct service *srv) +{ + int i, ret = 0; + + struct array_proc ap; + memset(&ap, 0, sizeof(struct array_proc)); + + struct array_proc proc_to_read; + memset(&proc_to_read, 0, sizeof(struct array_proc)); + + while(1) { + ret = srv_select (&ap, srv, &proc_to_read); + // printf ("on peut lire ces process:\n"); + // array_proc_print (&proc_to_read); + // printf ("-- \n\n"); + + if (ret == CONNECTION) { + handle_new_connection (srv, &ap); + } else if (ret == APPLICATION) { + handle_new_msg (&ap, &proc_to_read); + } else { // both new connection and new msg from at least one client + handle_new_connection (srv, &ap); + handle_new_msg (&ap, &proc_to_read); + } + array_proc_free (&proc_to_read); + } + + for (i = 0; i < ap.size; i++) { + if (srv_close_proc (ap.tab_proc[i]) < 0) { + handle_error( "srv_close_proc < 0"); + } + } +} + + +/* + * service ping-pong + * + * 1. creates the named pipe /tmp/, then listens + * 2. opens the named pipes in & out + * 3. talks with the (test) program + * 4. closes the test program named pipes + * 5. removes the named pipe /tmp/ + */ + +int main(int argc, char * argv[], char **env) +{ + struct service srv; + memset (&srv, 0, sizeof (struct service)); + srv.index = 0; + srv.version = 0; + + // unlink("/tmp/ipc/pongd-0-0"); + + if (srv_init (argc, argv, env, &srv, PONGD_SERVICE_NAME) < 0) { + handle_error("srv_init < 0"); + return EXIT_FAILURE; + } + printf ("Listening on %s.\n", srv.spath); + + printf("MAIN: server created\n" ); + + // the service will loop until the end of time, a specific message, a signal + main_loop (&srv); + + // the application will shut down, and remove the service named pipe + if (srv_close (&srv) < 0) { + handle_error("srv_close < 0"); + } + + return EXIT_SUCCESS; +}