From d3b04f0209ea826c67a2ee84ced889ee907f49a0 Mon Sep 17 00:00:00 2001 From: jacomi Date: Wed, 12 Aug 1998 10:23:25 +0000 Subject: version relookee en ivy --- src/Makefile | 36 +-- src/bus.c | 690 ------------------------------------------------------- src/bus.h | 74 ------ src/buschannel.h | 43 ---- src/busloop.c | 179 --------------- src/busloop.h | 39 ---- src/bussocket.c | 516 ----------------------------------------- src/bussocket.h | 72 ------ src/busxtloop.c | 116 ---------- src/busxtloop.h | 40 ---- src/ivy.c | 690 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ivy.h | 74 ++++++ src/ivyloop.c | 179 +++++++++++++++ src/ivyloop.h | 39 ++++ src/ivysocket.c | 516 +++++++++++++++++++++++++++++++++++++++++ src/ivysocket.h | 72 ++++++ src/ivyxtloop.c | 116 ++++++++++ src/ivyxtloop.h | 40 ++++ src/testbus.c | 237 ------------------- src/testivy.c | 237 +++++++++++++++++++ 20 files changed, 1981 insertions(+), 2024 deletions(-) delete mode 100644 src/bus.c delete mode 100644 src/bus.h delete mode 100644 src/buschannel.h delete mode 100644 src/busloop.c delete mode 100644 src/busloop.h delete mode 100644 src/bussocket.c delete mode 100644 src/bussocket.h delete mode 100644 src/busxtloop.c delete mode 100644 src/busxtloop.h create mode 100644 src/ivy.c create mode 100644 src/ivy.h create mode 100644 src/ivyloop.c create mode 100644 src/ivyloop.h create mode 100644 src/ivysocket.c create mode 100644 src/ivysocket.h create mode 100644 src/ivyxtloop.c create mode 100644 src/ivyxtloop.h delete mode 100644 src/testbus.c create mode 100644 src/testivy.c diff --git a/src/Makefile b/src/Makefile index c61c797..2ae8a26 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,32 +1,32 @@ XTINC =-I/usr/X11R6/include XTLIB =-L/usr/X11R6/lib CC=gcc -g -DDEBUG -OBJ = busloop.o timer.o bussocket.o bus.o -GOBJ = busloop.o timer.o bussocket.o gbus.o -XTOBJ = busxtloop.o bussocket.o bus.o +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 -all: libbus.a libgbus.a libxtbus.a testbus testxtbus +all: libivy.a libgivy.a libxtivy.a testivy testxtivy -gbus.o: bus.c - $(CC) -DGNU_REGEXP -c $(CFLAGS) -o gbus.o bus.c +givy.o: ivy.c + $(CC) -DGNU_REGEXP -c $(CFLAGS) -o givy.o ivy.c -testbus: testbus.o $(OBJ) - $(CC) -o testbus testbus.o $(OBJ) +testivy: testivy.o $(OBJ) + $(CC) -o testivy testivy.o $(OBJ) -testxtbus.o : testbus.c - $(CC) -c testbus.c -o testxtbus.o $(XTINC) -DXTMAINLOOP +testxtivy.o : testivy.c + $(CC) -c testivy.c -o testxtivy.o $(XTINC) -DXTMAINLOOP -testxtbus: testxtbus.o $(XTOBJ) - $(CC) -o testxtbus testxtbus.o $(XTOBJ) $(XTLIB) -lXt -lX11 +testxtivy: testxtivy.o $(XTOBJ) + $(CC) -o testxtivy testxtivy.o $(XTOBJ) $(XTLIB) -lXt -lX11 -libbus.a: $(OBJ) - ar q libbus.a $(OBJ) +libivy.a: $(OBJ) + ar q libivy.a $(OBJ) -libgbus.a: $(GOBJ) - ar q libgbus.a $(GOBJ) +libgivy.a: $(GOBJ) + ar q libgivy.a $(GOBJ) -libxtbus.a: $(XTOBJ) - ar q libxtbus.a $(XTOBJ) +libxtivy.a: $(XTOBJ) + ar q libxtivy.a $(XTOBJ) diff --git a/src/bus.c b/src/bus.c deleted file mode 100644 index aa1c897..0000000 --- a/src/bus.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * - * $Id$ - */ -#include - -#include -#include -#include - -#include - -#include - -#include "buschannel.h" -#include "bussocket.h" -#include "list.h" -#include "bus.h" - -#define VERSION 3 - -#define MAX_MATCHING_ARGS 20 - -#define ARG_START "\002" -#define ARG_END "\003" - - -typedef enum { - - Bye, /* l'application emettrice se termine */ - AddRegexp, /* expression reguliere d'un client */ - Msg, /* message reel */ - Error, /* error message */ - DelRegexp, /* Remove expression reguliere */ - EndRegexp, /* end of the regexp list */ - StartRegexp, /* debut des expressions */ - DirectMsg, /* message direct a destination de l'appli */ - Die /* demande de terminaison de l'appli */ - -}MsgType; - - -typedef struct _msg_snd *MsgSndPtr; - -struct _msg_rcv { /* requete d'emission d'un client */ - MsgRcvPtr next; - int id; - const char *regexp; /* regexp du message a recevoir */ - MsgCallback callback; /* callback a declanche a la reception */ - void *user_data; /* stokage d'info client */ -}; - - -struct _msg_snd { /* requete de reception d'un client */ - MsgSndPtr next; - int id; - char *str_regexp; /* la regexp sous forme inhumaine */ - regex_t regexp; /* la regexp sous forme machine */ -}; - -struct _clnt_lst { - BusClientPtr next; - Client client; /* la socket client */ - MsgSndPtr msg_send; /* liste des requetes recues */ - char *app_name; /* nom de l'application */ - unsigned short app_port; /* port de l'application */ - }; - -/* numero de port TCP en mode serveur */ -static unsigned short ApplicationPort; - -/* numero de port UDP */ -static unsigned short SupervisionPort; - -/* client pour la socket supervision */ -static Client broadcast; - -static const char *ApplicationName = NULL; - -/* classes de messages emis par l'application utilise pour le filtrage */ -static int messages_classes_count = 0; -static const char **messages_classes = NULL; - -/* callback appele sur reception d'un message direct */ -static MsgDirectCallback direct_callback = NULL; -static *direct_user_data = NULL; - -/* callback appele sur changement d'etat d'application */ -static BusApplicationCallback application_callback; -static *application_user_data = NULL; - -/* callback appele sur demande de terminaison d'application */ -static BusDieCallback application_die_callback; -static *application_die_user_data = NULL; - -/* liste des messages a recevoir */ -static MsgRcvPtr msg_recv = NULL; - - -/* liste des clients connectes */ -static BusClientPtr clients = NULL; - -static const char *ready_message = NULL; - -static void MsgSendTo( Client client,MsgType msgtype, int id, const char *message ) -{ -SocketSend( client, "%d %d" ARG_START "%s\n",msgtype,id,message); -} -static void BusCleanup() -{ -BusClientPtr clnt; - - /* destruction des connexion clients */ - LIST_EACH( clients, clnt ) - { - /* on dit au revoir */ - MsgSendTo( clnt->client, Bye, 0, "" ); - SocketClose( clnt->client ); - LIST_EMPTY( clnt->msg_send ); - } - LIST_EMPTY( clients ); - -} -static int MsgCall( const char *message, MsgSndPtr msg, Client client ) -{ - regmatch_t match[MAX_MATCHING_ARGS+1]; -#ifdef GNU_REGEXP - regmatch_t* p; -#else - unsigned int i; -#endif - memset( match, -1, sizeof(match )); /* work around bug !!!*/ - if (regexec(&msg->regexp, message, MAX_MATCHING_ARGS, match, 0)==0) { -#ifdef DEBUG - printf( "Sending message id=%d '%s'\n",msg->id,message); -#endif - SocketSend( client, "%d %d" ARG_START ,Msg, msg->id); - -#ifdef DEBUG - printf( "Send matching args count %d\n",msg->regexp.re_nsub); -#endif //DEBUG - -#ifdef GNU_REGEXP - p = &match[1]; - while ( p->rm_so != -1 ) { - SocketSend( client, "%.*s" ARG_END , p->rm_eo - p->rm_so, - message + p->rm_so); - ++p; - } -#else - for ( i = 1; i < msg->regexp.re_nsub+1; i ++ ) - { - if ( match[i].rm_so != -1 ) - { -#ifdef DEBUG - printf( "Send matching arg%d %d %d\n",i,match[i].rm_so , match[i].rm_eo); - printf( "Send matching arg%d %.*s\n",i,match[i].rm_eo - match[i].rm_so, - message + match[i].rm_so); -#endif - SocketSend( client, "%.*s" ARG_END ,match[i].rm_eo - match[i].rm_so, - message + match[i].rm_so); - } - else - { - SocketSend( client, ARG_END ); -#ifdef DEBUG - printf( "Send matching arg%d VIDE\n",i); -#endif //DEBUG - } - } -#endif - - SocketSend( client, "\n"); - return 1; - } - return 0; -} - -int ClientCall( BusClientPtr clnt, const char *message ) -{ -MsgSndPtr msg; -int match_count = 0; - /* recherche dans la liste des requetes recues de ce client */ - LIST_EACH( clnt->msg_send, msg ) - { - match_count+= MsgCall( message, msg, clnt->client ); - } - return match_count; -} -static int CheckRegexp(char *exp) -{ - /* accepte tout par default */ - int i; - int regexp_ok = 1; - if ( *exp =='^' && messages_classes_count !=0 ) - { - regexp_ok = 0; - for ( i = 0 ; i < messages_classes_count; i++ ) - { - if (strncmp( messages_classes[i], exp+1, strlen( messages_classes[i] )) == 0) - return 1; - } - } - return regexp_ok; -} -static int CheckConnected( BusClientPtr clnt ) -{ -BusClientPtr client; -struct in_addr *addr1; -struct in_addr *addr2; - if ( clnt->app_port == 0 ) - return 0; - /* recherche dans la liste des clients de la presence de clnt */ - LIST_EACH( clients, client ) - { - /* client different mais port identique */ - if ( (client != clnt) && (clnt->app_port == client->app_port) ) - { - /* et meme machine */ - addr1 = SocketGetRemoteAddr( client->client ); - addr2 = SocketGetRemoteAddr( clnt->client ); - if ( addr1->s_addr == addr2->s_addr ) - return 1; - } - - } - return 0; -} -static void Receive( Client client, void *data, char *line ) -{ - BusClientPtr clnt; - int err,id,reg; - MsgSndPtr snd; - MsgRcvPtr rcv; - int argc = 0; - char *argv[MAX_MATCHING_ARGS]; - char *arg; - int kind_of_msg = Bye; - regex_t regexp; - - err = sscanf( line ,"%d %d", &kind_of_msg, &id ); - arg = strstr( line , ARG_START ); - if ( (err != 2) || (arg == NULL) ) - { - printf("Quitting bad format %s\n", line); - MsgSendTo( client, Error, Error, "bad format request expected 'type id ...'" ); - MsgSendTo( client, Bye, 0, "" ); - SocketClose( client ); - return; - } - arg++; - clnt = (BusClientPtr)data; - switch( kind_of_msg ) - { - case Bye: - -#ifdef DEBUG - printf("Quitting %s\n", line); -#endif //DEBUG - - SocketClose( client ); - break; - case Error: - printf("Receive error %d %s\n", id, arg); - break; - case AddRegexp: - -#ifdef DEBUG - printf("Regexp id=%d exp='%s'\n", id, arg); -#endif //DEBUG - if ( !CheckRegexp( arg ) ) - { -#ifdef DEBUG - printf("Warning exp='%s' can't match removing from %s\n",arg,ApplicationName); -#endif //DEBUG - return; - } - reg = regcomp(®exp, arg, REG_ICASE|REG_EXTENDED); - if ( reg == 0 ) - { - LIST_ADD( clnt->msg_send, snd ) - if ( snd ) - { - snd->id = id; - snd->str_regexp = strdup( arg ); - snd->regexp = regexp; - } - } - else - { - char errbuf[4096]; - regerror (reg, ®exp, errbuf, 4096); - printf("Error compiling '%s', %s\n",arg,errbuf); - MsgSendTo( client, Error, reg, errbuf ); - } - break; - case DelRegexp: - -#ifdef DEBUG - printf("Regexp Delete id=%d\n", id); -#endif //DEBUG - - LIST_ITER( clnt->msg_send, snd, ( id != snd->id )); - if ( snd ) - { - free( snd->str_regexp ); - LIST_REMOVE( clnt->msg_send, snd ); - } - break; - case StartRegexp: - -#ifdef DEBUG - printf("Regexp Start id=%d App='%s'\n", id, arg); -#endif //DEBUG - clnt->app_name = strdup( arg ); - clnt->app_port = id; - if ( CheckConnected( clnt ) ) - { -#ifdef DEBUG - printf("Quitting already connected %s\n", line); -#endif //DEBUG - SendError( clnt, 0, "Application already connected" ); - SocketClose( client ); - } - break; - case EndRegexp: - -#ifdef DEBUG - printf("Regexp End id=%d\n", id); -#endif //DEBUG - if ( application_callback ) - { - (*application_callback)( clnt, application_user_data, BusApplicationConnected ); - } - if ( ready_message ) - { - int count; - count = ClientCall( clnt, ready_message ); - -#ifdef DEBUG - printf(" Sendind ready message %d\n", count); -#endif //DEBUG - - } - break; - case Msg: - -#ifdef DEBUG - printf("Message id=%d msg='%s'\n", id, arg); -#endif //DEBUG - - LIST_EACH( msg_recv, rcv ) - { - if ( id == rcv->id ) - { - arg = strtok( arg, ARG_END); - while ( arg ) - { - argv[argc++] = arg; - arg = strtok( NULL, ARG_END ); - } -#ifdef DEBUG - printf("Calling id=%d argc=%d for %s\n", id, argc,rcv->regexp); -#endif - if ( rcv->callback ) (*rcv->callback)( clnt, rcv->user_data, argc, argv ); - return; - } - } - printf("Callback Message id=%d not found!!!'\n", id); - break; - case DirectMsg: - -#ifdef DEBUG - printf("Direct Message id=%d msg='%s'\n", id, arg); -#endif //DEBUG - - if ( direct_callback) - (*direct_callback)( clnt, direct_user_data, id, arg ); - break; - - case Die: - -#ifdef DEBUG - printf("Die Message\n"); -#endif //DEBUG - - if ( application_die_callback) - (*application_die_callback)( clnt, application_die_user_data, id ); - BusCleanup(); - exit(0); - break; - - default: - printf("Receive unhandled message %s\n", line); - break; - } - -} - -static BusClientPtr SendService( Client client ) -{ - BusClientPtr clnt; - MsgRcvPtr msg; - LIST_ADD( clients, clnt ) - if ( clnt ) - { - clnt->msg_send = NULL; - clnt->client = client; - clnt->app_name = strdup("Unknown"); - clnt->app_port = 0; - MsgSendTo( client, StartRegexp, ApplicationPort, ApplicationName); - LIST_EACH(msg_recv, msg ) - { - MsgSendTo( client, AddRegexp,msg->id,msg->regexp); - } - MsgSendTo( client, EndRegexp, 0, ""); - } - return clnt; -} - -static void ClientDelete( Client client, void *data ) -{ - BusClientPtr clnt; - MsgSndPtr msg; - char *remotehost; - unsigned short remoteport; - clnt = (BusClientPtr)data; - if ( application_callback ) - { - (*application_callback)( clnt, application_user_data, BusApplicationDisconnected ); - } - SocketGetRemote( client, &remotehost, &remoteport ); - -#ifdef DEBUG - printf("Deconnexion de %s:%hu\n", remotehost, remoteport ); -#endif //DEBUG - - if ( clnt->app_name ) free( clnt->app_name ); - LIST_EACH( clnt->msg_send, msg) - { - /*regfree(msg->regexp);*/ - free( msg->str_regexp); - } - LIST_EMPTY( clnt->msg_send ); - LIST_REMOVE( clients, clnt ); -} - -static void *ClientCreate( Client client ) -{ - char *remotehost; - unsigned short remoteport; - SocketGetRemote( client, &remotehost, &remoteport ); - -#ifdef DEBUG - printf("Connexion de %s:%hu\n", remotehost, remoteport ); -#endif //DEBUG - - return SendService( client ); -} - -static void BroadcastReceive( Client client, void *data, char *line ) -{ - Client app; - char *remotehost; - int err; - int version; - unsigned short remoteport; - unsigned short serviceport; - SocketGetRemote( client, &remotehost, &remoteport ); - - err = sscanf(line,"%d %hu",&version, &serviceport); - if ( err != 2 ) - { - /* ignore the message */ - printf(" Bad Supervision message expected 'version port' from %s:%d\n",remotehost, remoteport); - return; - } - if ( version != VERSION ) - { - /* ignore the message */ - printf(" Bad Bus verion number expected %d receive %d from %s:%d\n", VERSION,version,remotehost, remoteport); - return; - } - /* check if we receive our own message - should test also the host */ - if ( serviceport == ApplicationPort ) return; - -#ifdef DEBUG - printf(" Broadcast de %s:%hu port %hu\n", remotehost, remoteport, serviceport ); -#endif //DEBUG - - /* connect to the service and send the regexp */ - app = SocketConnectAddr(SocketGetRemoteAddr(client), serviceport, NULL, Receive, ClientDelete ); - if ( app ) - { - BusClientPtr clnt; - clnt = SendService( app ); - SocketSetData( app, clnt); - } -} -void BusInit(const char *AppName, unsigned short busnumber, const char *ready, - BusApplicationCallback callback, void *data, - BusDieCallback die_callback, void *die_data - ) -{ - SocketInit(); - - ApplicationName = AppName; - SupervisionPort = busnumber; - application_callback = callback; - application_user_data = data; - application_die_callback = die_callback; - application_die_user_data = die_data; - ready_message = ready; - ApplicationPort = SocketServer( ANYPORT, ClientCreate, ClientDelete, Receive ); - broadcast = SocketBroadcastCreate( SupervisionPort, NULL, BroadcastReceive ); - -} - -void BusClasses( int argc, const char **argv) -{ - messages_classes_count = argc; - messages_classes = argv; -} - -void BusStart() -{ - - SocketSendBroadcast( broadcast, 143 << 24 | 196 << 16 | 1 << 8 | 255, SupervisionPort, "%d %hu\n", VERSION, ApplicationPort); - SocketSendBroadcast( broadcast, 143 << 24 | 196 << 16 | 2 << 8 | 255, SupervisionPort, "%d %hu\n", VERSION, ApplicationPort); - - fprintf(stderr,"Server Ready TCP:%hu\n",ApplicationPort); -} - -/* desabonnements */ -void UnbindMsg( MsgRcvPtr msg ) -{ -BusClientPtr clnt; - /* Send to already connected clients */ - LIST_EACH( clients, clnt ) - { - MsgSendTo( clnt->client, DelRegexp,msg->id, ""); - } -} - -/* demande de reception d'un message */ -static MsgRcvPtr _BindMsg( MsgCallback callback, void *user_data, const char *regexp ) -{ - static int recv_id = 0; - BusClientPtr clnt; - MsgRcvPtr msg; - /* add Msg to the query list */ - LIST_ADD( msg_recv, msg ); - if ( msg ) - { - msg->id = recv_id++; - msg->regexp = strdup(regexp); - msg->callback = callback; - msg->user_data = user_data; - } - /* Send to already connected clients */ - /* recherche dans la liste des requetes recues de mes clients */ - LIST_EACH( clients, clnt ) - { - MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); - } - return msg; -} -MsgRcvPtr BindMsg( 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 ) -{ -BusClientPtr clnt; -int match_count = 0; - - /* recherche dans la liste des requetes recues de mes clients */ - LIST_EACH( clients, clnt ) - { - match_count+= ClientCall( clnt, message ); - } -#ifdef DEBUG - if ( match_count == 0 ) printf( "Warning no recipient for %s\n",message); -#endif - return match_count; -} -int SendMsg(const char *fmt, ...) -{ - char buffer[4096]; - va_list ap; - - va_start( ap, fmt ); - vsprintf( buffer, fmt, ap ); - va_end ( ap ); - return _SendMsg( buffer ); -} -void SendError( BusClientPtr app, int id, const char *fmt, ... ) -{ - char buffer[4096]; - va_list ap; - - va_start( ap, fmt ); - vsprintf( buffer, fmt, ap ); - va_end ( ap ); - MsgSendTo( app->client, Error, id, buffer); -} -void BindDirectMsg( MsgDirectCallback callback, void *user_data) -{ -direct_callback = callback; -direct_user_data = user_data; -} -void SendDirectMsg( BusClientPtr app, int id, char *msg ) -{ - MsgSendTo( app->client, DirectMsg, id, msg); -} - -void SendDieMsg( BusClientPtr app ) -{ - MsgSendTo( app->client, Die, 0, "" ); -} - -char *GetApplicationName( BusClientPtr app ) -{ - if ( app && app->app_name ) - return app->app_name; - else return "Unknown"; -} - -char *GetApplicationHost( BusClientPtr app ) -{ - if ( app && app->client ) - return SocketGetPeerHost( app->client ); - else return NULL; -} - -void BusDefaultApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event) -{ - switch ( event ) { - case BusApplicationConnected: - printf("Application: %s ready on %s\n",GetApplicationName( app ), GetApplicationHost(app)); - break; - case BusApplicationDisconnected: - printf("Application: %s bye on %s\n",GetApplicationName( app ), GetApplicationHost(app)); - break; - default: - printf("Application: %s unkown event %d\n",GetApplicationName( app ), event); - break; - } -} - -BusClientPtr GetApplication( char *name ) -{ - BusClientPtr app = NULL; - LIST_ITER( clients, app, strcmp(name, app->app_name) != 0 ); - return app; -} - -char *GetApplicationList() -{ - static char applist[4096]; - BusClientPtr app; - applist[0] = '\0'; - LIST_EACH( clients, app ) - { - strcat( applist, app->app_name ); - strcat( applist, " " ); - } - return applist; -} - -char **GetApplicationMessages( BusClientPtr app ) -{ - static char *messagelist[200]; - MsgSndPtr msg; - int msgCount= 0; - memset( messagelist, 0 , sizeof( messagelist )); - /* recherche dans la liste des requetes recues de ce client */ - LIST_EACH( app->msg_send, msg ) - { - messagelist[msgCount++]= msg->str_regexp; - } - return messagelist; -} diff --git a/src/bus.h b/src/bus.h deleted file mode 100644 index 1f0154a..0000000 --- a/src/bus.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef _BUS_H -#define _BUS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* numero par default du bus */ - -#define DEFAULT_BUS 2010 - -typedef struct _clnt_lst *BusClientPtr; - -typedef enum { BusApplicationConnected, BusApplicationDisconnected } BusApplicationEvent; - -extern void BusDefaultApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event ) ; -/* callback callback appele sur connection deconnection d'une appli */ -typedef void (*BusApplicationCallback)( BusClientPtr app, void *user_data, BusApplicationEvent event ) ; -/* callback appele sur reception de die */ -typedef void (*BusDieCallback)( BusClientPtr app, void *user_data, int id ) ; - -/* callback appele sur reception de messages normaux */ -typedef void (*MsgCallback)( BusClientPtr app, void *user_data, int argc, char **argv ) ; -/* callback appele sur reception de messages directs */ -typedef void (*MsgDirectCallback)( BusClientPtr app, void *user_data, int id, char *msg ) ; - -/* identifiant d'une expression reguliere ( Bind/Unbind ) */ -typedef struct _msg_rcv *MsgRcvPtr; - -/* filtrage des regexps */ -void BusClasses( int argc, const char **argv); - -void BusInit( - const char *AppName, /* nom de l'application */ - unsigned short busnumber, /* numero de bus ( port UDP ) */ - const char *ready, /* ready Message peut etre NULL */ - BusApplicationCallback callback, /* callback appele sur connection deconnection d'une appli */ - void *data, /* user data passe au callback */ - BusDieCallback die_callback, /* last change callback before die */ - void *die_data ); /* user data */ - -void BusStart(); /* emission du bonjour */ - -/* query sur les applications connectees */ -char *GetApplicationName( BusClientPtr app ); -char *GetApplicationHost( BusClientPtr app ); -BusClientPtr GetApplication( char *name ); -char *GetApplicationList(); -char **GetApplicationMessages( BusClientPtr app); -/* demande de reception d'un message */ - -MsgRcvPtr BindMsg( MsgCallback callback, void *user_data, const char *fmt_regexp, ... ); /* avec sprintf prealable */ -void UnbindMsg( MsgRcvPtr id ); - -/* emmission d'un message d'erreur */ -void SendError( BusClientPtr app, int id, const char *fmt, ... ); - -/* emmission d'un message die pour terminer l'application */ -void SendDieMsg( BusClientPtr app ); - -/* emmission d'un message retourne le nb effectivement emis */ - -int SendMsg( const char *fmt_message, ... ); /* avec sprintf prealable */ - -/* Message Direct Inter-application */ - -void BindDirectMsg( MsgDirectCallback callback, void *user_data); -void SendDirectMsg( BusClientPtr app, int id, char *msg ); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/src/buschannel.h b/src/buschannel.h deleted file mode 100644 index 2d05ff4..0000000 --- a/src/buschannel.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _BUSCHANNEL_H -#define _BUSCHANNEL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* general Handle */ - -#ifdef WIN32 -#include -#define HANDLE SOCKET -#else -#define HANDLE int -#endif - -typedef struct _channel *Channel; -/* callback declenche par la gestion de boucle sur evenement exception sur le canal */ -typedef void (*ChannelHandleDelete)( void *data ); -/* callback declenche par la gestion de boucle sur donnees pretes sur le canal */ -typedef void (*ChannelHandleRead)( Channel channel, HANDLE fd, void *data); - -/* fonction appele par le bus pour initialisation */ -typedef void (*ChannelInit)(void); - -/* fonction appele par le bus pour mise en place des callback sur le canal */ -typedef Channel (*ChannelSetUp)( - HANDLE fd, - void *data, - ChannelHandleDelete handle_delete, - ChannelHandleRead handle_read - ); -/* fonction appele par le bus pour fermeture du canal */ -typedef void (*ChannelClose)( Channel channel ); - -/* mise en place des fonction de gestion des canaux */ -void BusSetChannelManagement( ChannelInit init_chan, ChannelSetUp setup_chan, ChannelClose close_chan ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/busloop.c b/src/busloop.c deleted file mode 100644 index 346a505..0000000 --- a/src/busloop.c +++ /dev/null @@ -1,179 +0,0 @@ -#ifdef WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef WIN32 -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - - -#include "list.h" -#include "buschannel.h" -#include "busloop.h" -#include "timer.h" - -struct _channel { - Channel next; - HANDLE fd; - void *data; - int tobedeleted; - ChannelHandleDelete handle_delete; - ChannelHandleRead handle_read; - }; - - - -static Channel channels_list = NULL; - -static int channel_initialized = 0; - -static fd_set open_fds; -static int MainLoop = 1; - -#ifdef WIN32 -WSADATA WsaData; -#endif - -void BusLoopChannelClose( Channel channel ) -{ - channel->tobedeleted = 1; -} - -static void BusLoopChannelDelete( Channel channel ) -{ - if ( channel->handle_delete ) - (*channel->handle_delete)( channel->data ); - - FD_CLR(channel->fd, &open_fds); - LIST_REMOVE( channels_list, channel ); -} -static void ChannelDefferedDelete() -{ - Channel channel,next; - LIST_EACH_SAFE( channels_list, channel,next) - { - if ( channel->tobedeleted ) - { - BusLoopChannelDelete( channel ); - } - } -} - -Channel BusLoopChannelSetUp(HANDLE fd, void *data, - ChannelHandleDelete handle_delete, - ChannelHandleRead handle_read - ) -{ - Channel channel; - - LIST_ADD( channels_list, channel ); - if ( !channel ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } - channel->fd = fd; - channel->tobedeleted = 0; - channel->handle_delete = handle_delete; - channel->handle_read = handle_read; - channel->data = data; - - FD_SET( channel->fd, &open_fds ); - - return channel; -} - -static void BusLoopChannelHandleRead(fd_set *current) -{ - Channel channel,next; - - LIST_EACH_SAFE( channels_list, channel, next ) - { - if ( FD_ISSET( channel->fd, current ) ) - { - (*channel->handle_read)(channel,channel->fd,channel->data); - } - } -} -static void BusLoopChannelHandleExcpt(fd_set *current) -{ - Channel channel,next; - LIST_EACH_SAFE( channels_list, channel, next ) - { - if (FD_ISSET( channel->fd, current ) ) - { - (*channel->handle_delete)(channel->data); -// BusLoopChannelClose( channel ); - } - } -} - -void BusLoopChannelInit(void) -{ -#ifdef WIN32 - int error; -#else - /* pour eviter les plantages quand les autres applis font core-dump */ - signal( SIGPIPE, SIG_IGN); -#endif - if ( channel_initialized ) return; - - FD_ZERO( &open_fds ); - -#ifdef WIN32 - error = WSAStartup( 0x0101, &WsaData ); - if ( error == SOCKET_ERROR ) { - printf( "WSAStartup failed.\n" ); - } -#endif - channel_initialized = 1; -} - - -void BusLoopChannelStop(void) -{ - MainLoop = 0; -} -void BusLoopChannelMainLoop(void(*hook)(void)) -{ - -fd_set rdset; -fd_set exset; -int ready; - - - - while (MainLoop) { - ChannelDefferedDelete(); - if ( hook ) (*hook)(); - rdset = open_fds; - exset = open_fds; - ready = select(64, &rdset, 0, &exset, TimerGetSmallestTimeout()); - if ( ready < 0 && ( errno != EINTR )) - { - perror("select"); - return; - } - TimerScan(); - if ( ready > 0 ) - { - BusLoopChannelHandleExcpt(&exset); - BusLoopChannelHandleRead(&rdset); - continue; - } - } -} - diff --git a/src/busloop.h b/src/busloop.h deleted file mode 100644 index 1eab8b6..0000000 --- a/src/busloop.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _BUSLOOP_H -#define _BUSLOOP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "buschannel.h" - -/* general Handle */ - -#define ANYPORT 0 - -#ifdef WIN32 -#include -#define HANDLE SOCKET -#else -#define HANDLE int -#endif - -extern void BusLoopChannelInit(void); -extern void BusLoopChannelStop(void); -extern void BusLoopChannelMainLoop(void(*hook)(void) ); - -extern Channel BusLoopChannelSetUp( - HANDLE fd, - void *data, - ChannelHandleDelete handle_delete, - ChannelHandleRead handle_read - ); - -extern void BusLoopChannelClose( Channel channel ); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/bussocket.c b/src/bussocket.c deleted file mode 100644 index ca5ec08..0000000 --- a/src/bussocket.c +++ /dev/null @@ -1,516 +0,0 @@ -#ifdef WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef WIN32 -#define close closesocket -/*#define perror( a ) printf(a" error=%d\n",WSAGetLastError());*/ -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "list.h" -#include "buschannel.h" -#include "bussocket.h" - -static ChannelInit channel_init = NULL; -static ChannelSetUp channel_setup = NULL; -static ChannelClose channel_close = NULL; - -#define MAX_BUFFER 2048 - - -typedef struct _server *Server; - -struct _server { - Server next; - Channel channel; - void *(*create)(Client client); - void (*handle_delete)(Client client, void *data); - SocketInterpretation interpretation; - }; - -struct _client { - Client next; - HANDLE fd; - Channel channel; - unsigned short port; - struct sockaddr_in from; - SocketInterpretation interpretation; - void (*handle_delete)(Client client, void *data); - char buffer[MAX_BUFFER+2]; - char *ptr; - void *data; - }; - - -static Server servers_list = NULL; -static Client clients_list = NULL; - - - - -#ifdef WIN32 -WSADATA WsaData; -#endif - -void BusSetChannelManagement( ChannelInit init_chan, ChannelSetUp setup_chan, ChannelClose close_chan ) -{ - channel_init = init_chan; - channel_setup = setup_chan; - channel_close = close_chan; -} - - -void SocketInit() -{ - if ( ! channel_init ) - { - fprintf( stderr, "You Must call BusSetChannelManagement before all !!!\n"); - exit(-1); - } - (*channel_init)(); -} - -static void DeleteSocket(void *data) -{ - Client client = ( Client )data; - if ( client->handle_delete ) - (*client->handle_delete)( client, client->data ); - shutdown( client->fd, 2 ); - close( client->fd ); - LIST_REMOVE( clients_list, client ); -} -static void HandleSocket( Channel channel, HANDLE fd, void *data) -{ - Client client = (Client)data; - char *ptr; - char *ptr_nl; - long nb_to_read = 0; - long nb; - int len; - - /* limitation taille buffer */ - nb_to_read = MAX_BUFFER - ( client->ptr - client->buffer ); - if( nb_to_read == 0 ) { - fprintf(stderr, "Erreur message trop long sans LF\n"); - client->ptr = client->buffer; - return; - }; - len = sizeof( client->from ); - nb = recvfrom( fd, client->ptr, nb_to_read,0,(struct sockaddr *)&client->from,&len); - if (nb < 0) { - perror(" Read Socket "); - (*channel_close)( client->channel ); - return; - }; - if ( nb == 0 ) - { - (*channel_close)( client->channel ); - return; - } - - client->ptr += nb; - *(client->ptr) = '\0'; - ptr = client->buffer; - while( (ptr_nl = strchr( ptr, '\n' ))) - { - *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' ) - { /* recopie ligne incomplete au debut du buffer */ - strcpy( client->buffer, ptr ); - client->ptr = client->buffer + strlen(client->buffer); - } - else - { - client->ptr = client->buffer; - } -} -static void HandleServer(Channel channel, HANDLE fd, void *data) -{ - Server server = ( Server ) data; - Client client; - HANDLE ns; - int addrlen; - struct sockaddr_in remote2; - - addrlen = sizeof( remote2 ); - if ((ns = accept( fd, (struct sockaddr *)&remote2, &addrlen)) <0) - { - perror ( "*** accept ***"); - return; - }; - LIST_ADD( clients_list, client ); - if ( !client ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close( fd ); - exit(0); - } - client->from = remote2; - client->fd = ns; - client->channel = (*channel_setup)( ns, client, DeleteSocket, HandleSocket ); - client->interpretation = server->interpretation; - client->ptr = client->buffer; - client->handle_delete = server->handle_delete; - client->data = (*server->create)( client ); - -} -int SocketServer(unsigned short port, - void*(*create)(Client client), - void(*handle_delete)(Client client, void *data), - void(*interpretation)( Client client, void *data, char *ligne)) -{ - Server server; - HANDLE fd; - int one=1; - struct sockaddr_in local; - int addrlen; - - - if ((fd = socket( AF_INET, SOCK_STREAM, 0)) < 0){ - perror( "***open socket ***"); - exit(0); - }; - - - local.sin_family = AF_INET; - local.sin_addr.s_addr = INADDR_ANY; - local.sin_port = htons (port); - - if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&one,sizeof(one)) < 0) - { - perror( "*** set socket option SO_REUSEADDR ***"); - exit(0); - } - -#ifdef SO_REUSEPORT - - if (setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, (char *)&one, sizeof( one)) < 0) - { - perror( "*** set socket option REUSEPORT ***"); - exit(0); - } -#endif - - if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) - { - perror( "*** bind ***"); - exit(0); - } - - addrlen = sizeof( local ); - if (getsockname(fd,(struct sockaddr *)&local, &addrlen) < 0) - { - perror( "***get socket name ***"); - exit(0); - } - - if (listen( fd, 128) < 0){ - perror( "*** listen ***"); - exit(0); - }; - - - LIST_ADD( servers_list, server ); - if ( !server ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } - server->channel = (*channel_setup)( fd, server, DeleteSocket, HandleServer ); - server->create = create; - server->handle_delete = handle_delete; - server->interpretation = interpretation; - return ntohs(local.sin_port); -} -char *SocketGetPeerHost( Client client ) -{ - int err; - struct sockaddr_in name; - struct hostent *host; - int len = sizeof(name); - err = getpeername( client->fd, (struct sockaddr *)&name, &len ); - if ( err < 0 ) return "can't get peer"; - host = gethostbyaddr( (char *)&name.sin_addr.s_addr,sizeof(name.sin_addr.s_addr),name.sin_family); - if ( host == NULL ) return "can't translate addr"; - return host->h_name; -} -struct in_addr * SocketGetRemoteAddr( Client client ) -{ - return &client->from.sin_addr; -} -void SocketGetRemote( Client client, char **host, unsigned short *port ) -{ - struct hostent *hostp; - /* extract hostname and port from last message received */ - hostp = gethostbyaddr( (char *)&client->from.sin_addr.s_addr, - sizeof(client->from.sin_addr.s_addr),client->from.sin_family); - if ( hostp == NULL ) *host = "unknown"; - else *host = hostp->h_name; - *port = ntohs( client->from.sin_port ); -} -void SocketClose( Client client ) -{ - (*channel_close)( client->channel ); -} - -void SocketSendRaw( Client client, char *buffer, int len ) -{ - int err; - err = send( client->fd, buffer, len, 0 ); - if ( err != len ) - perror( "*** send ***"); -} -void SocketSetData( Client client, void *data ) -{ - client->data = data; -} -void SocketSend( Client client, char *fmt, ... ) -{ - char buffer[4096]; - va_list ap; - int len; - va_start( ap, fmt ); - len = vsprintf( buffer, fmt, ap ); - SocketSendRaw( client, buffer, len ); - va_end ( ap ); -} -void *SocketGetData( Client client ) -{ - return client->data; -} -void SocketBroadcast( char *fmt, ... ) -{ - Client client; - char buffer[4096]; - va_list ap; - int len; - - va_start( ap, fmt ); - len = vsprintf( buffer, fmt, ap ); - va_end ( ap ); - LIST_EACH( clients_list, client ) - { - SocketSendRaw( client, buffer, len ); - } -} -/* -Ouverture d'un canal TCP/IP en mode client -*/ -Client SocketConnect( char * host, unsigned short port, - void *data, - SocketInterpretation interpretation, - void (*handle_delete)(Client client, void *data) - ) -{ -struct hostent *rhost; - - -if ((rhost = gethostbyname( host )) == NULL){ - fprintf(stderr, "Erreur %s Calculateur inconnu !\n",host); - return NULL; - }; -return SocketConnectAddr( (struct in_addr*)(rhost->h_addr), port, data, interpretation, handle_delete); -} -Client SocketConnectAddr( struct in_addr * addr, unsigned short port, - void *data, - SocketInterpretation interpretation, - void (*handle_delete)(Client client, void *data) - ) -{ -HANDLE handle; -Client client; -struct sockaddr_in remote; - -remote.sin_family = AF_INET; -remote.sin_addr = *addr; -remote.sin_port = htons (port); - -if ((handle = socket( AF_INET, SOCK_STREAM, 0)) < 0){ - perror( "*** client socket ***"); - return NULL; - }; - -if ( connect( handle, (struct sockaddr *)&remote, sizeof(remote) ) < 0){ - perror( "*** client connect ***"); - return NULL; - }; - -LIST_ADD( clients_list, client ); -if ( !client ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close( handle ); - exit(0); - } - -client->fd = handle; -client->channel = (*channel_setup)( handle, client, DeleteSocket, HandleSocket ); -client->interpretation = interpretation; -client->ptr = client->buffer; -client->data = data; -client->handle_delete = handle_delete; -client->from.sin_family = AF_INET; -client->from.sin_addr = *addr; -client->from.sin_port = htons (port); - -return client; -} -int SocketWaitForReply( Client client, char *buffer, int size, int delai) -{ - fd_set rdset; - struct timeval timeout; - struct timeval *timeoutptr = &timeout; - int ready; - char *ptr; - char *ptr_nl; - long nb_to_read = 0; - long nb; - HANDLE fd; - - fd = client->fd; - ptr = buffer; - timeout.tv_sec = delai; - timeout.tv_usec = 0; - do { - /* limitation taille buffer */ - nb_to_read = size - ( ptr - buffer ); - if( nb_to_read == 0 ) - { - fprintf(stderr, "Erreur message trop long sans LF\n"); - ptr = buffer; - return -1; - } - FD_ZERO( &rdset ); - FD_SET( fd, &rdset ); - ready = select(fd+1, &rdset, 0, 0, timeoutptr); - if ( ready < 0 ) - { - perror("select"); - return -1; - } - if ( ready == 0 ) - { - return -2; - } - if ((nb = recv( fd , ptr, nb_to_read, 0 )) < 0) - { - perror(" Read Socket "); - return -1; - } - if ( nb == 0 ) - return 0; - - ptr += nb; - *ptr = '\0'; - ptr_nl = strchr( buffer, '\n' ); - } while ( !ptr_nl ); - *ptr_nl = '\0'; - return (ptr_nl - buffer); -} - - -/* Socket UDP */ - -Client SocketBroadcastCreate( unsigned short port, - void *data, - SocketInterpretation interpretation - ) -{ -HANDLE handle; -Client client; -struct sockaddr_in local; -int on = 1; - -local.sin_family = AF_INET; -local.sin_addr.s_addr = INADDR_ANY; -local.sin_port = htons (port); - -if ((handle = socket( AF_INET, SOCK_DGRAM, 0)) < 0){ - perror( "*** dgram socket ***"); - return NULL; - }; - -/* wee need to used multiple client on the same host */ -if (setsockopt( handle, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof( on)) < 0) - { - perror( "*** set socket option REUSEADDR ***"); - return NULL; - }; -#ifdef SO_REUSEPORT - -if (setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof( on)) < 0) - { - perror( "*** set socket option REUSEPORT ***"); - return NULL; - } -#endif -/* wee need to broadcast */ -if (setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof( on)) < 0) - { - perror( "*** BROADCAST ***"); - return NULL; - }; - -if (bind(handle, (struct sockaddr *)&local, sizeof(local)) < 0) - { - perror( "*** test BIND ***"); - return NULL; - }; - -LIST_ADD( clients_list, client ); -if ( !client ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close( handle ); - exit(0); - } - -client->fd = handle; -client->channel = (*channel_setup)( handle, client, DeleteSocket, HandleSocket ); -client->interpretation = interpretation; -client->ptr = client->buffer; -client->data = data; - -return client; -} - -void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *fmt, ... ) -{ - struct sockaddr_in remote; - char buffer[4096]; - va_list ap; - int err,len; - - va_start( ap, fmt ); - len = vsprintf( 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, - (struct sockaddr *)&remote,sizeof(remote)); - if ( err != len ) - { - perror( "*** send ***"); - } va_end ( ap ); -} diff --git a/src/bussocket.h b/src/bussocket.h deleted file mode 100644 index 956aa1a..0000000 --- a/src/bussocket.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _BUSSOCKET_H -#define _BUSSOCKET_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* general Handle */ - -#define ANYPORT 0 - -#ifdef WIN32 -#include -#define HANDLE SOCKET -#else -#define HANDLE int -#include -#endif - - -/* Server Part */ -typedef struct _client *Client; -typedef void (*SocketInterpretation)( Client client, void *data, char *ligne); - -extern void SocketInit(); - -extern void SocketClose( Client client ); -extern void SocketSend( Client client, char *fmt, ... ); -extern void SocketSendRaw( Client client, char *buffer, int len ); -extern char *SocketGetPeerHost( Client client ); -extern void SocketSetData( Client client, void *data ); -extern void *SocketGetData( Client client ); -extern void SocketBroadcast( char *fmt, ... ); - -extern int SocketServer(unsigned short port, - void*(*create)(Client client), - void(*handle_delete)(Client client, void *data), - SocketInterpretation interpretation); - -/* Client Part */ - -extern Client SocketConnect( char * host, unsigned short port, - void *data, - SocketInterpretation interpretation, - void (*handle_delete)(Client client, void *data) - ); -extern Client SocketConnectAddr( struct in_addr * addr, unsigned short port, - void *data, - SocketInterpretation interpretation, - void (*handle_delete)(Client client, void *data) - ); -extern int SocketWaitForReply( Client client, char *buffer, int size, int delai); - -/* Socket UDP */ -/* Creation d'une socket en mode non connecte */ -/* et ecoute des messages */ -extern Client SocketBroadcastCreate( - unsigned short port, - void *data, - SocketInterpretation interpretation - ); -/* recuperation de l'emetteur du message */ -extern struct in_addr * SocketGetRemoteAddr( Client client ); -extern void SocketGetRemote( Client client, char **host, unsigned short *port ); -/* emmission d'un broadcast UDP */ -extern void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *fmt, ... ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/busxtloop.c b/src/busxtloop.c deleted file mode 100644 index fcaa10e..0000000 --- a/src/busxtloop.c +++ /dev/null @@ -1,116 +0,0 @@ -#ifdef WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef WIN32 -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - - -#include - -#include "buschannel.h" -#include "busxtloop.h" - -struct _channel { - XtInputId id_read; - XtInputId id_delete; - void *data; - ChannelHandleDelete handle_delete; - ChannelHandleRead handle_read; - }; - - -static int channel_initialized = 0; - - -static XtAppContext app = NULL; - - -void BusXtChannelClose( Channel channel ) -{ - - if ( channel->handle_delete ) - (*channel->handle_delete)( channel->data ); - XtRemoveInput( channel->id_read ); - XtRemoveInput( channel->id_delete ); -} - -static void BusXtHandleChannelRead( XtPointer closure, int* source, XtInputId* id ) -{ - Channel channel = (Channel)closure; -#ifdef DEBUG - printf("Handle Channel read %d\n",*source ); -#endif - (*channel->handle_read)(channel,*source,channel->data); -} -static void BusXtHandleChannelDelete( XtPointer closure, int* source, XtInputId* id ) -{ - Channel channel = (Channel)closure; -#ifdef DEBUG - printf("Handle Channel delete %d\n",*source ); -#endif - (*channel->handle_delete)(channel->data); -} -Channel BusXtChannelSetUp(HANDLE fd, void *data, - ChannelHandleDelete handle_delete, - ChannelHandleRead handle_read - ) -{ - Channel channel; - - channel = XtNew( struct _channel ); - if ( !channel ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } - - channel->handle_delete = handle_delete; - channel->handle_read = handle_read; - channel->data = data; - - channel->id_read = XtAppAddInput( app, fd, (XtPointer)XtInputReadMask, BusXtHandleChannelRead, channel); - channel->id_delete = XtAppAddInput( app, fd, (XtPointer)XtInputExceptMask, BusXtHandleChannelDelete, channel); - - return channel; -} - - -void BusXtChannelAppContext( XtAppContext cntx ) -{ - app = cntx; -} - -void BusXtChannelInit(void) -{ - - if ( channel_initialized ) return; - - /* pour eviter les plantages quand les autres applis font core-dump */ -#ifndef WIN32 - signal( SIGPIPE, SIG_IGN); -#endif - /* verifie si init correct */ - if ( !app ) - { - fprintf( stderr, "You Must call BusXtChannelAppContext to Use XtMainLoop !!!\n"); - exit(-1); - } - channel_initialized = 1; -} - - diff --git a/src/busxtloop.h b/src/busxtloop.h deleted file mode 100644 index 8f48460..0000000 --- a/src/busxtloop.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _BUSXTLOOP_H -#define _BUSXTLOOP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* general Handle */ - -#define ANYPORT 0 - -#ifdef WIN32 -#include -#define HANDLE SOCKET -#else -#define HANDLE int -#endif - -#include "buschannel.h" - -extern void BusXtChannelInit(void); - -extern Channel BusXtChannelSetUp( - HANDLE fd, - void *data, - ChannelHandleDelete handle_delete, - ChannelHandleRead handle_read - ); - -extern void BusXtChannelClose( Channel channel ); - -extern void BusXtChannelAppContext( XtAppContext cntx ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/ivy.c b/src/ivy.c new file mode 100644 index 0000000..08cfef1 --- /dev/null +++ b/src/ivy.c @@ -0,0 +1,690 @@ +/* + * + * $Id$ + */ +#include + +#include +#include +#include + +#include + +#include + +#include "ivychannel.h" +#include "ivysocket.h" +#include "list.h" +#include "ivy.h" + +#define VERSION 3 + +#define MAX_MATCHING_ARGS 20 + +#define ARG_START "\002" +#define ARG_END "\003" + + +typedef enum { + + Bye, /* l'application emettrice se termine */ + AddRegexp, /* expression reguliere d'un client */ + Msg, /* message reel */ + Error, /* error message */ + DelRegexp, /* Remove expression reguliere */ + EndRegexp, /* end of the regexp list */ + StartRegexp, /* debut des expressions */ + DirectMsg, /* message direct a destination de l'appli */ + Die /* demande de terminaison de l'appli */ + +}MsgType; + + +typedef struct _msg_snd *MsgSndPtr; + +struct _msg_rcv { /* requete d'emission d'un client */ + MsgRcvPtr next; + int id; + const char *regexp; /* regexp du message a recevoir */ + MsgCallback callback; /* callback a declanche a la reception */ + void *user_data; /* stokage d'info client */ +}; + + +struct _msg_snd { /* requete de reception d'un client */ + MsgSndPtr next; + int id; + char *str_regexp; /* la regexp sous forme inhumaine */ + regex_t regexp; /* la regexp sous forme machine */ +}; + +struct _clnt_lst { + BusClientPtr next; + Client client; /* la socket client */ + MsgSndPtr msg_send; /* liste des requetes recues */ + char *app_name; /* nom de l'application */ + unsigned short app_port; /* port de l'application */ + }; + +/* numero de port TCP en mode serveur */ +static unsigned short ApplicationPort; + +/* numero de port UDP */ +static unsigned short SupervisionPort; + +/* client pour la socket supervision */ +static Client broadcast; + +static const char *ApplicationName = NULL; + +/* classes de messages emis par l'application utilise pour le filtrage */ +static int messages_classes_count = 0; +static const char **messages_classes = NULL; + +/* callback appele sur reception d'un message direct */ +static MsgDirectCallback direct_callback = NULL; +static *direct_user_data = NULL; + +/* callback appele sur changement d'etat d'application */ +static BusApplicationCallback application_callback; +static *application_user_data = NULL; + +/* callback appele sur demande de terminaison d'application */ +static BusDieCallback application_die_callback; +static *application_die_user_data = NULL; + +/* liste des messages a recevoir */ +static MsgRcvPtr msg_recv = NULL; + + +/* liste des clients connectes */ +static BusClientPtr clients = NULL; + +static const char *ready_message = NULL; + +static void MsgSendTo( Client client,MsgType msgtype, int id, const char *message ) +{ +SocketSend( client, "%d %d" ARG_START "%s\n",msgtype,id,message); +} +static void BusCleanup() +{ +BusClientPtr clnt; + + /* destruction des connexion clients */ + LIST_EACH( clients, clnt ) + { + /* on dit au revoir */ + MsgSendTo( clnt->client, Bye, 0, "" ); + SocketClose( clnt->client ); + LIST_EMPTY( clnt->msg_send ); + } + LIST_EMPTY( clients ); + +} +static int MsgCall( const char *message, MsgSndPtr msg, Client client ) +{ + regmatch_t match[MAX_MATCHING_ARGS+1]; +#ifdef GNU_REGEXP + regmatch_t* p; +#else + unsigned int i; +#endif + memset( match, -1, sizeof(match )); /* work around bug !!!*/ + if (regexec(&msg->regexp, message, MAX_MATCHING_ARGS, match, 0)==0) { +#ifdef DEBUG + printf( "Sending message id=%d '%s'\n",msg->id,message); +#endif + SocketSend( client, "%d %d" ARG_START ,Msg, msg->id); + +#ifdef DEBUG + printf( "Send matching args count %d\n",msg->regexp.re_nsub); +#endif //DEBUG + +#ifdef GNU_REGEXP + p = &match[1]; + while ( p->rm_so != -1 ) { + SocketSend( client, "%.*s" ARG_END , p->rm_eo - p->rm_so, + message + p->rm_so); + ++p; + } +#else + for ( i = 1; i < msg->regexp.re_nsub+1; i ++ ) + { + if ( match[i].rm_so != -1 ) + { +#ifdef DEBUG + printf( "Send matching arg%d %d %d\n",i,match[i].rm_so , match[i].rm_eo); + printf( "Send matching arg%d %.*s\n",i,match[i].rm_eo - match[i].rm_so, + message + match[i].rm_so); +#endif + SocketSend( client, "%.*s" ARG_END ,match[i].rm_eo - match[i].rm_so, + message + match[i].rm_so); + } + else + { + SocketSend( client, ARG_END ); +#ifdef DEBUG + printf( "Send matching arg%d VIDE\n",i); +#endif //DEBUG + } + } +#endif + + SocketSend( client, "\n"); + return 1; + } + return 0; +} + +int ClientCall( BusClientPtr clnt, const char *message ) +{ +MsgSndPtr msg; +int match_count = 0; + /* recherche dans la liste des requetes recues de ce client */ + LIST_EACH( clnt->msg_send, msg ) + { + match_count+= MsgCall( message, msg, clnt->client ); + } + return match_count; +} +static int CheckRegexp(char *exp) +{ + /* accepte tout par default */ + int i; + int regexp_ok = 1; + if ( *exp =='^' && messages_classes_count !=0 ) + { + regexp_ok = 0; + for ( i = 0 ; i < messages_classes_count; i++ ) + { + if (strncmp( messages_classes[i], exp+1, strlen( messages_classes[i] )) == 0) + return 1; + } + } + return regexp_ok; +} +static int CheckConnected( BusClientPtr clnt ) +{ +BusClientPtr client; +struct in_addr *addr1; +struct in_addr *addr2; + if ( clnt->app_port == 0 ) + return 0; + /* recherche dans la liste des clients de la presence de clnt */ + LIST_EACH( clients, client ) + { + /* client different mais port identique */ + if ( (client != clnt) && (clnt->app_port == client->app_port) ) + { + /* et meme machine */ + addr1 = SocketGetRemoteAddr( client->client ); + addr2 = SocketGetRemoteAddr( clnt->client ); + if ( addr1->s_addr == addr2->s_addr ) + return 1; + } + + } + return 0; +} +static void Receive( Client client, void *data, char *line ) +{ + BusClientPtr clnt; + int err,id,reg; + MsgSndPtr snd; + MsgRcvPtr rcv; + int argc = 0; + char *argv[MAX_MATCHING_ARGS]; + char *arg; + int kind_of_msg = Bye; + regex_t regexp; + + err = sscanf( line ,"%d %d", &kind_of_msg, &id ); + arg = strstr( line , ARG_START ); + if ( (err != 2) || (arg == NULL) ) + { + printf("Quitting bad format %s\n", line); + MsgSendTo( client, Error, Error, "bad format request expected 'type id ...'" ); + MsgSendTo( client, Bye, 0, "" ); + SocketClose( client ); + return; + } + arg++; + clnt = (BusClientPtr)data; + switch( kind_of_msg ) + { + case Bye: + +#ifdef DEBUG + printf("Quitting %s\n", line); +#endif //DEBUG + + SocketClose( client ); + break; + case Error: + printf("Receive error %d %s\n", id, arg); + break; + case AddRegexp: + +#ifdef DEBUG + printf("Regexp id=%d exp='%s'\n", id, arg); +#endif //DEBUG + if ( !CheckRegexp( arg ) ) + { +#ifdef DEBUG + printf("Warning exp='%s' can't match removing from %s\n",arg,ApplicationName); +#endif //DEBUG + return; + } + reg = regcomp(®exp, arg, REG_ICASE|REG_EXTENDED); + if ( reg == 0 ) + { + LIST_ADD( clnt->msg_send, snd ) + if ( snd ) + { + snd->id = id; + snd->str_regexp = strdup( arg ); + snd->regexp = regexp; + } + } + else + { + char errbuf[4096]; + regerror (reg, ®exp, errbuf, 4096); + printf("Error compiling '%s', %s\n",arg,errbuf); + MsgSendTo( client, Error, reg, errbuf ); + } + break; + case DelRegexp: + +#ifdef DEBUG + printf("Regexp Delete id=%d\n", id); +#endif //DEBUG + + LIST_ITER( clnt->msg_send, snd, ( id != snd->id )); + if ( snd ) + { + free( snd->str_regexp ); + LIST_REMOVE( clnt->msg_send, snd ); + } + break; + case StartRegexp: + +#ifdef DEBUG + printf("Regexp Start id=%d App='%s'\n", id, arg); +#endif //DEBUG + clnt->app_name = strdup( arg ); + clnt->app_port = id; + if ( CheckConnected( clnt ) ) + { +#ifdef DEBUG + printf("Quitting already connected %s\n", line); +#endif //DEBUG + SendError( clnt, 0, "Application already connected" ); + SocketClose( client ); + } + break; + case EndRegexp: + +#ifdef DEBUG + printf("Regexp End id=%d\n", id); +#endif //DEBUG + if ( application_callback ) + { + (*application_callback)( clnt, application_user_data, BusApplicationConnected ); + } + if ( ready_message ) + { + int count; + count = ClientCall( clnt, ready_message ); + +#ifdef DEBUG + printf(" Sendind ready message %d\n", count); +#endif //DEBUG + + } + break; + case Msg: + +#ifdef DEBUG + printf("Message id=%d msg='%s'\n", id, arg); +#endif //DEBUG + + LIST_EACH( msg_recv, rcv ) + { + if ( id == rcv->id ) + { + arg = strtok( arg, ARG_END); + while ( arg ) + { + argv[argc++] = arg; + arg = strtok( NULL, ARG_END ); + } +#ifdef DEBUG + printf("Calling id=%d argc=%d for %s\n", id, argc,rcv->regexp); +#endif + if ( rcv->callback ) (*rcv->callback)( clnt, rcv->user_data, argc, argv ); + return; + } + } + printf("Callback Message id=%d not found!!!'\n", id); + break; + case DirectMsg: + +#ifdef DEBUG + printf("Direct Message id=%d msg='%s'\n", id, arg); +#endif //DEBUG + + if ( direct_callback) + (*direct_callback)( clnt, direct_user_data, id, arg ); + break; + + case Die: + +#ifdef DEBUG + printf("Die Message\n"); +#endif //DEBUG + + if ( application_die_callback) + (*application_die_callback)( clnt, application_die_user_data, id ); + BusCleanup(); + exit(0); + break; + + default: + printf("Receive unhandled message %s\n", line); + break; + } + +} + +static BusClientPtr SendService( Client client ) +{ + BusClientPtr clnt; + MsgRcvPtr msg; + LIST_ADD( clients, clnt ) + if ( clnt ) + { + clnt->msg_send = NULL; + clnt->client = client; + clnt->app_name = strdup("Unknown"); + clnt->app_port = 0; + MsgSendTo( client, StartRegexp, ApplicationPort, ApplicationName); + LIST_EACH(msg_recv, msg ) + { + MsgSendTo( client, AddRegexp,msg->id,msg->regexp); + } + MsgSendTo( client, EndRegexp, 0, ""); + } + return clnt; +} + +static void ClientDelete( Client client, void *data ) +{ + BusClientPtr clnt; + MsgSndPtr msg; + char *remotehost; + unsigned short remoteport; + clnt = (BusClientPtr)data; + if ( application_callback ) + { + (*application_callback)( clnt, application_user_data, BusApplicationDisconnected ); + } + SocketGetRemote( client, &remotehost, &remoteport ); + +#ifdef DEBUG + printf("Deconnexion de %s:%hu\n", remotehost, remoteport ); +#endif //DEBUG + + if ( clnt->app_name ) free( clnt->app_name ); + LIST_EACH( clnt->msg_send, msg) + { + /*regfree(msg->regexp);*/ + free( msg->str_regexp); + } + LIST_EMPTY( clnt->msg_send ); + LIST_REMOVE( clients, clnt ); +} + +static void *ClientCreate( Client client ) +{ + char *remotehost; + unsigned short remoteport; + SocketGetRemote( client, &remotehost, &remoteport ); + +#ifdef DEBUG + printf("Connexion de %s:%hu\n", remotehost, remoteport ); +#endif //DEBUG + + return SendService( client ); +} + +static void BroadcastReceive( Client client, void *data, char *line ) +{ + Client app; + char *remotehost; + int err; + int version; + unsigned short remoteport; + unsigned short serviceport; + SocketGetRemote( client, &remotehost, &remoteport ); + + err = sscanf(line,"%d %hu",&version, &serviceport); + if ( err != 2 ) + { + /* ignore the message */ + printf(" Bad Supervision message expected 'version port' from %s:%d\n",remotehost, remoteport); + return; + } + if ( version != VERSION ) + { + /* ignore the message */ + printf(" Bad Bus verion number expected %d receive %d from %s:%d\n", VERSION,version,remotehost, remoteport); + return; + } + /* check if we receive our own message + should test also the host */ + if ( serviceport == ApplicationPort ) return; + +#ifdef DEBUG + printf(" Broadcast de %s:%hu port %hu\n", remotehost, remoteport, serviceport ); +#endif //DEBUG + + /* connect to the service and send the regexp */ + app = SocketConnectAddr(SocketGetRemoteAddr(client), serviceport, NULL, Receive, ClientDelete ); + if ( app ) + { + BusClientPtr clnt; + clnt = SendService( app ); + SocketSetData( app, clnt); + } +} +void BusInit(const char *AppName, unsigned short busnumber, const char *ready, + BusApplicationCallback callback, void *data, + BusDieCallback die_callback, void *die_data + ) +{ + SocketInit(); + + ApplicationName = AppName; + SupervisionPort = busnumber; + application_callback = callback; + application_user_data = data; + application_die_callback = die_callback; + application_die_user_data = die_data; + ready_message = ready; + ApplicationPort = SocketServer( ANYPORT, ClientCreate, ClientDelete, Receive ); + broadcast = SocketBroadcastCreate( SupervisionPort, NULL, BroadcastReceive ); + +} + +void BusClasses( int argc, const char **argv) +{ + messages_classes_count = argc; + messages_classes = argv; +} + +void BusStart() +{ + + SocketSendBroadcast( broadcast, 143 << 24 | 196 << 16 | 1 << 8 | 255, SupervisionPort, "%d %hu\n", VERSION, ApplicationPort); + SocketSendBroadcast( broadcast, 143 << 24 | 196 << 16 | 2 << 8 | 255, SupervisionPort, "%d %hu\n", VERSION, ApplicationPort); + + fprintf(stderr,"Server Ready TCP:%hu\n",ApplicationPort); +} + +/* desabonnements */ +void UnbindMsg( MsgRcvPtr msg ) +{ +BusClientPtr clnt; + /* Send to already connected clients */ + LIST_EACH( clients, clnt ) + { + MsgSendTo( clnt->client, DelRegexp,msg->id, ""); + } +} + +/* demande de reception d'un message */ +static MsgRcvPtr _BindMsg( MsgCallback callback, void *user_data, const char *regexp ) +{ + static int recv_id = 0; + BusClientPtr clnt; + MsgRcvPtr msg; + /* add Msg to the query list */ + LIST_ADD( msg_recv, msg ); + if ( msg ) + { + msg->id = recv_id++; + msg->regexp = strdup(regexp); + msg->callback = callback; + msg->user_data = user_data; + } + /* Send to already connected clients */ + /* recherche dans la liste des requetes recues de mes clients */ + LIST_EACH( clients, clnt ) + { + MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); + } + return msg; +} +MsgRcvPtr BindMsg( 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 ) +{ +BusClientPtr clnt; +int match_count = 0; + + /* recherche dans la liste des requetes recues de mes clients */ + LIST_EACH( clients, clnt ) + { + match_count+= ClientCall( clnt, message ); + } +#ifdef DEBUG + if ( match_count == 0 ) printf( "Warning no recipient for %s\n",message); +#endif + return match_count; +} +int SendMsg(const char *fmt, ...) +{ + char buffer[4096]; + va_list ap; + + va_start( ap, fmt ); + vsprintf( buffer, fmt, ap ); + va_end ( ap ); + return _SendMsg( buffer ); +} +void SendError( BusClientPtr app, int id, const char *fmt, ... ) +{ + char buffer[4096]; + va_list ap; + + va_start( ap, fmt ); + vsprintf( buffer, fmt, ap ); + va_end ( ap ); + MsgSendTo( app->client, Error, id, buffer); +} +void BindDirectMsg( MsgDirectCallback callback, void *user_data) +{ +direct_callback = callback; +direct_user_data = user_data; +} +void SendDirectMsg( BusClientPtr app, int id, char *msg ) +{ + MsgSendTo( app->client, DirectMsg, id, msg); +} + +void SendDieMsg( BusClientPtr app ) +{ + MsgSendTo( app->client, Die, 0, "" ); +} + +char *GetApplicationName( BusClientPtr app ) +{ + if ( app && app->app_name ) + return app->app_name; + else return "Unknown"; +} + +char *GetApplicationHost( BusClientPtr app ) +{ + if ( app && app->client ) + return SocketGetPeerHost( app->client ); + else return NULL; +} + +void BusDefaultApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event) +{ + switch ( event ) { + case BusApplicationConnected: + printf("Application: %s ready on %s\n",GetApplicationName( app ), GetApplicationHost(app)); + break; + case BusApplicationDisconnected: + printf("Application: %s bye on %s\n",GetApplicationName( app ), GetApplicationHost(app)); + break; + default: + printf("Application: %s unkown event %d\n",GetApplicationName( app ), event); + break; + } +} + +BusClientPtr GetApplication( char *name ) +{ + BusClientPtr app = NULL; + LIST_ITER( clients, app, strcmp(name, app->app_name) != 0 ); + return app; +} + +char *GetApplicationList() +{ + static char applist[4096]; + BusClientPtr app; + applist[0] = '\0'; + LIST_EACH( clients, app ) + { + strcat( applist, app->app_name ); + strcat( applist, " " ); + } + return applist; +} + +char **GetApplicationMessages( BusClientPtr app ) +{ + static char *messagelist[200]; + MsgSndPtr msg; + int msgCount= 0; + memset( messagelist, 0 , sizeof( messagelist )); + /* recherche dans la liste des requetes recues de ce client */ + LIST_EACH( app->msg_send, msg ) + { + messagelist[msgCount++]= msg->str_regexp; + } + return messagelist; +} diff --git a/src/ivy.h b/src/ivy.h new file mode 100644 index 0000000..7b450d0 --- /dev/null +++ b/src/ivy.h @@ -0,0 +1,74 @@ +#ifndef _IVY_H +#define _IVY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* numero par default du bus */ + +#define DEFAULT_BUS 2010 + +typedef struct _clnt_lst *BusClientPtr; + +typedef enum { BusApplicationConnected, BusApplicationDisconnected } BusApplicationEvent; + +extern void BusDefaultApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event ) ; +/* callback callback appele sur connection deconnection d'une appli */ +typedef void (*BusApplicationCallback)( BusClientPtr app, void *user_data, BusApplicationEvent event ) ; +/* callback appele sur reception de die */ +typedef void (*BusDieCallback)( BusClientPtr app, void *user_data, int id ) ; + +/* callback appele sur reception de messages normaux */ +typedef void (*MsgCallback)( BusClientPtr app, void *user_data, int argc, char **argv ) ; +/* callback appele sur reception de messages directs */ +typedef void (*MsgDirectCallback)( BusClientPtr app, void *user_data, int id, char *msg ) ; + +/* identifiant d'une expression reguliere ( Bind/Unbind ) */ +typedef struct _msg_rcv *MsgRcvPtr; + +/* filtrage des regexps */ +void BusClasses( int argc, const char **argv); + +void BusInit( + const char *AppName, /* nom de l'application */ + unsigned short busnumber, /* numero de bus ( port UDP ) */ + const char *ready, /* ready Message peut etre NULL */ + BusApplicationCallback callback, /* callback appele sur connection deconnection d'une appli */ + void *data, /* user data passe au callback */ + BusDieCallback die_callback, /* last change callback before die */ + void *die_data ); /* user data */ + +void BusStart(); /* emission du bonjour */ + +/* query sur les applications connectees */ +char *GetApplicationName( BusClientPtr app ); +char *GetApplicationHost( BusClientPtr app ); +BusClientPtr GetApplication( char *name ); +char *GetApplicationList(); +char **GetApplicationMessages( BusClientPtr app); +/* demande de reception d'un message */ + +MsgRcvPtr BindMsg( MsgCallback callback, void *user_data, const char *fmt_regexp, ... ); /* avec sprintf prealable */ +void UnbindMsg( MsgRcvPtr id ); + +/* emmission d'un message d'erreur */ +void SendError( BusClientPtr app, int id, const char *fmt, ... ); + +/* emmission d'un message die pour terminer l'application */ +void SendDieMsg( BusClientPtr app ); + +/* emmission d'un message retourne le nb effectivement emis */ + +int SendMsg( const char *fmt_message, ... ); /* avec sprintf prealable */ + +/* Message Direct Inter-application */ + +void BindDirectMsg( MsgDirectCallback callback, void *user_data); +void SendDirectMsg( BusClientPtr app, int id, char *msg ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ivyloop.c b/src/ivyloop.c new file mode 100644 index 0000000..e02800c --- /dev/null +++ b/src/ivyloop.c @@ -0,0 +1,179 @@ +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include +#include + +#ifdef WIN32 +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#include "list.h" +#include "ivychannel.h" +#include "ivyloop.h" +#include "timer.h" + +struct _channel { + Channel next; + HANDLE fd; + void *data; + int tobedeleted; + ChannelHandleDelete handle_delete; + ChannelHandleRead handle_read; + }; + + + +static Channel channels_list = NULL; + +static int channel_initialized = 0; + +static fd_set open_fds; +static int MainLoop = 1; + +#ifdef WIN32 +WSADATA WsaData; +#endif + +void BusLoopChannelClose( Channel channel ) +{ + channel->tobedeleted = 1; +} + +static void BusLoopChannelDelete( Channel channel ) +{ + if ( channel->handle_delete ) + (*channel->handle_delete)( channel->data ); + + FD_CLR(channel->fd, &open_fds); + LIST_REMOVE( channels_list, channel ); +} +static void ChannelDefferedDelete() +{ + Channel channel,next; + LIST_EACH_SAFE( channels_list, channel,next) + { + if ( channel->tobedeleted ) + { + BusLoopChannelDelete( channel ); + } + } +} + +Channel BusLoopChannelSetUp(HANDLE fd, void *data, + ChannelHandleDelete handle_delete, + ChannelHandleRead handle_read + ) +{ + Channel channel; + + LIST_ADD( channels_list, channel ); + if ( !channel ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + exit(0); + } + channel->fd = fd; + channel->tobedeleted = 0; + channel->handle_delete = handle_delete; + channel->handle_read = handle_read; + channel->data = data; + + FD_SET( channel->fd, &open_fds ); + + return channel; +} + +static void BusLoopChannelHandleRead(fd_set *current) +{ + Channel channel,next; + + LIST_EACH_SAFE( channels_list, channel, next ) + { + if ( FD_ISSET( channel->fd, current ) ) + { + (*channel->handle_read)(channel,channel->fd,channel->data); + } + } +} +static void BusLoopChannelHandleExcpt(fd_set *current) +{ + Channel channel,next; + LIST_EACH_SAFE( channels_list, channel, next ) + { + if (FD_ISSET( channel->fd, current ) ) + { + (*channel->handle_delete)(channel->data); +// BusLoopChannelClose( channel ); + } + } +} + +void BusLoopChannelInit(void) +{ +#ifdef WIN32 + int error; +#else + /* pour eviter les plantages quand les autres applis font core-dump */ + signal( SIGPIPE, SIG_IGN); +#endif + if ( channel_initialized ) return; + + FD_ZERO( &open_fds ); + +#ifdef WIN32 + error = WSAStartup( 0x0101, &WsaData ); + if ( error == SOCKET_ERROR ) { + printf( "WSAStartup failed.\n" ); + } +#endif + channel_initialized = 1; +} + + +void BusLoopChannelStop(void) +{ + MainLoop = 0; +} +void BusLoopChannelMainLoop(void(*hook)(void)) +{ + +fd_set rdset; +fd_set exset; +int ready; + + + + while (MainLoop) { + ChannelDefferedDelete(); + if ( hook ) (*hook)(); + rdset = open_fds; + exset = open_fds; + ready = select(64, &rdset, 0, &exset, TimerGetSmallestTimeout()); + if ( ready < 0 && ( errno != EINTR )) + { + perror("select"); + return; + } + TimerScan(); + if ( ready > 0 ) + { + BusLoopChannelHandleExcpt(&exset); + BusLoopChannelHandleRead(&rdset); + continue; + } + } +} + diff --git a/src/ivyloop.h b/src/ivyloop.h new file mode 100644 index 0000000..1eb7166 --- /dev/null +++ b/src/ivyloop.h @@ -0,0 +1,39 @@ +#ifndef _IVYLOOP_H +#define _IVYLOOP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ivychannel.h" + +/* general Handle */ + +#define ANYPORT 0 + +#ifdef WIN32 +#include +#define HANDLE SOCKET +#else +#define HANDLE int +#endif + +extern void BusLoopChannelInit(void); +extern void BusLoopChannelStop(void); +extern void BusLoopChannelMainLoop(void(*hook)(void) ); + +extern Channel BusLoopChannelSetUp( + HANDLE fd, + void *data, + ChannelHandleDelete handle_delete, + ChannelHandleRead handle_read + ); + +extern void BusLoopChannelClose( Channel channel ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ivysocket.c b/src/ivysocket.c new file mode 100644 index 0000000..04e44bf --- /dev/null +++ b/src/ivysocket.c @@ -0,0 +1,516 @@ +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include +#include + +#ifdef WIN32 +#define close closesocket +/*#define perror( a ) printf(a" error=%d\n",WSAGetLastError());*/ +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "list.h" +#include "ivychannel.h" +#include "ivysocket.h" + +static ChannelInit channel_init = NULL; +static ChannelSetUp channel_setup = NULL; +static ChannelClose channel_close = NULL; + +#define MAX_BUFFER 2048 + + +typedef struct _server *Server; + +struct _server { + Server next; + Channel channel; + void *(*create)(Client client); + void (*handle_delete)(Client client, void *data); + SocketInterpretation interpretation; + }; + +struct _client { + Client next; + HANDLE fd; + Channel channel; + unsigned short port; + struct sockaddr_in from; + SocketInterpretation interpretation; + void (*handle_delete)(Client client, void *data); + char buffer[MAX_BUFFER+2]; + char *ptr; + void *data; + }; + + +static Server servers_list = NULL; +static Client clients_list = NULL; + + + + +#ifdef WIN32 +WSADATA WsaData; +#endif + +void BusSetChannelManagement( ChannelInit init_chan, ChannelSetUp setup_chan, ChannelClose close_chan ) +{ + channel_init = init_chan; + channel_setup = setup_chan; + channel_close = close_chan; +} + + +void SocketInit() +{ + if ( ! channel_init ) + { + fprintf( stderr, "You Must call BusSetChannelManagement before all !!!\n"); + exit(-1); + } + (*channel_init)(); +} + +static void DeleteSocket(void *data) +{ + Client client = ( Client )data; + if ( client->handle_delete ) + (*client->handle_delete)( client, client->data ); + shutdown( client->fd, 2 ); + close( client->fd ); + LIST_REMOVE( clients_list, client ); +} +static void HandleSocket( Channel channel, HANDLE fd, void *data) +{ + Client client = (Client)data; + char *ptr; + char *ptr_nl; + long nb_to_read = 0; + long nb; + int len; + + /* limitation taille buffer */ + nb_to_read = MAX_BUFFER - ( client->ptr - client->buffer ); + if( nb_to_read == 0 ) { + fprintf(stderr, "Erreur message trop long sans LF\n"); + client->ptr = client->buffer; + return; + }; + len = sizeof( client->from ); + nb = recvfrom( fd, client->ptr, nb_to_read,0,(struct sockaddr *)&client->from,&len); + if (nb < 0) { + perror(" Read Socket "); + (*channel_close)( client->channel ); + return; + }; + if ( nb == 0 ) + { + (*channel_close)( client->channel ); + return; + } + + client->ptr += nb; + *(client->ptr) = '\0'; + ptr = client->buffer; + while( (ptr_nl = strchr( ptr, '\n' ))) + { + *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' ) + { /* recopie ligne incomplete au debut du buffer */ + strcpy( client->buffer, ptr ); + client->ptr = client->buffer + strlen(client->buffer); + } + else + { + client->ptr = client->buffer; + } +} +static void HandleServer(Channel channel, HANDLE fd, void *data) +{ + Server server = ( Server ) data; + Client client; + HANDLE ns; + int addrlen; + struct sockaddr_in remote2; + + addrlen = sizeof( remote2 ); + if ((ns = accept( fd, (struct sockaddr *)&remote2, &addrlen)) <0) + { + perror ( "*** accept ***"); + return; + }; + LIST_ADD( clients_list, client ); + if ( !client ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + close( fd ); + exit(0); + } + client->from = remote2; + client->fd = ns; + client->channel = (*channel_setup)( ns, client, DeleteSocket, HandleSocket ); + client->interpretation = server->interpretation; + client->ptr = client->buffer; + client->handle_delete = server->handle_delete; + client->data = (*server->create)( client ); + +} +int SocketServer(unsigned short port, + void*(*create)(Client client), + void(*handle_delete)(Client client, void *data), + void(*interpretation)( Client client, void *data, char *ligne)) +{ + Server server; + HANDLE fd; + int one=1; + struct sockaddr_in local; + int addrlen; + + + if ((fd = socket( AF_INET, SOCK_STREAM, 0)) < 0){ + perror( "***open socket ***"); + exit(0); + }; + + + local.sin_family = AF_INET; + local.sin_addr.s_addr = INADDR_ANY; + local.sin_port = htons (port); + + if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&one,sizeof(one)) < 0) + { + perror( "*** set socket option SO_REUSEADDR ***"); + exit(0); + } + +#ifdef SO_REUSEPORT + + if (setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, (char *)&one, sizeof( one)) < 0) + { + perror( "*** set socket option REUSEPORT ***"); + exit(0); + } +#endif + + if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) + { + perror( "*** bind ***"); + exit(0); + } + + addrlen = sizeof( local ); + if (getsockname(fd,(struct sockaddr *)&local, &addrlen) < 0) + { + perror( "***get socket name ***"); + exit(0); + } + + if (listen( fd, 128) < 0){ + perror( "*** listen ***"); + exit(0); + }; + + + LIST_ADD( servers_list, server ); + if ( !server ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + exit(0); + } + server->channel = (*channel_setup)( fd, server, DeleteSocket, HandleServer ); + server->create = create; + server->handle_delete = handle_delete; + server->interpretation = interpretation; + return ntohs(local.sin_port); +} +char *SocketGetPeerHost( Client client ) +{ + int err; + struct sockaddr_in name; + struct hostent *host; + int len = sizeof(name); + err = getpeername( client->fd, (struct sockaddr *)&name, &len ); + if ( err < 0 ) return "can't get peer"; + host = gethostbyaddr( (char *)&name.sin_addr.s_addr,sizeof(name.sin_addr.s_addr),name.sin_family); + if ( host == NULL ) return "can't translate addr"; + return host->h_name; +} +struct in_addr * SocketGetRemoteAddr( Client client ) +{ + return &client->from.sin_addr; +} +void SocketGetRemote( Client client, char **host, unsigned short *port ) +{ + struct hostent *hostp; + /* extract hostname and port from last message received */ + hostp = gethostbyaddr( (char *)&client->from.sin_addr.s_addr, + sizeof(client->from.sin_addr.s_addr),client->from.sin_family); + if ( hostp == NULL ) *host = "unknown"; + else *host = hostp->h_name; + *port = ntohs( client->from.sin_port ); +} +void SocketClose( Client client ) +{ + (*channel_close)( client->channel ); +} + +void SocketSendRaw( Client client, char *buffer, int len ) +{ + int err; + err = send( client->fd, buffer, len, 0 ); + if ( err != len ) + perror( "*** send ***"); +} +void SocketSetData( Client client, void *data ) +{ + client->data = data; +} +void SocketSend( Client client, char *fmt, ... ) +{ + char buffer[4096]; + va_list ap; + int len; + va_start( ap, fmt ); + len = vsprintf( buffer, fmt, ap ); + SocketSendRaw( client, buffer, len ); + va_end ( ap ); +} +void *SocketGetData( Client client ) +{ + return client->data; +} +void SocketBroadcast( char *fmt, ... ) +{ + Client client; + char buffer[4096]; + va_list ap; + int len; + + va_start( ap, fmt ); + len = vsprintf( buffer, fmt, ap ); + va_end ( ap ); + LIST_EACH( clients_list, client ) + { + SocketSendRaw( client, buffer, len ); + } +} +/* +Ouverture d'un canal TCP/IP en mode client +*/ +Client SocketConnect( char * host, unsigned short port, + void *data, + SocketInterpretation interpretation, + void (*handle_delete)(Client client, void *data) + ) +{ +struct hostent *rhost; + + +if ((rhost = gethostbyname( host )) == NULL){ + fprintf(stderr, "Erreur %s Calculateur inconnu !\n",host); + return NULL; + }; +return SocketConnectAddr( (struct in_addr*)(rhost->h_addr), port, data, interpretation, handle_delete); +} +Client SocketConnectAddr( struct in_addr * addr, unsigned short port, + void *data, + SocketInterpretation interpretation, + void (*handle_delete)(Client client, void *data) + ) +{ +HANDLE handle; +Client client; +struct sockaddr_in remote; + +remote.sin_family = AF_INET; +remote.sin_addr = *addr; +remote.sin_port = htons (port); + +if ((handle = socket( AF_INET, SOCK_STREAM, 0)) < 0){ + perror( "*** client socket ***"); + return NULL; + }; + +if ( connect( handle, (struct sockaddr *)&remote, sizeof(remote) ) < 0){ + perror( "*** client connect ***"); + return NULL; + }; + +LIST_ADD( clients_list, client ); +if ( !client ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + close( handle ); + exit(0); + } + +client->fd = handle; +client->channel = (*channel_setup)( handle, client, DeleteSocket, HandleSocket ); +client->interpretation = interpretation; +client->ptr = client->buffer; +client->data = data; +client->handle_delete = handle_delete; +client->from.sin_family = AF_INET; +client->from.sin_addr = *addr; +client->from.sin_port = htons (port); + +return client; +} +int SocketWaitForReply( Client client, char *buffer, int size, int delai) +{ + fd_set rdset; + struct timeval timeout; + struct timeval *timeoutptr = &timeout; + int ready; + char *ptr; + char *ptr_nl; + long nb_to_read = 0; + long nb; + HANDLE fd; + + fd = client->fd; + ptr = buffer; + timeout.tv_sec = delai; + timeout.tv_usec = 0; + do { + /* limitation taille buffer */ + nb_to_read = size - ( ptr - buffer ); + if( nb_to_read == 0 ) + { + fprintf(stderr, "Erreur message trop long sans LF\n"); + ptr = buffer; + return -1; + } + FD_ZERO( &rdset ); + FD_SET( fd, &rdset ); + ready = select(fd+1, &rdset, 0, 0, timeoutptr); + if ( ready < 0 ) + { + perror("select"); + return -1; + } + if ( ready == 0 ) + { + return -2; + } + if ((nb = recv( fd , ptr, nb_to_read, 0 )) < 0) + { + perror(" Read Socket "); + return -1; + } + if ( nb == 0 ) + return 0; + + ptr += nb; + *ptr = '\0'; + ptr_nl = strchr( buffer, '\n' ); + } while ( !ptr_nl ); + *ptr_nl = '\0'; + return (ptr_nl - buffer); +} + + +/* Socket UDP */ + +Client SocketBroadcastCreate( unsigned short port, + void *data, + SocketInterpretation interpretation + ) +{ +HANDLE handle; +Client client; +struct sockaddr_in local; +int on = 1; + +local.sin_family = AF_INET; +local.sin_addr.s_addr = INADDR_ANY; +local.sin_port = htons (port); + +if ((handle = socket( AF_INET, SOCK_DGRAM, 0)) < 0){ + perror( "*** dgram socket ***"); + return NULL; + }; + +/* wee need to used multiple client on the same host */ +if (setsockopt( handle, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof( on)) < 0) + { + perror( "*** set socket option REUSEADDR ***"); + return NULL; + }; +#ifdef SO_REUSEPORT + +if (setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof( on)) < 0) + { + perror( "*** set socket option REUSEPORT ***"); + return NULL; + } +#endif +/* wee need to broadcast */ +if (setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof( on)) < 0) + { + perror( "*** BROADCAST ***"); + return NULL; + }; + +if (bind(handle, (struct sockaddr *)&local, sizeof(local)) < 0) + { + perror( "*** test BIND ***"); + return NULL; + }; + +LIST_ADD( clients_list, client ); +if ( !client ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + close( handle ); + exit(0); + } + +client->fd = handle; +client->channel = (*channel_setup)( handle, client, DeleteSocket, HandleSocket ); +client->interpretation = interpretation; +client->ptr = client->buffer; +client->data = data; + +return client; +} + +void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *fmt, ... ) +{ + struct sockaddr_in remote; + char buffer[4096]; + va_list ap; + int err,len; + + va_start( ap, fmt ); + len = vsprintf( 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, + (struct sockaddr *)&remote,sizeof(remote)); + if ( err != len ) + { + perror( "*** send ***"); + } va_end ( ap ); +} diff --git a/src/ivysocket.h b/src/ivysocket.h new file mode 100644 index 0000000..2258caf --- /dev/null +++ b/src/ivysocket.h @@ -0,0 +1,72 @@ +#ifndef _IVYSOCKET_H +#define _IVYSOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* general Handle */ + +#define ANYPORT 0 + +#ifdef WIN32 +#include +#define HANDLE SOCKET +#else +#define HANDLE int +#include +#endif + + +/* Server Part */ +typedef struct _client *Client; +typedef void (*SocketInterpretation)( Client client, void *data, char *ligne); + +extern void SocketInit(); + +extern void SocketClose( Client client ); +extern void SocketSend( Client client, char *fmt, ... ); +extern void SocketSendRaw( Client client, char *buffer, int len ); +extern char *SocketGetPeerHost( Client client ); +extern void SocketSetData( Client client, void *data ); +extern void *SocketGetData( Client client ); +extern void SocketBroadcast( char *fmt, ... ); + +extern int SocketServer(unsigned short port, + void*(*create)(Client client), + void(*handle_delete)(Client client, void *data), + SocketInterpretation interpretation); + +/* Client Part */ + +extern Client SocketConnect( char * host, unsigned short port, + void *data, + SocketInterpretation interpretation, + void (*handle_delete)(Client client, void *data) + ); +extern Client SocketConnectAddr( struct in_addr * addr, unsigned short port, + void *data, + SocketInterpretation interpretation, + void (*handle_delete)(Client client, void *data) + ); +extern int SocketWaitForReply( Client client, char *buffer, int size, int delai); + +/* Socket UDP */ +/* Creation d'une socket en mode non connecte */ +/* et ecoute des messages */ +extern Client SocketBroadcastCreate( + unsigned short port, + void *data, + SocketInterpretation interpretation + ); +/* recuperation de l'emetteur du message */ +extern struct in_addr * SocketGetRemoteAddr( Client client ); +extern void SocketGetRemote( Client client, char **host, unsigned short *port ); +/* emmission d'un broadcast UDP */ +extern void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *fmt, ... ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ivyxtloop.c b/src/ivyxtloop.c new file mode 100644 index 0000000..e2620aa --- /dev/null +++ b/src/ivyxtloop.c @@ -0,0 +1,116 @@ +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include +#include + +#ifdef WIN32 +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#include + +#include "ivychannel.h" +#include "ivyxtloop.h" + +struct _channel { + XtInputId id_read; + XtInputId id_delete; + void *data; + ChannelHandleDelete handle_delete; + ChannelHandleRead handle_read; + }; + + +static int channel_initialized = 0; + + +static XtAppContext app = NULL; + + +void BusXtChannelClose( Channel channel ) +{ + + if ( channel->handle_delete ) + (*channel->handle_delete)( channel->data ); + XtRemoveInput( channel->id_read ); + XtRemoveInput( channel->id_delete ); +} + +static void BusXtHandleChannelRead( XtPointer closure, int* source, XtInputId* id ) +{ + Channel channel = (Channel)closure; +#ifdef DEBUG + printf("Handle Channel read %d\n",*source ); +#endif + (*channel->handle_read)(channel,*source,channel->data); +} +static void BusXtHandleChannelDelete( XtPointer closure, int* source, XtInputId* id ) +{ + Channel channel = (Channel)closure; +#ifdef DEBUG + printf("Handle Channel delete %d\n",*source ); +#endif + (*channel->handle_delete)(channel->data); +} +Channel BusXtChannelSetUp(HANDLE fd, void *data, + ChannelHandleDelete handle_delete, + ChannelHandleRead handle_read + ) +{ + Channel channel; + + channel = XtNew( struct _channel ); + if ( !channel ) + { + fprintf(stderr,"NOK Memory Alloc Error\n"); + exit(0); + } + + channel->handle_delete = handle_delete; + channel->handle_read = handle_read; + channel->data = data; + + channel->id_read = XtAppAddInput( app, fd, (XtPointer)XtInputReadMask, BusXtHandleChannelRead, channel); + channel->id_delete = XtAppAddInput( app, fd, (XtPointer)XtInputExceptMask, BusXtHandleChannelDelete, channel); + + return channel; +} + + +void BusXtChannelAppContext( XtAppContext cntx ) +{ + app = cntx; +} + +void BusXtChannelInit(void) +{ + + if ( channel_initialized ) return; + + /* pour eviter les plantages quand les autres applis font core-dump */ +#ifndef WIN32 + signal( SIGPIPE, SIG_IGN); +#endif + /* verifie si init correct */ + if ( !app ) + { + fprintf( stderr, "You Must call BusXtChannelAppContext to Use XtMainLoop !!!\n"); + exit(-1); + } + channel_initialized = 1; +} + + diff --git a/src/ivyxtloop.h b/src/ivyxtloop.h new file mode 100644 index 0000000..17e053f --- /dev/null +++ b/src/ivyxtloop.h @@ -0,0 +1,40 @@ +#ifndef _IVYXTLOOP_H +#define _IVYXTLOOP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* general Handle */ + +#define ANYPORT 0 + +#ifdef WIN32 +#include +#define HANDLE SOCKET +#else +#define HANDLE int +#endif + +#include "ivychannel.h" + +extern void BusXtChannelInit(void); + +extern Channel BusXtChannelSetUp( + HANDLE fd, + void *data, + ChannelHandleDelete handle_delete, + ChannelHandleRead handle_read + ); + +extern void BusXtChannelClose( Channel channel ); + +extern void BusXtChannelAppContext( XtAppContext cntx ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/testbus.c b/src/testbus.c deleted file mode 100644 index ae10eea..0000000 --- a/src/testbus.c +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include -#ifdef WIN32 -#include -#else -#include -#include -#endif -#ifdef XTMAINLOOP -#include "busxtloop.h" -#else -#include "busloop.h" -#endif -#include "bussocket.h" -#include "bus.h" -#include "timer.h" -#ifdef XTMAINLOOP -#include -XtAppContext cntx; -#endif - -int app_count = 0; -int wait_count = 0; - -void Callback( BusClientPtr app, void *user_data, int argc, char *argv[]) -{ - int i; - printf(" %s Called function %d args:",GetApplicationName(app),argc); - for ( i = 0; i < argc; i++ ) - printf(" '%s'",argv[i]); - printf("\n"); -} -void HandleStdin( Channel channel, HANDLE fd, void *data) -{ - char buf[4096]; - char *line; - char *cmd; - char *arg; - int id; - BusClientPtr app; - int err; - line = gets( buf); - if ( !line ) - { -#ifdef XTMAINLOOP - BusXtChannelClose( channel ); -#else - BusLoopChannelClose( channel ); - BusLoopChannelStop(); -#endif - return; - } - if ( *line == '.' ) - { - cmd = strtok( line, ".: "); - if ( strcmp(cmd, "die" ) == 0 ) - { - arg = strtok( NULL, " " ); - if ( arg ) - { - app = GetApplication( arg ); - if ( app ) - SendDieMsg( app ); - else printf( "No Application %s!!!\n",arg); - } - } - if ( strcmp(cmd, "dieall-yes-i-am-sure") == 0 ) - { - arg = GetApplicationList(); - arg = strtok( arg, " " ); - while ( arg ) - { - app = GetApplication( arg ); - if ( app ) - SendDieMsg( app ); - else printf( "No Application %s!!!\n",arg); - arg = strtok( NULL, " "); - } - - } - - if ( strcmp(cmd, "bind" ) == 0 ) - { - arg = strtok( NULL, "'" ); - if ( arg ) - { - BindMsg( Callback, NULL, arg ); - } - } - if ( strcmp(cmd, "where" ) == 0 ) - { - arg = strtok( NULL, " " ); - if ( arg ) - { - app = GetApplication( arg ); - if ( app ) - printf( "Application %s on %s\n",arg, GetApplicationHost( app )); - else printf( "No Application %s!!!\n",arg); - } - } - if ( strcmp(cmd, "direct" ) == 0 ) - { - arg = strtok( NULL, " " ); - if ( arg ) - { - app = GetApplication( arg ); - if ( app ) - { - arg = strtok( NULL, " " ); - id = atoi( arg ) ; - arg = strtok( NULL, "'" ); - SendDirectMsg( app, id, arg ); - } - else printf( "No Application %s!!!\n",arg); - } - - } - if ( strcmp(cmd, "who") == 0 ) - { - printf("Apps: %s\n", GetApplicationList()); - } - if ( strcmp(cmd, "help") == 0 ) - { - printf("Commands list:\n"); - printf(" .help - this help\n"); - printf(" .quit - terminate this application\n"); - printf(" .die appname - send die msg to appname\n"); - printf(" .direct appname id 'arg' - send direct msg to appname\n"); - printf(" .where appname - on which host is appname\n"); - printf(" .bind 'regexp' - add a msg to receive\n"); - printf(" .who - who is on the bus\n"); - } - if ( strcmp(cmd, "quit") == 0 ) - { - exit(0); - } - } - else - { - err = SendMsg( buf ); - printf("Sent:%d\n",err); - } -} - -void ApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event) -{ - char *appname; - char *host; - char **msgList; - appname = GetApplicationName( app ); - host = GetApplicationHost( app ); - switch ( event ) { - case BusApplicationConnected: - app_count++; - printf("Application(%s): ready on %s\n", appname, host); - printf("Application(%s): Begin Messages\n", appname); - msgList = GetApplicationMessages( app ); - while( *msgList ) - printf("Application(%s): Receive '%s'\n",appname,*msgList++); - printf("Application(%s): End Messages\n",appname); - if ( app_count == wait_count ) -#ifdef XTMAINLOOP - BusXtChannelSetUp( 0, NULL, NULL, HandleStdin); -#else - BusLoopChannelSetUp( 0, NULL, NULL, HandleStdin); -#endif - break; - case BusApplicationDisconnected: - app_count--; - printf("Application(%s): bye on %s\n", appname, host); - break; - default: - printf("Application(%s): unkown event %d\n", appname, event); - break; - } - -} -#ifndef XTMAINLOOP -void TimerCall(TimerId id, void *user_data, unsigned long delta) -{ - printf("Timer callback: %d delta %lu ms\n", (int)user_data, delta ); - SendMsg( "TEST TIMER %d", (int)user_data); - /*if ( (int)user_data == 5 ) TimerModify( id, 2000 );*/ -} -#endif -int main(int argc, char *argv[]) -{ - - unsigned short bport = DEFAULT_BUS; - int c; - int timer_test = 0; - while ((c = getopt(argc, argv, "b:w:t")) != EOF) - switch (c) - { - case 'b': - bport = atoi(optarg) ; - break; - case 'w': - wait_count = atoi(optarg) ; - break; - case 't': - timer_test = 1; - break; - } - /* Mainloop management */ -#ifdef XTMAINLOOP - /*XtToolkitInitialize();*/ - cntx = XtCreateApplicationContext(); - BusXtChannelAppContext( cntx ); - BusSetChannelManagement( BusXtChannelInit, BusXtChannelSetUp, BusXtChannelClose ); -#else - BusSetChannelManagement( BusLoopChannelInit, BusLoopChannelSetUp, BusLoopChannelClose ); -#endif - BusInit("TEST",bport,"TEST READY",ApplicationCallback,NULL,NULL,NULL); - for ( ; optind < argc; optind++ ) - BindMsg( Callback, NULL, argv[optind] ); - if ( wait_count == 0 ) -#ifdef XTMAINLOOP - BusXtChannelSetUp( 0, NULL, NULL, HandleStdin); -#else - BusLoopChannelSetUp( 0, NULL, NULL, HandleStdin); -#endif - BusStart( ); - if ( timer_test ) - { -#ifndef XTMAINLOOP - TimerRepeatAfter( TIMER_LOOP, 1000, TimerCall, (void*)1 ); - TimerRepeatAfter( 5, 5000, TimerCall, (void*)5 ); -#endif - } -#ifdef XTMAINLOOP - XtAppMainLoop(cntx); -#else - BusLoopChannelMainLoop(NULL); -#endif - return 0; -} diff --git a/src/testivy.c b/src/testivy.c new file mode 100644 index 0000000..eee0a5e --- /dev/null +++ b/src/testivy.c @@ -0,0 +1,237 @@ +#include +#include +#ifdef WIN32 +#include +#else +#include +#include +#endif +#ifdef XTMAINLOOP +#include "ivyxtloop.h" +#else +#include "ivyloop.h" +#endif +#include "ivysocket.h" +#include "ivy.h" +#include "timer.h" +#ifdef XTMAINLOOP +#include +XtAppContext cntx; +#endif + +int app_count = 0; +int wait_count = 0; + +void Callback( BusClientPtr app, void *user_data, int argc, char *argv[]) +{ + int i; + printf(" %s Called function %d args:",GetApplicationName(app),argc); + for ( i = 0; i < argc; i++ ) + printf(" '%s'",argv[i]); + printf("\n"); +} +void HandleStdin( Channel channel, HANDLE fd, void *data) +{ + char buf[4096]; + char *line; + char *cmd; + char *arg; + int id; + BusClientPtr app; + int err; + line = gets( buf); + if ( !line ) + { +#ifdef XTMAINLOOP + BusXtChannelClose( channel ); +#else + BusLoopChannelClose( channel ); + BusLoopChannelStop(); +#endif + return; + } + if ( *line == '.' ) + { + cmd = strtok( line, ".: "); + if ( strcmp(cmd, "die" ) == 0 ) + { + arg = strtok( NULL, " " ); + if ( arg ) + { + app = GetApplication( arg ); + if ( app ) + SendDieMsg( app ); + else printf( "No Application %s!!!\n",arg); + } + } + if ( strcmp(cmd, "dieall-yes-i-am-sure") == 0 ) + { + arg = GetApplicationList(); + arg = strtok( arg, " " ); + while ( arg ) + { + app = GetApplication( arg ); + if ( app ) + SendDieMsg( app ); + else printf( "No Application %s!!!\n",arg); + arg = strtok( NULL, " "); + } + + } + + if ( strcmp(cmd, "bind" ) == 0 ) + { + arg = strtok( NULL, "'" ); + if ( arg ) + { + BindMsg( Callback, NULL, arg ); + } + } + if ( strcmp(cmd, "where" ) == 0 ) + { + arg = strtok( NULL, " " ); + if ( arg ) + { + app = GetApplication( arg ); + if ( app ) + printf( "Application %s on %s\n",arg, GetApplicationHost( app )); + else printf( "No Application %s!!!\n",arg); + } + } + if ( strcmp(cmd, "direct" ) == 0 ) + { + arg = strtok( NULL, " " ); + if ( arg ) + { + app = GetApplication( arg ); + if ( app ) + { + arg = strtok( NULL, " " ); + id = atoi( arg ) ; + arg = strtok( NULL, "'" ); + SendDirectMsg( app, id, arg ); + } + else printf( "No Application %s!!!\n",arg); + } + + } + if ( strcmp(cmd, "who") == 0 ) + { + printf("Apps: %s\n", GetApplicationList()); + } + if ( strcmp(cmd, "help") == 0 ) + { + printf("Commands list:\n"); + printf(" .help - this help\n"); + printf(" .quit - terminate this application\n"); + printf(" .die appname - send die msg to appname\n"); + printf(" .direct appname id 'arg' - send direct msg to appname\n"); + printf(" .where appname - on which host is appname\n"); + printf(" .bind 'regexp' - add a msg to receive\n"); + printf(" .who - who is on the bus\n"); + } + if ( strcmp(cmd, "quit") == 0 ) + { + exit(0); + } + } + else + { + err = SendMsg( buf ); + printf("Sent:%d\n",err); + } +} + +void ApplicationCallback( BusClientPtr app, void *user_data, BusApplicationEvent event) +{ + char *appname; + char *host; + char **msgList; + appname = GetApplicationName( app ); + host = GetApplicationHost( app ); + switch ( event ) { + case BusApplicationConnected: + app_count++; + printf("Application(%s): ready on %s\n", appname, host); + printf("Application(%s): Begin Messages\n", appname); + msgList = GetApplicationMessages( app ); + while( *msgList ) + printf("Application(%s): Receive '%s'\n",appname,*msgList++); + printf("Application(%s): End Messages\n",appname); + if ( app_count == wait_count ) +#ifdef XTMAINLOOP + BusXtChannelSetUp( 0, NULL, NULL, HandleStdin); +#else + BusLoopChannelSetUp( 0, NULL, NULL, HandleStdin); +#endif + break; + case BusApplicationDisconnected: + app_count--; + printf("Application(%s): bye on %s\n", appname, host); + break; + default: + printf("Application(%s): unkown event %d\n", appname, event); + break; + } + +} +#ifndef XTMAINLOOP +void TimerCall(TimerId id, void *user_data, unsigned long delta) +{ + printf("Timer callback: %d delta %lu ms\n", (int)user_data, delta ); + SendMsg( "TEST TIMER %d", (int)user_data); + /*if ( (int)user_data == 5 ) TimerModify( id, 2000 );*/ +} +#endif +int main(int argc, char *argv[]) +{ + + unsigned short bport = DEFAULT_BUS; + int c; + int timer_test = 0; + while ((c = getopt(argc, argv, "b:w:t")) != EOF) + switch (c) + { + case 'b': + bport = atoi(optarg) ; + break; + case 'w': + wait_count = atoi(optarg) ; + break; + case 't': + timer_test = 1; + break; + } + /* Mainloop management */ +#ifdef XTMAINLOOP + /*XtToolkitInitialize();*/ + cntx = XtCreateApplicationContext(); + BusXtChannelAppContext( cntx ); + BusSetChannelManagement( BusXtChannelInit, BusXtChannelSetUp, BusXtChannelClose ); +#else + BusSetChannelManagement( BusLoopChannelInit, BusLoopChannelSetUp, BusLoopChannelClose ); +#endif + BusInit("TEST",bport,"TEST READY",ApplicationCallback,NULL,NULL,NULL); + for ( ; optind < argc; optind++ ) + BindMsg( Callback, NULL, argv[optind] ); + if ( wait_count == 0 ) +#ifdef XTMAINLOOP + BusXtChannelSetUp( 0, NULL, NULL, HandleStdin); +#else + BusLoopChannelSetUp( 0, NULL, NULL, HandleStdin); +#endif + BusStart( ); + if ( timer_test ) + { +#ifndef XTMAINLOOP + TimerRepeatAfter( TIMER_LOOP, 1000, TimerCall, (void*)1 ); + TimerRepeatAfter( 5, 5000, TimerCall, (void*)5 ); +#endif + } +#ifdef XTMAINLOOP + XtAppMainLoop(cntx); +#else + BusLoopChannelMainLoop(NULL); +#endif + return 0; +} -- cgit v1.1