#include "mhshmnetwork.h" struct daemon { struct daemon *next; char *host; int port; } *daemons_head; unsigned char shared_page[4096]; void quit (void); void printinfo (void); void sighandler (int signal) { switch (signal) { case SIGTERM: case SIGINT: quit(); break; case SIGHUP: printinfo(); break; default: fprintf (stderr, "recu signal %d\n", signal); } } void quit (void) { struct daemon *daemon = daemons_head; struct mhshm_net_packet packet; packet.type = SERVQUIT; while (daemon) { send_packet (daemon->host, daemon->port, &packet); daemon = daemon->next; } exit (0); } void printinfo (void) { struct daemon *daemon = daemons_head; fprintf (stderr, "Info :\n"); while (daemon) { fprintf (stderr, "démon sur %s:%d\n", daemon->host, daemon->port); daemon = daemon->next; } fprintf (stderr, ".\n"); } /* le serveur recoit l'enregistrement d'un nouveau démon */ void server_newdaemon (char *host, unsigned port) { struct daemon *daemon = (struct daemon*)malloc (sizeof (struct daemon)); struct mhshm_net_packet packet; char *tmp = strdup (host); if (!daemon || !tmp) { if (daemon) free (daemon); if (tmp) free (tmp); fprintf (stderr, "Erreur: malloc: %s\n", strerror (errno)); packet.type = ERROR; send_packet (host, port, &packet); return; } /* insertion en tete de liste */ daemon->host = tmp; daemon->port = port; daemon->next = daemons_head; daemons_head = daemon; packet.type = INITPAGE; memcpy (&packet.data.page, &shared_page, sizeof (shared_page)); send_packet (daemon->host, daemon->port, &packet); } /* le démon se termine */ void server_diedaemon (char *host, int port) { struct daemon **pdaemon = &daemons_head; struct daemon *daemon; /* on retire le démon d'host host et de port port de la liste */ while ((daemon = *pdaemon)) { if (!strcmp (daemon->host, host) && daemon->port == port) { *pdaemon = daemon->next; free (daemon->host); free (daemon); } else pdaemon = &daemon->next; } } /* le serveur recoit une modification d'un démon */ void server_newmod (char *host, int dport, struct mhshm_net_mod *mod) { struct daemon *daemon = daemons_head; struct mhshm_net_packet packet; unsigned int i; /* met a jour la page de référence */ fprintf (stderr, "recu %lu modifications:\n", mod->nb_mod); for (i = 0 ; i < mod->nb_mod ; i++) { fprintf (stderr, "off: %lu, data: %u\n", mod->mod[i].offset, mod->mod[i].data); shared_page[mod->mod[i].offset] = mod->mod[i].data; } /* et transmet les modifications aux autres daemons */ packet.type = DISPMOD; memcpy (&packet.data.moddata, mod, sizeof (*mod)); while (daemon) { /* on ne réémet pas la modification vers l'émetteur */ if (strcmp (host, daemon->host) || dport != daemon->port) send_packet (daemon->host, daemon->port, &packet); daemon = daemon->next; } } /* * cree un serveur qui sera maitre sur le contenu d'une page partagée */ void server (int listened_socket) { struct mhshm_net_packet packet; struct sockaddr_in sa; int salen; int sock_in; char *host; daemons_head = NULL; /* la page partagée est initialement a 0 */ memset (&shared_page, 0, sizeof (shared_page)); for (;;) { /* on attend une connection entrante */ do { /* evite d'utiliser le processeur a 100% */ usleep (10000); salen = sizeof (sa); sock_in = accept (listened_socket, (struct sockaddr *)&sa, &salen); } while ((sock_in == -1) && (errno == EAGAIN)); if (sock_in == -1) { fprintf (stderr, "Error: accept: %s\n", strerror (errno)); usleep (100000); continue; } host = strdup (inet_ntoa (sa.sin_addr)); if (!host) { fprintf (stderr, "Error: malloc: %s\n", strerror (errno)); usleep (100000); continue; } printf ("Connection de %s\n", host); if (read_packet (sock_in, &packet)) { fprintf (stderr, "Erreur a la réception du paquet - paquet ignoré\n"); continue; } switch (packet.type) { case SENDMOD: server_newmod (host, packet.port, &packet.data.moddata); break; case NEWDAEMON: server_newdaemon (host, packet.port); break; case DIEDAEMON: server_diedaemon (host, packet.port); break; default: fprintf (stderr, "Erreur: recu paquet de type %d (%s)\n", (int)packet.type, pkt2str(packet.type)); } free (host); } } int main (int argc, char **argv) { int port; int listened_socket; if (argc < 2) { fprintf (stderr, "Usage : %s \n", argv[0]); exit (1); } signal (SIGTERM, sighandler); signal (SIGINT, sighandler); signal (SIGHUP, sighandler); port = atoi (argv[1]); listened_socket = listen_socket (port); fprintf (stderr, "Serveur en écoute sur le port %d\n", port); server (listened_socket); shutdown (listened_socket, SHUT_RDWR); close (listened_socket); return 0; }