Comment servir des pintes de Guinness "over Internet" ;) Reprise/Fork d'un très ancien code d'un pilier de f.m.b.l : http://tnemeth.free.fr/projets/guinness-server.html
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

274 lines
6.7 KiB

/*
* guinnessd
* architecture clients/serveur guinness : broadcast messages
* Thomas Nemeth -- le 15 juin 2001
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>
#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;
}