/* * guinnessd * architecture clients/serveur guinness : broadcast messages * Thomas Nemeth -- le 15 juin 2001 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "printlog.h" #include "xmem.h" #include "guinnessd.h" #include "lists.h" #include "tools.h" #include "broadcast.h" #include "drinks.h" extern Elt *clients_list; extern FILE *outerr; static int count = 0; static unsigned long id = 0; static Elt *bdcast_list = NULL; unsigned long get_first_id () { unsigned long ret = id; if (bdcast_list) { char *first_msg; first_msg = elt_number (bdcast_list, 0); ret = strtoul (first_msg, (char **)NULL, 10); } return ret; } unsigned long get_last_id () { unsigned long ret = id; if (bdcast_list) { char *last_msg; last_msg = elt_number (bdcast_list, get_nb_elts (bdcast_list) - 1); ret = strtoul (last_msg, (char **)NULL, 10); } return ret; } void next_broadcast (int new) { #ifdef DEBUG printlog (LOG_NOTIFY, "Suivant ? (%ld restants / %s)\n", get_nb_elts (bdcast_list), new ? "NEW" : "SUITE"); #endif if ( (new && (get_nb_elts (bdcast_list) == 1) ) || ( (!new) && (get_nb_elts (bdcast_list) >= 1) ) ) { pthread_mutex_lock (&mutex_clients); count = get_nb_elts (clients_list); pthread_mutex_unlock (&mutex_clients); id = get_last_id (); #ifdef DEBUG printlog (LOG_NOTIFY, "Message en lisse (id = %ld / count = %d)...\n", id, count); #endif } } int broadcast (int t, const char *f, const char *m) { int taille; char sid[MAXSTRLEN]; char stype[MAXSTRLEN]; char *message; pthread_mutex_lock (&mutex_clients); if (get_nb_elts (clients_list) == 0) { pthread_mutex_unlock (&mutex_clients); return TRUE; } pthread_mutex_unlock (&mutex_clients); pthread_mutex_lock (&mutex_broadcast); memset (sid, 0, MAXSTRLEN); memset (stype, 0, MAXSTRLEN); snprintf (sid, MAXSTRLEN - 1, "%ld", get_last_id () + 1); snprintf (stype, MAXSTRLEN - 1, "%d", t); taille = (strlen (sid) + strlen (stype) + (f ? strlen (f) : 3) + (m ? strlen (m) : 0) + 5) * sizeof (char); message = xmalloc (taille); memset (message, 0, taille); /* i_| t_| f_| m_ */ snprintf (message, taille, "%s%s%s%s%s%s%s", sid, SEP, stype, SEP, f ? f : "---", SEP, m ? m : ""); add_elt (&bdcast_list, message); free (message); next_broadcast (TRUE); #ifdef DEBUG printlog (LOG_NOTIFY, "Broadcast id = %s\t" "type = %s\t" "de = %s\n", sid, t == 1 ? "QUITTER" : t == 2 ? "TOURNEE" : t == 3 ? "MESSAGE" : "RIEN", f); #endif pthread_mutex_unlock (&mutex_broadcast); return TRUE; } int new_message (long cid) { int res; pthread_mutex_lock (&mutex_broadcast); res = (id > cid); pthread_mutex_unlock (&mutex_broadcast); return res; } int get_broadcastid () { int res; pthread_mutex_lock (&mutex_broadcast); res = id; pthread_mutex_unlock (&mutex_broadcast); return res; } void get_broadcastmsg (int *t, char **f, char **m) { char *token, *bdcast, *saveptr; pthread_mutex_lock (&mutex_broadcast); bdcast = xstrdup (elt_number (bdcast_list, 0)); pthread_mutex_unlock (&mutex_broadcast); if (bdcast) { #ifdef DEBUG printf ("Broadcast tokenisation : %s\n", bdcast); #endif /* id */ token = strtok_r (bdcast, SEP, &saveptr); #ifdef DEBUG printf ("Recu : ID = %s\n", token); #endif /* type */ token = strtok_r (NULL, SEP, &saveptr); #ifdef DEBUG printf ("Recu : TYPE = %s\n", token); #endif *t = atoi (token); /* from */ token = strtok_r (NULL, SEP, &saveptr); #ifdef DEBUG printf ("Recu : FROM = %s\n", token); #endif *f = NULL; if (token) *f = xstrdup (token); /* message */ token = strtok_r (NULL, SEP, &saveptr); #ifdef DEBUG printf ("Recu : MESSAGE = %s\n", token); #endif *m = NULL; if (token) *m = xstrdup (token); pthread_mutex_lock (&mutex_broadcast); if (count > 0) count--; #ifdef DEBUG printf ("count = %d\n", count); #endif if (count == 0) { remove_elt_n (&bdcast_list, 0); #ifdef DEBUG printf ("Suppression du premier element. Liste = %s\n", bdcast_list ? "OK." : "NULL !"); #endif next_broadcast (FALSE); } pthread_mutex_unlock (&mutex_broadcast); } } int send_broadcast (int socket_service, userinfos *infos) { char datas[MAXSTRLEN]; char head[MAXSTRLEN]; char *from = NULL, *mesg = NULL, *breuv = NULL; int type, cont = TRUE; memset (datas, 0, MAXSTRLEN); get_broadcastmsg (&type, &from, &mesg); printlog (LOG_NOTIFY, "Broadcast pour [%s] : %s\n", infos->nom, type == 1 ? "QUITTER" : type == 2 ? "TOURNEE" : type == 3 ? "MESSAGE" : "ERREUR"); printlog (LOG_NOTIFY, " de [%s] : %s\n", from, mesg ? mesg : "RIEN"); switch (type) { case QUITTER: /* Un utilisateur se deconnecte */ snprintf (datas, MAXSTRLEN - 1, "Deconnexion de [%s] : %s", from, mesg); break; case TOURNEE: /* Tournee generale */ if (mesg == NULL) { snprintf (head, MAXSTRLEN - 1, " -+- Tournee generale offerte par %s ! -+-", from); breuv = drinks_get (infos->prefb); } else { snprintf (head, MAXSTRLEN - 1, " -+- Tournee de %s offerte par %s ! -+-", mesg, from); breuv = drinks_get (mesg); } snprintf (datas, MAXSTRLEN - 1, "%s\n%s%s\n", head, breuv, head); free (breuv); break; case MESSAGE: /* Message */ snprintf (datas, MAXSTRLEN - 1, "<%s> %s\n", from, mesg); break; default: printlog (LOG_ERROR, "Type de message broadcast non supporte.\n"); type = -1; } if (from) free (from); if (mesg) free (mesg); if (type != -1) cont = send_infos (socket_service, datas); return cont; }