From 6bf117656574521545694a1a4e5169755077631e Mon Sep 17 00:00:00 2001 From: fcolin Date: Wed, 19 Apr 2006 08:28:14 +0000 Subject: correction de probleme potentiel en multithread ( Ada rejeu ) ajout d'un warning en cas de client bloquant si la varaiable d'env IVY_DEBUG_SEND est positionne --- src/Makefile | 12 ++--- src/Makefile.win32 | 9 ++-- src/ivy.c | 101 ++++++++++++++++++----------------- src/ivy.h | 4 +- src/ivyloop.c | 16 +++--- src/ivyloop.h | 20 +++++-- src/ivyperf.c | 7 +-- src/ivyprobe.c | 2 +- src/ivysocket.c | 154 ++++++++++++++++++++++++----------------------------- src/ivysocket.h | 7 +-- src/list.h | 18 +++++-- src/timer.c | 22 ++++---- 12 files changed, 191 insertions(+), 181 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 778da73..fdd3e28 100644 --- a/src/Makefile +++ b/src/Makefile @@ -69,12 +69,12 @@ CHANNEL = -DTCL_CHANNEL_INTEGRATION CFLAGS = -g -Wall -OBJ = ivyloop.o timer.o ivysocket.o ivy.o -GOBJ = ivyloop.o timer.o ivysocket.o givy.o -XTOBJ = ivyxtloop.o ivysocket.o ivy.o -GLIBOBJ = ivyglibloop.o ivysocket.o ivy.o -GLUTOBJ = ivyglutloop.o ivysocket.o ivy.o -TCLOBJ = ivytcl.o timer.o ivysocket.o givy.o +OBJ = ivyloop.o timer.o ivysocket.o ivy.o ivybuffer.o +GOBJ = ivyloop.o timer.o ivysocket.o givy.o ivybuffer.o +XTOBJ = ivyxtloop.o ivysocket.o ivy.o ivybuffer.o +GLIBOBJ = ivyglibloop.o ivysocket.o ivy.o ivybuffer.o +GLUTOBJ = ivyglutloop.o ivysocket.o ivy.o ivybuffer.o +TCLOBJ = ivytcl.o timer.o ivysocket.o givy.o ivybuffer.o # WINDOWS add ivyloop.o if TCL_CHANNEL_INTEGRATION is not set TARGETS = ivyprobe ivyperf ivyglibprobe ivyxtprobe diff --git a/src/Makefile.win32 b/src/Makefile.win32 index 52f024e..f7aec5a 100755 --- a/src/Makefile.win32 +++ b/src/Makefile.win32 @@ -19,8 +19,11 @@ MAJOR=3 MINOR=8 -PCREINC = -I "C:\Program Files\GnuWin32\include" #`pcre-config --cflags` -PCRELIB = "C:\Program Files\GnuWin32\lib\libpcre.lib" #`pcre-config --libs` +PCREINC = -I "C:\Documents and Settings\fcolin\My Documents\Visual Studio 2005\Projects\pcre-6.4" +PCRELIB = "C:\Documents and Settings\fcolin\My Documents\Visual Studio 2005\Projects\pcre-6.4\lib\libpcre.lib" #`pcre-config --libs` + +#PCREINC = -I "C:\Program Files\GnuWin32\include" #`pcre-config --cflags` +#PCRELIB = "C:\Program Files\GnuWin32\lib\libpcre.lib" #`pcre-config --libs` PCRE_OPT = PCRE_CASELESS REGCOMP_OPT = REG_ICASE @@ -34,7 +37,7 @@ PCREOBJ = #CC=gcc #CFLAGS = -g -Wall -CFLAGS = -DWIN32 -nologo +CFLAGS = -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -nologo #LIBTOOL=ar q # linux and solaris #LIBTOOL=libtool -static -o LIBTOOL=lib -nologo /out: diff --git a/src/ivy.c b/src/ivy.c index f03a4b1..07e262e 100644 --- a/src/ivy.c +++ b/src/ivy.c @@ -38,11 +38,12 @@ #include "ivychannel.h" #include "ivysocket.h" #include "list.h" +#include "ivybuffer.h" #include "ivy.h" #define VERSION 3 -#define MAX_MATCHING_ARGS 20 +#define MAX_MATCHING_ARGS 40 #define ARG_START "\002" #define ARG_END "\003" @@ -161,9 +162,9 @@ static char * nextArg( char *s, const char *separator ) if ( end == start ) return NULL; return start; } -static void MsgSendTo( Client client, MsgType msgtype, int id, const char *message ) +static int MsgSendTo( Client client, MsgType msgtype, int id, const char *message ) { - SocketSend( client, "%d %d" ARG_START "%s\n", msgtype, id, message); + return SocketSend( client, "%d %d" ARG_START "%s\n", msgtype, id, message); } static void IvyCleanup() @@ -187,11 +188,11 @@ static void IvyCleanup() #ifdef USE_PCRE_REGEX static int -MsgCall (const char *message, MsgSndPtr msg, Client client) +MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) { - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ - int offset = 0; + int waiting = 0; + static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + int err; int ovector[OVECSIZE]; int index; int rc=pcre_exec( @@ -207,32 +208,35 @@ MsgCall (const char *message, MsgSndPtr msg, Client client) #ifdef DEBUG printf( "Sending message id=%d '%s'\n",msg->id,message); #endif + buffer.offset = 0; // il faut essayer d'envoyer le message en une seule fois sur la socket // pour eviter au maximun de passer dans le select plusieur fois par message du protocole Ivy // pour eviter la latence ( PB de perfo detecte par ivyperf ping roudtrip ) - offset += make_message_var( &buffer, &size, offset, "%d %d" ARG_START ,Msg, msg->id); + err = make_message_var( &buffer, "%d %d" ARG_START ,Msg, msg->id); #ifdef DEBUG printf( "Send matching args count %ld\n",msg->regexp.re_nsub); #endif index=1; while ( indexclient, buffer.data , buffer.offset); + if ( waiting ) + fprintf(stderr, "Ivy: Slow client : %s\n", client->app_name ); return 1; } #else /* we don't USE_PCRE_REGEX */ static int -MsgCall (const char *message, MsgSndPtr msg, Client client) +MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) { - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ - int offset = 0; - + int waiting = 0; + static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + int err; + regmatch_t match[MAX_MATCHING_ARGS+1]; #ifdef GNU_REGEXP regmatch_t* p; @@ -249,7 +253,8 @@ MsgCall (const char *message, MsgSndPtr msg, Client client) // il faut essayer d'envoyer le message en une seule fois sur la socket // pour eviter au maximun de passer dans le select plusieur fois par message du protocole Ivy // pour eviter la latence ( PB detecte par ivyperf ping roudtrip ) - offset += make_message_var( &buffer, &size, offset, "%d %d" ARG_START ,Msg, msg->id); + buffer.offset = 0; + err = make_message_var( &buffer, "%d %d" ARG_START ,Msg, msg->id); #ifdef DEBUG printf( "Send matching args count %ld\n",msg->regexp.re_nsub); @@ -258,7 +263,7 @@ MsgCall (const char *message, MsgSndPtr msg, Client client) #ifdef GNU_REGEXP p = &match[1]; while ( p->rm_so != -1 ) { - offset += make_message_var( &buffer, &size, offset, "%.*s" ARG_END , p->rm_eo - p->rm_so, + err = make_message_var( &buffer, "%.*s" ARG_END , p->rm_eo - p->rm_so, message + p->rm_so); ++p; } @@ -270,10 +275,10 @@ MsgCall (const char *message, MsgSndPtr msg, Client client) printf ("Send matching arg%d %.*s\n",i,(int)(match[i].rm_eo - match[i].rm_so), message + match[i].rm_so); #endif - offset += make_message_var( &buffer, &size, offset, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so), + buffer.offset += make_message_var( &buffer, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so), message + match[i].rm_so); } else { - offset += make_message_var( &buffer, &size, offset, ARG_END ); + buffer.offset += make_message_var( &buffer, ARG_END ); #ifdef DEBUG printf( "Send matching arg%d VIDE\n",i); #endif //DEBUG @@ -281,8 +286,8 @@ MsgCall (const char *message, MsgSndPtr msg, Client client) } #endif - offset += make_message_var( &buffer, &size, offset, "\n"); - SocketSendRaw(client, buffer , offset); + err = make_message_var( &buffer,"\n"); + SocketSendRaw(client->client, buffer.data , buffer.offset); return 1; } #endif /* USE_PCRE_REGEX */ @@ -294,7 +299,7 @@ ClientCall (IvyClientPtr clnt, const char *message) int match_count = 0; /* recherche dans la liste des requetes recues de ce client */ IVY_LIST_EACH (clnt->msg_send, msg) { - match_count+= MsgCall (message, msg, clnt->client); + match_count+= MsgCall (message, msg, clnt); } return match_count; } @@ -401,9 +406,7 @@ static void Receive( Client client, void *data, char *line ) reg = regcomp(®exp, arg, REGCOMP_OPT|REG_EXTENDED); if ( reg == 0 ) { - IVY_LIST_ADD( clnt->msg_send, snd ) - if ( snd ) - { + IVY_LIST_ADD_START( clnt->msg_send, snd ) snd->id = id; snd->str_regexp = strdup( arg ); snd->regexp = regexp; @@ -411,7 +414,7 @@ static void Receive( Client client, void *data, char *line ) { (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyAddBind ); } - } + IVY_LIST_ADD_END( clnt->msg_send, snd ) } else { @@ -424,9 +427,7 @@ static void Receive( Client client, void *data, char *line ) regexp = pcre_compile(arg, PCRE_OPT,&errbuf,&erroffset,NULL); if ( regexp != NULL ) { - IVY_LIST_ADD( clnt->msg_send, snd ) - if ( snd ) - { + IVY_LIST_ADD_START( clnt->msg_send, snd ) snd->id = id; snd->str_regexp = strdup( arg ); snd->regexp = regexp; @@ -440,7 +441,8 @@ static void Receive( Client client, void *data, char *line ) { (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyAddBind ); } - } + IVY_LIST_ADD_END( clnt->msg_send, snd ) + } else { @@ -564,9 +566,8 @@ static IvyClientPtr SendService( Client client ) { IvyClientPtr clnt; MsgRcvPtr msg; - IVY_LIST_ADD( clients, clnt ) - if ( clnt ) - { + IVY_LIST_ADD_START( clients, clnt ) + clnt->msg_send = 0; clnt->client = client; clnt->app_name = strdup("Unknown"); @@ -577,7 +578,8 @@ static IvyClientPtr SendService( Client client ) MsgSendTo( client, AddRegexp,msg->id,msg->regexp); } MsgSendTo( client, EndRegexp, 0, ""); - } + + IVY_LIST_ADD_END( clients, clnt ) return clnt; } @@ -837,25 +839,24 @@ IvyUnbindMsg (MsgRcvPtr msg) MsgRcvPtr IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... ) { - static char *buffer = NULL; - static int size = 0; + static IvyBuffer buffer = { NULL, 0, 0}; va_list ap; static int recv_id = 0; IvyClientPtr clnt; MsgRcvPtr msg; va_start (ap, fmt_regex ); - make_message( &buffer, &size, 0, fmt_regex, ap ); + buffer.offset = 0; + make_message( &buffer, fmt_regex, ap ); va_end (ap ); /* add Msg to the query list */ - IVY_LIST_ADD( msg_recv, msg ); - if (msg) { + IVY_LIST_ADD_START( msg_recv, msg ) msg->id = recv_id++; - msg->regexp = strdup(buffer); + msg->regexp = strdup(buffer.data); msg->callback = callback; msg->user_data = user_data; - } + IVY_LIST_ADD_END( msg_recv, msg ) /* Send to already connected clients */ /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH( clients, clnt ) { @@ -868,17 +869,17 @@ int IvySendMsg(const char *fmt, ...) { IvyClientPtr clnt; int match_count = 0; - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = { NULL, 0, 0}; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; va_start( ap, fmt ); - make_message( &buffer, &size, 0, fmt, ap ); + buffer.offset = 0; + make_message( &buffer, fmt, ap ); va_end ( ap ); /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH (clients, clnt) { - match_count += ClientCall (clnt, buffer); + match_count += ClientCall (clnt, buffer.data); } #ifdef DEBUG if ( match_count == 0 ) printf( "Warning no recipient for %s\n",buffer); @@ -888,14 +889,14 @@ int IvySendMsg(const char *fmt, ...) void IvySendError( IvyClientPtr app, int id, const char *fmt, ... ) { - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = { NULL, 0, 0}; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; va_start( ap, fmt ); - make_message( &buffer, &size, 0, fmt, ap ); + buffer.offset = 0; + make_message( &buffer, fmt, ap ); va_end ( ap ); - MsgSendTo( app->client, Error, id, buffer); + MsgSendTo( app->client, Error, id, buffer.data); } void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data) diff --git a/src/ivy.h b/src/ivy.h index 1ea319a..9911137 100644 --- a/src/ivy.h +++ b/src/ivy.h @@ -65,10 +65,10 @@ void IvyInit( void *die_data /* user data */ ); - void IvySetBindCallback( +void IvySetBindCallback( IvyBindCallback bind_callback, void *bind_data ); - void IvyDelBindCallback(); +void IvyDelBindCallback(); void IvyStart (const char*); void IvyStop (); diff --git a/src/ivyloop.c b/src/ivyloop.c index 9ccd427..cf121e3 100644 --- a/src/ivyloop.c +++ b/src/ivyloop.c @@ -98,17 +98,14 @@ Channel IvyChannelSetUp (HANDLE fd, void *data, { Channel channel; - IVY_LIST_ADD (channels_list, channel); - if (!channel) { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } + IVY_LIST_ADD_START (channels_list, channel) channel->fd = fd; channel->tobedeleted = 0; channel->handle_delete = handle_delete; channel->handle_read = handle_read; channel->data = data; - + IVY_LIST_ADD_END (channels_list, channel) + FD_SET (channel->fd, &open_fds); return channel; @@ -165,7 +162,7 @@ void IvyStop (void) MainLoop = 0; } -void IvyMainLoop(void(*hook)(void)) +void IvyMainLoop(void(*BeforeSelect)(void),void(*AfterSelect)(void)) { fd_set rdset; @@ -174,10 +171,12 @@ void IvyMainLoop(void(*hook)(void)) while (MainLoop) { ChannelDefferedDelete(); - if (hook) (*hook)(); + if (BeforeSelect) (*BeforeSelect)(); rdset = open_fds; exset = open_fds; ready = select(64, &rdset, 0, &exset, TimerGetSmallestTimeout()); + if (AfterSelect) (*AfterSelect)(); + if (ready < 0 && (errno != EINTR)) { fprintf (stderr, "select error %d\n",errno); perror("select"); @@ -187,7 +186,6 @@ void IvyMainLoop(void(*hook)(void)) if (ready > 0) { IvyChannelHandleExcpt(&exset); IvyChannelHandleRead(&rdset); - continue; } } } diff --git a/src/ivyloop.h b/src/ivyloop.h index c4af6eb..0696d40 100644 --- a/src/ivyloop.h +++ b/src/ivyloop.h @@ -36,9 +36,23 @@ extern "C" { #define HANDLE int #endif - - -extern void IvyMainLoop(void(*hook)(void) ); +/* +Boucle principale d'IVY baseé sur un select +les fonctions hook et unhook encradre le select +de la maniere suivante: + + BeforeSelect est appeler avant l'appel system select + AfterSelect est appeler avent l'appel system select + ces function peuvent utilisées pour depose un verrou dans le cas + d'utilisation de la mainloop Ivy dans une thread separe + + BeforeSelect ==> on libere l'acces avant la mise en attente sur le select + AfterSelect == > on verrouille l'acces en sortie du select + + !!!! Attention donc l'appel des callbacks ivy se fait avec l'acces verrouille ! +*/ + +extern void IvyMainLoop(void(*BeforeSelect)(void),void(*AfterSelect)(void) ); extern void IvyChannelInit(void); diff --git a/src/ivyperf.c b/src/ivyperf.c index 11e9522..999fb69 100755 --- a/src/ivyperf.c +++ b/src/ivyperf.c @@ -76,9 +76,10 @@ void TimerCall(TimerId id, void *user_data, unsigned long delta) int main(int argc, char *argv[]) { - + long time=200; /* Mainloop management */ + if ( argc > 1 ) time = atol( argv[1] ); IvyInit ("IvyPerf", "IvyPerf ready", NULL,NULL,NULL,NULL); @@ -87,9 +88,9 @@ int main(int argc, char *argv[]) IvyStart (0); - TimerRepeatAfter (TIMER_LOOP, 200, TimerCall, (void*)1); + TimerRepeatAfter (TIMER_LOOP, time, TimerCall, (void*)1); - IvyMainLoop (0); + IvyMainLoop (0,0); return 0; } diff --git a/src/ivyprobe.c b/src/ivyprobe.c index 10a3b00..4bcc167 100644 --- a/src/ivyprobe.c +++ b/src/ivyprobe.c @@ -398,7 +398,7 @@ int main(int argc, char *argv[]) #endif #ifdef IVYMAINLOOP - IvyMainLoop (0); + IvyMainLoop (0,0); #endif return 0; } diff --git a/src/ivysocket.c b/src/ivysocket.c index 1bb9c62..5b2fa93 100644 --- a/src/ivysocket.c +++ b/src/ivysocket.c @@ -41,6 +41,7 @@ #include "ivychannel.h" #include "ivysocket.h" #include "ivyloop.h" +#include "ivybuffer.h" #define BUFFER_SIZE 4096 /* taille buffer initiale on multiple pas deux a chaque realloc */ @@ -63,59 +64,26 @@ struct _client { SocketInterpretation interpretation; void (*handle_delete)(Client client, void *data); char terminator; /* character delimiter of the message */ + /* Buffer de reception */ long buffer_size; char *buffer; /* dynamicaly reallocated */ char *ptr; + /* user data */ void *data; }; static Server servers_list = NULL; static Client clients_list = NULL; -#ifdef WIN32 -WSADATA WsaData; +#ifdef DEBUG +static int debug_send = 1; +#else +static int debug_send = 0; #endif -// fonction de formtage a la printf d'un buffer avec reallocation dynamique -int make_message(char ** buffer, int *size, int offset, const char *fmt, va_list ap) -{ - /* Guess we need no more than BUFFER_INIT_SIZE bytes. */ - int n; - if ( *size == 0 || *buffer == NULL ) - { - *size = BUFFER_SIZE; - *buffer = malloc (BUFFER_SIZE); - if ( *buffer == NULL ) - return -1; - } - while (1) { - /* Try to print in the allocated space. */ #ifdef WIN32 - n = _vsnprintf (*buffer + offset, *size - offset, fmt, ap); -#else - n = vsnprintf (*buffer + offset, *size - offset, fmt, ap); +WSADATA WsaData; #endif - /* If that worked, return the string size. */ - if (n > -1 && n < *size) - return n; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - *size = n+1; /* precisely what is needed */ - else /* glibc 2.0 */ - *size *= 2; /* twice the old size */ - if ((*buffer = realloc (*buffer, *size)) == NULL) - return -1; - } -} -int make_message_var(char ** buffer, int *size, int offset, const char *fmt, ... ) -{ - va_list ap; - int len; - va_start (ap, fmt ); - len = make_message (buffer,size, offset, fmt, ap ); - va_end (ap ); - return len; -} void SocketInit() { @@ -124,6 +92,7 @@ void SocketInit() fprintf (stderr, "Channel management functions not set, exiting.\n"); exit(-1); } + if ( getenv( "IVY_DEBUG_SEND" )) debug_send = 1; (*channel_init)(); } @@ -223,13 +192,8 @@ static void HandleServer(Channel channel, HANDLE fd, void *data) #ifdef DEBUG printf( "Accepting Connection ret\n"); #endif //DEBUG - IVY_LIST_ADD (clients_list, client ); - if (!client ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close (fd ); - exit(0); - } + IVY_LIST_ADD_START (clients_list, client ); + client->buffer_size = BUFFER_SIZE; client->buffer = malloc( client->buffer_size ); if (!client->buffer ) @@ -245,6 +209,9 @@ static void HandleServer(Channel channel, HANDLE fd, void *data) client->ptr = client->buffer; client->handle_delete = server->handle_delete; client->data = (*server->create) (client ); + + IVY_LIST_ADD_END (clients_list, client ); + } Server SocketServer(unsigned short port, @@ -306,18 +273,15 @@ Server SocketServer(unsigned short port, }; - IVY_LIST_ADD (servers_list, server ); - if (!server ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } + IVY_LIST_ADD_START (servers_list, server ); server->fd = fd; server->channel = (*channel_setup) (fd, server, DeleteServerSocket, HandleServer ); server->create = create; server->handle_delete = handle_delete; server->interpretation = interpretation; server->port = ntohs(local.sin_port); + IVY_LIST_ADD_END (servers_list, server ); + return server; } @@ -376,16 +340,45 @@ void SocketClose (Client client ) (*channel_close) (client->channel ); } -void SocketSendRaw (Client client, char *buffer, int len ) +int SocketSendRaw (Client client, char *buffer, int len ) { int err; + int waiting= 0; if (!client) - return; + return waiting; + + if ( debug_send ) + { + /* try to determine if we are going to block */ + fd_set wrset; + int ready; + struct timeval timeout; + timeout.tv_usec = 0; + timeout.tv_sec = 0; + FD_ZERO(&wrset); + FD_SET( client->fd, &wrset ); + ready = select(client->fd+1, 0, &wrset, 0, &timeout); + //fprintf(stderr,"Ivy: select ready=%d fd=%d\n",ready,FD_ISSET( client->fd, &wrset ) ); + if(ready < 0) { + perror("Ivy: SocketSendRaw select"); + } + if ( !FD_ISSET( client->fd, &wrset ) ) + { + fprintf(stderr,"Ivy: Client Queue Full Waiting.........."); + waiting = 1; + } + + } err = send (client->fd, buffer, len, 0 ); if (err != len ) perror ("*** send ***"); + if ( debug_send && waiting ) + { + fprintf(stderr,"... OK\n"); + } + return waiting; } void SocketSetData (Client client, void *data ) @@ -394,18 +387,20 @@ void SocketSetData (Client client, void *data ) client->data = data; } -void SocketSend (Client client, char *fmt, ... ) +int SocketSend (Client client, char *fmt, ... ) { - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ + int waiting = 0; + static IvyBuffer buffer = {NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; int len; if (!client) - return; + return waiting; va_start (ap, fmt ); - len = make_message (&buffer,&size, 0, fmt, ap ); - SocketSendRaw (client, buffer, len ); + buffer.offset = 0; + len = make_message (&buffer, fmt, ap ); + waiting = SocketSendRaw (client, buffer.data, len ); va_end (ap ); + return waiting; } void *SocketGetData (Client client ) @@ -416,17 +411,16 @@ void *SocketGetData (Client client ) void SocketBroadcast ( char *fmt, ... ) { Client client; - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = {NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; int len; va_start (ap, fmt ); - len = make_message (&buffer, &size, 0, fmt, ap ); + len = make_message (&buffer, fmt, ap ); va_end (ap ); IVY_LIST_EACH (clients_list, client ) { - SocketSendRaw (client, buffer, len ); + SocketSendRaw (client, buffer.data, len ); } } @@ -472,12 +466,7 @@ Client SocketConnectAddr (struct in_addr * addr, unsigned short port, return NULL; }; - IVY_LIST_ADD (clients_list, client ); - if (!client ) { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close (handle ); - exit(0); - } + IVY_LIST_ADD_START(clients_list, client ); client->buffer_size = BUFFER_SIZE; client->buffer = malloc( client->buffer_size ); @@ -496,6 +485,8 @@ Client SocketConnectAddr (struct in_addr * addr, unsigned short port, client->from.sin_family = AF_INET; client->from.sin_addr = *addr; client->from.sin_port = htons (port); + IVY_LIST_ADD_END(clients_list, client ); + return client; } // TODO factoriser avec HandleRead !!!! @@ -600,34 +591,30 @@ Client SocketBroadcastCreate (unsigned short port, return NULL; }; - IVY_LIST_ADD(clients_list, client ); - if (!client ) { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close (handle ); - exit(0); - } + IVY_LIST_ADD_START(clients_list, client ); client->buffer_size = BUFFER_SIZE; client->buffer = malloc( client->buffer_size ); if (!client->buffer ) { - fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); + perror("HandleSocket Buffer Memory Alloc Error: "); exit(0); } - client->terminator = '\n'; + client->terminator = '\n'; client->fd = handle; client->channel = (*channel_setup) (handle, client, DeleteSocket, HandleSocket ); client->interpretation = interpretation; client->ptr = client->buffer; client->data = data; + IVY_LIST_ADD_END(clients_list, client ); + return client; } void SocketSendBroadcast (Client client, unsigned long host, unsigned short port, char *fmt, ... ) { struct sockaddr_in remote; - static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - static int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; int err,len; @@ -635,13 +622,14 @@ void SocketSendBroadcast (Client client, unsigned long host, unsigned short port return; va_start (ap, fmt ); - len = make_message (&buffer, &size, 0, fmt, ap ); + buffer.offset = 0; + len = make_message (&buffer, fmt, ap ); /* Send UDP packet to the dest */ remote.sin_family = AF_INET; remote.sin_addr.s_addr = htonl (host ); remote.sin_port = htons(port); err = sendto (client->fd, - buffer, len,0, + buffer.data, len,0, (struct sockaddr *)&remote,sizeof(remote)); if (err != len) { perror ("*** send ***"); diff --git a/src/ivysocket.h b/src/ivysocket.h index 4602b64..c656312 100644 --- a/src/ivysocket.h +++ b/src/ivysocket.h @@ -48,9 +48,6 @@ extern "C" { /* General Init */ extern void SocketInit(); -/* utility fonction do make vsprintf without buffer limit */ -extern int make_message(char ** buffer, int *size, int offset, const char *fmt, va_list ap); -extern int make_message_var(char ** buffer, int *size, int offset, const char *fmt, ...); /* Forward def */ typedef struct _client *Client; @@ -68,8 +65,8 @@ extern void SocketServerClose( Server server ); /* Client Part */ extern void SocketClose( Client client ); -extern void SocketSend( Client client, char *fmt, ... ); -extern void SocketSendRaw( Client client, char *buffer, int len ); +extern int SocketSend( Client client, char *fmt, ... ); +extern int SocketSendRaw( Client client, char *buffer, int len ); extern char *SocketGetPeerHost( Client client ); extern void SocketSetData( Client client, void *data ); extern void *SocketGetData( Client client ); diff --git a/src/list.h b/src/list.h index 472d2fc..968f619 100644 --- a/src/list.h +++ b/src/list.h @@ -50,14 +50,24 @@ }\ } \ } - -#define IVY_LIST_ADD(list, p ) \ +/* +on place le code d'initialisation de l'objet entre START et END +pour eviter de chainer un objet non initialise +*/ +#define IVY_LIST_ADD_START(list, p ) \ if ((p = (TYPEOF(p)) (malloc( sizeof( *p ))))) \ { \ - memset( p, 0 , sizeof( *p ));\ + memset( p, 0 , sizeof( *p )); + +#define IVY_LIST_ADD_END(list, p ) \ p->next = list; \ list = p; \ - } + } \ + else \ + { \ + perror( "IVY LIST ADD malloc" ); \ + exit(0); \ + } #define IVY_LIST_EACH( list, p ) \ for ( p = list ; p ; p = p -> next ) diff --git a/src/timer.c b/src/timer.c index f147232..565271e 100644 --- a/src/timer.c +++ b/src/timer.c @@ -103,18 +103,16 @@ TimerId TimerRepeatAfter( int count, long time, TimerCb cb, void *user_data ) /* si y a rien a faire et ben on fait rien */ if ( cb == NULL ) return NULL; - IVY_LIST_ADD( timers, timer ) - if ( timer ) - { - timer->repeat = count; - timer->callback = cb; - timer->user_data = user_data; - stamp = currentTime(); - timer->period = time; - timer->when = stamp + time; - if ( (timer->when < nextTimeout) || (timeoutptr == NULL)) - SetNewTimeout( stamp, timer->when ); - } + IVY_LIST_ADD_START( timers, timer ) + timer->repeat = count; + timer->callback = cb; + timer->user_data = user_data; + stamp = currentTime(); + timer->period = time; + timer->when = stamp + time; + if ( (timer->when < nextTimeout) || (timeoutptr == NULL)) + SetNewTimeout( stamp, timer->when ); + IVY_LIST_ADD_END( timers, timer ) return timer; } void TimerRemove( TimerId timer ) -- cgit v1.1