|
|
@ -0,0 +1,576 @@ |
|
|
|
/* |
|
|
|
* guinnessd |
|
|
|
* architecture clients/serveur guinness |
|
|
|
* Thomas Nemeth -- le 15 juin 2001 |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <time.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <signal.h> |
|
|
|
#include <pthread.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <getopt.h> |
|
|
|
#include <sys/types.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <netinet/in.h> |
|
|
|
#include <string.h> |
|
|
|
#include <strings.h> |
|
|
|
#include <locale.h> |
|
|
|
#include "defines.h" |
|
|
|
#include "xmem.h" |
|
|
|
#include "tools.h" |
|
|
|
#include "printlog.h" |
|
|
|
#include "lists.h" |
|
|
|
#include "broadcast.h" |
|
|
|
#include "drinks.h" |
|
|
|
#include "clients.h" |
|
|
|
#include "guinnessd.h" |
|
|
|
#include "commands.h" |
|
|
|
#include "config.h" |
|
|
|
|
|
|
|
/* Config spécifique serveur */ |
|
|
|
char *adr_ip = NULL; |
|
|
|
int port = 0; |
|
|
|
int online = TRUE; |
|
|
|
char *fichierlog = NULL; |
|
|
|
char *fichiercfg = NULL; |
|
|
|
char *chemin = NULL; |
|
|
|
char *admin_passwd = NULL; |
|
|
|
FILE *logfile = NULL; |
|
|
|
FILE *outerr = NULL; |
|
|
|
Elt *clients_list = NULL; |
|
|
|
Elt *drinks_list = NULL; |
|
|
|
|
|
|
|
/* Config spécifique connexion des clients */ |
|
|
|
char *pseudo = NULL; |
|
|
|
char *drink = NULL; |
|
|
|
char *logout = NULL; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef SunOS |
|
|
|
char *crypt(const char *key, const char *salt); |
|
|
|
#else |
|
|
|
extern char *crypt __P ((__const char *__key, __const char *__salt)); |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
void install_handler (); |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Gestionnaire de signal SIGPIPE, SIGTERM, SIGQUIT et SIGINT |
|
|
|
* |
|
|
|
*/ |
|
|
|
void handler_signaux (int sig) { |
|
|
|
switch (sig) { |
|
|
|
case SIGPIPE: |
|
|
|
printlog (LOG_NOTIFY, "Signal SIGPIPE reçu...\n"); |
|
|
|
install_handler (); |
|
|
|
break; |
|
|
|
case SIGTERM: |
|
|
|
case SIGQUIT: |
|
|
|
case SIGINT: |
|
|
|
online = FALSE; |
|
|
|
printlog (LOG_NOTIFY, "Signal de terminaison reçu...\n"); |
|
|
|
break; |
|
|
|
default: |
|
|
|
printlog (LOG_NOTIFY, "Signal reçu...\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Lecture du fichier de config : récupération des valeurs |
|
|
|
* |
|
|
|
*/ |
|
|
|
char *get_string_from_token (char *line) { |
|
|
|
char *result = line; |
|
|
|
char *tmp; |
|
|
|
int keyval = 0; |
|
|
|
|
|
|
|
while ( (keyval != 1) && (result [0] != 0) ) { |
|
|
|
if (result [0] == '=') keyval = 1; |
|
|
|
if (keyval == 0) result++; |
|
|
|
} |
|
|
|
tmp = result++; |
|
|
|
while (tmp [0] != 0) { |
|
|
|
if (tmp [0] == '\n') tmp [0] = 0; |
|
|
|
tmp++; |
|
|
|
} |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Lecture du fichier de config |
|
|
|
* |
|
|
|
*/ |
|
|
|
void load_config () { |
|
|
|
FILE *file; |
|
|
|
char tmpstr[MAXSTRLEN + 1]; |
|
|
|
char *value; |
|
|
|
|
|
|
|
/* Ouverture du fichier */ |
|
|
|
if ( (file = fopen (fichiercfg?fichiercfg:CONFIG_FILE, "r") ) != NULL) { |
|
|
|
/* Lecture du fichier */ |
|
|
|
while (! feof (file) ) { |
|
|
|
memset (tmpstr, 0, MAXSTRLEN + 1); |
|
|
|
fgets (tmpstr, (int) MAXSTRLEN, file); |
|
|
|
value = get_string_from_token (tmpstr); |
|
|
|
if ( (strncmp (tmpstr, "port=", 5) == 0) && (port == 0) ) |
|
|
|
port = atoi (value); |
|
|
|
if ( (strncmp (tmpstr, "passwd=", 7) == 0) && |
|
|
|
(admin_passwd == NULL) ) |
|
|
|
admin_passwd = xstrdup (crypt (value, "Gs") + 2); |
|
|
|
if ( (strncmp (tmpstr, "rep=", 4) == 0) && (chemin == NULL) ) |
|
|
|
chemin = xstrdup (value); |
|
|
|
if ( (strncmp (tmpstr, "pseudo=", 7) == 0) && (pseudo == NULL) ) |
|
|
|
pseudo = xstrdup (value); |
|
|
|
if ( (strncmp (tmpstr, "drink=", 6) == 0) && (drink == NULL) ) |
|
|
|
drink = xstrdup (value); |
|
|
|
if ( (strncmp (tmpstr, "logout=", 7) == 0) && (logout == NULL) ) |
|
|
|
logout = xstrdup (value); |
|
|
|
} |
|
|
|
fclose (file); |
|
|
|
#ifdef DEBUG |
|
|
|
} else { |
|
|
|
fprintf (stderr, "Pas de fichier de config (%s).\n", CONFIG_FILE); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Aide |
|
|
|
* |
|
|
|
*/ |
|
|
|
void Usage (int help) { |
|
|
|
printf ("guinnessd by Thomas Nemeth - v %s (compilation %s : %s)\n", |
|
|
|
VERSION, OS_TYPE, COMPIL_DATE); |
|
|
|
if (help) |
|
|
|
printf ("Usage : guinnessd [-h] [-v] [-b] [-p port] " |
|
|
|
"[-s passwd] [-d chemin] [-l fichier] [-f fichier]\n" |
|
|
|
" -h : aide sur les paramètres\n" |
|
|
|
" -v : affiche la version\n" |
|
|
|
" -b : détache le serveur du terminal\n" |
|
|
|
" -a adresse : spécifie l'adresse du serveur\n" |
|
|
|
" -p port : spécifie le numéro du port\n" |
|
|
|
" -s passwd : spécifie le mot de passe d'aministration\n" |
|
|
|
" -d chemin : indique le chemin où se" |
|
|
|
" trouvent les ascii-arts\n" |
|
|
|
" -l fichier : fichier de log\n" |
|
|
|
" -f fichier : fichier de configuration\n\n"); |
|
|
|
exit (1); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Traitement des arguments |
|
|
|
* |
|
|
|
*/ |
|
|
|
int traite_argv (int argc, char *argv[]) { |
|
|
|
int option; |
|
|
|
int detach = FALSE; |
|
|
|
|
|
|
|
/* Vérification des paramètres */ |
|
|
|
while ((option = getopt (argc, argv, "hvba:p:s:d:l:f:")) != -1) { |
|
|
|
switch (option) { |
|
|
|
case 'h' : |
|
|
|
Usage (TRUE); |
|
|
|
break; |
|
|
|
case 'v' : |
|
|
|
Usage (FALSE); |
|
|
|
break; |
|
|
|
case 'b' : |
|
|
|
detach = TRUE; |
|
|
|
break; |
|
|
|
case 'a' : |
|
|
|
adr_ip = optarg; |
|
|
|
break; |
|
|
|
case 'p' : |
|
|
|
port = atoi (optarg); |
|
|
|
break; |
|
|
|
case 's' : |
|
|
|
admin_passwd = xstrdup (crypt (optarg, "Gs") + 2); |
|
|
|
break; |
|
|
|
case 'd' : |
|
|
|
if (! chemin) { |
|
|
|
if (optarg[0] == '/') { |
|
|
|
chemin = xstrdup (optarg); |
|
|
|
} else { |
|
|
|
char *Pwd; |
|
|
|
Pwd = xmalloc ((MAXSTRLEN + 1) * sizeof (char)); |
|
|
|
getcwd (Pwd, MAXSTRLEN); |
|
|
|
chemin = xmalloc ( (strlen (Pwd) + strlen (optarg) + 2) |
|
|
|
* sizeof (char) ); |
|
|
|
snprintf (chemin, MAXSTRLEN, "%s/%s", |
|
|
|
Pwd, optarg); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'l' : |
|
|
|
if (! fichierlog) { |
|
|
|
fichierlog = xstrdup (optarg); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'f' : |
|
|
|
if (! fichiercfg) { |
|
|
|
fichiercfg = xstrdup (optarg); |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
Usage (TRUE); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (optind < argc) { |
|
|
|
if (argc - optind == 1) |
|
|
|
fprintf (stderr, "%s: option inconnue --", argv[0]); |
|
|
|
else |
|
|
|
fprintf (stderr, "%s: options inconnues --", argv[0]); |
|
|
|
for ( ; optind < argc ; optind++) |
|
|
|
fprintf (stderr, " %s", argv[optind]); |
|
|
|
fprintf (stderr, "\n"); |
|
|
|
Usage (TRUE); |
|
|
|
} |
|
|
|
|
|
|
|
return detach; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Fonction initiant la connexion. |
|
|
|
* |
|
|
|
*/ |
|
|
|
int initiate (int socket_service, userinfos *infos) { |
|
|
|
int cont = TRUE; |
|
|
|
char userdatas[MAXSTRLEN]; |
|
|
|
char *datas, *token, *saveptr; |
|
|
|
char delim[] = "\n\r"; |
|
|
|
char *nom_distant = NULL; |
|
|
|
char *ip_distant = NULL; |
|
|
|
int port_distant = 0; |
|
|
|
int port_local = 0; |
|
|
|
time_t now; |
|
|
|
struct tm *today; |
|
|
|
|
|
|
|
memset (userdatas, 0, MAXSTRLEN); |
|
|
|
|
|
|
|
/* Récupération des infos sur le connecté */ |
|
|
|
get_sock_infos (socket_service, |
|
|
|
&nom_distant, &ip_distant, |
|
|
|
&port_local, &port_distant); |
|
|
|
if (ip_distant) { |
|
|
|
snprintf (infos->ip, MAXSTRLEN, "%s", ip_distant); |
|
|
|
free (ip_distant); |
|
|
|
} else sprintf (infos->ip, "0.0.0.0"); |
|
|
|
if (nom_distant) { |
|
|
|
snprintf (infos->host, MAXSTRLEN, "%s", nom_distant); |
|
|
|
free (nom_distant); |
|
|
|
} else sprintf (infos->host, "none"); |
|
|
|
infos->port = port_distant; |
|
|
|
|
|
|
|
printlog (LOG_NOTIFY, "Connexion entrante : %s %s\n", |
|
|
|
infos->ip, infos->host ? infos->host : ""); |
|
|
|
printlog (LOG_NOTIFY, "Ports (loc/dist) : %d / %d\n", |
|
|
|
port_local, infos->port); |
|
|
|
|
|
|
|
/* PROTOCOLE DE CONNEXION */ |
|
|
|
/* 1. envoi des commandes du serveur */ |
|
|
|
if ( (cont = send_servercmds (socket_service)) == FALSE) |
|
|
|
return cont; |
|
|
|
|
|
|
|
/* 2. attente des données du connecté */ |
|
|
|
if ( (cont = read_infos (socket_service, userdatas)) == FALSE) |
|
|
|
return cont; |
|
|
|
|
|
|
|
/* FIN DU PROTOCOLE : Véricifations / ajout dans la liste / affichage */ |
|
|
|
datas = xstrdup (userdatas); |
|
|
|
|
|
|
|
/* Nom d'utilisateur */ |
|
|
|
token = strtok_r (datas, delim, &saveptr); |
|
|
|
snprintf (infos->nom, MAXSTRLEN, "%s", token ? token : pseudo); |
|
|
|
|
|
|
|
/* Boisson préférée */ |
|
|
|
token = strtok_r (NULL, delim, &saveptr); |
|
|
|
snprintf (infos->prefb, MAXSTRLEN, "%s", token ? token : drink); |
|
|
|
|
|
|
|
/* Message d'au-revoir */ |
|
|
|
token = strtok_r (NULL, delim, &saveptr); |
|
|
|
snprintf (infos->logout, MAXSTRLEN, "%s", token ? token : logout); |
|
|
|
|
|
|
|
/* Date de connexion */ |
|
|
|
time (&now); |
|
|
|
today = localtime (&now); |
|
|
|
strftime (infos->cxdate, MAXSTRLEN, "%a %d %b %Y %T", today); |
|
|
|
|
|
|
|
printlog (LOG_NOTIFY, "Utilisateur : [%s]\n", infos->nom); |
|
|
|
printlog (LOG_NOTIFY, "Boisson préférée : [%s]\n", infos->prefb); |
|
|
|
printlog (LOG_NOTIFY, "Message de logout : [%s]\n", infos->logout); |
|
|
|
printlog (LOG_NOTIFY, "Date de connexion : [%s]\n", infos->cxdate); |
|
|
|
|
|
|
|
pthread_mutex_lock (&mutex_clients); |
|
|
|
if (exist_elt (clients_list, infos->nom)) { |
|
|
|
char nick_ok[MAXSTRLEN]; |
|
|
|
snprintf (nick_ok, MAXSTRLEN, "@%s", infos->nom); |
|
|
|
snprintf (infos->nom, MAXSTRLEN, "%s", nick_ok); |
|
|
|
send_infos (socket_service, "@Pseudo déjà utilisé !\n"); |
|
|
|
printlog (LOG_NOTIFY, "Pseudo déjà utilisé => %s\n", infos->nom); |
|
|
|
pthread_mutex_unlock (&mutex_clients); |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
send_infos (socket_service, "Bienvenue sur le serveur de Guinness.\n"); |
|
|
|
add_client (infos); |
|
|
|
pthread_mutex_unlock (&mutex_clients); |
|
|
|
|
|
|
|
if (! exist_elt (drinks_list, infos->prefb)) |
|
|
|
send_infos (socket_service, |
|
|
|
"Votre boisson préférée n'est pas disponible sur ce" |
|
|
|
" serveur !\nVous aurez des Guinness à la place.\n"); |
|
|
|
|
|
|
|
/* Passage en mode non bloquant */ |
|
|
|
fcntl (socket_service, F_SETFL, O_NONBLOCK); |
|
|
|
|
|
|
|
return cont; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Fonction de traitement de la connexion avec les clients |
|
|
|
* |
|
|
|
*/ |
|
|
|
void thread_service (int *sock_serv) { |
|
|
|
pthread_t tid = pthread_self (); |
|
|
|
long old_id = get_broadcastid (); |
|
|
|
int socket_service = (int) *sock_serv; |
|
|
|
int cont = TRUE; |
|
|
|
int nb; |
|
|
|
userinfos infos; |
|
|
|
char commande[MAXSTRLEN + 1]; |
|
|
|
|
|
|
|
pthread_detach (tid); |
|
|
|
|
|
|
|
memset (infos.nom, 0, MAXSTRLEN + 1); |
|
|
|
memset (infos.prefb, 0, MAXSTRLEN + 1); |
|
|
|
memset (infos.logout, 0, MAXSTRLEN + 1); |
|
|
|
infos.admin = FALSE; |
|
|
|
infos.cold = FALSE; |
|
|
|
|
|
|
|
cont = initiate (socket_service, &infos); |
|
|
|
|
|
|
|
if (cont) { |
|
|
|
snprintf (commande, MAXSTRLEN, |
|
|
|
"%s a rejoint le serveur de Guinness.\n", infos.nom); |
|
|
|
broadcast (MESSAGE, NULL, commande); |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
printlog (LOG_NOTIFY, "Prêt à recevoir des commandes.\n"); |
|
|
|
#endif |
|
|
|
|
|
|
|
while (cont == TRUE) { |
|
|
|
memset (commande, 0, MAXSTRLEN + 1); |
|
|
|
|
|
|
|
/* Lecture des caractères reçus */ |
|
|
|
do { |
|
|
|
sleep (1); |
|
|
|
nb = read (socket_service, commande, MAXSTRLEN); |
|
|
|
if ( (nb == -1) || (nb == 0) ) { |
|
|
|
if ( (errno == EAGAIN) && (nb == -1) ) continue; |
|
|
|
if ( (errno == EPIPE) || (nb == 0) ) { |
|
|
|
cont = FALSE; |
|
|
|
} else { |
|
|
|
printlog (LOG_ERROR, "Erreur de connexion réception !\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
} while ( (cont != FALSE) && |
|
|
|
(nb < 0) && |
|
|
|
(new_message (old_id) != TRUE) ); |
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
printlog (LOG_NOTIFY, "Commande reçue.\n"); |
|
|
|
#endif |
|
|
|
if (cont == TRUE) { |
|
|
|
/* Traitement de la commande */ |
|
|
|
if (nb > 0) |
|
|
|
cont = reply (socket_service, commande, &infos); |
|
|
|
/* Broadcast */ |
|
|
|
if (new_message (old_id) == TRUE) { |
|
|
|
old_id = get_broadcastid (); |
|
|
|
cont = send_broadcast (socket_service, &infos); |
|
|
|
#ifdef DEBUG |
|
|
|
printlog (LOG_ERROR, "Émission broadcast pour %s (id = %ld)\n", |
|
|
|
infos.nom, old_id); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
printlog (LOG_NOTIFY, "Bye bye %s...\n", infos.nom); |
|
|
|
|
|
|
|
if (infos.nom[0] != '@') { |
|
|
|
pthread_mutex_lock (&mutex_clients); |
|
|
|
remove_client (&infos); |
|
|
|
pthread_mutex_unlock (&mutex_clients); |
|
|
|
|
|
|
|
broadcast (QUITTER, infos.nom, infos.logout); |
|
|
|
} |
|
|
|
|
|
|
|
close (socket_service); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Installation du gestionnaire de signal SIGPIPE et autres... |
|
|
|
* |
|
|
|
*/ |
|
|
|
void install_handler () { |
|
|
|
signal (SIGPIPE, handler_signaux); |
|
|
|
signal (SIGTERM, handler_signaux); |
|
|
|
signal (SIGQUIT, handler_signaux); |
|
|
|
signal (SIGINT, handler_signaux); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Initialisation générale |
|
|
|
* |
|
|
|
*/ |
|
|
|
void guinnessd_init (int argc, char *argv[]) { |
|
|
|
pthread_mutexattr_t mutex_attr; |
|
|
|
|
|
|
|
setlocale (LC_ALL, ""); |
|
|
|
install_handler (); |
|
|
|
|
|
|
|
/* Valeurs par défaut */ |
|
|
|
logfile = stdout; |
|
|
|
outerr = stderr; |
|
|
|
|
|
|
|
/* Traitement des paramètres */ |
|
|
|
if (traite_argv (argc, argv) == TRUE) { |
|
|
|
switch (fork()) { |
|
|
|
case -1: /* erreur */ |
|
|
|
perror ("fork()"); |
|
|
|
exit (-1); |
|
|
|
case 0: /* le fils */ |
|
|
|
setsid (); |
|
|
|
break; |
|
|
|
default: /* le père */ |
|
|
|
exit (0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Lecture du fichier de configuration */ |
|
|
|
load_config (); |
|
|
|
|
|
|
|
/* Initialisation des sémaphores */ |
|
|
|
pthread_mutexattr_init (&mutex_attr); |
|
|
|
pthread_mutex_init (&mutex_broadcast, &mutex_attr); |
|
|
|
pthread_mutex_init (&mutex_clients, &mutex_attr); |
|
|
|
|
|
|
|
/* Affectation des paramètres */ |
|
|
|
if (IS_NOT_GOOD (pseudo)) SET_STRING (pseudo, DEFAULT_PSEUDO); |
|
|
|
if (IS_NOT_GOOD (drink)) SET_STRING (drink, DEFAULT_DRINK); |
|
|
|
if (IS_NOT_GOOD (logout)) SET_STRING (logout, DEFAULT_LOGOUT); |
|
|
|
if (port == 0) port = DEFAULT_SERVER_PORT; |
|
|
|
if (fichierlog) { |
|
|
|
if ((logfile = fopen (fichierlog, "a"))) { |
|
|
|
outerr = logfile; |
|
|
|
} else { |
|
|
|
fprintf (stderr, "Impossible d'ouvrir le fichier %s : %s\n", |
|
|
|
fichierlog, strerror(errno)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Option pour le buffer de logs */ |
|
|
|
setvbuf (logfile, NULL, _IOLBF, 0); |
|
|
|
|
|
|
|
/* Création de la liste de boissons par défaut*/ |
|
|
|
add_elt (&drinks_list, "guinness"); |
|
|
|
|
|
|
|
if (! chemin) chemin = xstrdup (DRINKS_DIR); |
|
|
|
drinks_list_files (chemin); |
|
|
|
drinks_display_list (); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Fonction principale |
|
|
|
* |
|
|
|
*/ |
|
|
|
int main (int argc, char *argv[]) { |
|
|
|
int socket_ecoute; |
|
|
|
int socket_service; |
|
|
|
int lg_adresse = sizeof (struct sockaddr_in); |
|
|
|
struct sockaddr_in adresse; |
|
|
|
pthread_t pthread_id; |
|
|
|
|
|
|
|
guinnessd_init (argc, argv); |
|
|
|
|
|
|
|
/* Installation de l'écoute du serveur */ |
|
|
|
if ( (socket_ecoute = install_server (port, adr_ip, NULL)) == -1) { |
|
|
|
printlog (LOG_ERROR, "Impossible d'installer le service.\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Passage en mode non-bloquant */ |
|
|
|
fcntl (socket_ecoute, F_SETFL, O_NONBLOCK); |
|
|
|
|
|
|
|
/* Boucle d'attente et d'ouverture de connexions */ |
|
|
|
printlog (LOG_NOTIFY, "Serveur en attente de connexions (port %d)...\n", |
|
|
|
port); |
|
|
|
while (online == TRUE) { |
|
|
|
sleep (1); |
|
|
|
|
|
|
|
/* Attente d'une connexion */ |
|
|
|
socket_service = accept (socket_ecoute, (struct sockaddr *) &adresse, |
|
|
|
&lg_adresse); |
|
|
|
|
|
|
|
/* SIGPIPE */ |
|
|
|
if ( (socket_service == -1) && (errno == EINTR) ) continue; |
|
|
|
|
|
|
|
/* PAS DE CONNEXION => mode non bloquant pour attendre un ordre de |
|
|
|
* terminaison |
|
|
|
*/ |
|
|
|
if ( (socket_service == -1) && (errno == EAGAIN) ) continue; |
|
|
|
|
|
|
|
/* Autre erreur socket */ |
|
|
|
if (socket_service == -1) { |
|
|
|
/* Erreur */ |
|
|
|
printlog (LOG_ERROR, |
|
|
|
"Erreur d'acceptation de socket, errno = %d.\n", |
|
|
|
errno); |
|
|
|
perror (__FILE__ " accept"); |
|
|
|
close (socket_ecoute); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Ici connexion acceptée */ |
|
|
|
printlog (LOG_NOTIFY, "Connexion acceptée...\n"); |
|
|
|
|
|
|
|
/* Lancement d'une activité de traitement */ |
|
|
|
if (pthread_create (&pthread_id, NULL/*pthread_attr_default*/, |
|
|
|
(void *) thread_service, |
|
|
|
(void *) &socket_service) == -1) { |
|
|
|
printlog (LOG_ERROR, "Erreur création thread de service.\n"); |
|
|
|
close (socket_service); |
|
|
|
} |
|
|
|
/* fflush (logfile); */ |
|
|
|
sleep (2); |
|
|
|
} |
|
|
|
|
|
|
|
printlog (LOG_NOTIFY, "Arrêt du serveur demandé.\n"); |
|
|
|
/* fflush (logfile); */ |
|
|
|
close (socket_ecoute); |
|
|
|
|
|
|
|
free_list (&clients_list); |
|
|
|
free_list (&drinks_list); |
|
|
|
|
|
|
|
pthread_mutex_destroy (&mutex_broadcast); |
|
|
|
pthread_mutex_destroy (&mutex_clients); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |