summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile14
-rw-r--r--src/ivy.c80
-rw-r--r--src/ivysocket.c148
-rw-r--r--src/ivysocket.h9
-rw-r--r--src/version.h2
5 files changed, 181 insertions, 72 deletions
diff --git a/src/Makefile b/src/Makefile
index c1f3d17..b3f6cd1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -17,7 +17,7 @@
# change this in version.h too !!!!
MAJOR=3
-MINOR=6
+MINOR=7
XTINC = -I/usr/X11R6/include
XTLIB = -L/usr/X11R6/lib -lXt -lX11 -lSM -lICE
@@ -75,7 +75,7 @@ GLIBOBJ = ivyglibloop.o ivysocket.o ivy.o
GLUTOBJ = ivyglutloop.o ivysocket.o ivy.o
TCLOBJ = ivytcl.o timer.o ivysocket.o givy.o
# WINDOWS add ivyloop.o if TCL_CHANNEL_INTEGRATION is not set
-TARGETS = ivyprobe ivyglibprobe ivyxtprobe
+TARGETS = ivyprobe ivyperf ivyglibprobe ivyxtprobe
TARGETLIBS=libivy.so.$(MAJOR).$(MINOR) libgivy.so.$(MAJOR).$(MINOR) libxtivy.so.$(MAJOR).$(MINOR) libglibivy.so.$(MAJOR).$(MINOR) libtclivy.so.$(MAJOR).$(MINOR)
# not yet need Modified Glut ivyglutprobe
@@ -107,11 +107,17 @@ ivyglutloop.o: ivyglutloop.c ivyglutloop.h
ivyglibloop.o: ivyglibloop.c ivyglibloop.h
$(CC) -c $(CFLAGS) $(GLIBINC) ivyglibloop.c
-ivyprobe: ivyprobe.o
+ivyprobe: ivyprobe.o libivy.a
$(CC) $(CFLAGS) -o $@ ivyprobe.o -L. -livy $(PCRELIB) $(EXTRALIB)
-ivyprobe.o : ivyprobe.c
+ivyprobe.o : ivyprobe.c
$(CC) $(CFLAGS) $(REGEXP) -c ivyprobe.c -o $@
+
+ivyperf: ivyperf.o libivy.a
+ $(CC) $(CFLAGS) -o $@ ivyperf.o -L. -livy $(PCRELIB) $(EXTRALIB)
+
+ivyperf.o : ivyperf.c
+ $(CC) $(CFLAGS) $(REGEXP) -c ivyperf.c -o $@
ivyxtprobe.o : ivyprobe.c
$(CC) $(CFLAGS) $(REGEXP) -DXTMAINLOOP -c ivyprobe.c -o $@ $(XTINC)
diff --git a/src/ivy.c b/src/ivy.c
index 2fd0fa0..21e1841 100644
--- a/src/ivy.c
+++ b/src/ivy.c
@@ -201,17 +201,22 @@ MsgCall (const char *message, MsgSndPtr msg, Client client)
#ifdef DEBUG
printf( "Sending message id=%d '%s'\n",msg->id,message);
#endif
- SocketSend( client, "%d %d" ARG_START ,Msg, msg->id);
+ // 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 )
+ SocketSendBuffered( client, "%d %d" ARG_START ,Msg, msg->id);
#ifdef DEBUG
printf( "Send matching args count %ld\n",msg->regexp.re_nsub);
#endif
index=1;
while ( index<rc ) {
- SocketSend( client, "%.*s" ARG_END , ovector[2*index+1]- ovector[2*index],
+ SocketSendBuffered( client, "%.*s" ARG_END , ovector[2*index+1]- ovector[2*index],
message + ovector[2*index]);
++index;
}
- SocketSend (client, "\n");
+
+ SocketSendBuffered (client, "\n");
+ SocketFlush( client );
return 1;
}
@@ -232,7 +237,10 @@ MsgCall (const char *message, MsgSndPtr msg, Client client)
#ifdef DEBUG
printf( "Sending message id=%d '%s'\n",msg->id,message);
#endif
- SocketSend( client, "%d %d" ARG_START ,Msg, msg->id);
+ // 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 )
+ SocketSendBuffered( client, "%d %d" ARG_START ,Msg, msg->id);
#ifdef DEBUG
printf( "Send matching args count %ld\n",msg->regexp.re_nsub);
@@ -241,7 +249,7 @@ MsgCall (const char *message, MsgSndPtr msg, Client client)
#ifdef GNU_REGEXP
p = &match[1];
while ( p->rm_so != -1 ) {
- SocketSend( client, "%.*s" ARG_END , p->rm_eo - p->rm_so,
+ SocketSendBuffered( client, "%.*s" ARG_END , p->rm_eo - p->rm_so,
message + p->rm_so);
++p;
}
@@ -253,10 +261,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
- SocketSend (client, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so),
+ SocketSendBuffered (client, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so),
message + match[i].rm_so);
} else {
- SocketSend (client, ARG_END);
+ SocketSendBuffered (client, ARG_END);
#ifdef DEBUG
printf( "Send matching arg%d VIDE\n",i);
#endif //DEBUG
@@ -264,7 +272,8 @@ MsgCall (const char *message, MsgSndPtr msg, Client client)
}
#endif
- SocketSend (client, "\n");
+ SocketSendBuffered (client, "\n");
+ SocketFlush(client);
return 1;
}
#endif /* USE_PCRE_REGEX */
@@ -815,17 +824,26 @@ IvyUnbindMsg (MsgRcvPtr msg)
}
/* demande de reception d'un message */
-static MsgRcvPtr
-_BindMsg (MsgCallback callback, void *user_data, const char *regexp )
+
+MsgRcvPtr
+IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... )
{
+ static char *buffer = NULL;
+ static int size = 0;
+ va_list ap;
static int recv_id = 0;
IvyClientPtr clnt;
MsgRcvPtr msg;
+
+ va_start (ap, fmt_regex );
+ make_message( &buffer, &size, fmt_regex, ap );
+ va_end (ap );
+
/* add Msg to the query list */
IVY_LIST_ADD( msg_recv, msg );
if (msg) {
msg->id = recv_id++;
- msg->regexp = strdup(regexp);
+ msg->regexp = strdup(buffer);
msg->callback = callback;
msg->user_data = user_data;
}
@@ -837,27 +855,21 @@ _BindMsg (MsgCallback callback, void *user_data, const char *regexp )
return msg;
}
-MsgRcvPtr
-IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... )
-{
- char buffer[4096];
- va_list ap;
-
- va_start (ap, fmt_regex );
- vsprintf (buffer, fmt_regex, ap );
- va_end (ap );
- return _BindMsg (callback, user_data, buffer );
-}
-
-static int
-_SendMsg (const char *message)
+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 !!!! */
+ va_list ap;
+
+ va_start( ap, fmt );
+ make_message( &buffer, &size, fmt, ap );
+ va_end ( ap );
/* recherche dans la liste des requetes recues de mes clients */
IVY_LIST_EACH (clients, clnt) {
- match_count += ClientCall (clnt, message);
+ match_count += ClientCall (clnt, buffer);
}
#ifdef DEBUG
if ( match_count == 0 ) printf( "Warning no recipient for %s\n",message);
@@ -865,24 +877,14 @@ _SendMsg (const char *message)
return match_count;
}
-int IvySendMsg(const char *fmt, ...)
-{
- char buffer[4096];
- va_list ap;
-
- va_start( ap, fmt );
- vsprintf( buffer, fmt, ap );
- va_end ( ap );
- return _SendMsg( buffer );
-}
-
void IvySendError( IvyClientPtr app, int id, const char *fmt, ... )
{
- char buffer[4096];
+ static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */
+ static int size = 0; /* donc non reentrant !!!! */
va_list ap;
va_start( ap, fmt );
- vsprintf( buffer, fmt, ap );
+ make_message( &buffer, &size, fmt, ap );
va_end ( ap );
MsgSendTo( app->client, Error, id, buffer);
}
diff --git a/src/ivysocket.c b/src/ivysocket.c
index 7565015..1ce7305 100644
--- a/src/ivysocket.c
+++ b/src/ivysocket.c
@@ -6,7 +6,7 @@
*
* Sockets
*
- * Authors: Francois-Regis Colin <fcolin@cena.dgac.fr>
+ * Authors: Francois-Regis Colin <fcolin@cena.fr>
*
* $Id$
*
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <sys/ioctl.h>
#ifdef WIN32
#define close closesocket
@@ -42,7 +43,7 @@
#include "ivysocket.h"
#include "ivyloop.h"
-#define MAX_BUFFER 2048
+#define BUFFER_SIZE 4096 /* taille buffer initiale on multiple pas deux a chaque realloc */
struct _server {
Server next;
@@ -62,7 +63,10 @@ struct _client {
struct sockaddr_in from;
SocketInterpretation interpretation;
void (*handle_delete)(Client client, void *data);
- char buffer[MAX_BUFFER+2];
+ FILE *socket_output; /* Handle buffered output */
+ char terminator; /* character delimiter of the message */
+ long buffer_size;
+ char *buffer; /* dynamicaly reallocated */
char *ptr;
void *data;
};
@@ -74,6 +78,35 @@ static Client clients_list = NULL;
WSADATA WsaData;
#endif
+// fonction de formtage a la printf d'un buffer avec reallocation dynamique
+int make_message(char ** buffer, int *size, 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. */
+ n = vsnprintf (*buffer, *size, fmt, ap);
+ /* 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;
+ }
+}
+
+
void SocketInit()
{
if (! channel_init )
@@ -113,13 +146,19 @@ static void HandleSocket (Channel channel, HANDLE fd, void *data)
long nb_to_read = 0;
long nb;
socklen_t len;
-
+
/* limitation taille buffer */
- nb_to_read = MAX_BUFFER - (client->ptr - client->buffer );
+ nb_to_read = client->buffer_size - (client->ptr - client->buffer );
if (nb_to_read == 0 ) {
- fprintf(stderr, "Erreur message trop long sans LF\n");
- client->ptr = client->buffer;
- return;
+ client->buffer_size *= 2; /* twice old size */
+ client->buffer = realloc( client->buffer, client->buffer_size );
+ if (!client->buffer )
+ {
+ fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n");
+ exit(0);
+ }
+ fprintf(stderr, "Buffer Limit reached realloc new size %ld\n", client->buffer_size );
+ nb_to_read = client->buffer_size - (client->ptr - client->buffer );
}
len = sizeof (client->from );
nb = recvfrom (fd, client->ptr, nb_to_read,0,(struct sockaddr *)&client->from,
@@ -133,22 +172,21 @@ static void HandleSocket (Channel channel, HANDLE fd, void *data)
(*channel_close) (client->channel );
return;
}
-
client->ptr += nb;
- *(client->ptr) = '\0';
ptr = client->buffer;
- while ((ptr_nl = strchr (ptr, '\n' )))
+ while ((ptr_nl = memchr (ptr, client->terminator, client->ptr - ptr )))
{
- *ptr_nl = '\0';
+ *ptr_nl ='\0';
if (client->interpretation )
(*client->interpretation) (client, client->data, ptr );
else fprintf (stderr,"Socket No interpretation function ???\n");
ptr = ++ptr_nl;
}
- if (*ptr != '\0' )
+ if (ptr < client->ptr )
{ /* recopie ligne incomplete au debut du buffer */
- strcpy (client->buffer, ptr );
- client->ptr = client->buffer + strlen(client->buffer);
+ len = client->ptr - ptr;
+ memcpy (client->buffer, ptr, len );
+ client->ptr = client->buffer + len;
}
else
{
@@ -182,6 +220,14 @@ static void HandleServer(Channel channel, HANDLE fd, void *data)
close (fd );
exit(0);
}
+ client->buffer_size = BUFFER_SIZE;
+ client->buffer = malloc( client->buffer_size );
+ if (!client->buffer )
+ {
+ fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n");
+ exit(0);
+ }
+ client->terminator = '\n';
client->from = remote2;
client->fd = ns;
client->channel = (*channel_setup) (ns, client, DeleteSocket, HandleSocket );
@@ -189,7 +235,12 @@ static void HandleServer(Channel channel, HANDLE fd, void *data)
client->ptr = client->buffer;
client->handle_delete = server->handle_delete;
client->data = (*server->create) (client );
-
+ client->socket_output = fdopen( client->fd, "w" );
+ if (!client->socket_output )
+ {
+ perror("Socket Buffered output fdopen:");
+ exit(0);
+ }
}
Server SocketServer(unsigned short port,
@@ -341,17 +392,32 @@ void SocketSetData (Client client, void *data )
void SocketSend (Client client, char *fmt, ... )
{
- char buffer[4096];
+ static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */
+ static int size = 0; /* donc non reentrant !!!! */
va_list ap;
int len;
-
if (!client)
return;
va_start (ap, fmt );
- len = vsprintf (buffer, fmt, ap );
+ len = make_message (&buffer,&size, fmt, ap );
SocketSendRaw (client, buffer, len );
va_end (ap );
}
+void SocketSendBuffered (Client client, char *fmt, ... )
+{
+ va_list ap;
+ if (!client)
+ return;
+ va_start (ap, fmt );
+ vfprintf (client->socket_output, fmt, ap );
+ va_end (ap );
+}
+void SocketFlush ( Client client )
+{
+ if (!client)
+ return;
+ fflush( client->socket_output );
+}
void *SocketGetData (Client client )
{
@@ -361,12 +427,13 @@ void *SocketGetData (Client client )
void SocketBroadcast ( char *fmt, ... )
{
Client client;
- char buffer[4096];
+ static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */
+ static int size = 0; /* donc non reentrant !!!! */
va_list ap;
int len;
va_start (ap, fmt );
- len = vsprintf (buffer, fmt, ap );
+ len = make_message (&buffer, &size, fmt, ap );
va_end (ap );
IVY_LIST_EACH (clients_list, client )
{
@@ -423,6 +490,14 @@ Client SocketConnectAddr (struct in_addr * addr, unsigned short port,
exit(0);
}
+ client->buffer_size = BUFFER_SIZE;
+ client->buffer = malloc( client->buffer_size );
+ if (!client->buffer )
+ {
+ fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n");
+ exit(0);
+ }
+ client->terminator = '\n';
client->fd = handle;
client->channel = (*channel_setup) (handle, client, DeleteSocket, HandleSocket );
client->interpretation = interpretation;
@@ -432,10 +507,15 @@ 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);
-
+ client->socket_output = fdopen( client->fd, "w" );
+ if (!client->socket_output )
+ {
+ perror("Socket Buffered output fdopen:");
+ exit(0);
+ }
return client;
}
-
+// TODO factoriser avec HandleRead !!!!
int SocketWaitForReply (Client client, char *buffer, int size, int delai)
{
fd_set rdset;
@@ -483,7 +563,7 @@ int SocketWaitForReply (Client client, char *buffer, int size, int delai)
ptr += nb;
*ptr = '\0';
- ptr_nl = strchr (buffer, '\n' );
+ ptr_nl = strchr (buffer, client->terminator );
} while (!ptr_nl );
*ptr_nl = '\0';
return (ptr_nl - buffer);
@@ -544,19 +624,33 @@ Client SocketBroadcastCreate (unsigned short port,
exit(0);
}
+ client->buffer_size = BUFFER_SIZE;
+ client->buffer = malloc( client->buffer_size );
+ if (!client->buffer )
+ {
+ fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n");
+ exit(0);
+ }
+ client->terminator = '\n';
client->fd = handle;
client->channel = (*channel_setup) (handle, client, DeleteSocket, HandleSocket );
client->interpretation = interpretation;
client->ptr = client->buffer;
client->data = data;
-
+ client->socket_output = fdopen( client->fd, "w" );
+ if (!client->socket_output )
+ {
+ perror("Socket Buffered output fdopen:");
+ exit(0);
+ }
return client;
}
void SocketSendBroadcast (Client client, unsigned long host, unsigned short port, char *fmt, ... )
{
struct sockaddr_in remote;
- char buffer[4096];
+ static char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */
+ static int size = 0; /* donc non reentrant !!!! */
va_list ap;
int err,len;
@@ -564,7 +658,7 @@ void SocketSendBroadcast (Client client, unsigned long host, unsigned short port
return;
va_start (ap, fmt );
- len = vsprintf (buffer, fmt, ap );
+ len = make_message (&buffer, &size, fmt, ap );
/* Send UDP packet to the dest */
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = htonl (host );
diff --git a/src/ivysocket.h b/src/ivysocket.h
index 4afde64..5dfdf0a 100644
--- a/src/ivysocket.h
+++ b/src/ivysocket.h
@@ -20,7 +20,9 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
+#include <stdarg.h>
+
/* general Handle */
#define ANYPORT 0
@@ -46,6 +48,9 @@ extern "C" {
/* General Init */
extern void SocketInit();
+/* utility fonction do make vsprintf without buffer limit */
+extern int make_message(char ** buffer, int *size, const char *fmt, va_list ap);
+
/* Forward def */
typedef struct _client *Client;
typedef void (*SocketInterpretation) (Client client, void *data, char *ligne);
@@ -63,6 +68,8 @@ extern void SocketServerClose( Server server );
extern void SocketClose( Client client );
extern void SocketSend( Client client, char *fmt, ... );
+extern void SocketSendBuffered (Client client, char *fmt, ... );
+extern void SocketFlush ( Client client );
extern void SocketSendRaw( Client client, char *buffer, int len );
extern char *SocketGetPeerHost( Client client );
extern void SocketSetData( Client client, void *data );
diff --git a/src/version.h b/src/version.h
index e2d3a82..89fb803 100644
--- a/src/version.h
+++ b/src/version.h
@@ -26,4 +26,4 @@
*
*/
#define IVYMAJOR_VERSION 3
-#define IVYMINOR_VERSION 6
+#define IVYMINOR_VERSION 7