diff options
author | fourdan | 2007-01-29 10:09:59 +0000 |
---|---|---|
committer | fourdan | 2007-01-29 10:09:59 +0000 |
commit | 68e3c0ed570ba3e994f8a1c4b20594372fb0b514 (patch) | |
tree | 8d6c0d6876340742ea6f49dc9faa40aef9855563 /src | |
parent | 6fc08ea508e4fa39a9bf7f5495e84a68bd0bf88a (diff) | |
parent | f70181ffe0b37952384ff5e0ce0185541828014f (diff) | |
download | ivy-c-68e3c0ed570ba3e994f8a1c4b20594372fb0b514.zip ivy-c-68e3c0ed570ba3e994f8a1c4b20594372fb0b514.tar.gz ivy-c-68e3c0ed570ba3e994f8a1c4b20594372fb0b514.tar.bz2 ivy-c-68e3c0ed570ba3e994f8a1c4b20594372fb0b514.tar.xz |
Rename protocol_v3 as trunk to avoid confusion on protocol version to use.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 193 | ||||
-rwxr-xr-x | src/Makefile.mingw | 2 | ||||
-rwxr-xr-x | src/Makefile.win32 | 49 | ||||
-rwxr-xr-x | src/hash.c | 665 | ||||
-rwxr-xr-x | src/hash.h | 29 | ||||
-rw-r--r-- | src/intervalRegexp.c | 432 | ||||
-rw-r--r-- | src/intervalRegexp.h | 14 | ||||
-rw-r--r-- | src/ivy.c | 1045 | ||||
-rw-r--r-- | src/ivy.h | 71 | ||||
-rwxr-xr-x | src/ivyargument.c | 180 | ||||
-rwxr-xr-x | src/ivyargument.h | 35 | ||||
-rw-r--r-- | src/ivybind.c | 249 | ||||
-rw-r--r-- | src/ivybind.h | 22 | ||||
-rw-r--r-- | src/ivybuffer.c | 82 | ||||
-rw-r--r-- | src/ivybuffer.h | 39 | ||||
-rw-r--r-- | src/ivychannel.h | 19 | ||||
-rw-r--r-- | src/ivydebug.h | 30 | ||||
-rw-r--r-- | src/ivyglibloop.c | 26 | ||||
-rw-r--r-- | src/ivyglibloop.h | 3 | ||||
-rwxr-xr-x | src/ivyglutloop.c | 28 | ||||
-rwxr-xr-x | src/ivyglutloop.h | 6 | ||||
-rw-r--r-- | src/ivyloop.c | 66 | ||||
-rw-r--r-- | src/ivyloop.h | 37 | ||||
-rwxr-xr-x | src/ivyperf.c | 71 | ||||
-rw-r--r-- | src/ivyprobe.c | 333 | ||||
-rw-r--r-- | src/ivysocket.c | 408 | ||||
-rw-r--r-- | src/ivysocket.h | 31 | ||||
-rwxr-xr-x | src/ivytcl.c | 21 | ||||
-rwxr-xr-x | src/ivytcl.h | 6 | ||||
-rw-r--r-- | src/ivyxtloop.c | 29 | ||||
-rw-r--r-- | src/ivyxtloop.h | 8 | ||||
-rw-r--r-- | src/libIvy.def | 28 | ||||
-rw-r--r-- | src/list.h | 42 | ||||
-rw-r--r-- | src/timer.c | 35 | ||||
-rw-r--r-- | src/timer.h | 2 | ||||
-rw-r--r-- | src/version.h | 8 |
36 files changed, 1947 insertions, 2397 deletions
diff --git a/src/Makefile b/src/Makefile index b4f90ef..26789d0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,11 +4,11 @@ # Copyright (C) 1997-2002 # Centre d'Études de la Navigation Aérienne # -# Makefile +# Makefile # # Authors: François-Régis Colin <fcolin@cena.fr> -# Stéphane Chatty <chatty@cena.fr> -# Yannick Jestin <jestin@cena.fr> +# Stéphane Chatty <chatty@cena.fr> +# Yannick Jestin <jestin@cena.fr> # # Please refer to file version.h for the # copyright notice regarding this software @@ -16,11 +16,25 @@ # change this in version.h too !!!! -MAJOR=4 -MINOR=0 +MAJOR=3 +MINOR=9 -XTINC = -I/usr/X11R6/include -XTLIB = -L/usr/X11R6/lib -lXt -lX11 -lSM -lICE +PERHAPS64 := $(shell uname -m | perl -ne "print /64/ ? '64' : '';") +LIB = /lib$(PERHAPS64) +ifeq ($(PERHAPS64), "64") + FPIC= +else + FPIC=-fPIC +endif + +ifndef PREFIX + PREFIX=/usr/local +endif + +X11_PREFIX = /usr + +XTINC = -I$(X11_PREFIX)/include +XTLIB = -L$(X11_PREFIX)$(LIB) -lXt -lX11 -lSM -lICE GLIBINC = `pkg-config --cflags glib-2.0` GLIBLIB = `pkg-config --libs glib-2.0` GLUTINC = -I/usr/include -I. @@ -30,19 +44,22 @@ GLUTLIB = -L. -lglut -lGLU -lGL -lX11 -lXmu #TCLVERS = `perl -e '@_=sort map (m|/usr/lib/libtcl(\d\.\d)\.so|, glob ("/usr/lib/libtcl*")); print pop @_'` TCLVERS:= $(shell perl -e '@_=sort map (m|/usr/lib/libtcl(\d\.\d)\.so|, glob ("/usr/lib/libtcl*")); print pop @_') ifndef TCLVERS +TCLVERS:= $(shell perl -e '@_=sort map (m|/usr/lib64/libtcl(\d\.\d)\.so|, glob ("/usr/lib64/libtcl*")); print pop @_') +endif +ifndef TCLVERS TCLVERS=8.3 endif -TCLINCL = -I/usr/include/tcl$(TCLVERS) +TCLINCL = -I/usr/include/tcl$(TCLVERS) TCLLIB = -ltcl$(TCLVERS) #TCLINCL = -I/usr/include/tcl8.4 #TCLLIB = -ltcl8.4 # use these if you want to use Aqua Tcl on macOSX -#TCLINC = -I/Library/Frameworks/Tcl.framework/Headers +#TCLINC = -I/Library/Frameworks/Tcl.framework/Headers #TCLLIB = -framework Tcl PCREINC = `pcre-config --cflags` PCRELIB = `pcre-config --libs` -CASESENSITIVE = "no" +CASESENSITIVE = "yes" ifeq ($(CASESENSITIVE), "no") PCRE_OPT=PCRE_CASELESS REGCOMP_OPT=REG_ICASE @@ -61,22 +78,24 @@ CC=gcc LIBTOOL=ar q # linux and solaris #LIBTOOL=libtool -static -o -#REGEXP = -DGNU_REGEXP -DREGCOMP_OPT=$(REGCOMP_OPT) # deprecated ! +#REGEXP = -DGNU_REGEXP -DREGCOMP_OPT=$(REGCOMP_OPT) # deprecated ! REGEXP= -DUSE_PCRE_REGEX -DPCRE_OPT=$(PCRE_OPT) # on activeTCL , set #define CHANNEL to null, and add ivyloop.o in the ivytcl target, # see below CHANNEL = -DTCL_CHANNEL_INTEGRATION -CFLAGS = -g -Wall #-DDEBUG - -COMOBJ = hash.o ivysocket.o ivybind.o ivyargument.o ivy.o -OBJ = $(COMOBJ) ivyloop.o timer.o -XTOBJ = $(COMOBJ) ivyxtloop.o -GLIBOBJ = $(COMOBJ) ivyglibloop.o -GLUTOBJ = $(COMOBJ) ivyglutloop.o -TCLOBJ = $(COMOBJ) ivytcl.o timer.o +CFLAGS = -g -Wall $(FPIC) + + +OBJ = ivyloop.o timer.o ivysocket.o ivy.o ivybuffer.o ivybind.o intervalRegexp.o +GOBJ = ivyloop.o timer.o ivysocket.o givy.o ivybuffer.o ivybind.o intervalRegexp.o +XTOBJ = ivyxtloop.o ivysocket.o ivy.o ivybuffer.o ivybind.o intervalRegexp.o +GLIBOBJ = ivyglibloop.o ivysocket.o ivy.o ivybuffer.o ivybind.o intervalRegexp.o +GLUTOBJ = ivyglutloop.o ivysocket.o ivy.o ivybuffer.o ivybind.o intervalRegexp.o +TCLOBJ = ivytcl.o timer.o ivysocket.o givy.o ivybuffer.o ivybind.o intervalRegexp.o + # WINDOWS add ivyloop.o if TCL_CHANNEL_INTEGRATION is not set TARGETS = ivyprobe ivyperf ivyglibprobe ivyxtprobe -TARGETLIBS=libivy.so.$(MAJOR).$(MINOR) libxtivy.so.$(MAJOR).$(MINOR) libglibivy.so.$(MAJOR).$(MINOR) libtclivy.so.$(MAJOR).$(MINOR) +TARGETLIBS=libivy.so.$(MAJOR).$(MINOR) libgivy.so.$(MAJOR).$(MINOR) libxtivy.so.$(MAJOR).$(MINOR) libglibivy.so.$(MAJOR).$(MINOR) libtclivy.so.$(MAJOR).$(MINOR) # not yet need Modified Glut ivyglutprobe .c.o: @@ -84,7 +103,7 @@ TARGETLIBS=libivy.so.$(MAJOR).$(MINOR) libxtivy.so.$(MAJOR).$(MINOR) libglibivy. all: static-libs commands shared-libs -static-libs: libivy.a libxtivy.a libglibivy.a libtclivy.a +static-libs: libivy.a libgivy.a libxtivy.a libglibivy.a libtclivy.a # not yet need Modified Glut libglutivy.a shared-libs: $(TARGETLIBS) @@ -92,17 +111,15 @@ shared-libs: $(TARGETLIBS) commands: $(TARGETS) -ivytcl.o: ivytcl.c - $(CC) -c $(CFLAGS) $(TCLINCL) $(CHANNEL) ivytcl.c - -ivy.o: ivy.c - $(CC) -c $(CFLAGS) ivy.c - ivybind.o: ivybind.c $(CC) -c $(CFLAGS) $(REGEXP) $(PCREINC) ivybind.c -ivyargument.o: ivyargument.c - $(CC) -c $(CFLAGS) $(REGEXP) $(PCREINC) ivyargument.c + +ivytcl.o: ivytcl.c + $(CC) -c $(CFLAGS) $(TCLINCL) $(CHANNEL) ivytcl.c + +givy.o: ivy.c + $(CC) -c $(CFLAGS) -DDEBUG -o givy.o ivy.c ivyglutloop.o: ivyglutloop.c ivyglutloop.h $(CC) -c $(CFLAGS) $(GLUTINC) ivyglutloop.c @@ -115,13 +132,10 @@ ivyprobe: ivyprobe.o libivy.a ivyprobe.o : ivyprobe.c $(CC) $(CFLAGS) $(REGEXP) -c ivyprobe.c -o $@ - + ivyperf: ivyperf.o libivy.a $(CC) $(CFLAGS) -o $@ ivyperf.o -L. -livy $(PCRELIB) $(EXTRALIB) -ivyperf.o : ivyperf.c - $(CC) $(CFLAGS) $(REGEXP) -c ivyperf.c -o $@ - ivyxtprobe.o : ivyprobe.c $(CC) $(CFLAGS) $(REGEXP) -DXTMAINLOOP -c ivyprobe.c -o $@ $(XTINC) @@ -144,6 +158,10 @@ libivy.a: $(OBJ) rm -f $@ $(LIBTOOL) $@ $(OBJ) +libgivy.a: $(GOBJ) + rm -f $@ + $(LIBTOOL) $@ $(GOBJ) + libxtivy.a: $(XTOBJ) rm -f $@ $(LIBTOOL) $@ $(XTOBJ) @@ -166,6 +184,11 @@ libivy.so.$(MAJOR).$(MINOR): $(OBJ) # $(CC) -G -Wl,-h,libivy.so.$(MAJOR) -o $@ $(OBJ) #solaris # libtool -dynamic -o $@ $(OBJ) $(PCRELIB) -lc +libgivy.so.$(MAJOR).$(MINOR): $(GOBJ) + $(CC) -shared -Wl,-soname,libgivy.so.$(MAJOR) -o $@ $(GOBJ) $(PCRELIB) +# $(CC) -G -Wl,-h,libgivy.so.$(MAJOR) -o $@ $(GOBJ) #solaris +# libtool -dynamic -o $@ $(GOBJ) $(PCRELIB) -lc + libxtivy.so.$(MAJOR).$(MINOR): $(XTOBJ) $(CC) -shared -Wl,-soname,libxtivy.so.$(MAJOR) -o $@ $(XTOBJ) $(XTLIB) $(PCRELIB) # $(CC) -G -Wl,-h,libxtivy.so.$(MAJOR) -o $@ $(XTOBJ) $(XTLIB) #solaris @@ -190,55 +213,73 @@ clean: -rm -f $(TARGETS) $(TARGETLIBS) *.o *.a *.so *.so.* *~ installlibs: static-libs shared-libs - test -d $(PREFIX)/usr/lib || mkdirhier $(PREFIX)/usr/lib - test -d $(PREFIX)/usr/X11R6/lib || mkdirhier $(PREFIX)/usr/X11R6/lib - test -d $(PREFIX)/usr/include || mkdirhier $(PREFIX)/usr/include - install -m644 libivy.a $(PREFIX)/usr/lib - install -m644 libxtivy.a $(PREFIX)/usr/X11R6/lib - install -m644 libtclivy.a $(PREFIX)/usr/lib - install -m644 libglibivy.a $(PREFIX)/usr/lib - - install -m644 libivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib - install -m644 libxtivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/X11R6/lib - install -m644 libtclivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib - install -m644 libglibivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib - - install -m644 *.h $(PREFIX)/usr/include + test -d $(DESTDIR)$(PREFIX)$(LIB) || mkdirhier $(DESTDIR)$(PREFIX)$(LIB) + test -d $(DESTDIR)$(X11_PREFIX)$(LIB) || mkdirhier $(DESTDIR)$(X11_PREFIX)$(LIB) + + install -m644 libivy.a $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libgivy.a $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libxtivy.a $(DESTDIR)$(X11_PREFIX)$(LIB) + install -m644 libtclivy.a $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libglibivy.a $(DESTDIR)$(PREFIX)$(LIB) + + install -m644 libivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libgivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libxtivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(X11_PREFIX)$(LIB) + install -m644 libtclivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB) + install -m644 libglibivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB) + +includes: + test -d $(DESTDIR)$(PREFIX)/include/Ivy || mkdirhier $(DESTDIR)$(PREFIX)/include/Ivy + install -m644 ivy.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivybind.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivybuffer.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivychannel.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivydebug.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivyglibloop.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivyglutloop.h* $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivyloop.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivysocket.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivytcl.h* $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 ivyxtloop.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 list.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 timer.h $(DESTDIR)$(PREFIX)/include/Ivy/ + install -m644 version.h $(DESTDIR)$(PREFIX)/include/Ivy/ installliblinks: installlibs - ln -fs /usr/lib/libivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib/libivy.so - ln -fs /usr/lib/libivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib/libivy.so.$(MAJOR) - ln -fs /usr/X11R6/lib/libxtivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/X11R6/lib/libxtivy.so - ln -fs /usr/X11R6/lib/libxtivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/X11R6/lib/libxtivy.so.$(MAJOR) - ln -fs /usr/lib/libtclivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib/libtclivy.so - ln -fs /usr/lib/libtclivy.so.$(MAJOR).$(MINOR) $(PREFIX)/usr/lib/libtclivy.so.$(MAJOR) + ln -fs $(PREFIX)$(LIB)/libivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libivy.so + ln -fs $(PREFIX)$(LIB)/libivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libivy.so.$(MAJOR) + ln -fs $(PREFIX)$(LIB)/libgivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libgivy.so + ln -fs $(PREFIX)$(LIB)/libgivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libgivy.so.$(MAJOR) + ln -fs $(X11_PREFIX)$(LIB)/libxtivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(X11_PREFIX)$(LIB)/libxtivy.so + ln -fs $(X11_PREFIX)$(LIB)/libxtivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(X11_PREFIX)$(LIB)/libxtivy.so.$(MAJOR) + ln -fs $(PREFIX)$(LIB)/libtclivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libtclivy.so + ln -fs $(PREFIX)$(LIB)/libtclivy.so.$(MAJOR).$(MINOR) $(DESTDIR)$(PREFIX)$(LIB)/libtclivy.so.$(MAJOR) installbins: commands - test -d $(PREFIX)/usr/bin || mkdirhier $(PREFIX)/usr/bin - test -d $(PREFIX)/usr/X11R6/bin || mkdirhier $(PREFIX)/usr/X11R6/bin - install -m755 ivyprobe $(PREFIX)/usr/bin - #install -m755 ivyxtprobe $(PREFIX)/usr/X11R6/bin - #install -m755 ivyglibprobe $(PREFIX)/usr/bin - #install -m755 ivyglutprobe $(PREFIX)/usr/X11R6/bin + test -d $(DESTDIR)$(PREFIX)/bin || mkdirhier $(DESTDIR)$(PREFIX)/bin + install -m755 ivyprobe $(DESTDIR)$(PREFIX)/bin + #install -m755 ivyxtprobe $(DESTDIR)$(PREFIX)/bin + #install -m755 ivyglibprobe $(DESTDIR)$(PREFIX)/bin + #install -m755 ivyglutprobe $(DESTDIR)$(PREFIX)/bin installdocs: - test -d $(PREFIX)/usr/share/doc/ivy-c || mkdirhier $(PREFIX)/usr/share/doc/ivy-c - for f in `find ../doc/*.html -type f -maxdepth 1`; do \ - install -m 644 $$f $(PREFIX)/usr/share/doc/ivy-c; \ - done - test -d $(PREFIX)/usr/man/man1 || mkdirhier $(PREFIX)/usr/man/man1 - for f in `find ../doc/*.1 -type f -maxdepth 1`; do \ - install -m 644 $$f $(PREFIX)/usr/man/man1; \ - done - test -d $(PREFIX)/usr/share/doc/ivy-c/examples || mkdirhier $(PREFIX)/usr/share/doc/ivy-c/examples - install -m 644 version.h $(PREFIX)/usr/share/doc/ivy-c/copyright - install -m 644 ../examples/motifButtonIvy.c $(PREFIX)/usr/share/doc/ivy-c/examples - install -m 644 ../examples/testUnbind.c $(PREFIX)/usr/share/doc/ivy-c/examples - install -m 766 ../examples/Test.tcl $(PREFIX)/usr/share/doc/ivy-c/examples - install -m 766 ../examples/button.tk $(PREFIX)/usr/share/doc/ivy-c/examples - install -m 766 ../examples/unBind.tcl $(PREFIX)/usr/share/doc/ivy-c/examples - -install: installlibs installbins installliblinks installdocs + test -d $(DESTDIR)$(PREFIX)/share/doc/ivy-c || mkdirhier $(DESTDIR)$(PREFIX)/share/doc/ivy-c + for f in `find ../doc/*.html -type f -maxdepth 1`; do \ + install -m 644 $$f $(DESTDIR)$(PREFIX)/share/doc/ivy-c; \ + done + test -d $(DESTDIR)$(PREFIX)/man/man1 || mkdirhier $(DESTDIR)$(PREFIX)/man/man1 + for f in `find ../doc/*.1 -type f -maxdepth 1`; do \ + install -m 644 $$f $(DESTDIR)$(PREFIX)/man/man1; \ + done + test -d $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples || mkdirhier $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + install -m 644 version.h $(DESTDIR)$(PREFIX)/share/doc/ivy-c/copyright + install -m 644 ../examples/motifButtonIvy.c $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + install -m 644 ../examples/testUnbind.c $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + install -m 766 ../examples/Test.tcl $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + install -m 766 ../examples/button.tk $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + install -m 766 ../examples/unBind.tcl $(DESTDIR)$(PREFIX)/share/doc/ivy-c/examples + +install: installlibs installbins installliblinks installdocs includes rpm:: /usr/bin/rpmize diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 6c98e87..3bac78f 100755 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -17,7 +17,7 @@ MAJOR=3 -MINOR=6 +MINOR=9 RM=del #RM=rm -f XTINC = diff --git a/src/Makefile.win32 b/src/Makefile.win32 index 6e7e43c..8bcdb97 100755 --- a/src/Makefile.win32 +++ b/src/Makefile.win32 @@ -16,11 +16,14 @@ # change this in version.h too !!!! -MAJOR=4 -MINOR=0 +MAJOR=3 +MINOR=9 -PCREINC = -I "C:\Program Files\GnuWin32\include" #`pcre-config --cflags` -PCRELIB = "C:\Program Files\GnuWin32\lib\libpcre.lib" #`pcre-config --libs` +PCREINC = -I "C:\Documents and Settings\fcolin\My Documents\Visual Studio 2005\Projects\pcre-6.4\\" +PCRELIB = Debug\pcre.lib + +#PCREINC = -I "C:\Program Files\GnuWin32\include" #`pcre-config --cflags` +#PCRELIB = "C:\Program Files\GnuWin32\lib\libpcre.lib" #`pcre-config --libs` PCRE_OPT = PCRE_CASELESS REGCOMP_OPT = REG_ICASE @@ -34,61 +37,57 @@ PCREOBJ = #CC=gcc #CFLAGS = -g -Wall -CFLAGS = -DWIN32 -D_CRTDBG_MAP_ALLOC -nologo -GS -Zi -MDd #-DDEBUG +CFLAGS = /W3 /DWIN32 /D_CRT_SECURE_NO_DEPRECATE /nologo #LIBTOOL=ar q # linux and solaris #LIBTOOL=libtool -static -o -LIBTOOL=lib -nologo /out: +LIBTOOL=lib /nologo /out: #REGEXP = -DGNU_REGEXP -DREGCOMP_OPT=$(REGCOMP_OPT) # deprecated ! -REGEXP= -DUSE_PCRE_REGEX -DPCRE_OPT=$(PCRE_OPT) +REGEXP= /DUSE_PCRE_REGEX /DPCRE_OPT=$(PCRE_OPT) # on activeTCL , set #define CHANNEL to null, and add ivyloop.obj in the ivytcl target, # see below CHANNEL = -DTCL_CHANNEL_INTEGRATION - -OBJ = hash.obj ivyloop.obj timer.obj ivysocket.obj ivy.obj ivybind.obj ivyargument.obj +OBJ = intervalRegexp.obj ivyloop.obj timer.obj ivysocket.obj ivy.obj ivybuffer.obj ivybind.obj getopt.obj # WINDOWS add ivyloop.obj if TCL_CHANNEL_INTEGRATION is not set TARGETS = ivyprobe.exe ivyperf.exe -TARGETLIBS=ivy.dll +TARGETLIBS=libivy.dll .c.obj: - $(CC) $(CFLAGS) -c $*.c + $(CC) $(CFLAGS) /c $*.c all: static-libs commands shared-libs -static-libs: ivy-static.lib +static-libs: libivy.lib shared-libs: $(TARGETLIBS) commands: $(TARGETS) ivybind.obj: ivybind.c - $(CC) -c $(CFLAGS) $(REGEXP) $(PCREINC) ivybind.c + $(CC) $(CFLAGS) $(REGEXP) $(PCREINC) /c ivybind.c -ivyprobe.exe: ivyprobe.obj getopt.obj ivy.dll - $(CC) $(CFLAGS) -o $@ ivyprobe.obj getopt.obj ivy.lib wsock32.lib $(PCRELIB) +ivyprobe.exe: ivyprobe.obj libivy.lib + $(CC) $(CFLAGS) /Fe$@ ivyprobe.obj libivy.lib wsock32.lib $(PCRELIB) ivyprobe.obj : ivyprobe.c - $(CC) -c $(CFLAGS) $(REGEXP) $(PCREINC) ivyprobe.c + $(CC) $(CFLAGS) $(REGEXP) $(PCREINC) /c ivyprobe.c -ivyperf.exe: ivyperf.obj getopt.obj ivy.dll - $(CC) $(CFLAGS) -o $@ ivyperf.obj getopt.obj ivy.lib wsock32.lib $(PCRELIB) - -ivyperf.obj : ivyperf.c - $(CC) -c $(CFLAGS) $(REGEXP) $(PCREINC) ivyperf.c +ivyperf.exe: ivyperf.obj libivy.lib + $(CC) $(CFLAGS) /Fe$@ ivyperf.obj libivy.lib wsock32.lib $(PCRELIB) -ivy-static.lib: $(OBJ) +libivy.lib: $(OBJ) del /f $@ $(LIBTOOL)$@ $(OBJ) -ivy.dll: $(OBJ) - $(CC) -nologo /LD -o $@ $(OBJ) wsock32.lib $(PCRELIB) /link /debug /def:libIvy.def /version:$(MAJOR).$(MINOR) +libivy.dll: $(OBJ) + $(CC) /dll /out: $@ $(OBJ) $(PCRELIB) clean: - -del /f $(TARGETS) $(TARGETLIBS) *.obj *.a *.dll *.lib *.pdb *~ + -del /f $(TARGETS) $(TARGETLIBS) *.obj *.lib *.dll *~ diff --git a/src/hash.c b/src/hash.c deleted file mode 100755 index a8076ae..0000000 --- a/src/hash.c +++ /dev/null @@ -1,665 +0,0 @@ -/************************************************************************ - hash.c - This module maintains a hash table of key/value pairs. - Keys can be strings of any size, or numbers up to size - unsigned long (HASHKEYTYPE). - Values should be a pointer to some data you wish to store. - See hash_usage() for an example of use. - ************************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <stdarg.h> - -#include "hash.h" - -// Enums -typedef enum {FindEmpty = 0, FindExisting = 1} enumFind; - -// Structs -struct ROW -{ - HASHKEYTYPE Key; - int Type; - void * Data; -}; - -struct HASHTABLE_T -{ - int KeyIsString; - unsigned long MaxLoad; - unsigned long MaxRows; - unsigned long ItemCount; - struct ROW *Rows; -}; - -// Function prototypes -static void hash_expand(HASHTABLE OldTable); - -// Current module name (used by error processing) -static char *module = "hash"; - -// Error list -static const char *ERR_MUST_CREATE_HASH_TABLE_FIRST = "You must create the hash table before using it!"; -static const char *ERR_NOT_STRING_TABLE = "Not a string hash table!"; - -// Deleted entry indicator -static const int Empty = 0x00000000; -static const int InUse = 0x11111111; -static const int Deleted = 0xffffffff; - -// Expand the table when the usage exceeds this amount (80%) -static double LoadFactor = 0.8; - - -/************************************************************************ - ExitEarly - Quit the program early - ************************************************************************/ -static void ExitEarly(const char *strModule, const char *strFunction, const char *errmsg, ...) -{ - va_list args; - fprintf(stderr, "Error in module %s, function %s: ", strModule, strFunction); - va_start(args, errmsg); - vfprintf(stderr, errmsg, args); - va_end(args); - exit(1); -} - -/************************************************************************ - hash1 - Calculate a hash value for the desired key - ************************************************************************/ -static HASHKEYTYPE hash1(HASHKEYTYPE Key, BOOL KeyIsString) -{ - - if (!KeyIsString) - { - return Key; - } - else - { - unsigned char *s = (unsigned char *)Key; - HASHKEYTYPE h = 0; - while (*s) - h = h * 31UL + *s++; - return h ; - } -} - -/************************************************************************ - hash2 - Calculate a secondary hash value for the desired key - ************************************************************************/ -static HASHKEYTYPE hash2(HASHKEYTYPE Key, BOOL KeyIsString) -{ - return hash1(Key, KeyIsString) >> 3; -} - -/************************************************************************ - NextPrime - Return the next prime number past a certain number. - ************************************************************************/ -static unsigned long NextPrime(unsigned long NumberDesired) -{ - unsigned long i; - unsigned long HalfwayPoint; - int IsDivisible ; - - do - { - NumberDesired++; - IsDivisible = FALSE; - HalfwayPoint = NumberDesired / 2; - for (i = 2; i <= HalfwayPoint; i++) - { - if (NumberDesired % i == 0) - { - IsDivisible = TRUE; - break; - } - } - } while (IsDivisible); - - return NumberDesired; - -}; - -/************************************************************************ - hash_create - Create a new hash table - ************************************************************************/ -HASHTABLE hash_create(unsigned long InitialSize, BOOL KeyIsString) -{ - HASHTABLE table; - - // Allocate space for the hash table. - table = malloc(sizeof(*table)); - memset( table, 0, sizeof(*table) ); - - // Minimum size of hash table is 8. - if (InitialSize < 8 ) - InitialSize = 8; - - // Allocate it large enough so that it's not more than 80% full. - InitialSize = (unsigned long)(InitialSize * 1.25); - - // Allocate space for the rows in the hash table - InitialSize = NextPrime(InitialSize); - table->MaxLoad = (unsigned long)(InitialSize * LoadFactor); - table->MaxRows = InitialSize; - table->Rows = malloc(InitialSize * sizeof(struct ROW)); - table->KeyIsString = KeyIsString; - - memset( table->Rows, 0, InitialSize * sizeof(struct ROW) ); - - - return table; - -} - - -/************************************************************************ - hash_destroy - Destroy a hash table. - ************************************************************************/ -HASHTABLE hash_destroy(HASHTABLE table) -{ - char *function = "hash_destroy"; - - // Make sure the table is valid - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - // Free the rows in the table - free(table->Rows); - - // Free the table itself - free(table); - - // Return NULL - return NULL; -} - - -/************************************************************************ - FindSlot - Find a slot in the hash table, either empty or existing. - ************************************************************************/ -static int FindSlot(HASHTABLE table, HASHKEYTYPE Key, int FindMethod, HASHKEYTYPE *Slot) -{ - char *function = "FindSlot"; - HASHKEYTYPE hash = 0; - unsigned long i; - HASHKEYTYPE AddlAmt = 0; - - // Hash the key. - hash = (HASHKEYTYPE)(hash1(Key, table->KeyIsString) % table->MaxRows); - - // Perform the lookup a maximum of MaxRows times. - for (i = 0; i < table->MaxRows; i++) - { - // Are we supposed to find an empty slot or look for an existing key? - if (FindMethod == FindExisting) - { - // Look for an existing key - if (table->Rows[hash].Type == Empty) - { - // Couldn't find the key - return FALSE; - } - else if (table->Rows[hash].Type == InUse && - ( (table->KeyIsString && strcmp((char *)table->Rows[hash].Key, (char *)Key) == 0) || - (!table->KeyIsString && table->Rows[hash].Key == Key) ) ) - - { - // Found the key - *Slot = hash; - return TRUE; - } - } - else - { - // Look for an empty slot to insert the new key into - if (table->Rows[hash].Type != InUse) - { - // Found a spot - *Slot = hash; - return TRUE; - } - else if ( (table->KeyIsString && strcmp((char *)table->Rows[hash].Key, (char *)Key) == 0) || - (!table->KeyIsString && table->Rows[hash].Key == Key) ) - { - // Key already exists! - return FALSE; - } - } - - // Rehash the hash and try again. - if (AddlAmt == 0) - AddlAmt = (HASHKEYTYPE)(hash2(Key, table->KeyIsString) % (table->MaxRows >> 3) + 1); - hash = (hash + AddlAmt) % table->MaxRows; - - } - - // Searched the whole table unsuccessfully! :-O - // Should never hit this point, because the table expands when it gets too full. - ExitEarly(module, function, "Findslot failed!"); - return FALSE; -} - - -/************************************************************************ - hash_add - Add an item to a hash table. - ************************************************************************/ -BOOL hash_add(HASHTABLE table, HASHKEYTYPE Key, const void *Data) -{ - char *function = "hash_add"; - HASHKEYTYPE position; - - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - // Do not let the table become overloaded - if (table->ItemCount > table->MaxLoad) - hash_expand(table); - - // Search for an empty slot - if (FindSlot(table, Key, FindEmpty, &position)) - { - // Insert the data into the table. - table->Rows[position].Key = Key; - table->Rows[position].Type = InUse; - table->Rows[position].Data = (void *)Data; - table->ItemCount++; - return TRUE; - } - else - { - // The entry already exists! - return FALSE; - } -} - - -/************************************************************************ - hash_addstring - Add an string to a hash table. - ************************************************************************/ -BOOL hash_addstring(HASHTABLE table, char * Key, const void * Data) -{ - char *function = "hash_addstring"; - - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - if (table->KeyIsString == FALSE) - ExitEarly(module, function, ERR_NOT_STRING_TABLE); - return hash_add(table, (HASHKEYTYPE)Key, Data); -} - -/************************************************************************ - hash_remove - Remove an item from a hash table. - ************************************************************************/ -void *hash_remove(HASHTABLE table, HASHKEYTYPE Key) -{ - char *function = "hash_remove"; - void *Data; - unsigned int position; - - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - if (FindSlot(table, Key, FindExisting, &position)) - { - // Found the item, now mark it as deleted. - Data = table->Rows[position].Data; - table->Rows[position].Key = 0; - table->Rows[position].Type = Deleted; - table->Rows[position].Data = 0; - table->ItemCount--; - return Data; - } - else - { - // Couldn't find the item to remove it. - return NULL; - } -} - -/************************************************************************ - hash_lookup - Lookup an item from a hash table. - ************************************************************************/ -void *hash_lookup(HASHTABLE table, HASHKEYTYPE Key) -{ - char *function = "hash_lookup"; - HASHKEYTYPE position; - - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - if (FindSlot(table, Key, FindExisting, &position)) - return table->Rows[position].Data; - else - return NULL; -} - -/************************************************************************ - hash_exists - Returns whether or not a key exists in the table. - ************************************************************************/ -BOOL hash_exists(HASHTABLE table, HASHKEYTYPE Key) -{ - char *function = "hash_lookup"; - HASHKEYTYPE position; - - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - if (FindSlot(table, Key, FindExisting, &position)) - return TRUE; - else - return FALSE; -} - -/************************************************************************ - hash_count - Return a count of all items in the hash table - ************************************************************************/ -extern size_t hash_count(HASHTABLE table) -{ - char *function = "hash_count"; - if (table == NULL) - ExitEarly(module, function, ERR_MUST_CREATE_HASH_TABLE_FIRST); - - return table->ItemCount; -} - -/************************************************************************ - hash_expand - Expand the hash table to accommodate more entries. - ************************************************************************/ -static void hash_expand(HASHTABLE OldTable) -{ - HASHTABLE NewTable; - unsigned long i; - - // Create a new temporary table - NewTable = hash_create(OldTable->MaxRows * 2, OldTable->KeyIsString); - - // Add the data from the old table into the new table - for (i = 0; i < OldTable->MaxRows; i++) - { - if (OldTable->Rows[i].Type == InUse) - hash_add(NewTable, OldTable->Rows[i].Key, OldTable->Rows[i].Data); - } - - // Free the old table rows - free(OldTable->Rows); - - // Overlay the old table values with the temporary table values. - OldTable->MaxRows = NewTable->MaxRows; - OldTable->MaxLoad = NewTable->MaxLoad; - OldTable->ItemCount = NewTable->ItemCount; - OldTable->Rows = NewTable->Rows; - - // Destroy the temporary table - NewTable->Rows = NULL; - free(NewTable); -} - -/************************************************************************ - hash_search - Search for an item in the hashtable. - ************************************************************************/ -extern void *hash_search(HASHTABLE table, BOOL (*Search)(HASHKEYTYPE key, void *, va_list), ...) -{ - va_list args; - unsigned int i; - void *p = NULL; - - va_start(args, Search); - for (i = 0; i < table->MaxRows; i++) - { - if (table->Rows[i].Type != Deleted && - table->Rows[i].Type != Empty) - { - if (Search(table->Rows[i].Key, table->Rows[i].Data, args) != FALSE) - { - p = table->Rows[i].Data; - break; - } - } - } - va_end(args); - return p; -} - -/************************************************************************ - hash_searchwithvalist - Search for an item in the hashtable. - A va_list has already been passed in, no need to extract one. - ************************************************************************/ -extern void *hash_searchwithvalist(HASHTABLE table, BOOL (*Search)(HASHKEYTYPE key, void *, va_list), va_list args) -{ - unsigned int i; - void *p = NULL; - - for (i = 0; i < table->MaxRows; i++) - { - if (table->Rows[i].Type != Deleted && - table->Rows[i].Type != Empty) - { - if (Search(table->Rows[i].Key, table->Rows[i].Data, args) != FALSE) - { - p = table->Rows[i].Data; - break; - } - } - } - return p; -} - -/************************************************************************ - * hash_usage - Example of how to use this module. - ************************************************************************/ -struct person_t -{ - int ID; - char Name[32]; - int Age; -}; - -extern void hash_usage(void) -{ - void *table; - struct person_t *p; - struct person_t *lookup; - char *StringKey = "Lloyd"; - int NumberKey = 1234567; - - // Create some data to store - p = malloc(sizeof(*p)); - memset ( p, 0 ,sizeof( *p)); - p->ID = NumberKey; - p->Age = 20; - sprintf(p->Name, StringKey); - - // Numeric hash example - - // Create the hash table - table = hash_create(10, FALSE); - - // Add a key/value pair to the table - if (hash_add(table, p->ID, p) == FALSE) - printf("Entry already exists!"); - - // Lookup a key/value pair in the table - if ((lookup = hash_lookup(table, NumberKey)) == FALSE) - printf("Entry not found!"); - else - printf("Person found by ID: %d. Name is: %s\n", lookup->ID, lookup->Name); - - // Remove a key/value pair from the table - if ((lookup = hash_remove(table, NumberKey)) == FALSE) - printf("Entry not found!"); - else - // you COULD free lookup here, but we're not done with it. - ; - - // Free the table. - table = hash_destroy(table); - - - // String hash example - - // Create the hash table - table = hash_create(10, TRUE); - - // Add a key/value pair to the table - if (hash_add(table, (HASHKEYTYPE)p->Name, p) == FALSE) - printf("Entry already exists!"); - - // Lookup a key/value pair in the table - if ((lookup = hash_lookup(table, (HASHKEYTYPE)StringKey)) == FALSE) - printf("Entry not found!"); - else - printf("Person found by name: %s. ID is: %d\n", lookup->Name, lookup->ID); - - // Remove a key/value pair from the table - if ((lookup = hash_remove(table, (HASHKEYTYPE)StringKey)) == FALSE) - printf("Entry not found!"); - else - free(lookup); - - // Free the table. - table = hash_destroy(table); -} - -/************************************************************************ - hash_test - Test the hash table. - ************************************************************************/ -static BOOL Search(HASHKEYTYPE key, void *p, va_list args) -{ - char *s = p; - char *find = va_arg(args, char *); - if (strcmp(s, find) == 0) - return TRUE; - else - return FALSE; -} - -static BOOL Iterate(HASHKEYTYPE key, void *p, va_list args) -{ - // Just iterate a counter. - unsigned int *i = va_arg(args, unsigned int *); - *i = *i + 1; - // Return false to keep searching. - return FALSE; -} - -extern BOOL hash_test(void) -{ - HASHTABLE table; - HASHTABLE strings; - int i; - int max = 1000000; - clock_t start; - char **s; - char temp[80]; - char *fmt = "\t%-8s %4d milliseconds, %8d per second.\n"; - unsigned int ctr = 0; - - // Logical tests - table = hash_create(8, FALSE); - if (hash_add(table, 0, &table) == FALSE) return FALSE; - if (hash_add(table, 1, &table) == FALSE) return FALSE; - if (hash_add(table, 0xffffffff, &table) == FALSE) return FALSE; - - strings = hash_create(8, TRUE); - if (hash_add(strings, (HASHKEYTYPE)"test1", &strings) == FALSE) return FALSE; - if (hash_add(strings, (HASHKEYTYPE)"test2", &strings) == FALSE) return FALSE; - if (hash_add(strings, (HASHKEYTYPE)"test3", &strings) == FALSE) return FALSE; - - if (hash_lookup(table, 0) != &table) return FALSE; - if (hash_lookup(table, 1) != &table) return FALSE; - if (hash_lookup(table, 0xffffffff) != &table) return FALSE; - - if (hash_lookup(strings, (HASHKEYTYPE)"test1") != &strings) return FALSE; - if (hash_lookup(strings, (HASHKEYTYPE)"test2") != &strings) return FALSE; - if (hash_lookup(strings, (HASHKEYTYPE)"test3") != &strings) return FALSE; - - if (hash_remove(strings, (HASHKEYTYPE)"test1") != &strings) return FALSE; - if (hash_lookup(strings, (HASHKEYTYPE)"test1") != FALSE) return FALSE; - - if (hash_destroy(table) != NULL) return FALSE; - if (hash_destroy(strings) != NULL) return FALSE; - - - // Stress tests for numbers - printf("HASH Numeric Tests for %d items\n", max); - table = hash_create(max, FALSE); - - start = clock(); - for (i = 0; i < max; i++) - hash_add(table, i, &table); - printf(fmt, "Adds:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - - start = clock(); - for (i = 0; i < max; i++) - if (hash_lookup(table, i) != &table) - break; - printf(fmt, "Lookups:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - - start = clock(); - for (i = 0; i < max; i++) - if (hash_remove(table, i) != &table) - break; - printf(fmt, "Deletes:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - if (hash_count(table) != 0) - return FALSE; - table = hash_destroy(table); - - // Stress tests for strings - printf("HASH strings Tests for %d items\n", max); - table = hash_create(max, TRUE); - s = malloc(sizeof(*s) * max); - memset ( s, 0 ,sizeof( *s)*max); - - for (i = 0; i < max; i++) - { - sprintf(temp, "Item %d", i); - s[i] = strdup(temp); - } - - start = clock(); - for (i = 0; i < max; i++) - hash_add(table, (HASHKEYTYPE)s[i], s[i]); - printf(fmt, "Adds:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - - start = clock(); - for (i = 0; i < max; i++) - if (hash_lookup(table, (HASHKEYTYPE)s[i]) != s[i]) - break; - printf(fmt, "Lookups:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - - // Test searching - if (hash_search(table, Search, "Item 271") != s[271]) - return FALSE; - if (hash_search(table, Search, "Not Found") != FALSE) - return FALSE; - - // Test iterating - ctr = 0; - start = clock(); - hash_search(table, Iterate, &ctr); - printf(fmt, "Iterate:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - printf("\t\t(Ctr is %u)\n", ctr); - - // Test deleting - start = clock(); - for (i = 0; i < max; i++) - if (hash_remove(table, (HASHKEYTYPE)s[i]) != s[i]) - break; - printf(fmt, "Deletes:", clock() - start, (max * CLOCKS_PER_SEC)/(clock() - start)); - if (hash_count(table) != 0) - return FALSE; - table = hash_destroy(table); - - // Free the test strings - for (i = 0; i < max; i++) - free(s[i]); - - - return TRUE; -} - - diff --git a/src/hash.h b/src/hash.h deleted file mode 100755 index 4ea7731..0000000 --- a/src/hash.h +++ /dev/null @@ -1,29 +0,0 @@ -/************************************************************************ - hash.h - ************************************************************************/ -#ifndef HASH_H -#define HASH_H - - -typedef unsigned int HASHKEYTYPE; -typedef struct HASHTABLE_T *HASHTABLE; -typedef int BOOL; - -#define FALSE 0 -#define TRUE 1 - -extern void hash_usage (void); -extern BOOL hash_test (void); -extern HASHTABLE hash_create (unsigned long InitialSize, BOOL KeyIsString); -extern HASHTABLE hash_destroy (HASHTABLE table); -extern BOOL hash_add (HASHTABLE table, HASHKEYTYPE Key, const void *Data); -extern BOOL hash_addstring (HASHTABLE table, char * Key, const void * Data); -extern void * hash_remove (HASHTABLE table, HASHKEYTYPE Key); -extern void * hash_lookup (HASHTABLE table, HASHKEYTYPE Key); -extern size_t hash_count (HASHTABLE table); -extern void * hash_search (HASHTABLE table, BOOL (*Search)(HASHKEYTYPE key, void *, va_list), ...); -extern void * hash_searchwithvalist(HASHTABLE table, BOOL (*Search)(HASHKEYTYPE key, void *, va_list), va_list args); -extern BOOL hash_exists (HASHTABLE table, HASHKEYTYPE Key); - - -#endif diff --git a/src/intervalRegexp.c b/src/intervalRegexp.c new file mode 100644 index 0000000..0132fce --- /dev/null +++ b/src/intervalRegexp.c @@ -0,0 +1,432 @@ +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include "intervalRegexp.h" + +#ifdef __PRETTY_FUNCTION__ +#else +#define __PRETTY_FUNCTION__ __FUNCTION__ +#endif + + +#define MAXINT( a , b ) ((a) > (b) ? (a) : (b)) +#define MININT( a , b ) ((a) < (b) ? (a) : (b)) + +#define Perr(...) (perr ( __PRETTY_FUNCTION__, __VA_ARGS__)) +#define CHECK_AND_RETURN(a) if (strlen (locBuf) <= buflen) { \ + strcpy (a, locBuf); \ + return success; \ + } else { \ + return Perr ("CHECK_AND_RETURN"); } + +#define EndLocBuf (&(locBuf[strlen(locBuf)])) +#ifdef WIN32 +#define snprintf _snprintf +#endif +#define AddLocBuf(...) snprintf (EndLocBuf, sizeof (locBuf)-strlen(locBuf), __VA_ARGS__) + +typedef struct { + int max; + int rank; +} NextMax ; + + +typedef char bool; + +const bool success = 1; +const bool fail = 0; + + +static bool strictPosRegexpGen (char *regexp, size_t buflen, long min, long max, const char* decimalPart, + const char* boundDecimalPart); +static bool genAtRank (char *regexp, size_t buflen, const char *min, const char *max, int rank); +static bool genPreRank (char *preRank, size_t buflen, const char *min, const char *max, int rank); +static bool genRank (char *outRank, size_t buflen, const char *min, const char *max, int rank); +static bool genPostRank (char *postRank, size_t buflen, int rank); +static bool substr (char *substring, size_t buflen, const char* expr, size_t pos, size_t len); +static char* reverse (char *string); +static char* longtoa (char *string, size_t buflen, long n); +static NextMax nextMax (const char *min, const char *max); +static bool perr (const char* func, const char *fmt, ...); + + + +/* +# __ _ _ __ _____ +# / _` | | '_ \ / ____| +# _ __ ___ | (_| | ___ __ __ | |_) | | | __ ___ _ __ +# | '__| / _ \ \__, | / _ \ \ \/ / | .__/ | | |_ | / _ \ | '_ \ +# | | | __/ __/ | | __/ > < | | | |__| | | __/ | | | | +# |_| \___| |___/ \___| /_/\_\ |_| \_____| \___| |_| |_| +*/ +int regexpGen (char *regexp, size_t buflen, long min, long max, int flottant) +{ + char *decimalPart = ""; + char *boundDecimalPart = ""; + char locBuf [8192] = "(?:"; + + + if (flottant) { + decimalPart = "(?:\\.\\d+)?"; + boundDecimalPart = "(?:\\.0+)?"; + } + + if (min > max) { + int nmin = max; + max = min; + min = nmin; + } + + if (min == max) { + AddLocBuf ("%ld%s", min, decimalPart); + } else if (min < 0) { + if (max < 0) { + // reg = '\-(?:' . strictPosRegexpGen (-max, -min, decimalPart, boundDecimalPart). ')'; + AddLocBuf ("\\-(?:"); + if (strictPosRegexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), -min, -max, decimalPart, + boundDecimalPart) == fail) return fail; + AddLocBuf (")"); + } else if (max == 0) { + AddLocBuf ("(?:0%s)|(?:-0%s)|-(?:", boundDecimalPart, decimalPart); + if (strictPosRegexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), 1, -min, decimalPart, + boundDecimalPart)== fail) return fail; + AddLocBuf (")"); + } else { + //reg ='(?:' . regexpGen (min, 0,withDecimal) . '|' . regexpGen (0, max, withDecimal). ')' ; + AddLocBuf ("(?:"); + if (regexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), min, 0, flottant)== fail) return fail; + AddLocBuf ("|"); + if (regexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), 0, max, flottant)== fail) return fail; + AddLocBuf (")"); + } + } else if (min == 0) { + // reg = "(?:0{decimalPart})|" . strictPosRegexpGen (1, max, decimalPart,boundDecimalPart) ; + AddLocBuf ("(?:0%s)|",decimalPart); + if (strictPosRegexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), 1, max, decimalPart, + boundDecimalPart)== fail) return fail; + } else { + if (strictPosRegexpGen (EndLocBuf, sizeof (locBuf)-strlen(locBuf), min, max, decimalPart, + boundDecimalPart)== fail) return fail; + } + + AddLocBuf (")(?![\\d.])"); + CHECK_AND_RETURN (regexp); +} + +/* +# _ _ _ _____ +# | | (_) | | | __ \ +# ___ | |_ _ __ _ ___ | |_ | |__) | ___ ___ +# / __| | __| | '__| | | / __| | __| | ___/ / _ \ / __| +# \__ \ \ |_ | | | | | (__ \ |_ | | | (_) | \__ \ +# |___/ \__| |_| |_| \___| \__| |_| \___/ |___/ +# _____ __ _ _ __ _____ +# | __ \ / _` | | '_ \ / ____| +# | |__) | ___ | (_| | ___ __ __ | |_) | | | __ ___ _ __ +# | _ / / _ \ \__, | / _ \ \ \/ / | .__/ | | |_ | / _ \ | '_ \ +# | | \ \ | __/ __/ | | __/ > < | | | |__| | | __/ | | | | +# |_| \_\ \___| |___/ \___| /_/\_\ |_| \_____| \___| |_| |_| +*/ +static bool strictPosRegexpGen (char *regexp, size_t buflen, long min, long max, const char* decimalPart, + const char* boundDecimalPart) +{ + +#define maxSubReg 64 +#define digitRegSize 128 + + char regList[maxSubReg][digitRegSize]; + char locBuf[maxSubReg*digitRegSize] ; + size_t regIndex=0,i; + size_t nbRank; + char maxAsString[32], minAsString[32]; + NextMax nMax; + + + if ((min <= 0) || (max <= 0)) return Perr ("min or max <= 0"); + if (min == max) { + sprintf (EndLocBuf, "%ld", max); + } else { + + max--; + + nbRank = strlen (longtoa (maxAsString, sizeof (maxAsString), max)); + do { + nMax = nextMax (longtoa (minAsString, sizeof (minAsString), min), + longtoa (maxAsString, sizeof (maxAsString), max)); + if (genAtRank (regList[regIndex++], digitRegSize, minAsString, + longtoa (maxAsString, sizeof (maxAsString), + nMax.max), nMax.rank) == fail) return fail; + if (regIndex == maxSubReg) return Perr ("regIndex == maxSubReg"); + min = nMax.max +1; + } while (nMax.max != max); + + locBuf[0] = 0; + for (i=0; i<regIndex; i++) { + sprintf (EndLocBuf, "(?:%s%s)|", regList[i], decimalPart); + } + + if (locBuf[strlen(locBuf)-1] == '|') { + locBuf[strlen(locBuf)-1] = 0; + } + max++; + sprintf (EndLocBuf, "|(?:%s%s)", + longtoa (maxAsString, sizeof (maxAsString), max), boundDecimalPart); + } + + CHECK_AND_RETURN (regexp); +} + +/* +# _ __ __ +# | | | \/ | +# _ __ ___ __ __ | |_ | \ / | __ _ __ __ +# | '_ \ / _ \ \ \/ / | __| | |\/| | / _` | \ \/ / +# | | | | | __/ > < \ |_ | | | | | (_| | > < +# |_| |_| \___| /_/\_\ \__| |_| |_| \__,_| /_/\_\ +*/ +static NextMax nextMax (const char *min, const char *max) +{ + NextMax nextMax ={0,0}; + char revMin[32], revMax[32]; + size_t nbDigitsMin, nbDigitsMax; + size_t rankRev=0, rankForw, rank=0; + int i; + int currMax; + + nbDigitsMin = strlen (min); + nbDigitsMax = strlen (max); + + for (i=nbDigitsMin-1; i >= 0; i--) { + revMin[nbDigitsMin-i-1]= min[i]; + // printf ("DBG> nextMax revMin[%d]= %c\n", nbDigitsMin-i-1, min[i]); + } + for (i=nbDigitsMax-nbDigitsMin; i >= 0; i--) { + revMin[nbDigitsMax-i]= '0'; + // printf ("DBG> nextMax revMin[%d]= %c\n", nbDigitsMax-i, '0'); + } + + for (i=nbDigitsMax-1; i >= 0; i--) { + revMax[nbDigitsMax-i-1]= max[i]; + } + revMin[nbDigitsMax] = revMax[nbDigitsMax] = 0; + rankForw = nbDigitsMax -1; + + // printf ("DBG> nextMax rev(%s)=%s rev(%s)=%s rankForw=%d\n", min, revMin, max, revMax, rankForw); + + // en partant des unitées (digit de poids faible), premier digit de min != 0 + while ((revMin[rankRev] == '0') && (rankRev < nbDigitsMax)) rankRev++; + // en partant du digit de poids fort, premier digit de max != du même digit de revMin + while ((revMin[rankForw] == revMax[rankForw]) && rankForw > 0) rankForw--; + + if (rankForw <= rankRev) { + rank = rankForw; + revMin[rankForw]= revMax[rankForw] - (rankForw ? 1 : 0); + for (i=0; i<rankForw; i++) revMin[i] = '9'; + } else { + rank = rankRev; + for (i=0; i<=rankRev; i++) revMin[i] = '9'; + } + + nextMax.max = atoi (reverse (revMin)); + nextMax.rank = rank+1; + + currMax = atoi (max); + if (nextMax.max > currMax) nextMax.max = currMax; + + // printf ("DBG> nextMax ('%s', '%s') = %d@%d\n", min, max, nextMax.max, nextMax.rank); + return (nextMax); +} + + +/* +# __ _ ____ _ +# / _` | / __ \ | | +# | (_| | ___ _ __ / / _` | _ __ __ _ _ __ | | _ +# \__, | / _ \ | '_ \ | | (_| | | '__| / _` | | '_ \ | |/ / +# __/ | | __/ | | | | \ \__,_| | | | (_| | | | | | | < +# |___/ \___| |_| |_| \____/ |_| \__,_| |_| |_| |_|\_\ +*/ +static bool genAtRank (char *regexp, size_t buflen, const char *min, const char *max, int rank) +{ + char locBuf [512]; + + if (genPreRank (locBuf, sizeof (locBuf), min, max, rank) == fail) return (fail); + if (genRank (EndLocBuf, sizeof (locBuf)-strlen(locBuf), min, max, rank) == fail) return (fail); + if (genPostRank (EndLocBuf, sizeof (locBuf)-strlen(locBuf), rank) == fail) return (fail); + + + CHECK_AND_RETURN (regexp); +} + +/* +# __ _ _____ _____ _ +# / _` | | __ \ | __ \ | | +# | (_| | ___ _ __ | |__) | _ __ ___ | |__) | __ _ _ __ | | _ +# \__, | / _ \ | '_ \ | ___/ | '__| / _ \ | _ / / _` | | '_ \ | |/ / +# __/ | | __/ | | | | | | | | | __/ | | \ \ | (_| | | | | | | < +# |___/ \___| |_| |_| |_| |_| \___| |_| \_\ \__,_| |_| |_| |_|\_\ +*/ +static bool genPreRank (char *preRank, size_t buflen, const char *min, const char *max, int rank) +{ + char locBuf [512], locBufMax[512]; + const char *lmin, *lmax; + int i=0, j=0; + + while (min[i] == '0') i++; + while (max[j] == '0') j++; + + lmin = &(min[i]); + lmax = &(max[j]); + + // printf ("DBG> genPreRank (lmin='%s'[%d], lmax='%s'[%d], rank=%d\n", lmin, (int) strlen (lmin), lmax, + // (int) strlen (lmax), rank); + + if (substr (locBuf, sizeof (locBuf), lmin, 0, strlen (lmin) - rank) == fail) return fail; + if (substr (locBufMax, sizeof (locBufMax), lmax, 0, strlen (lmax) - rank) == fail) return fail; + + if (strncmp (locBuf, locBufMax, MININT (sizeof (locBuf), sizeof (locBufMax))) != 0) + return Perr ("min=%s[%s] and max=%s[%s] should be invariants at rank %d", locBuf, min, locBufMax, max, rank); + + // printf ("DBG> genPreRank ('%s', '%s', %d) = '%s'\n", min, max, rank, locBuf); + + CHECK_AND_RETURN (preRank); +} + + +/* +# __ _ _____ _ +# / _` | | __ \ | | +# | (_| | ___ _ __ | |__) | __ _ _ __ | | _ +# \__, | / _ \ | '_ \ | _ / / _` | | '_ \ | |/ / +# __/ | | __/ | | | | | | \ \ | (_| | | | | | | < +# |___/ \___| |_| |_| |_| \_\ \__,_| |_| |_| |_|\_\ +*/ +static bool genRank (char *outRank, size_t buflen, const char *min, const char *max, int rank) +{ + char locBuf [512]; + + char a,b,lmin,lmax; + a = min[strlen(min)-rank]; + b = max[strlen(max)-rank]; + + lmin = MININT (a,b); + lmax = MAXINT (a,b); + + if ((lmin == '0') && (lmax == '9')) { + strcpy (locBuf, "\\d"); + } else if (lmin == lmax) { + locBuf[0] = lmin; + locBuf[1] = 0; + } else if (lmax == (lmin+1)) { + sprintf (locBuf, "[%c%c]", lmin, lmax); + } else { + sprintf (locBuf, "[%c-%c]", lmin, lmax); + } + + CHECK_AND_RETURN (outRank); +} + +/* +# __ _ _____ _ _____ +# / _` | | __ \ | | | __ \ +# | (_| | ___ _ __ | |__) | ___ ___ | |_ | |__) | __ _ _ __ +# \__, | / _ \ | '_ \ | ___/ / _ \ / __| | __| | _ / / _` | | '_ \ +# __/ | | __/ | | | | | | | (_) | \__ \ \ |_ | | \ \ | (_| | | | | | +# |___/ \___| |_| |_| |_| \___/ |___/ \__| |_| \_\ \__,_| |_| |_| +*/ +static bool genPostRank (char *postRank, size_t buflen, int rank) +{ + char locBuf [512]; + + if (rank <= 1) { + strcpy (locBuf, ""); + } else if (rank == 2) { + sprintf (locBuf, "\\d"); + } else { + sprintf (locBuf, "\\d{%d}", rank -1); + } + + CHECK_AND_RETURN (postRank); +} + +/* +# _ _ +# | | | | +# ___ _ _ | |__ ___ | |_ _ __ +# / __| | | | | | '_ \ / __| | __| | '__| +# \__ \ | |_| | | |_) | \__ \ \ |_ | | +# |___/ \__,_| |_.__/ |___/ \__| |_| +*/ +static bool substr (char *substring, size_t buflen, const char* expr, size_t pos, size_t len) +{ + char locBuf [512]; + size_t i, j=0; + + len = MAXINT (0, MININT (len, strlen (expr) - pos)); + for (i=pos; i<(pos+len); i++) { + locBuf[j++]= expr[i]; + } + locBuf[j] = 0; + + // printf ("DBG> substr ('%s', %d, %d) = '%s'\n", expr, pos, len, locBuf); + CHECK_AND_RETURN (substring); +} + +/* +# +# +# _ __ ___ __ __ ___ _ __ ___ ___ +# | '__| / _ \ \ \ / / / _ \ | '__| / __| / _ \ +# | | | __/ \ V / | __/ | | \__ \ | __/ +# |_| \___| \_/ \___| |_| |___/ \___| +*/ +static char* reverse (char *string) +{ + char *locBuf ; + int i; + size_t len = strlen (string); + + locBuf = malloc (len+1); + for (i=len-1; i >= 0; i--) { + locBuf[len-i-1]= string[i]; + //printf ("DBG> reverse locBuf[%d]= %c\n",len- i-1, string[i]); + } + locBuf [len] = 0; + + // printf ("DBG> reverse '%s' = '%s'\n", string, locBuf); + strcpy (string, locBuf); + free (locBuf); + return (string); +} + +static char* longtoa (char *string, size_t buflen, long n) +{ + snprintf (string, buflen, "%ld", n); + return (string); +} + + +/* +# _ __ +# | '_ \ +# | |_) | ___ _ __ _ __ +# | .__/ / _ \ | '__| | '__| +# | | | __/ | | | | +# |_| \___| |_| |_| +*/ +static bool perr (const char* func, const char *fmt, ...) +{ + char err[4096], buffer[2048]; + va_list args; + va_start( args, fmt ); + vsprintf( buffer, fmt, args ); + va_end( args ); + + + sprintf (err, "Erreur %s @ %s\n", buffer, func); + fprintf (stderr, err); + return (fail); +} diff --git a/src/intervalRegexp.h b/src/intervalRegexp.h new file mode 100644 index 0000000..a5ca2e3 --- /dev/null +++ b/src/intervalRegexp.h @@ -0,0 +1,14 @@ +#ifndef INTERVALREGEXP_H +#define INTERVALREGEXP_H + +#ifdef __cplusplus +extern "C" { +#endif + +int regexpGen (char *regexp, size_t buflen, long min, long max, int flottant); + +#ifdef __cplusplus +} +#endif + +#endif @@ -7,8 +7,7 @@ * * Main functions * - * Authors: Francois-Regis Colin <fcolin@cena.fr> - * Stephane Chatty <chatty@cena.fr> + * Authors: Francois-Regis Colin,Stephane Chatty * * $Id$ * @@ -16,31 +15,37 @@ * copyright notice regarding this software */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include <fcntl.h> +#include <stdlib.h> #ifdef WIN32 -#include <crtdbg.h> #include <windows.h> #else -#include <arpa/inet.h> #include <sys/time.h> -#include <unistd.h> -#include <netdb.h> +#include <arpa/inet.h> #endif +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <fcntl.h> + +#include "intervalRegexp.h" #include "ivychannel.h" -#include "ivybind.h" #include "ivysocket.h" #include "list.h" -#include "hash.h" +#include "ivybuffer.h" +#include "ivydebug.h" +#include "ivybind.h" #include "ivy.h" -#define VERSION 4 +#define VERSION 3 + +#define MAX_MATCHING_ARGS 40 + +#define ARG_START "\002" +#define ARG_END "\003" + #define DEFAULT_DOMAIN 127.255.255.255 /* stringification et concatenation du domaine et du port en 2 temps : @@ -50,37 +55,28 @@ #define GenerateIvyBus(domain,bus) str(domain)":"str(bus) static char* DefaultIvyBus = GenerateIvyBus(DEFAULT_DOMAIN,DEFAULT_BUS); -/* syntaxe des messages */ -#define MSGTYPE 0 -#define MSGID 1 -#define ARG_0 2 - 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 */ + 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 */ - Ping = 9, /* checks the presence of the other */ - Pong = 10, /* checks the presence of the other */ - AddBinding = 11, /* other methods for binding message based on hash table */ - DelBinding = 12, /* other methods for binding message based on hash table */ - ApplicationId = 13, /* on start send my ID and priority */ - + DirectMsg, /* message direct a destination de l'appli */ + Die, /* demande de terminaison de l'appli */ + Ping, /* message de controle ivy */ + Pong /* ivy doit renvoyer ce message à la reception d'un ping */ } MsgType; typedef struct _msg_snd *MsgSndPtr; struct _msg_rcv { /* requete d'emission d'un client */ - IvyBindingType type; + MsgRcvPtr next; int id; - char *regexp; /* regexp du message a recevoir */ - MsgCallback callback; /* callback a declanche a la reception */ + const char *regexp; /* regexp du message a recevoir */ + MsgCallback callback; /* callback a declanche a la reception */ void *user_data; /* stokage d'info client */ }; @@ -88,7 +84,7 @@ struct _msg_snd { /* requete de reception d'un client */ MsgSndPtr next; int id; char *str_regexp; /* la regexp sous forme inhumaine */ - IvyBinding bind; + IvyBinding binding; /* la regexp sous forme machine */ }; struct _clnt_lst { @@ -96,11 +92,12 @@ struct _clnt_lst { Client client; /* la socket client */ MsgSndPtr msg_send; /* liste des requetes recues */ char *app_name; /* nom de l'application */ - char *app_id; /* identificateur unique de l'application (time-ip-port) */ - int priority; /* client priority */ unsigned short app_port; /* port de l'application */ }; +/* flag pour le debug en cas de Filter de regexp */ +int debug_filter = 0; + /* server pour la socket application */ static Server server; @@ -114,17 +111,19 @@ static unsigned short SupervisionPort; static Client broadcast; static const char *ApplicationName = 0; +static const char *ApplicationID = 0; + /* callback appele sur reception d'un message direct */ static MsgDirectCallback direct_callback = 0; static void *direct_user_data = 0; /* callback appele sur changement d'etat d'application */ -static IvyApplicationCallback application_callback = 0; +static IvyApplicationCallback application_callback; static void *application_user_data = 0; /* callback appele sur ajout suppression de regexp */ -static IvyBindCallback application_bind_callback = 0; +static IvyBindCallback application_bind_callback; static void *application_bind_data = 0; /* callback appele sur demande de terminaison d'application */ @@ -132,241 +131,114 @@ static IvyDieCallback application_die_callback; static void *application_die_user_data = 0; /* liste des messages a recevoir */ -//static MsgRcvPtr msg_recv = 0; -static HASHTABLE msg_recv= NULL; - +static MsgRcvPtr msg_recv = 0; /* liste des clients connectes */ static IvyClientPtr clients = 0; static const char *ready_message = 0; +static void substituteInterval (IvyBuffer *src); -static char *applicationUniqueId = 0; -static int applicationPriority = DEFAULT_PRIORITY; - -/* get Current Time in milliseconds */ -static long currentTime() -{ - unsigned long current; -#ifdef WIN32 - current = GetTickCount(); -#else - struct timeval stamp; - gettimeofday( &stamp, NULL ); - current = stamp.tv_sec * 1000 + stamp.tv_usec/1000; -#endif - return current; -} - - -// fonction de formtage a la printf d'un buffer avec reallocation dynamique -#define MESSAGE_SIZE 4096 /* taille buffer initiale on multiple pas deux a chaque realloc */ - -static int make_message(char ** buffer, int *size, int offset, const char *fmt, va_list ap) -{ - /* Guess we need no more than BUFFER_INIT_SIZE bytes. */ - long n; - if ( *size == 0 || *buffer == NULL ) - { - *size = MESSAGE_SIZE; - *buffer = malloc (MESSAGE_SIZE); - if ( *buffer == NULL ) - return -1; - } - while (1) { - /* Try to print in the allocated space. */ -#ifdef WIN32 - n = _vsnprintf (*buffer + offset, *size - offset, fmt, ap); -#else - n = vsnprintf (*buffer + offset, *size - offset, fmt, ap); -#endif - /* If that worked, return the string size. */ - if (n > -1 && n < *size) - return n; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - *size = n+1; /* precisely what is needed */ - else /* glibc 2.0 */ - *size *= 2; /* twice the old size */ - if ((*buffer = realloc (*buffer, *size)) == NULL) - return -1; - } -} - -static char *DupArg( int len, void *s) -{ - char *ptr; - ptr = malloc( len+1 ); - if (!ptr ) - { - fprintf(stderr,"DupArg Buffer Memory Alloc Error\n"); - exit(-1); - } - memcpy( ptr, s, len ); - ptr[len] = '\0'; - return ptr; -} -/* returns < 0 if *p sorts lower than *q */ -static int keycmp (IvyClientPtr p, IvyClientPtr q) -{ - return p->priority - q->priority; -} - -/* merge 2 lists under dummy head item */ -static IvyClientPtr lmerge (IvyClientPtr p, IvyClientPtr q) -{ - IvyClientPtr r; - struct _clnt_lst head; - - for ( r = &head; p && q; ) - { - if ( keycmp(p, q) < 0 ) - { - r = r->next = p; - p = p->next; - } - else - { - r = r->next = q; - q = q->next; - } - } - r->next = (p ? p : q); - return head.next; -} - -/* split list into 2 parts, sort each recursively, merge */ -static IvyClientPtr lsort (IvyClientPtr p) -{ - IvyClientPtr q, r; - - if ( p ) - { - q = p; - for ( r = q->next; r && (r = r->next) != NULL; r = r->next ) - q = q->next; - r = q->next; - q->next = NULL; - if ( r ) - p = lmerge(lsort(r), lsort(p)); - } - return p; -} - - -static void SortClients() -{ - // sort client list again priority! - lsort( clients ); -} -static void MsgSendTo( Client client, MsgType msgtype, int id, int len_arg, const void *arg ) +/* + * function like strok but do not eat consecutive separator + * */ +static char * nextArg( char *s, const char *separator ) { - unsigned short header[3]; - -#ifdef DEBUG - printf( "Sending message type=%d id=%d '%.*s'\n",msgtype,id,len_arg,(char*)arg); -#endif - header[0] = htons( (unsigned short)msgtype ); - header[1] = htons( (unsigned short)id ); - header[2] = htons( (unsigned short)len_arg ); - SocketSend( client, (char *)header, sizeof(header) ); - if ( len_arg ) + static char *start = NULL; + static char *end = NULL; + if ( s ) { - SocketSend( client, arg, len_arg ); + end = s; } - SocketFlush( client ); -} - -static int MsgSendCallTo (Client client, const char *message, MsgSndPtr msg ) -{ - void * buffer = NULL; - int buf_len = 0; - int len; - IvyArgument args; - - - int rc = IvyBindingExec( msg->bind, message ); - - if (rc<1) return 0; /* no match */ -#ifdef DEBUG - printf( "Sending message id=%d '%s'\n",msg->id,message); -#endif - // il faut essayer d'envoyer le message en une seule fois sur la socket - // pour eviter au maximun de passer dans le select plusieur fois par message du protocole Ivy - // pour eviter la latence ( PB de perfo detecte par ivyperf ping roudtrip ) + start = end; -#ifdef DEBUG - printf( "Send matching args count %d\n",rc); -#endif - args = IvyBindingMatch( msg->bind, message ); - /* serialize into buffer */ - len = IvyArgumentSerialize(args, &buf_len, &buffer, 0); - - MsgSendTo( client, Msg, msg->id, len, buffer ); - IvyArgumentFree( args ); /* TODO supress malloc /free */ - free( buffer ); - return 1; + while ( *end && *end != *separator ) + end++; + if ( *end == *separator ) *end++ = '\0'; + if ( end == start ) return NULL; + return start; } -static BOOL RemoveBinding(HASHKEYTYPE key, void *data, va_list args) +static int MsgSendTo( Client client, MsgType msgtype, int id, const char *message ) { - MsgRcvPtr msg = (MsgRcvPtr)data; - free( msg->regexp ); - free ( msg ); - return FALSE; /* iter throught all hash table */ + return SocketSend( client, "%d %d" ARG_START "%s\n", msgtype, id, message); } + static void IvyCleanup() { IvyClientPtr clnt,next; - MsgSndPtr msg,msg_next; + /* destruction des connexions clients */ IVY_LIST_EACH_SAFE( clients, clnt, next ) { /* on dit au revoir */ - MsgSendTo( clnt->client, Bye, 0, 0, "" ); + MsgSendTo( clnt->client, Bye, 0, "" ); SocketClose( clnt->client ); - IVY_LIST_EACH_SAFE( clnt->msg_send, msg, msg_next ) - { - free( msg->str_regexp ); - IvyBindingFree( msg->bind ); - } IVY_LIST_EMPTY( clnt->msg_send ); } IVY_LIST_EMPTY( clients ); - /* destruction de mes bindings */ - hash_search( msg_recv, RemoveBinding); - hash_destroy( msg_recv ); - free( applicationUniqueId ); + /* destruction des sockets serveur et supervision */ SocketServerClose( server ); SocketClose( broadcast ); } -static int ClientCall (IvyClientPtr clnt, const char *message) +static int MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) +{ + int waiting = 0; + static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + int err; + int index; + int arglen; + const char *arg; + + int rc= IvyBindingExec( msg->binding, message ); + + if (rc<1) return 0; /* no match */ + + TRACE( "Sending message id=%d '%s'\n",msg->id,message); + + buffer.offset = 0; + // il faut essayer d'envoyer le message en une seule fois sur la socket + // pour eviter au maximun de passer dans le select plusieur fois par message du protocole Ivy + // pour eviter la latence ( PB de perfo detecte par ivyperf ping roudtrip ) + err = make_message_var( &buffer, "%d %d" ARG_START ,Msg, msg->id); + + TRACE( "Send matching args count %d\n",rc); + + for( index=1; index < rc ; index++ ) + { + IvyBindingMatch( msg->binding, message, index, &arglen, & arg ); + err = make_message_var( &buffer, "%.*s" ARG_END , arglen, arg ); + } + err = make_message_var( &buffer, "\n"); + waiting = SocketSendRaw(client->client, buffer.data , buffer.offset); + if ( waiting ) + fprintf(stderr, "Ivy: Slow client : %s\n", client->app_name ); + return 1; +} + + +static int +ClientCall (IvyClientPtr clnt, const char *message) { MsgSndPtr msg; int match_count = 0; - /* for simple binding message syntax msg arg1=val1 arg2=val2 ... argn=valn */ - IvyBindingParseMessage( message ); /* recherche dans la liste des requetes recues de ce client */ IVY_LIST_EACH (clnt->msg_send, msg) { - match_count+= MsgSendCallTo (clnt->client, message, msg ); + match_count+= MsgCall (message, msg, clnt); } return match_count; } - static int CheckConnected( IvyClientPtr clnt ) { IvyClientPtr client; struct in_addr *addr1; struct in_addr *addr2; - /* TODO check multiple instance of the same application name */ - if ( clnt->app_port == 0 ) /* Old Ivy Protocol Dont check */ return 0; /* recherche dans la liste des clients de la presence de clnt */ - /* TODO check based on appid not on the copule host:port */ IVY_LIST_EACH( clients, client ) { /* client different mais port identique */ @@ -378,193 +250,140 @@ static int CheckConnected( IvyClientPtr clnt ) if ( addr1->s_addr == addr2->s_addr ) return 1; } + /* client different mais applicationID identique */ + /* TODO est-ce utile ??? verif dans UDP + if ( (client != clnt) && (clnt->app_id == client->app_id) ) + { + return 1; + } + */ } return 0; } -static char* Receive( Client client, void *data, char *message, unsigned int len ) +static void Receive( Client client, void *data, char *line ) { IvyClientPtr clnt; - int id; - unsigned short len_args; + int err,id; MsgSndPtr snd; MsgRcvPtr rcv; - IvyArgument arguments; + int argc = 0; + char *argv[MAX_MATCHING_ARGS]; + char *arg; int kind_of_msg = Bye; IvyBinding bind; - char *ptr_end; - void *args =NULL; - char *str_regexp; - int adv_buffer; - - ptr_end = message; - - if ( len < 6 ) return NULL; /* incomplete message */ - kind_of_msg = ntohs( *((unsigned short *) ptr_end)++ ); - id = ntohs( *((unsigned short *) ptr_end)++ ); - len_args = ntohs( *((unsigned short *) ptr_end)++ ); - - if ( len_args ) - { - if ( len < (6 + len_args) ) return NULL; /* incomplete message */ - args = ptr_end; - ptr_end += len_args; - } -#ifdef DEBUG - printf("Receive Message type=%d id=%d arg=%.*s\n", kind_of_msg, id, len_args, (char*)args); -#endif //DEBUG + const char *errbuf; + int erroffset; + err = sscanf( line ,"%d %d", &kind_of_msg, &id ); + arg = strstr( line , ARG_START ); + if ( (err != 2) || (arg == 0) ) + { + 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 = (IvyClientPtr)data; switch( kind_of_msg ) { case Bye: -#ifdef DEBUG - printf("Quitting Bye %.*s\n", len_args, (char*)args); -#endif //DEBUG + TRACE("Quitting %s\n", line); SocketClose( client ); break; case Error: - /*TODO Callback */ - fprintf (stderr, "Received error %d %.*s from %s\n", id, len_args, (char*)args, clnt->app_name); + printf ("Received error %d %s\n", id, arg); break; case AddRegexp: -#ifdef DEBUG - printf("AddRegexp id=%d exp='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG - if ( !IvyBindingFilter( IvyBindRegexp, len_args, args ) ) - { -#ifdef DEBUG - printf("Warning: regexp '%.*s' illegal, removing from %s\n",len_args,(char*)args,ApplicationName); -#endif //DEBUG - return ptr_end; - } - str_regexp = DupArg( len_args, args ); - - bind = IvyBindingCompile( IvyBindRegexp, str_regexp ); - if ( bind != NULL ) - { - IVY_LIST_ADD( clnt->msg_send, snd ) - if ( snd ) - { - snd->id = id; - snd->str_regexp = str_regexp; /* should be Freeed on remove */ - snd->bind = bind; - if ( application_bind_callback ) - { - (*application_bind_callback)( clnt, application_bind_data, IvyAddBind, snd->str_regexp ); - } - } - } - else - { - int offset; - const char *errbuf; - IvyBindingGetCompileError( &offset, &errbuf ); - MsgSendTo( client, Error, offset, strlen(errbuf), errbuf ); - free( str_regexp ); /* not used so Free it */ - } - - break; - case DelRegexp: -#ifdef DEBUG - printf("DelRegexp id=%d\n", id); -#endif //DEBUG - IVY_LIST_ITER( clnt->msg_send, snd, ( id != snd->id )); - if ( snd ) + TRACE("Regexp id=%d exp='%s'\n", id, arg); + + if ( !IvyBindingFilter( arg ) ) { - if ( application_bind_callback ) - { - (*application_bind_callback)( clnt, application_bind_data, IvyRemoveBind, snd->str_regexp ); - } - free( snd->str_regexp ); - IvyBindingFree( snd->bind ); - IVY_LIST_REMOVE( clnt->msg_send, snd ); - } - break; - case AddBinding: + TRACE("Warning: regexp '%s' illegal, removing from %s\n",arg,ApplicationName); -#ifdef DEBUG - printf("AddBinding id=%d exp='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG - if ( !IvyBindingFilter( IvyBindSimple, len_args, args ) ) - { -#ifdef DEBUG - printf("Warning: regexp '%.*s' illegal, removing from %s\n",len_args,(char*)args,ApplicationName); -#endif //DEBUG - return ptr_end; - } - str_regexp = DupArg( len_args, args ); - - bind = IvyBindingCompile( IvyBindSimple, str_regexp ); - if ( bind != NULL ) - { - IVY_LIST_ADD( clnt->msg_send, snd ) - if ( snd ) - { - snd->id = id; - snd->str_regexp = str_regexp; - snd->bind = bind; - if ( application_bind_callback ) + if ( application_bind_callback ) { - (*application_bind_callback)( clnt, application_bind_data, IvyAddBind, snd->str_regexp ); + (*application_bind_callback)( clnt, application_bind_data, id, arg, IvyFilterBind ); } - } + return; } - else + + bind = IvyBindingCompile( arg, & erroffset, & errbuf ); + if ( bind != NULL ) { - int offset; - const char *errbuf; - IvyBindingGetCompileError( &offset, &errbuf ); - MsgSendTo( client, Error, offset, strlen(errbuf), errbuf ); - free( str_regexp ); + // On teste si c'est un change regexp : changement de regexp d'une id existante + IVY_LIST_ITER( clnt->msg_send, snd, ( id != snd->id )); + if ( snd ) { + free (snd->str_regexp); + snd->str_regexp = strdup( arg ); + snd->binding = bind; + if ( application_bind_callback ) + { + (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyChangeBind ); + } + } else { + IVY_LIST_ADD_START( clnt->msg_send, snd ) + snd->id = id; + snd->str_regexp = strdup( arg ); + snd->binding = bind; + if ( application_bind_callback ) + { + (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyAddBind ); + } + IVY_LIST_ADD_END( clnt->msg_send, snd ) + + } } - + else + { + printf("Error compiling '%s', %s\n", arg, errbuf); + MsgSendTo( client, Error, erroffset, errbuf ); + } + break; - case DelBinding: -#ifdef DEBUG - printf("DelBinding id=%d\n", id); -#endif //DEBUG + case DelRegexp: + + TRACE("Regexp Delete id=%d\n", id); IVY_LIST_ITER( clnt->msg_send, snd, ( id != snd->id )); if ( snd ) { if ( application_bind_callback ) { - (*application_bind_callback)( clnt, application_bind_data, IvyRemoveBind, snd->str_regexp ); + (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyRemoveBind ); } - free( snd->str_regexp ); - IvyBindingFree( snd->bind ); - + IvyBindingFree( snd->binding ); IVY_LIST_REMOVE( clnt->msg_send, snd ); } break; case StartRegexp: -#ifdef DEBUG - printf("Regexp Start id=%d Application='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG - clnt->app_name = DupArg( len_args, args ); + + TRACE("Regexp Start id=%d Application='%s'\n", id, arg); + + clnt->app_name = strdup( arg ); clnt->app_port = id; if ( CheckConnected( clnt ) ) { -#ifdef DEBUG - printf("Quitting already connected %.*s\n", len_args, (char*)args); -#endif //DEBUG + + TRACE("Quitting already connected %s\n", line); + IvySendError( clnt, 0, "Application already connected" ); SocketClose( client ); } break; case EndRegexp: -#ifdef DEBUG - printf("Regexp End id=%d\n", id); -#endif //DEBUG + TRACE("Regexp End id=%d\n", id); + if ( application_callback ) { (*application_callback)( clnt, application_user_data, IvyApplicationConnected ); @@ -574,94 +393,85 @@ static char* Receive( Client client, void *data, char *message, unsigned int len int count; count = ClientCall( clnt, ready_message ); -#ifdef DEBUG - printf(" Sendind ready message %d\n", count); -#endif //DEBUG - + TRACE(" Sendind ready message %d\n", count); } break; case Msg: -#ifdef DEBUG - printf("Message id=%d msg='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG - rcv = hash_lookup( msg_recv, id ); - if ( rcv && rcv->callback ) + TRACE("Message id=%d msg='%s'\n", id, arg); + + IVY_LIST_EACH( msg_recv, rcv ) + { + if ( id == rcv->id ) { - arguments = IvyArgumentDeserialize( len_args, args, &adv_buffer ); - -#ifdef DEBUG - printf("Calling id=%d for %s\n", id, rcv->regexp); -#endif - (*rcv->callback)( clnt, rcv->user_data, arguments ); - IvyArgumentFree( arguments ); /* TODO evy , suppress malloc/free on each callback */ - return ptr_end; + arg = nextArg( arg, ARG_END); + while ( arg ) + { + argv[argc++] = arg; + arg = nextArg( 0, ARG_END ); + } + TRACE("Calling id=%d argc=%d for %s\n", id, argc,rcv->regexp); + if ( rcv->callback ) (*rcv->callback)( clnt, rcv->user_data, argc, argv ); + return; } - else - printf("Callback Message id=%d not found!!!'\n", id); + } + printf("Callback Message id=%d not found!!!'\n", id); break; case DirectMsg: -#ifdef DEBUG - printf("Direct Message id=%d msg='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG + TRACE("Direct Message id=%d msg='%s'\n", id, arg); if ( direct_callback) - (*direct_callback)( clnt, direct_user_data, id, len_args, args ); + (*direct_callback)( clnt, direct_user_data, id, arg ); break; case Die: -#ifdef DEBUG - printf("Die Message\n"); -#endif //DEBUG + TRACE("Die Message\n"); if ( application_die_callback) (*application_die_callback)( clnt, application_die_user_data, id ); IvyCleanup(); exit(0); break; - case ApplicationId: -#ifdef DEBUG - printf("ApplicationId priority=%d appid='%.*s'\n", id, len_args, (char*)args); -#endif //DEBUG - clnt->app_id = DupArg( len_args, args ); - if ( id != clnt->priority ) - { - clnt->priority = id; - SortClients(); - } + + case Ping: + + TRACE("Ping Message\n"); + MsgSendTo( client, Pong, id, "" ); + break; + + case Pong: + + TRACE("Pong Message\n"); + printf("Receive unhandled Pong message (ivy-c not able to send ping)\n"); break; + default: - printf("Receive unhandled message %d\n", kind_of_msg); + printf("Receive unhandled message %s\n", line); break; } - return ptr_end; -} -static BOOL SendRegexp(HASHKEYTYPE key, void *data, va_list args) -{ - Client client = va_arg( args, Client); - MsgRcvPtr msg = (MsgRcvPtr)data; - MsgSendTo( client, msg->type == IvyBindRegexp ? AddRegexp : AddBinding, msg->id, strlen(msg->regexp), msg->regexp); - return FALSE; /* iter throught all hash table */ + } -static IvyClientPtr SendService( Client client ) + +static IvyClientPtr SendService( Client client, const char *appname ) { IvyClientPtr clnt; - IVY_LIST_ADD( clients, clnt ) - if ( clnt ) - { - SocketKeepAlive ( client, 1 ); + MsgRcvPtr msg; + IVY_LIST_ADD_START( clients, clnt ) + clnt->msg_send = 0; clnt->client = client; - clnt->app_name = strdup("Unknown"); + clnt->app_name = strdup(appname); clnt->app_port = 0; - clnt->priority = DEFAULT_PRIORITY; - MsgSendTo( client, ApplicationId, applicationPriority, strlen(applicationUniqueId), applicationUniqueId ); - MsgSendTo( client, StartRegexp, ApplicationPort, strlen(ApplicationName), ApplicationName ); - hash_search( msg_recv, SendRegexp, client); - MsgSendTo( client, EndRegexp, 0, 0,""); - } + MsgSendTo( client, StartRegexp, ApplicationPort, ApplicationName); + IVY_LIST_EACH(msg_recv, msg ) + { + MsgSendTo( client, AddRegexp,msg->id,msg->regexp); + } + MsgSendTo( client, EndRegexp, 0, ""); + + IVY_LIST_ADD_END( clients, clnt ) return clnt; } @@ -682,14 +492,13 @@ static void ClientDelete( Client client, void *data ) #ifdef DEBUG /* probably bogus call, but this is for debug only anyway */ SocketGetRemoteHost( client, &remotehost, &remoteport ); - printf("Deconnexion de %s:%hu\n", remotehost, remoteport ); + TRACE("Deconnexion de %s:%hu\n", remotehost, remoteport ); #endif //DEBUG if ( clnt->app_name ) free( clnt->app_name ); - if ( clnt->app_id ) free( clnt->app_id ); IVY_LIST_EACH( clnt->msg_send, msg) { - IvyBindingFree( msg->bind ); + /*regfree(msg->regexp);*/ free( msg->str_regexp); } IVY_LIST_EMPTY( clnt->msg_send ); @@ -703,69 +512,36 @@ static void *ClientCreate( Client client ) char *remotehost; unsigned short remoteport; SocketGetRemoteHost( client, &remotehost, &remoteport ); - printf("Connexion de %s:%hu\n", remotehost, remoteport ); + TRACE("Connexion de %s:%hu\n", remotehost, remoteport ); #endif //DEBUG - return SendService (client); -} -/* Hello packet Send */ -static void IvySendHello(unsigned long mask) -{ - char *packet; - char *ptr; - int lenAppId; - int lenAppName; - int len; - lenAppId = strlen( applicationUniqueId ); - lenAppName = strlen( ApplicationName ); - len = 4*sizeof(unsigned short) + lenAppId + lenAppName; - packet = malloc( len ); - ptr = packet; - *((unsigned short *) ptr)++ = htons( VERSION ); - *((unsigned short *) ptr)++ = htons( ApplicationPort ); - *((unsigned short *) ptr)++ = htons( lenAppId ); - strncpy( ptr, applicationUniqueId , lenAppId); - ptr += lenAppId; - *((unsigned short *) ptr)++ = htons( lenAppName ); - strncpy( ptr, ApplicationName , lenAppName); - - SocketSendBroadcast(broadcast, mask, SupervisionPort, packet,len ); - free( packet ); + + return SendService (client, "Unknown"); } -/* Hello packet Receive */ -static char* BroadcastReceive( Client client, void *data, char *message, unsigned int len) + +static void BroadcastReceive( Client client, void *data, char *line ) { Client app; - unsigned short version; + int err; + int version; unsigned short serviceport; - char appname[1024]; - char appid[1024]; - unsigned short len_appid; - unsigned short len_appname; + char appid[2048]; + char appname[2048]; #ifdef DEBUG unsigned short remoteport; char *remotehost = 0; #endif - - char *ptr_end; - ptr_end = message; - - if ( len < 6 ) return NULL; /* incomplete message */ - - version = ntohs( *((unsigned short *) ptr_end)++ ); - serviceport = ntohs( *((unsigned short *) ptr_end)++ ); - len_appid = ntohs( *((unsigned short *) ptr_end)++ ); - if ( len < (6 +len_appid) ) return NULL; /* incomplete message */ - - strncpy( appid , ptr_end, len_appid ); - appid[ len_appid ] = '\0'; - ptr_end += len_appid; - len_appname = ntohs( *((unsigned short *) ptr_end)++ ); - if ( len < (6 +len_appid + len_appname) ) return NULL; /* incomplete message */ - - strncpy( appname , ptr_end, len_appname ); - appname[ len_appname ] = '\0'; - ptr_end += len_appname; - + memset( appid, 0, sizeof( appid ) ); + memset( appname, 0, sizeof( appname ) ); + err = sscanf (line,"%d %hu %s %[^\n]", &version, &serviceport, appid, appname); + if ( err < 2 ) { + /* ignore the message */ + unsigned short remoteport; + char *remotehost; + SocketGetRemoteHost (client, &remotehost, &remoteport ); + printf (" Bad supervision message, expected 'version port' from %s:%d\n", + remotehost, remoteport); + return; + } if ( version != VERSION ) { /* ignore the message */ unsigned short remoteport; @@ -773,116 +549,82 @@ static char* BroadcastReceive( Client client, void *data, char *message, unsigne SocketGetRemoteHost (client, &remotehost, &remoteport ); fprintf (stderr, "Bad Ivy version, expected %d and got %d from %s:%d\n", VERSION, version, remotehost, remoteport); - return ptr_end; + return; } - /* check if we received our own message */ - if (strcmp( appid,applicationUniqueId )== 0) - return ptr_end; + /* check if we received our own message. SHOULD ALSO TEST THE HOST */ + if ( strcmp( appid , ApplicationID) ==0 ) return; + if (serviceport == ApplicationPort) return; #ifdef DEBUG SocketGetRemoteHost (client, &remotehost, &remoteport ); - printf(" Broadcast de %s:%hu port %hu %s %s\n", remotehost, remoteport, serviceport, appname, appid ); + TRACE(" Broadcast de %s:%hu port %hu\n", remotehost, remoteport, serviceport ); #endif //DEBUG - /* check if already the same name on the bus */ - if ( strcmp( appname,ApplicationName )== 0) - { - /* TODO rize some callback ? */ - fprintf(stderr,"!!! Warning a another instance of %s is arriving on the Bus !!!\n", ApplicationName ); - } /* connect to the service and send the regexp */ app = SocketConnectAddr(SocketGetRemoteAddr(client), serviceport, 0, Receive, ClientDelete ); if (app) { IvyClientPtr clnt; - clnt = SendService( app ); + clnt = SendService( app, appname ); SocketSetData( app, clnt); } - return ptr_end; +} +static unsigned long currentTime() +{ +#define MILLISEC 1000 + unsigned long current; +#ifdef WIN32 + current = GetTickCount(); +#else + struct timeval stamp; + gettimeofday( &stamp, NULL ); + current = stamp.tv_sec * MILLISEC + stamp.tv_usec/MILLISEC; +#endif + return current; } +static const char * GenApplicationUniqueIdentifier() +{ + static char appid[2048]; + unsigned long curtime; + curtime = currentTime(); + srand( curtime ); + sprintf(appid,"%d:%lu:%d",rand(),curtime,ApplicationPort); + return appid; +} void IvyInit (const char *appname, const char *ready, IvyApplicationCallback callback, void *data, IvyDieCallback die_callback, void *die_data ) { - char hostname[1024]; - struct hostent *host; - IvyChannelInit(); + SocketInit(); - msg_recv = hash_create( 1024, FALSE ); - if ( ! msg_recv ) - { - fprintf(stderr,"IvyInit can't create Binding hash Table\n"); - exit(-1); - } ApplicationName = appname; application_callback = callback; application_user_data = data; application_die_callback = die_callback; application_die_user_data = die_data; ready_message = ready; - /* - * Initialize TCP port - */ - server = SocketServer (ANYPORT, ClientCreate, ClientDelete, Receive); - ApplicationPort = SocketServerGetPort (server); - /* get Host Ip address */ - if ( gethostname(hostname,sizeof(hostname)) < 0 ) - { - perror("gethostname"); - exit(-1); - } - host = gethostbyname( hostname ); - if ( ! host ) - { - perror("gethostbyname"); - exit(-1); - } - /* generate application UniqueID (timeStamp-Ipaddress-port*/ - /* TODO bug if multiple interface */ - applicationUniqueId = malloc(1024); - sprintf( applicationUniqueId , "%lu-%u%u%u%u-%d", - currentTime(), - (unsigned char)host->h_addr[0], - (unsigned char)host->h_addr[1], - (unsigned char)host->h_addr[2], - (unsigned char)host->h_addr[3], - ApplicationPort); - } -void IvyStop() +void IvySetBindCallback( IvyBindCallback bind_callback, void *bind_data ) { - IvyCleanup(); - IvyChannelStop(); + application_bind_callback=bind_callback; + application_bind_data=bind_data; } -void IvySetApplicationPriority( int priority ) +void IvySetFilter( int argc, const char **argv) { - int len; - IvyClientPtr clnt; - applicationPriority = priority; - if ( clients ) - { - /* Send to already connected clients */ - len = strlen(applicationUniqueId); - IVY_LIST_EACH (clients, clnt ) { - MsgSendTo( clnt->client, ApplicationId, applicationPriority, len, applicationUniqueId); - } - } -} + IvyBindingSetFilter( argc, argv ); + if ( getenv( "IVY_DEBUG_FILTER" )) debug_filter = 1; -void IvySetBindCallback(IvyBindCallback bind_callback, void *bind_data) -{ - application_bind_callback=bind_callback; - application_bind_data=bind_data; } -void IvySetMyMessagesStart( int argc, const char **argv) +void IvyStop (void) { - IvyBindingSetFilter( argc, argv ); + IvyChannelStop(); } + void IvyStart (const char* bus) { @@ -898,6 +640,13 @@ void IvyStart (const char* bus) /* + * Initialize TCP port + */ + server = SocketServer (ANYPORT, ClientCreate, ClientDelete, Receive); + ApplicationPort = SocketServerGetPort (server); + ApplicationID = GenApplicationUniqueIdentifier(); + + /* * Find network list as well as broadcast port * (we accept things like 123.231,123.123:2000 or 123.231 or :2000), * Initialize UDP port @@ -956,7 +705,7 @@ void IvyStart (const char* bus) if ( IN_MULTICAST( mask ) ) SocketAddMember (broadcast , mask ); - IvySendHello( mask ); + SocketSendBroadcast (broadcast, mask, SupervisionPort, "%d %hu %s %s\n", VERSION, ApplicationPort, ApplicationID, ApplicationName); numelem = 0; mask = 0xffffffff; } @@ -986,123 +735,117 @@ void IvyStart (const char* bus) ++p; } -#ifdef DEBUG - fprintf (stderr,"Listening on TCP:%hu\n",ApplicationPort); -#endif + TRACE ("Listening on TCP:%hu\n",ApplicationPort); } /* desabonnements */ -void IvyUnbindMsg (MsgRcvPtr msg) +void +IvyUnbindMsg (MsgRcvPtr msg) { IvyClientPtr clnt; /* Send to already connected clients */ IVY_LIST_EACH (clients, clnt ) { - MsgSendTo( clnt->client, DelRegexp,msg->id, 0, ""); + MsgSendTo( clnt->client, DelRegexp,msg->id, ""); } - hash_remove( msg_recv, msg->id ); + IVY_LIST_REMOVE( msg_recv, msg ); } /* demande de reception d'un message */ -static MsgRcvPtr IvyBind ( IvyBindingType typ, MsgCallback callback, void *user_data, const char *fmt_regex, va_list ap ) + +MsgRcvPtr +IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... ) { - char *buffer = NULL; - int size = 0; + static IvyBuffer buffer = { NULL, 0, 0}; + va_list ap; static int recv_id = 0; IvyClientPtr clnt; MsgRcvPtr msg; - int len; - int MsgType = typ == IvyBindRegexp ? AddRegexp : AddBinding; - make_message( &buffer, &size, 0, fmt_regex, ap ); - + va_start (ap, fmt_regex ); + buffer.offset = 0; + make_message( &buffer, fmt_regex, ap ); + va_end (ap ); + + substituteInterval (&buffer); + /* add Msg to the query list */ - msg = malloc(sizeof(struct _msg_rcv)); - if (msg) { - msg->type = typ; + IVY_LIST_ADD_START( msg_recv, msg ) msg->id = recv_id++; - msg->regexp = buffer; + msg->regexp = strdup(buffer.data); msg->callback = callback; msg->user_data = user_data; - if ( !hash_add(msg_recv, msg->id, msg) ) - { - perror("IvyBindMsg can't hash_add Entry already exists!"); - exit(-1); - } - } - else - { - perror("IvyBindMsg can't allocate Binding"); - free ( buffer ); - exit(-1); - } - len = strlen(msg->regexp); + IVY_LIST_ADD_END( msg_recv, msg ) /* Send to already connected clients */ /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH( clients, clnt ) { - MsgSendTo( clnt->client, MsgType,msg->id, len, msg->regexp); + MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); } return msg; } - -MsgRcvPtr IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... ) +/* changement de regexp d'un bind existant precedement fait avec IvyBindMsg */ +MsgRcvPtr +IvyChangeMsg (MsgRcvPtr msg, const char *fmt_regex, ... ) { + static IvyBuffer buffer = { NULL, 0, 0}; va_list ap; - MsgRcvPtr msg; + IvyClientPtr clnt; va_start (ap, fmt_regex ); - msg = IvyBind ( IvyBindRegexp, callback, user_data, fmt_regex, ap ); + buffer.offset = 0; + make_message( &buffer, fmt_regex, ap ); va_end (ap ); - return msg; - -} -MsgRcvPtr IvyBindSimpleMsg( MsgCallback callback, void *user_data, const char *fmt_regex, ... ) -{ - va_list ap; - MsgRcvPtr msg; + substituteInterval (&buffer); - va_start (ap, fmt_regex ); - msg = IvyBind ( IvyBindSimple, callback, user_data, fmt_regex, ap ); - va_end (ap ); - return msg; + /* change Msg in the query list */ + msg->regexp = strdup(buffer.data); + /* Send to already connected clients */ + /* recherche dans la liste des requetes recues de mes clients */ + IVY_LIST_EACH( clients, clnt ) { + MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); + } + return msg; } +/* emmission d'un message avec formatage a la printf */ int IvySendMsg(const char *fmt, ...) { IvyClientPtr clnt; int match_count = 0; - char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = { NULL, 0, 0}; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; + if( fmt == 0 || strlen(fmt) == 0 ) return 0; va_start( ap, fmt ); - make_message( &buffer, &size, 0, fmt, ap ); + buffer.offset = 0; + make_message( &buffer, fmt, ap ); va_end ( ap ); /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH (clients, clnt) { - match_count += ClientCall (clnt, buffer); + match_count += ClientCall (clnt, buffer.data); + } + TRACE_IF( match_count == 0, "Warning no recipient for %s\n",buffer.data); + /* si le message n'est pas emit et qu'il y a des filtres alors WARNING */ + if ( match_count == 0 && debug_filter ) + { + IvyBindindFilterCheck( buffer.data ); } -#ifdef DEBUG - if ( match_count == 0 ) printf( "Warning no recipient for %s\n",buffer); -#endif - free(buffer); return match_count; } void IvySendError( IvyClientPtr app, int id, const char *fmt, ... ) { - char *buffer = NULL; /* Use satic mem to eliminate multiple call to malloc /free */ - int size = 0; /* donc non reentrant !!!! */ + static IvyBuffer buffer = { NULL, 0, 0}; /* Use satic mem to eliminate multiple call to malloc /free */ va_list ap; va_start( ap, fmt ); - make_message( &buffer, &size, 0, fmt, ap ); + buffer.offset = 0; + make_message( &buffer, fmt, ap ); va_end ( ap ); - MsgSendTo( app->client, Error, id, strlen(buffer), buffer); - free(buffer); + MsgSendTo( app->client, Error, id, buffer.data); } void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data) @@ -1111,14 +854,14 @@ void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data) direct_user_data = user_data; } -void IvySendDirectMsg( IvyClientPtr app, int id, int len, void *msg ) +void IvySendDirectMsg( IvyClientPtr app, int id, char *msg ) { - MsgSendTo( app->client, DirectMsg, id, len, msg); + MsgSendTo( app->client, DirectMsg, id, msg); } void IvySendDieMsg( IvyClientPtr app ) { - MsgSendTo( app->client, Die, 0, 0, "" ); + MsgSendTo( app->client, Die, 0, "" ); } char *IvyGetApplicationName( IvyClientPtr app ) @@ -1134,12 +877,7 @@ char *IvyGetApplicationHost( IvyClientPtr app ) return SocketGetPeerHost (app->client ); else return 0; } -char *IvyGetApplicationId( IvyClientPtr app ) -{ - if ( app && app->app_id ) - return app->app_id; - else return 0; -} + void IvyDefaultApplicationCallback( IvyClientPtr app, void *user_data, IvyApplicationEvent event) { switch ( event ) { @@ -1154,14 +892,21 @@ void IvyDefaultApplicationCallback( IvyClientPtr app, void *user_data, IvyApplic break; } } -void IvyDefaultBindCallback( IvyClientPtr app, void *user_data, IvyBindEvent event, char* regexp ) +void IvyDefaultBindCallback( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event) { switch ( event ) { case IvyAddBind: - printf("Application: %s on %s add regexp %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), regexp); + printf("Application: %s on %s add regexp %d : %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); break; case IvyRemoveBind: - printf("Application: %s on %s remove regexp %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), regexp); + printf("Application: %s on %s remove regexp %d :%s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + case IvyFilterBind: + printf("Application: %s on %s as been filtred regexp %d :%s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + case IvyChangeBind: + printf("Application: %s on %s change regexp %d : %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; break; default: printf("Application: %s unkown event %d\n",IvyGetApplicationName( app ), event); @@ -1176,22 +921,23 @@ IvyClientPtr IvyGetApplication( char *name ) return app; } -char **IvyGetApplicationList() +char *IvyGetApplicationList(const char *sep) { - static char* applist[500]; + static char applist[4096]; /* TODO remove that ugly Thing */ IvyClientPtr app; - int appCount= 0; - memset( applist, 0 , sizeof( applist )); + applist[0] = '\0'; IVY_LIST_EACH( clients, app ) { - applist[appCount++]= app->app_name; + strcat( applist, app->app_name ); + strcat( applist, sep ); } return applist; } char **IvyGetApplicationMessages( IvyClientPtr app ) { - static char *messagelist[200]; +#define MAX_REGEXP 4096 + static char *messagelist[MAX_REGEXP+1];/* TODO remove that ugly Thing */ MsgSndPtr msg; int msgCount= 0; memset( messagelist, 0 , sizeof( messagelist )); @@ -1199,6 +945,53 @@ char **IvyGetApplicationMessages( IvyClientPtr app ) IVY_LIST_EACH( app->msg_send, msg ) { messagelist[msgCount++]= msg->str_regexp; + if ( msgCount >= MAX_REGEXP ) + { + fprintf(stderr,"Too Much expression(%d) for buffer\n",msgCount); + break; + } } return messagelist; } + +static void substituteInterval (IvyBuffer *src) +{ + // pas de traitement couteux s'il n'y a rien à interpoler + if (strstr (src->data, "(?I") == NULL) { + return; + } else { + char *curPos; + char *itvPos; + IvyBuffer dst = {NULL, 0, 0}; + dst.size = 8192; + dst.data = malloc (dst.size); + + curPos = src->data; + while ((itvPos = strstr (curPos, "(?I")) != NULL) { + // copie depuis la position courante jusqu'à l'intervalle + int lenCp, min,max; + char withDecimal; + lenCp = itvPos-curPos; + memcpy (&(dst.data[dst.offset]), curPos, lenCp); + curPos=itvPos; + dst.offset += lenCp; + + // extraction des paramètres de l'intervalle + sscanf (itvPos, "(?I%d#%d%c", &min, &max, &withDecimal); + + // printf ("DBG> substituteInterval min=%d max=%d withDecimal=%d\n", + // min, max, (withDecimal != 'i')); + + // generation et copie de l'intervalle + regexpGen (&(dst.data[dst.offset]), dst.size-dst.offset, min, max, (withDecimal != 'i')); + dst.offset = strlen (dst.data); + + // consommation des caractères décrivant intervalle dans la chaine source + curPos = strstr (curPos, ")"); + curPos++; + } + strncat (dst.data, curPos, dst.size-dst.offset); + free (src->data); + src->data = dst.data; + } +} @@ -1,6 +1,4 @@ - /* - * \ingroup Ivy * Ivy, C interface * * Copyright (C) 1997-2000 @@ -8,17 +6,13 @@ * * Main functions * - * \author Authors: François-Régis Colin <fcolin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software - * \todo - * many things TODO - * \bug - * many introduced */ #ifndef IVY_H @@ -28,86 +22,67 @@ extern "C" { #endif -#include "IvyArgument.h" - /* numero par default du bus */ #define DEFAULT_BUS 2010 -#define DEFAULT_PRIORITY 100; typedef struct _clnt_lst *IvyClientPtr; typedef enum { IvyApplicationConnected, IvyApplicationDisconnected } IvyApplicationEvent; -typedef enum { IvyAddBind, IvyRemoveBind } IvyBindEvent; +typedef enum { IvyAddBind, IvyRemoveBind, IvyFilterBind, IvyChangeBind } IvyBindEvent; extern void IvyDefaultApplicationCallback( IvyClientPtr app, void *user_data, IvyApplicationEvent event ) ; -extern void IvyDefaultBindCallback( IvyClientPtr app, void *user_data, IvyBindEvent event, char* regexp ) ; +extern void IvyDefaultBindCallback( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event ) ; /* callback callback appele sur connexion deconnexion d'une appli */ typedef void (*IvyApplicationCallback)( IvyClientPtr app, void *user_data, IvyApplicationEvent event ) ; /* callback callback appele sur ajout ou suppression d'un bind */ -typedef void (*IvyBindCallback)( IvyClientPtr app, void *user_data, IvyBindEvent event, char* regexp ) ; +typedef void (*IvyBindCallback)( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event ) ; /* callback appele sur reception de die */ typedef void (*IvyDieCallback)( IvyClientPtr app, void *user_data, int id ) ; /* callback appele sur reception de messages normaux */ -typedef void (*MsgCallback)( IvyClientPtr app, void *user_data, IvyArgument args ) ; +typedef void (*MsgCallback)( IvyClientPtr app, void *user_data, int argc, char **argv ) ; /* callback appele sur reception de messages directs */ -typedef void (*MsgDirectCallback)( IvyClientPtr app, void *user_data, int id, int len, void *msg ) ; +typedef void (*MsgDirectCallback)( IvyClientPtr app, void *user_data, int id, char *msg ) ; /* identifiant d'une expression reguliere ( Bind/Unbind ) */ typedef struct _msg_rcv *MsgRcvPtr; /* filtrage des regexps */ -void IvySetMyMessagesStart( int argc, const char **argv); +void IvySetFilter( int argc, const char **argv); -/** - * - * \param AppName - * \param ready - * \param callback - * \param data - * \param die_callback - * \param die_data - */ void IvyInit( - const char * AppName, /* nom de l'application */ - const char * ready, /* ready Message peut etre NULL */ + const char *AppName, /* nom de l'application */ + const char *ready, /* ready Message peut etre NULL */ IvyApplicationCallback callback, /* callback appele sur connection deconnection d'une appli */ - void * data, /* user data passe au callback */ + void *data, /* user data passe au callback */ IvyDieCallback die_callback, /* last change callback before die */ - void * die_data /* user data */ + void *die_data /* user data */ ); + +void IvySetBindCallback( + IvyBindCallback bind_callback, + void *bind_data ); -/** - * - * \param priority prioritie de traitement des clients - */ -void IvySetApplicationPriority( int priority ); -void IvySetBindCallback( IvyBindCallback bind_callback, void *bind_data ); -/** - * - * \param bus - */ -void IvyStart (const char* bus); +void IvyStart (const char*); void IvyStop (); /* query sur les applications connectees */ char *IvyGetApplicationName( IvyClientPtr app ); char *IvyGetApplicationHost( IvyClientPtr app ); -char *IvyGetApplicationId( IvyClientPtr app ); IvyClientPtr IvyGetApplication( char *name ); -char ** IvyGetApplicationList(); +char *IvyGetApplicationList(const char *sep); char **IvyGetApplicationMessages( IvyClientPtr app); /* demande de reception d'un message */ MsgRcvPtr IvyBindMsg( MsgCallback callback, void *user_data, const char *fmt_regexp, ... ); /* avec sprintf prealable */ -void IvyUnbindMsg( MsgRcvPtr id ); +MsgRcvPtr IvyChangeMsg (MsgRcvPtr msg, const char *fmt_regex, ... ); /* avec sprintf prealable */ -MsgRcvPtr IvyBindSimpleMsg( MsgCallback callback, void *user_data, const char *fmt_regexp, ... ); /* avec sprintf prealable */ +void IvyUnbindMsg( MsgRcvPtr id ); /* emission d'un message d'erreur */ void IvySendError( IvyClientPtr app, int id, const char *fmt, ... ); @@ -122,11 +97,7 @@ int IvySendMsg( const char *fmt_message, ... ); /* avec sprintf prealable */ /* Message Direct Inter-application */ void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data); -void IvySendDirectMsg( IvyClientPtr app, int id, int len, void *msg ); - -/* boucle principale d'Ivy */ -/* use of internal MainLoop or XtMainLoop, or other MainLoop integration */ -extern void IvyMainLoop(void(*hook)(void)); +void IvySendDirectMsg( IvyClientPtr app, int id, char *msg ); #ifdef __cplusplus } diff --git a/src/ivyargument.c b/src/ivyargument.c deleted file mode 100755 index 5d398d9..0000000 --- a/src/ivyargument.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Ivy, C interface - * - * Copyright (C) 1997-2000 - * Centre d'Études de la Navigation Aérienne - * - * Argument message comtent - * - * Authors: François-Régis Colin <fcolin@cena.fr> - * - * $Id$ - * - * Please refer to file version.h for the - * copyright notice regarding this software - */ -/* Module de gestion de la syntaxe des messages Ivy */ - -#include <stdio.h> -#include <sys/types.h> -#include <time.h> -#include <stdlib.h> -#include <memory.h> -#include <string.h> - -#ifdef WIN32 -#include <crtdbg.h> -#include <windows.h> -#else -#include <arpa/inet.h> -#include <sys/time.h> -#include <unistd.h> -#include <netdb.h> -#endif - - -#include "list.h" -#include "ivyargument.h" - - - -struct _argument { - /* childrens */ - struct _argument *next; - struct _argument *childrens; - /* arg value */ - int value_len; - const void *value; - }; - -IvyArgument IvyArgumentNew( int len, const void * value ) -{ - IvyArgument arg = malloc( sizeof( *arg ) ); - arg->value_len = len; - arg->value = value; - arg->next = 0; - arg->childrens = 0; - return arg; -} -void IvyArgumentFree( IvyArgument arg ) -{ - IvyArgument p; - IvyArgument psuiv; - IVY_LIST_EACH_SAFE( arg->childrens, p, psuiv ) - { - IvyArgumentFree(p); - } - free( arg ); -} -void IvyArgumentGetValue( IvyArgument arg, int * len, const void **val ) -{ - *len = arg->value_len; - *val = arg->value; -} -IvyArgument IvyArgumentGetChildrens( IvyArgument arg ) -{ - return arg->childrens; -} -IvyArgument IvyArgumentGetNextChild( IvyArgument arg ) -{ - return arg->next; -} -IvyArgument IvyAddChildValue( IvyArgument arg, int childvaluelen, const void* childvalue ) -{ - /* ADD Child to the beginning of the list */ - IvyArgument child; - IVY_LIST_ADD( arg->childrens, child ) - if ( child ) - { - child->value_len = childvaluelen; - child->value = childvalue; - } - return child; -} -void IvyAddChild( IvyArgument arg, IvyArgument child ) -{ - /* ADD Child to the beginning of the list */ - child->next = arg->childrens; - arg->childrens = child; -} -int IvyArgumentGetChildCount( IvyArgument arg ) -{ - IvyArgument p; - int count = 0; - IVY_LIST_EACH( arg->childrens, p ) - { - count++; - } - return count; -} -IvyArgument IvyArgumentDeserialize( int buf_len, void* buffer, int * buf_adv ) -{ - int i; - void *ptr_end = buffer; - int adv; - unsigned short value_len; - unsigned short nbchild; - IvyArgument arg; - IvyArgument child; - - adv = 0; - arg = IvyArgumentNew( 0, 0); - /* reading value */ - value_len = ntohs( *((unsigned short *) ptr_end)++ ); - if ( value_len ) - { - arg->value_len = value_len; - arg->value = ptr_end; - ((unsigned char *)ptr_end) += value_len; - } - /* reading child */ - nbchild = ntohs( *((unsigned short *) ptr_end)++ ); - - if ( nbchild ) - { - for ( i= 0; i < nbchild; i++ ) - { - child = IvyArgumentDeserialize( buf_len - ((unsigned char *)ptr_end - (unsigned char *)buffer) , ptr_end, &adv ); - IvyAddChild( arg, child ); - ((unsigned char *)ptr_end) += adv; - } - } - *buf_adv += (unsigned char *)ptr_end - (unsigned char *)buffer; -#ifdef DEBUG - printf( "IvyArgumentDeserialize value='%.*s' nbchild=%d size=%d\n",arg->value_len, (char*)arg->value, nbchild, *buf_adv); -#endif - return arg; -} -int IvyArgumentSerialize(IvyArgument arg, int *buf_len, void **buffer, int offset) -{ - int nb_child; - IvyArgument child; - void *ptr; - - /* check buffer space */ - if ( (*buf_len - offset) < (2 * sizeof( unsigned short ) + arg->value_len) ) - { - *buf_len += 4096; - *buffer = realloc( *buffer, *buf_len ); - } - ptr = (unsigned char*)(*buffer) + offset; - /* writing value */ - *((unsigned short*)ptr)++ = htons( (unsigned short)arg->value_len ); - if ( arg->value_len ) - { - memcpy( ptr, arg->value, arg->value_len ); - (unsigned char*)ptr += arg->value_len; - } - /* writing child */ - nb_child = IvyArgumentGetChildCount( arg ); - *((unsigned short*)ptr)++ = htons( (unsigned short)nb_child ); - IVY_LIST_EACH ( arg->childrens, child ) - { - (unsigned char*)ptr += IvyArgumentSerialize( child, buf_len, buffer, (unsigned char*)ptr - (unsigned char*)*buffer ); - } -#ifdef DEBUG - printf( "IvyArgumentSerialize value='%.*s' nbchild=%d buff size=%d\n",arg->value_len, (char*)arg->value, nb_child, (unsigned char*)ptr - (unsigned char*)*buffer - offset); -#endif - return (unsigned char*)ptr - (unsigned char*)*buffer - offset; -} - diff --git a/src/ivyargument.h b/src/ivyargument.h deleted file mode 100755 index 0176f21..0000000 --- a/src/ivyargument.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Ivy, C interface - * - * Copyright (C) 1997-2005 - * Centre d'Études de la Navigation Aérienne - * - * Argument message comtent - * - * Authors: François-Régis Colin <fcolin@cena.fr> - * - * $Id$ - * - * Please refer to file version.h for the - * copyright notice regarding this software - */ -#ifndef IVY_ARGUMENT_H -#define IVY_ARGUMENT_H -/* Module de gestion de la syntaxe des messages Ivy */ - -typedef struct _argument *IvyArgument; - -IvyArgument IvyArgumentNew( int len, const void * value ); -void IvyArgumentFree( IvyArgument arg ); -int IvyArgumentGetChildCount( IvyArgument arg ); -void IvyArgumentGetValue( IvyArgument arg, int * len, const void **val ); -IvyArgument IvyArgumentGetChildrens( IvyArgument arg ); -IvyArgument IvyArgumentGetNextChild( IvyArgument arg ); -void IvyAddChild( IvyArgument arg, IvyArgument child ); -IvyArgument IvyAddChildValue( IvyArgument arg, int childvaluelen, const void* childvalue ); - -IvyArgument IvyArgumentDeserialize( int buf_len, void* buffer, int * buf_adv); -int IvyArgumentSerialize(IvyArgument arg, int *buf_len, void **buffer, int offset); - -#endif - diff --git a/src/ivybind.c b/src/ivybind.c index 237ee78..c506ab3 100644 --- a/src/ivybind.c +++ b/src/ivybind.c @@ -31,78 +31,41 @@ #ifdef USE_PCRE_REGEX #define OVECSIZE 60 /* must be multiple of 3, for regexp return */ #include <pcre.h> -#else +#else /* we don't USE_PCRE_REGEX */ #define MAX_MSG_FIELDS 200 #include <regex.h> -#endif +#endif /* USE_PCRE_REGEX */ #include "list.h" -#include "hash.h" #include "ivybind.h" static int err_offset; #ifdef USE_PCRE_REGEX static const char *err_buf; -#else +#else /* we don't USE_PCRE_REGEX */ static char err_buf[4096]; -#endif +#endif /* USE_PCRE_REGEX */ struct _binding { - IvyBindingType type; - const char *msgname; /* msg tag name first word of message */ - char **msgargs; /* list of msg argument name */ - IvyArgument args; /* result */ #ifdef USE_PCRE_REGEX pcre *regexp; pcre_extra *inspect; int nb_match; int ovector[OVECSIZE]; -#else +#else /* we don't USE_PCRE_REGEX */ regex_t regexp; /* la regexp sous forme machine */ regmatch_t match[MAX_MSG_FIELDS+1]; /* resultat du match */ -#endif +#endif /* USE_PCRE_REGEX */ }; - /* classes de messages emis par l'application utilise pour le filtrage */ static int messages_classes_count = 0; static const char **messages_classes = 0; +/* regexp d'extraction du mot clef des regexp client pour le filtrage des regexp , ca va c'est clair ??? */ +static IvyBinding token_extract; - -/* stokage du message parse avant l'execution des regles de binding simple */ -static char *current_msg = NULL; -static char *msgtag; -static HASHTABLE msg_args_values = NULL; - -static IvyBinding IvyBindingCompileSimple( IvyBindingType typ, const char * expression ) -{ - int nb_arg= 0; - char *argname; - char **argv; - char *expr; - IvyBinding bind=0; - - expr = strdup( expression ); //Allocate a new buffer of separated token - /* count nb args */ - argname = expr; - while ( *argname ) - { - if ( *argname++ == ' ' ) nb_arg++; - } - - bind = (IvyBinding)malloc( sizeof( struct _binding )); - memset( bind, 0, sizeof(*bind ) ); - bind->type = IvyBindSimple; - bind->msgname = strtok( expr, " "); - bind->msgargs = malloc ( sizeof( char* ) * ( nb_arg + 1) ); - argv = bind->msgargs; - while ( (argname = strtok( NULL, " ")) ) - *argv++ = argname; - *argv++ = argname; /* end with NULL */ - return bind; -} -static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expression ) +IvyBinding IvyBindingCompile( const char * expression, int *erroffset, const char **errmessage ) { IvyBinding bind=0; #ifdef USE_PCRE_REGEX @@ -111,9 +74,13 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr if ( regexp != NULL ) { bind = (IvyBinding)malloc( sizeof( struct _binding )); + if ( ! bind ) + { + perror( "IvyBindingCompile malloc error: "); + exit(-1); + } memset( bind, 0, sizeof(*bind ) ); bind->regexp = regexp; - bind->type = IvyBindRegexp; bind->inspect = pcre_study(regexp,0,&err_buf); if (err_buf!=NULL) { @@ -122,9 +89,11 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr } else { + *erroffset = err_offset; + *errmessage = err_buf; printf("Error compiling '%s', %s\n", expression, err_buf); } -#else +#else /* we don't USE_PCRE_REGEX */ regex_t regexp; int reg; reg = regcomp(®exp, expression, REGCOMP_OPT|REG_EXTENDED); @@ -138,38 +107,26 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr else { regerror (reg, ®exp, err_buf, sizeof(err_buf) ); - err_offset = 0; // TODO unkown offset error + *erroffset = err_offset; + *errmessage = err_buf; printf("Error compiling '%s', %s\n", expression, err_buf); } -#endif +#endif /* USE_PCRE_REGEX */ return bind; } -IvyBinding IvyBindingCompile( IvyBindingType typ, const char * expression ) -{ - if ( typ == IvyBindRegexp ) - return IvyBindingCompileRegexp( typ, expression); - else - return IvyBindingCompileSimple( typ, expression); -} -void IvyBindingGetCompileError( int *offset, const char **errmessage ) -{ - *offset = err_offset; - *errmessage = err_buf; -} + void IvyBindingFree( IvyBinding bind ) { #ifdef USE_PCRE_REGEX - if (bind->inspect!=NULL) pcre_free(bind->inspect); + if (bind->inspect!=NULL) + pcre_free(bind->inspect); pcre_free(bind->regexp); -#else -#endif - if (bind->msgname) - free ( bind->msgname ); - if (bind->msgargs) - free ( bind->msgargs ); +#else /* we don't USE_PCRE_REGEX */ + free( bind->regexp ); +#endif /* USE_PCRE_REGEX */ free ( bind ); } -int IvyBindingExecRegexp( IvyBinding bind, const char * message ) +int IvyBindingExec( IvyBinding bind, const char * message ) { int nb_match = 0; #ifdef USE_PCRE_REGEX @@ -185,9 +142,7 @@ int IvyBindingExecRegexp( IvyBinding bind, const char * message ) OVECSIZE); if (nb_match<1) return 0; /* no match */ bind->nb_match = nb_match; - nb_match--; // firts arg wall string ??? - -#else +#else /* we don't USE_PCRE_REGEX */ memset( bind->match, -1, sizeof(bind->match )); /* work around bug !!!*/ nb_match = regexec (&bind->regexp, message, MAX_MSG_FIELDS, bind->match, 0) if (nb_match == REG_NOMATCH) @@ -197,126 +152,90 @@ int IvyBindingExecRegexp( IvyBinding bind, const char * message ) if ( bind->match[i].rm_so != -1 ) nb_match++; } -#endif +#endif /* USE_PCRE_REGEX */ return nb_match; } -int IvyBindingExecSimple( IvyBinding bind, const char * message ) -{ - char **msg_args; - if ( strcmp( bind->msgname, msgtag ) != 0 ) - return 0; - msg_args = bind->msgargs; - bind->args = IvyArgumentNew( 0,NULL ); - while( *msg_args ) - { - char *value; - value = hash_lookup(msg_args_values, (HASHKEYTYPE)*msg_args++); - if ( !value ) value = ""; /* TODO should we report matching ??? */ - IvyAddChildValue( bind->args, strlen( value ), value); - } - return 1; -} -int IvyBindingExec( IvyBinding bind, const char * message ) -{ - if ( bind->type == IvyBindRegexp ) - return IvyBindingExecRegexp( bind, message); - else - return IvyBindingExecSimple( bind, message); -} -static IvyArgument IvyBindingMatchSimple( IvyBinding bind, const char *message) -{ - return bind->args; -} -static IvyArgument IvyBindingMatchRegexp( IvyBinding bind, const char *message) + +void IvyBindingMatch( IvyBinding bind, const char *message, int argnum, int *arglen, const char **arg) { - int index=1;// firts arg wall string ??? - int arglen; - const void* arg; - IvyArgument args; - args = IvyArgumentNew( 0,NULL ); - #ifdef USE_PCRE_REGEX - while ( index<bind->nb_match ) { - arglen = bind->ovector[2*index+1]- bind->ovector[2*index]; - arg = message + bind->ovector[2*index]; - index++; + + *arglen = bind->ovector[2*argnum+1]- bind->ovector[2*argnum]; + *arg = message + bind->ovector[2*argnum]; #else /* we don't USE_PCRE_REGEX */ - for ( index = 1; index < MAX_MSG_FIELDS; index++ ) - { + regmatch_t* p; - p = &bind->match[index]; + p = &bind->match[argnum]; if ( p->rm_so != -1 ) { - arglen = p->rm_eo - p->rm_so; - arg = message + p->rm_so; + *arglen = p->rm_eo - p->rm_so; + *arg = message + p->rm_so; } else { // ARG VIDE - arglen = 0; - arg = NULL; - } -#endif // USE_PCRE_REGEX - IvyAddChildValue( args, arglen, arg ); + *arglen = 0; + *arg = NULL; } - return args; -} -IvyArgument IvyBindingMatch( IvyBinding bind, const char *message) -{ - if ( bind->type == IvyBindRegexp ) - return IvyBindingMatchRegexp( bind, message); - else - return IvyBindingMatchSimple( bind, message); +#endif /* USE_PCRE_REGEX */ + } //filter Expression Bind +int IvyBindingGetFilterCount() +{ +return messages_classes_count; +} void IvyBindingSetFilter( int argc, const char **argv) { + const char *errbuf; + int erroffset; + messages_classes_count = argc; messages_classes = argv; -} -void IvyBindingParseMessage( const char *msg ) -{ - char *arg; - if ( current_msg ) free( current_msg ); - if ( msg_args_values ) hash_destroy( msg_args_values ); - current_msg = strdup( msg ); - msg_args_values = hash_create( 256, TRUE ); - msgtag = strtok( current_msg, " " ); - while( (arg = strtok( NULL, " =" )) ) + /* compile the token extraction regexp */ + + token_extract = IvyBindingCompile("^\\^([a-zA-Z_0-9-]+).*", & erroffset, & errbuf); + if ( !token_extract ) { - char *val = strtok( NULL, " ="); - if ( arg && val ) - hash_addstring( msg_args_values, arg, val ); + printf("Error compiling Token Extract regexp: %s\n", errbuf); } } -int IvyBindingFilter(IvyBindingType typ, int len, const char *exp) + +int IvyBindingFilter(const char *expression) { - /* TODO check args limits !!!*/ int i; - /* accepte tout par default */ - int regexp_ok = 1; - // TODO simplify test 3 conditions - if ( typ == IvyBindRegexp ) - { - if ( *exp =='^' && messages_classes_count !=0 ) + int err; + int regexp_ok = 1; /* accepte tout par default */ + int tokenlen; + const char *token; + + if ( *expression =='^' && messages_classes_count !=0 ) { regexp_ok = 0; + + /* extract token */ + err = IvyBindingExec( token_extract, expression ); + if ( err < 1 ) return 1; + IvyBindingMatch( token_extract, expression , 1, &tokenlen, &token ); for ( i = 0 ; i < messages_classes_count; i++ ) { - if (strncmp( messages_classes[i], exp+1, strlen( messages_classes[i] )) == 0) - return 1; + if (strncmp( messages_classes[i], token, tokenlen ) == 0) { + return 1; } + // else { + //printf ("DBG> %s eliminé [%s]\n", token, expression); + //} } } - } - else - { - if ( messages_classes_count !=0 ) + return regexp_ok; +} +/* recherche si le message commence par un mot clef de la table */ +void IvyBindindFilterCheck( const char *message ) +{ + int i; + for ( i = 0 ; i < messages_classes_count; i++ ) { - regexp_ok = 0; - for ( i = 0 ; i < messages_classes_count; i++ ) + if (strcmp( messages_classes[i], message ) == 0) { - if (strncmp( messages_classes[i], exp, strlen( messages_classes[i] )) == 0) - return 1; - } - } + return; + } } - return regexp_ok; -}
\ No newline at end of file + fprintf(stderr,"*** WARNING *** message '%s' not sent due to missing keyword in filter table!!!\n", message ); +} diff --git a/src/ivybind.h b/src/ivybind.h index 9846d3f..adfc340 100644 --- a/src/ivybind.h +++ b/src/ivybind.h @@ -1,7 +1,7 @@ /* * Ivy, C interface * - * Copyright (C) 1997-2000 + * Copyright (C) 1997-2006 * Centre d'Études de la Navigation Aérienne * * Bind syntax for extracting message comtent @@ -14,18 +14,22 @@ * Please refer to file version.h for the * copyright notice regarding this software */ -#include "ivyargument.h" - /* Module de gestion de la syntaxe des messages Ivy */ typedef struct _binding *IvyBinding; -typedef enum { IvyBindRegexp, IvyBindSimple } IvyBindingType; -void IvyBindingParseMessage( const char *msg ); +/* Mise en place des Filtrages */ +int IvyBindingGetFilterCount(); void IvyBindingSetFilter( int argc, const char ** argv ); -int IvyBindingFilter( IvyBindingType typ, int len, const char *exp ); -IvyBinding IvyBindingCompile( IvyBindingType typ, const char * expression ); -void IvyBindingGetCompileError( int *erroffset, const char **errmessage ); +int IvyBindingFilter( const char *expression ); +void IvyBindindFilterCheck( const char *message ); + +/* Creation, Compilation */ +IvyBinding IvyBindingCompile( const char *expression, int *erroffset, const char **errmessage ); void IvyBindingFree( IvyBinding bind ); + +/* Execution , extraction */ int IvyBindingExec( IvyBinding bind, const char * message ); -IvyArgument IvyBindingMatch( IvyBinding bind, const char *message ); +/* Get Argument */ +void IvyBindingMatch( IvyBinding bind, const char *message, int argnum, int *arglen, const char **arg ); + diff --git a/src/ivybuffer.c b/src/ivybuffer.c new file mode 100644 index 0000000..0d85d98 --- /dev/null +++ b/src/ivybuffer.c @@ -0,0 +1,82 @@ +/* + * Ivy, C interface + * + * Copyright 1997-2000 + * Centre d'Etudes de la Navigation Aerienne + * + * Sockets + * + * Authors: Francois-Regis Colin <fcolin@cena.fr> + * + * $Id$ + * + * Please refer to file version.h for the + * copyright notice regarding this software + */ + +#ifdef WIN32 +#include <windows.h> +#endif +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#include "ivybuffer.h" + +#define BUFFER_SIZE 4096 /* taille buffer initiale on multiple par deux a chaque realloc */ + +// fonction de formtage a la printf d'un buffer avec reallocation dynamique +int make_message(IvyBuffer* buffer, const char *fmt, va_list ap) +{ + /* Guess we need no more than BUFFER_INIT_SIZE bytes. */ + int n; + if ( buffer->size == 0 || buffer->data == NULL ) + { + buffer->size = BUFFER_SIZE; + buffer->offset = 0; + buffer->data = malloc (BUFFER_SIZE); + if ( buffer->data == NULL ) + { + perror(" Ivy make message MALLOC error: " ); + return -1; + } + } + while (1) { + /* Try to print in the allocated space. */ +#ifdef WIN32 + n = _vsnprintf (buffer->data + buffer->offset, buffer->size - buffer->offset, fmt, ap); +#else + n = vsnprintf (buffer->data + buffer->offset, buffer->size - buffer->offset, fmt, ap); +#endif + /* If that worked, return the string size. */ + if (n > -1 && n < buffer->size) + { + buffer->offset += n; + return n; + } + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + buffer->size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + buffer->size *= 2; /* twice the old size */ + if ((buffer->data = realloc (buffer->data, buffer->size)) == NULL) + { + perror(" Ivy make message REALLOC error: " ); + return -1; + } + } +} +int make_message_var(IvyBuffer* buffer, const char *fmt, ... ) +{ + va_list ap; + int len; + va_start (ap, fmt ); + len = make_message (buffer, fmt, ap ); + va_end (ap ); + return len; +} + + + diff --git a/src/ivybuffer.h b/src/ivybuffer.h new file mode 100644 index 0000000..86c5474 --- /dev/null +++ b/src/ivybuffer.h @@ -0,0 +1,39 @@ +/* + * Ivy, C interface + * + * Copyright 1997-2000 + * Centre d'Etudes de la Navigation Aerienne + * + * Sockets + * + * Authors: Francois-Regis Colin <fcolin@cena.dgac.fr> + * + * $Id$ + * + * Please refer to file version.h for the + * copyright notice regarding this software + */ + +#ifndef IVYBUFFER_H +#define IVYBUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +typedef struct { + char * data; + int size; + int offset; + } IvyBuffer; +/* utility fonction do make vsprintf without buffer limit */ +extern int make_message(IvyBuffer * buffer, const char *fmt, va_list ap); +extern int make_message_var(IvyBuffer* buffer, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/ivychannel.h b/src/ivychannel.h index ff9974d..ce6ecd3 100644 --- a/src/ivychannel.h +++ b/src/ivychannel.h @@ -6,7 +6,7 @@ * * Basic I/O handling * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * @@ -25,33 +25,34 @@ extern "C" { #ifdef WIN32 #include <windows.h> -#define IVY_HANDLE SOCKET +#define HANDLE SOCKET #else -#define IVY_HANDLE int +#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, IVY_HANDLE fd, void *data); +typedef void (*ChannelHandleRead)( Channel channel, HANDLE fd, void *data); /* fonction appele par le bus pour initialisation */ extern void IvyChannelInit(void); -/* fonction appele par le bus pour terminaison */ -extern void IvyChannelStop(void); - + +extern void IvyChannelStop (void); + /* fonction appele par le bus pour mise en place des callback sur le canal */ extern Channel IvyChannelAdd( - IVY_HANDLE fd, + HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ); -/* fonction appele par le bus pour fermeture du canal */ +/* fonction appele par le bus pour suppression des callback sur le canal */ extern void IvyChannelRemove( Channel channel ); + #ifdef __cplusplus } #endif diff --git a/src/ivydebug.h b/src/ivydebug.h new file mode 100644 index 0000000..ee73f0e --- /dev/null +++ b/src/ivydebug.h @@ -0,0 +1,30 @@ +#ifndef IVY_DEBUG_H +#define IVY_DEBUG_H + +#ifdef WIN32 +#ifdef DEBUG +#define TRACE(format,...) \ + fprintf (stderr, format , __VA_ARGS__ ) + +#define TRACE_IF( cond, format, ...) \ + if ( cond ) fprintf (stderr, format , __VA_ARGS__ ) + +#else +#define TRACE(format, ...) /**/ +#define TRACE_IF( cond, format, ...) /**/ +#endif +#else +#ifdef DEBUG +#define TRACE(format, args...) \ + fprintf (stderr, format , ## args) + +#define TRACE_IF( cond, format, args...) \ + if ( cond ) fprintf (stderr, format , ## args) + +#else +#define TRACE(format, args...) /**/ +#define TRACE_IF( cond, format, args...) /**/ +#endif +#endif + +#endif diff --git a/src/ivyglibloop.c b/src/ivyglibloop.c index e1944dd..c4976b1 100644 --- a/src/ivyglibloop.c +++ b/src/ivyglibloop.c @@ -26,7 +26,8 @@ #endif #include <glib.h> - +#include "ivydebug.h" +#include "ivychannel.h" #include "ivyglibloop.h" struct _channel { @@ -58,13 +59,9 @@ void IvyChannelInit(void) { channel_initialized = 1; } -void IvyChannelStop( ) -{ - channel_initialized = 0; -} -Channel IvyChannelAdd(IVY_HANDLE fd, void *data, +Channel IvyChannelAdd(HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ) { @@ -95,14 +92,13 @@ void IvyChannelRemove( Channel channel ) { g_source_remove( channel->id_read ); g_source_remove( channel->id_delete ); } + static gboolean IvyGlibHandleChannelRead(GIOChannel *source, GIOCondition condition, gpointer data) { Channel channel = (Channel)data; -#ifdef DEBUG - printf("Handle Channel read %d\n",source ); -#endif + TRACE("Handle Channel read %d\n",source ); (*channel->handle_read)(channel, g_io_channel_unix_get_fd(source), channel->data); return TRUE; } @@ -111,15 +107,15 @@ static gboolean IvyGlibHandleChannelDelete(GIOChannel *source, GIOCondition condition, gpointer data) { Channel channel = (Channel)data; -#ifdef DEBUG - printf("Handle Channel delete %d\n",source ); -#endif + TRACE("Handle Channel delete %d\n",source ); (*channel->handle_delete)(channel->data); return TRUE; } -void IvyMainLoop(void(*hook)(void)) + +void +IvyChannelStop () { - GMainLoop *ml = g_main_loop_new(NULL, FALSE); - g_main_loop_run(ml); + /* To be implemented */ } + diff --git a/src/ivyglibloop.h b/src/ivyglibloop.h index f5026aa..e06a923 100644 --- a/src/ivyglibloop.h +++ b/src/ivyglibloop.h @@ -21,8 +21,7 @@ extern "C" { #endif -#include "ivychannel.h" - +/* Nothnig special */ #ifdef __cplusplus } #endif diff --git a/src/ivyglutloop.c b/src/ivyglutloop.c index 3dea326..b383d8f 100755 --- a/src/ivyglutloop.c +++ b/src/ivyglutloop.c @@ -6,8 +6,8 @@ * * Main loop based on GLUT ( OpenGL ) Toolkit * - * Authors: François-Régis Colin <colin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <colin@cenatoulouse.dgac.fr> + * Stéphane Chatty <chatty@cenatoulouse.dgac.fr> * * $Id$ * @@ -39,6 +39,7 @@ #include <GL/glut.h> +#include "ivydebug.h" #include "ivychannel.h" #include "ivyglutloop.h" @@ -53,8 +54,6 @@ struct _channel { static int channel_initialized = 0; - - void IvyChannelInit(void) { @@ -66,10 +65,7 @@ void IvyChannelInit(void) #endif channel_initialized = 1; } -void IvyChannelStop(void) -{ - channel_initialized = 0; -} + void IvyChannelRemove( Channel channel ) { @@ -83,22 +79,18 @@ void IvyChannelRemove( Channel channel ) static void IvyGlutHandleChannelRead( int source, GLUTInputId id, void *data ) { Channel channel = (Channel)data; -#ifdef DEBUG - printf("Handle Channel read %d\n",source ); -#endif + TRACE("Handle Channel read %d\n",source ); (*channel->handle_read)(channel,source,channel->data); } static void IvyGlutHandleChannelDelete( int source, GLUTInputId id, void *data ) { Channel channel = (Channel)data; -#ifdef DEBUG - printf("Handle Channel delete %d\n",source ); -#endif + TRACE("Handle Channel delete %d\n",source ); (*channel->handle_delete)(channel->data); } -Channel IvyChannelAdd(IVY_HANDLE fd, void *data, +Channel IvyChannelAdd(HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ) @@ -122,8 +114,10 @@ Channel IvyChannelAdd(IVY_HANDLE fd, void *data, return channel; } -extern void IvyMainLoop(void(*hook)(void)) + +void +IvyChannelStop () { - glutMainLoop(); + /* To be implemented */ } diff --git a/src/ivyglutloop.h b/src/ivyglutloop.h index 53437d6..9374390 100755 --- a/src/ivyglutloop.h +++ b/src/ivyglutloop.h @@ -6,8 +6,8 @@ * * Main loop based on GLUT ( OpenGL ) Toolkit * - * Authors: François-Régis Colin <colin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <colin@cenatoulouse.dgac.fr> + * Stéphane Chatty <chatty@cenatoulouse.dgac.fr> * * $Id$ * @@ -24,8 +24,8 @@ extern "C" { #include <GL/Glut.h> +/* general Handle */ -#include "ivychannel.h" #ifdef __cplusplus } diff --git a/src/ivyloop.c b/src/ivyloop.c index ab50f75..3d1008c 100644 --- a/src/ivyloop.c +++ b/src/ivyloop.c @@ -6,8 +6,8 @@ * * Main loop based on select * - * Authors: François-Régis Colin <fcolin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * * $Id$ * @@ -15,17 +15,16 @@ * copyright notice regarding this software */ - +#ifdef WIN32 +#include <windows.h> +#endif #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <stdarg.h> #include <string.h> -#ifdef WIN32 -#include <crtdbg.h> -#include <windows.h> -#else +#ifndef WIN32 #include <unistd.h> #include <sys/time.h> #include <sys/types.h> @@ -43,14 +42,13 @@ struct _channel { Channel next; - IVY_HANDLE fd; + HANDLE fd; void *data; int tobedeleted; ChannelHandleDelete handle_delete; ChannelHandleRead handle_read; }; - static Channel channels_list = NULL; static int channel_initialized = 0; @@ -58,6 +56,13 @@ static int channel_initialized = 0; static fd_set open_fds; static int MainLoop = 1; +/* Hook callback & data */ +static IvyHookPtr BeforeSelect = NULL; +static IvyHookPtr AfterSelect = NULL; + +static void *BeforeSelectData = NULL; +static void *AfterSelectData = NULL; + #ifdef WIN32 WSADATA WsaData; #endif @@ -89,24 +94,21 @@ ChannelDefferedDelete () } } -Channel IvyChannelAdd (IVY_HANDLE fd, void *data, +Channel IvyChannelAdd (HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ) { Channel channel; - IVY_LIST_ADD (channels_list, channel); - if (!channel) { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } + IVY_LIST_ADD_START (channels_list, channel) channel->fd = fd; channel->tobedeleted = 0; channel->handle_delete = handle_delete; channel->handle_read = handle_read; channel->data = data; - + IVY_LIST_ADD_END (channels_list, channel) + FD_SET (channel->fd, &open_fds); return channel; @@ -132,7 +134,7 @@ IvyChannelHandleExcpt (fd_set *current) if (FD_ISSET (channel->fd, current)) { if (channel->handle_delete) (*channel->handle_delete)(channel->data); -/* IvyChannelRemove (channel); */ +/* IvyChannelClose (channel); */ } } } @@ -161,10 +163,9 @@ void IvyChannelInit (void) void IvyChannelStop (void) { MainLoop = 0; - ChannelDefferedDelete(); /* this will force select to exit on multithread */ } -void IvyMainLoop(void(*hook)(void)) +void IvyMainLoop(void) { fd_set rdset; @@ -172,23 +173,29 @@ void IvyMainLoop(void(*hook)(void)) int ready; while (MainLoop) { + ChannelDefferedDelete(); - if (hook) (*hook)(); + + if (BeforeSelect) + (*BeforeSelect)(BeforeSelectData); rdset = open_fds; exset = open_fds; ready = select(64, &rdset, 0, &exset, TimerGetSmallestTimeout()); + + if (AfterSelect) + (*AfterSelect)(AfterSelectData); + if (ready < 0 && (errno != EINTR)) { fprintf (stderr, "select error %d\n",errno); perror("select"); return; } - TimerScan(); - if ( MainLoop && ready > 0) { + TimerScan(); /* should be spliited in two part ( next timeout & callbacks */ + if (ready > 0) { IvyChannelHandleExcpt(&exset); IvyChannelHandleRead(&rdset); - continue; } - } + } } void IvyIdle() @@ -216,3 +223,14 @@ void IvyIdle() } + +void IvySetBeforeSelectHook(IvyHookPtr before, void *data ) +{ + BeforeSelect = before; + BeforeSelectData = data; +} +void IvySetAfterSelectHook(IvyHookPtr after, void *data ) +{ + AfterSelect = after; + AfterSelectData = data; +} diff --git a/src/ivyloop.h b/src/ivyloop.h index 1d0b623..f272212 100644 --- a/src/ivyloop.h +++ b/src/ivyloop.h @@ -6,8 +6,8 @@ * * Main loop handling around select * - * Authors: François-Régis Colin <fcolin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * * $Id$ * @@ -25,10 +25,39 @@ extern "C" { #include "ivychannel.h" +/* general Handle */ -extern void IvyMainLoop(void(*hook)(void) ); -extern void IvyIdle(); +#define ANYPORT 0 +#ifdef WIN32 +#include <windows.h> +#define HANDLE SOCKET +#else +#define HANDLE int +#endif + +/* +Boucle principale d'IVY baseé sur un select +les fonctions hook et unhook encradre le select +de la maniere suivante: + + BeforeSelect est appeler avant l'appel system select + AfterSelect est appeler avent l'appel system select + ces function peuvent utilisées pour depose un verrou dans le cas + d'utilisation de la mainloop Ivy dans une thread separe + + BeforeSelect ==> on libere l'acces avant la mise en attente sur le select + AfterSelect == > on verrouille l'acces en sortie du select + + !!!! Attention donc l'appel des callbacks ivy se fait avec l'acces verrouille ! +*/ + +extern void IvyMainLoop(void); + +typedef void ( *IvyHookPtr) ( void *data ); + +extern void IvySetBeforeSelectHook(IvyHookPtr before, void *data ); +extern void IvySetAfterSelectHook(IvyHookPtr after, void *data ); #ifdef __cplusplus } diff --git a/src/ivyperf.c b/src/ivyperf.c index f8e9250..07453e3 100755 --- a/src/ivyperf.c +++ b/src/ivyperf.c @@ -39,6 +39,9 @@ extern int optind; #include "ivyloop.h" #define MILLISEC 1000.0 +const char *mymessages[] = { "IvyPerf", "ping", "pong" }; +static double origin = 0; + static double currentTime() { double current; @@ -52,64 +55,62 @@ static double currentTime() return current; } -void Reply (IvyClientPtr app, void *user_data, IvyArgument args) +void Reply (IvyClientPtr app, void *user_data, int argc, char *argv[]) { - IvyArgument arg; - int len; - const void* val; - arg = IvyArgumentGetChildrens( args ); - IvyArgumentGetValue( arg , &len, &val); - IvySendMsg ("pong ts=%.*s tr=%f", len, (char*)val, currentTime()); + IvySendMsg ("pong ts=%s tr=%f", *argv, currentTime()- origin); } -void Pong (IvyClientPtr app, void *user_data, IvyArgument args) +void Pong (IvyClientPtr app, void *user_data, int argc, char *argv[]) { - double current, ts, tr, roundtrip1, roundtrip2, roundtrip3; - IvyArgument arg; - int len; - const void* val; - /* TODO bug atof non limite a la longeur de la valeur !!!*/ - - current = currentTime(); - arg = IvyArgumentGetChildrens( args ); - IvyArgumentGetValue( arg , &len, &val); - ts = atof( (char*)val ); - arg = IvyArgumentGetNextChild( arg ); - IvyArgumentGetValue( arg , &len, &val); - tr = atof( (char*)val ); - roundtrip1 = tr-ts; - roundtrip2 = current - tr; - roundtrip3 = current - ts; + double current = currentTime() - origin ; + double ts = atof( *argv++ ); + double tr = atof( *argv++ ); + double roundtrip1 = tr-ts; + double roundtrip2 = current - tr; + double roundtrip3 = current - ts; fprintf(stderr,"roundtrip %f %f %f \n", roundtrip1, roundtrip2, roundtrip3 ); } void TimerCall(TimerId id, void *user_data, unsigned long delta) { - int count = IvySendMsg ("ping ts=%f", currentTime() ); + int count = IvySendMsg ("ping ts=%f", currentTime() - origin ); if ( count == 0 ) fprintf(stderr, "." ); } +void binCB( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event ) +{ + char *app_name = IvyGetApplicationName( app ); + switch ( event ) + { + case IvyAddBind: + printf("Application:%s bind '%s' ADDED\n", app_name, regexp ); + break; + case IvyRemoveBind: + printf("Application:%s bind '%s' REMOVED\n", app_name, regexp ); + break; + case IvyFilterBind: + printf("Application:%s bind '%s' FILTRED\n", app_name, regexp ); + break; + } +} int main(int argc, char *argv[]) { - + long time=200; /* Mainloop management */ + if ( argc > 1 ) time = atol( argv[1] ); IvyInit ("IvyPerf", "IvyPerf ready", NULL,NULL,NULL,NULL); - -#ifdef USE_REGEXP + IvySetFilter( sizeof( mymessages )/ sizeof( char *),mymessages ); + IvySetBindCallback( binCB, 0 ), IvyBindMsg (Reply, NULL, "^ping ts=(.*)"); IvyBindMsg (Pong, NULL, "^pong ts=(.*) tr=(.*)"); -#else - IvyBindSimpleMsg (Reply, NULL, "ping ts"); - IvyBindSimpleMsg (Pong, NULL, "pong ts tr"); -#endif - + origin = currentTime(); IvyStart (0); - TimerRepeatAfter (TIMER_LOOP, 200, TimerCall, (void*)1); + TimerRepeatAfter (TIMER_LOOP, time, TimerCall, (void*)1); - IvyMainLoop (0); + IvyMainLoop (); return 0; } diff --git a/src/ivyprobe.c b/src/ivyprobe.c index dc134a0..b6d9607 100644 --- a/src/ivyprobe.c +++ b/src/ivyprobe.c @@ -34,109 +34,96 @@ #include <string.h> #ifdef WIN32 #include <windows.h> +#include "getopt.h" #ifdef __MINGW32__ +#include <regex.h> #include <getopt.h> +#endif #else -#include "getopt.h" -#endif // __MINGW32__ -#else // WIN32 #include <sys/time.h> #include <unistd.h> #ifdef __INTERIX extern char *optarg; extern int optind; -#endif // __INTERIX -#endif // WIN32 - -#ifdef USE_PCRE_REGEX -#define OVECSIZE 60 /* must be multiple of 3, for regexp return */ -#include <pcre.h> -#else -#include <regex.h> #endif -#include "ivychannel.h" +#endif +#ifdef XTMAINLOOP +#include "ivyxtloop.h" +#endif +#ifdef GLIBMAINLOOP +#include <glib.h> +#include "ivyglibloop.h" +#endif +#ifdef GLUTMAINLOOP +#include "ivyglutloop.h" +#endif +#ifdef IVYMAINLOOP +#include "ivyloop.h" +#endif #include "ivysocket.h" +#include "ivychannel.h" +#include "ivybind.h" /* to test regexp before passing to BinMsg */ #include "ivy.h" #include "timer.h" #ifdef XTMAINLOOP -#include "ivyxtloop.h" #include <X11/Intrinsic.h> XtAppContext cntx; - #endif int app_count = 0; int wait_count = 0; int fbindcallback = 0; +int filter_count = 0; +const char *filter[4096]; +char *classes; -void DirectCallback(IvyClientPtr app, void *user_data, int id, int len, void *msg ) +void DirectCallback(IvyClientPtr app, void *user_data, int id, char *msg ) { - printf("%s sent a direct message, id=%d, message=%.*s\n", - IvyGetApplicationName(app),id,len,(char*)msg); + printf("%s sent a direct message, id=%d, message=%s\n", + IvyGetApplicationName(app),id,msg); } -void BindCallback(IvyClientPtr app, void *user_data, IvyBindEvent event, char *regexp ) -{ - char *sevent; - sevent= event==IvyAddBind ? "added" :"removed"; - - printf("%s has modified his binding, regexp=%s is %s\n", - IvyGetApplicationName(app),regexp,sevent); -} -void Callback (IvyClientPtr app, void *user_data, IvyArgument args) +void Callback (IvyClientPtr app, void *user_data, int argc, char *argv[]) { - IvyArgument arg; - int len; - const void* value; - printf ("%s sent:",IvyGetApplicationName(app)); - arg = IvyArgumentGetChildrens ( args ) ; - while( arg ) - { - IvyArgumentGetValue( arg, &len, &value ); - printf(" '%.*s'",len, (char*)value ); - arg = IvyArgumentGetNextChild( arg ); - } + int i; + printf ("%s sent ",IvyGetApplicationName(app)); + for (i = 0; i < argc; i++) + printf(" '%s'",argv[i]); printf("\n"); } char * Chop(char *arg) { - int len; + size_t len; if (arg==NULL) return arg; len=strlen(arg)-1; if ((*(arg+len))=='\n') *(arg+len)=0; return arg; } -void HandleStdin (Channel channel, IVY_HANDLE fd, void *data) - +void HandleStdin (Channel channel, HANDLE fd, void *data) { char buf[4096]; char *line; char *cmd; char *arg; - char *choparg; - char **applist; int id; IvyClientPtr app; int err; line = fgets(buf, 4096, stdin); if (!line) { -#ifdef WIN32 -#else + IvyChannelRemove (channel); -#endif IvyStop(); return; - } if (*line == '.') { cmd = strtok (line, ".: \n"); if (strcmp (cmd, "die") == 0) { - arg = strtok (NULL, "\n"); /* no space separator appname can containt space*/ + arg = strtok (NULL, " \n"); if (arg) { app = IvyGetApplication (arg); if (app) @@ -145,50 +132,34 @@ void HandleStdin (Channel channel, IVY_HANDLE fd, void *data) } } else if (strcmp(cmd, "dieall-yes-i-am-sure") == 0) { - applist = IvyGetApplicationList(); - while (*applist) { - app = IvyGetApplication (*applist); + arg = IvyGetApplicationList("#"); + arg = strtok (arg, "#"); + while (arg) { + app = IvyGetApplication (arg); if (app) IvySendDieMsg (app); else - printf ("No Application %s!!!\n",*applist); - applist++; + printf ("No Application %s!!!\n",arg); + arg = strtok (NULL, " "); } } else if (strcmp(cmd, "bind") == 0) { arg = strtok (NULL, "'"); + Chop(arg); if (arg) { -#ifdef USE_PCRE_REGEX - pcre *regexp; + IvyBinding bind; const char *errbuf; int erroffset; - Chop(arg); - regexp = pcre_compile(arg, 0,&errbuf,&erroffset,NULL); - if (regexp==NULL) { - printf("Error compiling '%s', %s, not bound\n", arg, errbuf); -#else - regex_t reg; - int err; - Chop(arg); - if (err=regcomp(®,arg,REG_ICASE|REG_EXTENDED)!=0) { - char errbuf[4096]; - regerror (err, ®, errbuf, 4096); - printf("Error compiling '%s', %s, not bound\n", arg, errbuf); - -#endif + bind = IvyBindingCompile(arg, & erroffset, & errbuf); + if (bind==NULL) { + printf("Error compiling '%s', %s, not bound\n", arg, errbuf); } else { - IvyBindMsg (Callback, NULL, Chop(arg)); + IvyBindingFree( bind ); + IvyBindMsg (Callback, NULL, arg); } } - } - else if (strcmp(cmd, "bindsimple") == 0) { - arg = strtok (NULL, "'"); - if (arg) { - IvyBindSimpleMsg (Callback, NULL, Chop(arg)); - } - } - else if (strcmp(cmd, "where") == 0) { + } else if (strcmp(cmd, "where") == 0) { arg = strtok (NULL, " \n"); if (arg) { app = IvyGetApplication (arg); @@ -199,103 +170,54 @@ void HandleStdin (Channel channel, IVY_HANDLE fd, void *data) } else if (strcmp(cmd, "direct") == 0) { arg = strtok (NULL, " \n"); if (arg) { - choparg = Chop(arg); app = IvyGetApplication (arg); if (app) { arg = strtok (NULL, " "); id = atoi (arg) ; arg = strtok (NULL, "'"); - IvySendDirectMsg (app, id, strlen(choparg), choparg); + IvySendDirectMsg (app, id, Chop(arg)); } else printf ("No Application %s!!!\n",arg); } } else if (strcmp(cmd, "who") == 0) { - applist = IvyGetApplicationList(); - while (*applist) { - printf ("Application '%s'\n",*applist); - applist++; - } + printf("Apps: %s\n", IvyGetApplicationList(",")); } else if (strcmp(cmd, "help") == 0) { fprintf(stderr,"Commands list:\n"); - printf(" .help - this help\n"); - printf(" .quit - terminate this application\n"); - printf(" .die appname - send die msg to appname\n"); - printf(" .dieall-yes-i-am-sure - send die msg to all applis\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 using regexp\n"); - printf(" .bindsimple 'expr' - add a msg to receive using simple msg format tag param param\n"); - printf(" .bindcall - toogle callback to binding\n"); - printf(" .who - who is on the bus\n"); - } else if (strcmp(cmd, "bindcall") == 0) { + printf(" .help - this help\n"); + printf(" .quit - terminate this application\n"); + printf(" .die appname - send die msg to appname\n"); + printf(" .dieall-yes-i-am-sure - send die msg to all applis\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(" .showbind - show bindings \n"); + + printf(" .who - who is on the bus\n"); + } else if (strcmp(cmd, "showbind") == 0) { if (!fbindcallback) { - IvySetBindCallback(BindCallback, NULL); + IvySetBindCallback(IvyDefaultBindCallback, NULL); fbindcallback=1; } else { - IvySetBindCallback(NULL, NULL); + IvySetBindCallback(NULL, NULL); fbindcallback=0; } } else if (strcmp(cmd, "quit") == 0) { - IvyStop(); /* this wil exit MainLoop */ - //exit(0); -#ifdef WIN32 - ExitThread( 0 ); /* exit STDin handle thread */ -#endif + exit(0); } } else { cmd = strtok (buf, "\n"); - if ( cmd ) - { err = IvySendMsg (cmd); printf("-> Sent to %d peer%s\n", err, err == 1 ? "" : "s"); - } } } -#ifdef WIN32 -DWORD WINAPI HandleStdinThread( LPVOID lpParam ) -{ - while( 1 ) - HandleStdin( 0,0,0); -} -void CreateStdinThread() -{ - DWORD dwThreadId, dwThrdParam = 1; - HANDLE hThread; - - hThread = CreateThread( - NULL, // default security attributes - 0, // use default stack size - HandleStdinThread, // thread function - &dwThrdParam, // argument to thread function - 0, // use default creation flags - &dwThreadId); // returns the thread identifier - - // Check the return value for success. - - if (hThread == NULL) - { - printf( "CreateThread failed (%d)\n", GetLastError() ); - } -} -#endif -void StartHandleStdin() -{ -#ifdef WIN32 - /* Stdin not compatible with select , select only accept socket */ - /* use Thread to Read StdIn */ - CreateStdinThread(); -#else - IvyChannelAdd (0, NULL, NULL, HandleStdin); -#endif -} void ApplicationCallback (IvyClientPtr app, void *user_data, IvyApplicationEvent event) { char *appname; char *host; - char **msgList; +/* char **msgList;*/ appname = IvyGetApplicationName (app); host = IvyGetApplicationHost (app); switch (event) { @@ -304,12 +226,17 @@ void ApplicationCallback (IvyClientPtr app, void *user_data, IvyApplicationEvent app_count++; printf("%s connected from %s\n", appname, host); /* printf("Application(%s): Begin Messages\n", appname);*/ +/* double usage with -s flag remove it msgList = IvyGetApplicationMessages (app); while (*msgList ) printf("%s subscribes to '%s'\n",appname,*msgList++); +*/ /* printf("Application(%s): End Messages\n",appname);*/ +#ifndef WIN32 +/* Stdin not compatible with select , select only accept socket */ if (app_count == wait_count) - StartHandleStdin(); + IvyChannelAdd (0, NULL, NULL, HandleStdin); +#endif break; case IvyApplicationDisconnected: @@ -322,13 +249,40 @@ void ApplicationCallback (IvyClientPtr app, void *user_data, IvyApplicationEvent break; } } +void IvyPrintBindCallback( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event) +{ + switch ( event ) { + case IvyAddBind: + if ( fbindcallback ) + printf("Application: %s on %s add regexp %d : %s\n", + IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + case IvyRemoveBind: + if ( fbindcallback ) + printf("Application: %s on %s remove regexp %d :%s\n", + IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + case IvyFilterBind: + printf("Application: %s on %s as been filtred regexp %d :%s\n", + IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + case IvyChangeBind: + if ( fbindcallback ) + printf("Application: %s on %s change regexp %d : %s\n", + IvyGetApplicationName( app ), IvyGetApplicationHost(app), id, regexp); + break; + default: + printf("Application: %s unkown event %d\n",IvyGetApplicationName( app ), event); + break; + } +} -#ifndef XTMAINLOOP +#ifdef IVYMAINLOOP void TimerCall(TimerId id, void *user_data, unsigned long delta) { - printf("Timer callback: %d delta %lu ms\n", (int)user_data, delta); - IvySendMsg ("TEST TIMER %d", (int)user_data); + printf("Timer callback: %ld delta %lu ms\n", (long)user_data, delta); + IvySendMsg ("TEST TIMER %d", (long)user_data); /*if ((int)user_data == 5) TimerModify (id, 2000);*/ } #endif @@ -341,18 +295,62 @@ display(void) } #endif +void BindMsgOfFile( const char * regex_file ) +{ + char line[4096]; + size_t size; + FILE* file; + file = fopen( regex_file, "r" ); + if ( !file ) { + perror( "Regexp file open "); + return; + } + while( !feof( file ) ) + { + if ( fgets( line, sizeof(line), file ) ) + { + size = strlen(line); + if ( size > 1 ) + { + line[size-1] = '\0'; /* supress \n */ + IvyBindMsg (Callback, NULL, line); + } + } + } +} +void BuildFilterRegexp() +{ + char *word=strtok( classes, "," ); + while ( word != NULL && (filter_count < 4096 )) + { + filter[filter_count++] = word; + word = strtok( NULL, ","); + } + if ( filter_count ) + IvySetFilter( filter_count, filter ); +} int main(int argc, char *argv[]) { int c; int timer_test = 0; char busbuf [1024] = ""; const char* bus = 0; + const char* regex_file = 0; char agentnamebuf [1024] = ""; const char* agentname = DEFAULT_IVYPROBE_NAME; char agentready [1024] = ""; const char* helpmsg = - "[options] [regexps]\n\t-b bus\tdefines the Ivy bus to which to connect to, defaults to 127:2010\n\t-t\ttriggers the timer test\n\t-n name\tchanges the name of the agent, defaults to IVYPROBE\n\t-v\tprints the ivy relase number\n\nregexp is a Perl5 compatible regular expression (see ivyprobe(1) and pcrepattern(3) for more info\nuse .help within ivyprobe\n\t-s bindcall\tactive the interception of regexp's subscribing or unscribing\n"; - while ((c = getopt(argc, argv, "vn:d:b:w:t:s")) != EOF) + "[options] [regexps]\n\t-b bus\tdefines the Ivy bus to which to connect to, defaults to 127:2010\n" + "\t-t\ttriggers the timer test\n" + "\t-n name\tchanges the name of the agent, defaults to IVYPROBE\n" + "\t-v\tprints the ivy relase number\n\n" + "regexp is a Perl5 compatible regular expression (see ivyprobe(1) and pcrepattern(3) for more info\n" + "use .help within ivyprobe\n" + "\t-s bindcall\tactive the interception of regexp's subscribing or unscribing\n" + "\t-f regexfile\tread list of regexp's from file one by line\n" + "\t-c msg1,msg2,msg3,...\tfilter the regexp's not beginning with words\n" + ; + while ((c = getopt(argc, argv, "vn:d:b:w:t:sf:c:")) != EOF) switch (c) { case 'b': strcpy (busbuf, optarg); @@ -361,6 +359,9 @@ int main(int argc, char *argv[]) case 'w': wait_count = atoi(optarg) ; break; + case 'f': + regex_file = optarg ; + break; case 'n': strcpy(agentnamebuf, optarg); agentname=agentnamebuf; @@ -371,9 +372,11 @@ int main(int argc, char *argv[]) timer_test = 1; break; case 's': - IvySetBindCallback(BindCallback, NULL); fbindcallback=1; break; + case 'c': + classes= strdup(optarg); + break; default: printf("usage: %s %s",argv[0],helpmsg); exit(1); @@ -393,13 +396,21 @@ int main(int argc, char *argv[]) glutDisplayFunc(display); #endif IvyInit (agentname, agentready, ApplicationCallback,NULL,NULL,NULL); - IvySetApplicationPriority( 0 ); /* lower priority */ + IvySetBindCallback(IvyPrintBindCallback, NULL); + IvyBindDirectMsg( DirectCallback,NULL); + if ( classes ) + BuildFilterRegexp(); + if ( regex_file ) + BindMsgOfFile( regex_file ); for (; optind < argc; optind++) IvyBindMsg (Callback, NULL, argv[optind]); if (wait_count == 0) - StartHandleStdin(); +#ifndef WIN32 +/* Stdin not compatible with select , select only accept socket */ + IvyChannelAdd (0, NULL, NULL, HandleStdin); +#endif IvyStart (bus); @@ -413,11 +424,19 @@ int main(int argc, char *argv[]) #ifdef XTMAINLOOP XtAppMainLoop (cntx); #endif +#ifdef GLIBMAINLOOP + { + GMainLoop *ml = g_main_loop_new(NULL, FALSE); + g_main_loop_run(ml); + } +#endif +#ifdef GLUTMAINLOOP + glutMainLoop(); +#endif - IvyMainLoop (0); - #ifdef _CRTDBG_MAP_ALLOC - _CrtDumpMemoryLeaks(); - #endif - +#ifdef IVYMAINLOOP + IvyMainLoop (); +#endif return 0; } + diff --git a/src/ivysocket.c b/src/ivysocket.c index 9ff66a0..b31ab4a 100644 --- a/src/ivysocket.c +++ b/src/ivysocket.c @@ -14,15 +14,16 @@ * copyright notice regarding this software */ - +#ifdef WIN32 +#include <windows.h> +#endif #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <stdarg.h> #include <string.h> + #ifdef WIN32 -#include <crtdbg.h> -#include <windows.h> #define close closesocket /*#define perror (a ) printf(a" error=%d\n",WSAGetLastError());*/ #else @@ -39,46 +40,54 @@ #include "list.h" #include "ivychannel.h" #include "ivysocket.h" +#include "ivyloop.h" +#include "ivybuffer.h" +#include "ivydebug.h" #define BUFFER_SIZE 4096 /* taille buffer initiale on multiple pas deux a chaque realloc */ struct _server { Server next; - IVY_HANDLE fd; + HANDLE fd; Channel channel; unsigned short port; - SocketCreate create; - SocketDelete handle_delete; + void *(*create)(Client client); + void (*handle_delete)(Client client, void *data); SocketInterpretation interpretation; }; struct _client { Client next; - IVY_HANDLE fd; + HANDLE fd; Channel channel; unsigned short port; struct sockaddr_in from; SocketInterpretation interpretation; - SocketDelete handle_delete; - /* input buffer */ - int in_buffer_size; - char *in_buffer; /* dynamicaly reallocated */ - char *in_ptr; - /* output buffer */ - int out_buffer_size; - char *out_buffer; /* dynamicaly reallocated */ - char *out_ptr; - + void (*handle_delete)(Client client, void *data); + char terminator; /* character delimiter of the message */ + /* Buffer de reception */ + long buffer_size; + char *buffer; /* dynamicaly reallocated */ + char *ptr; + /* user data */ void *data; }; static Server servers_list = NULL; static Client clients_list = NULL; +static int debug_send = 0; + #ifdef WIN32 WSADATA WsaData; #endif +void SocketInit() +{ + if ( getenv( "IVY_DEBUG_SEND" )) debug_send = 1; + IvyChannelInit(); +} + static void DeleteSocket(void *data) { Client client = (Client )data; @@ -86,8 +95,6 @@ static void DeleteSocket(void *data) (*client->handle_delete) (client, client->data ); shutdown (client->fd, 2 ); close (client->fd ); - free( client->in_buffer ); - free( client->out_buffer ); IVY_LIST_REMOVE (clients_list, client ); } @@ -96,136 +103,116 @@ static void DeleteServerSocket(void *data) Server server = (Server )data; #ifdef BUGGY_END if (server->handle_delete ) - (*server->handle_delete) (server->channel, NULL ); + (*server->handle_delete) (server, NULL ); #endif shutdown (server->fd, 2 ); close (server->fd ); IVY_LIST_REMOVE (servers_list, server); } -static void HandleSocket (Channel channel, IVY_HANDLE fd, void *data) +static void HandleSocket (Channel channel, HANDLE fd, void *data) { Client client = (Client)data; char *ptr; - char *ptr_end; + char *ptr_nl; long nb_to_read = 0; long nb; socklen_t len; /* limitation taille buffer */ - nb_to_read = client->in_buffer_size - (client->in_ptr - client->in_buffer ); + nb_to_read = client->buffer_size - (client->ptr - client->buffer ); if (nb_to_read == 0 ) { - client->in_buffer_size *= 2; /* twice old size */ - client->in_buffer = realloc( client->in_buffer, client->in_buffer_size ); - if (!client->in_buffer ) + client->buffer_size *= 2; /* twice old size */ + client->buffer = realloc( client->buffer, client->buffer_size ); + if (!client->buffer ) { fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); exit(0); } - fprintf(stderr, "Buffer Limit reached realloc new size %d\n", client->in_buffer_size ); - nb_to_read = client->in_buffer_size - (client->in_ptr - client->in_buffer ); + fprintf(stderr, "Buffer Limit reached realloc new size %ld\n", client->buffer_size ); + nb_to_read = client->buffer_size - (client->ptr - client->buffer ); } len = sizeof (client->from ); - nb = recvfrom (fd, client->in_ptr, nb_to_read,0,(struct sockaddr *)&client->from, + nb = recvfrom (fd, client->ptr, nb_to_read,0,(struct sockaddr *)&client->from, &len); if (nb < 0) { perror(" Read Socket "); - IvyChannelRemove(client->channel ); + IvyChannelRemove (client->channel ); return; } if (nb == 0 ) { - IvyChannelRemove(client->channel ); - return; - } - client->in_ptr += nb; - if (! client->interpretation ) - { - client->in_ptr = client->in_buffer; - fprintf (stderr,"Socket No interpretation function ??? skipping data\n"); + IvyChannelRemove (client->channel ); return; } - ptr = client->in_buffer; - - while ( (client->in_ptr > ptr )&&(ptr_end = (*client->interpretation) (client, client->data, ptr, client->in_ptr - ptr ))) + client->ptr += nb; + ptr = client->buffer; + while ((ptr_nl = memchr (ptr, client->terminator, client->ptr - ptr ))) { - ptr = ptr_end; + *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 < client->in_ptr ) - { /* recopie message incomplet au debut du buffer */ - len = client->in_ptr - ptr; - memcpy (client->in_buffer, ptr, len ); - client->in_ptr = client->in_buffer + len; + if (ptr < client->ptr ) + { /* recopie ligne incomplete au debut du buffer */ + len = client->ptr - ptr; + memcpy (client->buffer, ptr, len ); + client->ptr = client->buffer + len; } else { - client->in_ptr = client->in_buffer; + client->ptr = client->buffer; } } -static Client CreateClient(int handle) -{ - Client client; - IVY_LIST_ADD (clients_list, client ); - if (!client ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - close ( handle ); - exit(-1); - } - client->in_buffer_size = BUFFER_SIZE; - client->in_buffer = malloc( client->in_buffer_size ); - if (!client->in_buffer ) - { - fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); - exit(-1); - } - client->in_ptr = client->in_buffer; - client->out_buffer_size = BUFFER_SIZE; - client->out_buffer = malloc( client->out_buffer_size ); - if (!client->in_buffer ) - { - fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); - exit(-1); - } - client->out_ptr = client->out_buffer; - client->fd = handle; - client->channel = IvyChannelAdd (client->fd, client, DeleteSocket, HandleSocket ); - return client; -} - -static void HandleServer(Channel channel, IVY_HANDLE fd, void *data) +static void HandleServer(Channel channel, HANDLE fd, void *data) { Server server = (Server ) data; Client client; - IVY_HANDLE ns; + HANDLE ns; socklen_t addrlen; struct sockaddr_in remote2; -#ifdef DEBUG - printf( "Accepting Connection...\n"); -#endif //DEBUG + + TRACE( "Accepting Connection...\n"); + addrlen = sizeof (remote2 ); if ((ns = accept (fd, (struct sockaddr *)&remote2, &addrlen)) <0) { perror ("*** accept ***"); return; }; -#ifdef DEBUG - printf( "Accepting Connection ret\n"); -#endif //DEBUG - client = CreateClient(ns); + + TRACE( "Accepting Connection ret\n"); + + IVY_LIST_ADD_START (clients_list, client ); + + client->buffer_size = BUFFER_SIZE; + client->buffer = malloc( client->buffer_size ); + if (!client->buffer ) + { + fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); + exit(0); + } + client->terminator = '\n'; client->from = remote2; + client->fd = ns; + client->channel = IvyChannelAdd (ns, client, DeleteSocket, HandleSocket ); client->interpretation = server->interpretation; + client->ptr = client->buffer; client->handle_delete = server->handle_delete; client->data = (*server->create) (client ); -} + IVY_LIST_ADD_END (clients_list, client ); + +} Server SocketServer(unsigned short port, - SocketCreate create, - SocketDelete handle_delete, - SocketInterpretation interpretation ) + void*(*create)(Client client), + void(*handle_delete)(Client client, void *data), + void(*interpretation) (Client client, void *data, char *ligne)) { Server server; - IVY_HANDLE fd; + HANDLE fd; int one=1; struct sockaddr_in local; socklen_t addrlen; @@ -278,18 +265,15 @@ Server SocketServer(unsigned short port, }; - IVY_LIST_ADD (servers_list, server ); - if (!server ) - { - fprintf(stderr,"NOK Memory Alloc Error\n"); - exit(0); - } + IVY_LIST_ADD_START (servers_list, server ); server->fd = fd; - server->channel = IvyChannelAdd(fd, server, DeleteServerSocket, HandleServer ); + server->channel = IvyChannelAdd (fd, server, DeleteServerSocket, HandleServer ); server->create = create; server->handle_delete = handle_delete; server->interpretation = interpretation; server->port = ntohs(local.sin_port); + IVY_LIST_ADD_END (servers_list, server ); + return server; } @@ -302,8 +286,7 @@ void SocketServerClose (Server server ) { if (!server) return; - IvyChannelRemove( server->channel ); - IVY_LIST_REMOVE (servers_list, server ); + IvyChannelRemove (server->channel ); } char *SocketGetPeerHost (Client client ) @@ -348,44 +331,89 @@ void SocketClose (Client client ) if (client) IvyChannelRemove (client->channel ); } + +int SocketSendRaw (Client client, char *buffer, int len ) +{ + int err; + int waiting= 0; + + if (!client) + return waiting; + + if ( debug_send ) + { + /* try to determine if we are going to block */ + fd_set wrset; + int ready; + struct timeval timeout; + timeout.tv_usec = 0; + timeout.tv_sec = 0; + FD_ZERO(&wrset); + FD_SET( client->fd, &wrset ); + ready = select(client->fd+1, 0, &wrset, 0, &timeout); + //fprintf(stderr,"Ivy: select ready=%d fd=%d\n",ready,FD_ISSET( client->fd, &wrset ) ); + if(ready < 0) { + perror("Ivy: SocketSendRaw select"); + } + if ( !FD_ISSET( client->fd, &wrset ) ) + { + fprintf(stderr,"Ivy: Client Queue Full Waiting.........."); + waiting = 1; + } + + } + + err = send (client->fd, buffer, len, 0 ); + if (err != len ) + perror ("*** send ***"); + if ( debug_send && waiting ) + { + fprintf(stderr,"... OK\n"); + } + return waiting; +} + void SocketSetData (Client client, void *data ) { if (client) client->data = data; } -void *SocketGetData (Client client ) -{ - return client ? client->data : 0; -} -void SocketSend(Client client, const char *buffer, int len ) +int SocketSend (Client client, char *fmt, ... ) { - unsigned long usedspace; + int waiting = 0; + static IvyBuffer buffer = {NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + va_list ap; + int len; if (!client) - return; - usedspace = client->out_ptr - client->out_buffer; - if ( len >= client->out_buffer_size - usedspace ) - { - /* not enought space */ - client->out_buffer_size += len - usedspace +1; - client->out_buffer = realloc (client->out_buffer, client->out_buffer_size); - } - memcpy ( client->out_ptr, buffer, len ); - client->out_ptr += len; + return waiting; + va_start (ap, fmt ); + buffer.offset = 0; + len = make_message (&buffer, fmt, ap ); + waiting = SocketSendRaw (client, buffer.data, len ); + va_end (ap ); + return waiting; } -void SocketFlush (Client client) +void *SocketGetData (Client client ) { - int err; - unsigned long len; + return client ? client->data : 0; +} - if (!client) - return; - len = client->out_ptr - client->out_buffer; - err = send (client->fd, client->out_buffer, len, 0 ); - if (err != len ) - perror ("*** send ***"); - client->out_ptr = client->out_buffer; +void SocketBroadcast ( char *fmt, ... ) +{ + Client client; + static IvyBuffer buffer = {NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + va_list ap; + int len; + + va_start (ap, fmt ); + len = make_message (&buffer, fmt, ap ); + va_end (ap ); + IVY_LIST_EACH (clients_list, client ) + { + SocketSendRaw (client, buffer.data, len ); + } } /* @@ -394,7 +422,7 @@ Ouverture d'un canal TCP/IP en mode client Client SocketConnect (char * host, unsigned short port, void *data, SocketInterpretation interpretation, - SocketDelete handle_delete + void (*handle_delete)(Client client, void *data) ) { struct hostent *rhost; @@ -409,10 +437,10 @@ Client SocketConnect (char * host, unsigned short port, Client SocketConnectAddr (struct in_addr * addr, unsigned short port, void *data, SocketInterpretation interpretation, - SocketDelete handle_delete + void (*handle_delete)(Client client, void *data) ) { - IVY_HANDLE handle; + HANDLE handle; Client client; struct sockaddr_in remote; @@ -430,25 +458,91 @@ Client SocketConnectAddr (struct in_addr * addr, unsigned short port, return NULL; }; - client = CreateClient(handle); + IVY_LIST_ADD_START(clients_list, client ); + + client->buffer_size = BUFFER_SIZE; + client->buffer = malloc( client->buffer_size ); + if (!client->buffer ) + { + fprintf(stderr,"HandleSocket Buffer Memory Alloc Error\n"); + exit(0); + } + client->terminator = '\n'; + client->fd = handle; + client->channel = IvyChannelAdd (handle, client, DeleteSocket, HandleSocket ); client->interpretation = interpretation; - client->handle_delete = handle_delete; + 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); + IVY_LIST_ADD_END(clients_list, client ); + return client; } +// TODO factoriser avec HandleRead !!!! +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, client->terminator ); + } while (!ptr_nl ); + *ptr_nl = '\0'; + return (ptr_nl - buffer); +} /* Socket UDP */ -Client SocketBroadcastCreate ( - unsigned short port, +Client SocketBroadcastCreate (unsigned short port, void *data, SocketInterpretation interpretation ) { - IVY_HANDLE handle; + HANDLE handle; Client client; struct sockaddr_in local; int on = 1; @@ -489,43 +583,51 @@ Client SocketBroadcastCreate ( return NULL; }; - client = CreateClient(handle); + IVY_LIST_ADD_START(clients_list, client ); + + client->buffer_size = BUFFER_SIZE; + client->buffer = malloc( client->buffer_size ); + if (!client->buffer ) + { + perror("HandleSocket Buffer Memory Alloc Error: "); + exit(0); + } + client->terminator = '\n'; + client->fd = handle; + client->channel = IvyChannelAdd (handle, client, DeleteSocket, HandleSocket ); client->interpretation = interpretation; + client->ptr = client->buffer; client->data = data; + IVY_LIST_ADD_END(clients_list, client ); + return client; } -void SocketSendBroadcast(Client client, unsigned long host, unsigned short port, char *buffer, int len ) +void SocketSendBroadcast (Client client, unsigned long host, unsigned short port, char *fmt, ... ) { struct sockaddr_in remote; - int err; + static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ + va_list ap; + int err,len; if (!client) return; + va_start (ap, fmt ); + buffer.offset = 0; + len = make_message (&buffer, fmt, ap ); /* Send UDP packet to the dest */ remote.sin_family = AF_INET; remote.sin_addr.s_addr = htonl (host ); remote.sin_port = htons(port); err = sendto (client->fd, - buffer, len,0, + buffer.data, len,0, (struct sockaddr *)&remote,sizeof(remote)); if (err != len) { perror ("*** send ***"); - } -} -void SocketKeepAlive( Client client,int keepalive ) -{ - int alive = keepalive; - if (setsockopt(client->fd,SOL_SOCKET,SO_KEEPALIVE,(char*)&alive,sizeof(alive)) < 0) - { -#ifdef WIN32 - fprintf(stderr," setsockopt %d\n",WSAGetLastError()); -#endif - perror ("*** set socket option SO_KEEPALIVE ***"); - exit(0); - } + } va_end (ap ); } + /* Socket Multicast */ int SocketAddMember(Client client, unsigned long host ) diff --git a/src/ivysocket.h b/src/ivysocket.h index b491f0f..c656312 100644 --- a/src/ivysocket.h +++ b/src/ivysocket.h @@ -6,7 +6,7 @@ * * Sockets * - * Authors: Francois-Regis Colin <fcolin@cena.fr> + * Authors: Francois-Regis Colin <fcolin@cena.dgac.fr> * * $Id$ * @@ -32,11 +32,13 @@ extern "C" { #ifdef __MINGW32__ #include <ws2tcpip.h> #endif +#define HANDLE SOCKET #define socklen_t int #ifndef IN_MULTICAST #define IN_MULTICAST(i) (((long)(i) & 0xf0000000) == 0xe0000000) #endif #else +#define HANDLE int #include <netinet/in.h> #endif #ifdef __INTERIX @@ -44,40 +46,43 @@ extern "C" { #endif /* General Init */ +extern void SocketInit(); + /* Forward def */ typedef struct _client *Client; -typedef char* (*SocketInterpretation) (Client client, void *data, char *ligne, unsigned int len); -typedef void* (*SocketCreate) (Client client); -typedef void (*SocketDelete) (Client client, void *data); +typedef void (*SocketInterpretation) (Client client, void *data, char *ligne); /* Server Part */ typedef struct _server *Server; extern Server SocketServer(unsigned short port, - SocketCreate create, - SocketDelete handle_delete, + void*(*create)(Client client), + void(*handle_delete)(Client client, void *data), SocketInterpretation interpretation); extern unsigned short SocketServerGetPort( Server server ); extern void SocketServerClose( Server server ); /* Client Part */ -extern void SocketKeepAlive( Client client,int keepalive ); + extern void SocketClose( Client client ); -extern void SocketSend( Client client, const char *buffer, int len ); -extern void SocketFlush (Client client); +extern int SocketSend( Client client, char *fmt, ... ); +extern int SocketSendRaw( Client client, char *buffer, int len ); extern char *SocketGetPeerHost( Client client ); extern void SocketSetData( Client client, void *data ); extern void *SocketGetData( Client client ); +extern void SocketBroadcast( char *fmt, ... ); extern Client SocketConnect( char * host, unsigned short port, void *data, SocketInterpretation interpretation, - SocketDelete handle_delete - ); + void (*handle_delete)(Client client, void *data) + ); extern Client SocketConnectAddr( struct in_addr * addr, unsigned short port, void *data, SocketInterpretation interpretation, - SocketDelete handle_delete + 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 */ @@ -93,7 +98,7 @@ extern int SocketAddMember( Client client, unsigned long host ); extern struct in_addr * SocketGetRemoteAddr( Client client ); extern void SocketGetRemoteHost (Client client, char **host, unsigned short *port ); /* emmission d'un broadcast UDP */ -extern void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *buffer, int len ); +extern void SocketSendBroadcast( Client client, unsigned long host, unsigned short port, char *fmt, ... ); #ifdef __cplusplus } diff --git a/src/ivytcl.c b/src/ivytcl.c index 6c82e54..a43821a 100755 --- a/src/ivytcl.c +++ b/src/ivytcl.c @@ -6,7 +6,7 @@ * * Main loop based on Tcl * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * @@ -29,6 +29,7 @@ #include "ivytcl.h" #include "ivysocket.h" +#include "ivychannel.h" #include "ivy.h" #include "timer.h" @@ -38,7 +39,6 @@ // mais il y a des problemes sur les socket server // Il n'y a pas de Tcl_MakeTCPserver - struct _channel { HANDLE fd; void *data; @@ -75,15 +75,6 @@ void IvyChannelInit(void) #endif channel_initialized = 1; } -void IvyChannelStop(void) -{ - channel_initialized = 0; - -#ifndef TCL_CHANNEL_INTEGRATION - Tcl_CancelIdleCall(IvyIdleProc,0); -#endif - -} static void IvyHandleFd(ClientData cd, int mask) @@ -143,6 +134,14 @@ void IvyIdleProc(ClientData clientData) } #endif +void +IvyChannelStop () +{ + /* To be implemented */ +#ifndef TCL_CHANNEL_INTEGRATION + Tcl_CancelIdleCall(IvyIdleProc,0); +#endif +} /* Code from PLC */ #define INTEGER_SPACE 30 diff --git a/src/ivytcl.h b/src/ivytcl.h index 99c05d7..c482a60 100755 --- a/src/ivytcl.h +++ b/src/ivytcl.h @@ -6,7 +6,7 @@ * * Main loop based on Tcl * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * @@ -21,10 +21,6 @@ extern "C" { #endif - -#include "ivychannel.h" - - #ifdef __cplusplus } #endif diff --git a/src/ivyxtloop.c b/src/ivyxtloop.c index 6a451a1..6613307 100644 --- a/src/ivyxtloop.c +++ b/src/ivyxtloop.c @@ -6,8 +6,8 @@ * * Main loop based on the X Toolkit * - * Authors: François-Régis Colin <fcolin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * * $Id$ * @@ -39,6 +39,7 @@ #include <X11/Intrinsic.h> +#include "ivydebug.h" #include "ivychannel.h" #include "ivyxtloop.h" @@ -83,25 +84,19 @@ void IvyChannelRemove( Channel channel ) XtRemoveInput( channel->id_read ); XtRemoveInput( channel->id_delete ); } -void IvyChannelStop() -{ -} + static void IvyXtHandleChannelRead( XtPointer closure, int* source, XtInputId* id ) { Channel channel = (Channel)closure; -#ifdef DEBUG - printf("Handle Channel read %d\n",*source ); -#endif + TRACE("Handle Channel read %d\n",*source ); (*channel->handle_read)(channel,*source,channel->data); } static void IvyXtHandleChannelDelete( XtPointer closure, int* source, XtInputId* id ) { Channel channel = (Channel)closure; -#ifdef DEBUG - printf("Handle Channel delete %d\n",*source ); -#endif + TRACE("Handle Channel delete %d\n",*source ); (*channel->handle_delete)(channel->data); } @@ -111,7 +106,7 @@ void IvyXtChannelAppContext( XtAppContext cntx ) app = cntx; } -Channel IvyChannelAdd(IVY_HANDLE fd, void *data, +Channel IvyChannelAdd(HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ) @@ -134,7 +129,11 @@ Channel IvyChannelAdd(IVY_HANDLE fd, void *data, return channel; } -void IvyMainLoop(void(*hook)(void)) + + +void +IvyChannelStop () { - XtAppMainLoop (app); -}
\ No newline at end of file + /* To be implemented */ +} + diff --git a/src/ivyxtloop.h b/src/ivyxtloop.h index 162f398..0087274 100644 --- a/src/ivyxtloop.h +++ b/src/ivyxtloop.h @@ -6,8 +6,8 @@ * * Main loop based on the X Toolkit * - * Authors: François-Régis Colin <colin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <colin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * * $Id$ * @@ -24,10 +24,6 @@ extern "C" { #include <X11/Intrinsic.h> -#include "ivychannel.h" - - - extern void IvyXtChannelAppContext( XtAppContext cntx ); #ifdef __cplusplus diff --git a/src/libIvy.def b/src/libIvy.def index 4f7e3ba..df671c7 100644 --- a/src/libIvy.def +++ b/src/libIvy.def @@ -3,7 +3,9 @@ LIBRARY Ivy EXPORTS IvyDefaultApplicationCallback -IvySetMyMessagesStart +IvyDefaultBindCallback + +IvySetFilter IvyInit IvyStart IvyStop @@ -15,32 +17,24 @@ IvyGetApplication IvyGetApplicationList IvyGetApplicationMessages IvyBindMsg -IvyBindSimpleMsg IvyUnbindMsg IvySendError IvySendDieMsg IvySendMsg -IvySetApplicationPriority -IvySetBindCallback + IvyBindDirectMsg IvySendDirectMsg - -IvyArgumentNew -IvyArgumentFree -IvyArgumentGetValue -IvyArgumentGetChildrens -IvyArgumentGetNextChild -IvyAddChild -IvyAddChildValue - - +IvySetBeforeSelectHook +IvySetAfterSelectHook IvyMainLoop IvyChannelInit IvyChannelRemove IvyChannelAdd -TimerRepeatAfter -TimerModify -TimerRemove +IvyBindingCompile +IvyBindingFree + +IvyBindingExec +IvyBindingMatch @@ -6,22 +6,18 @@ * * Simple lists in C * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software */ -#ifdef WIN32 -#define TYPEOF(p) void* -#else -#if (__GNUC__ >= 2) +#if (__GNUC__ >= 3) #define TYPEOF(p) typeof (p) #else #define TYPEOF(p) void * #endif -#endif #define IVY_LIST_ITER( list, p, cond ) \ p = list; \ @@ -54,36 +50,30 @@ }\ } \ } - -#define IVY_LIST_ADD(list, p ) \ +/* +on place le code d'initialisation de l'objet entre START et END +pour eviter de chainer un objet non initialise +*/ +#define IVY_LIST_ADD_START(list, p ) \ if ((p = (TYPEOF(p)) (malloc( sizeof( *p ))))) \ { \ - memset( p, 0 , sizeof( *p ));\ - p->next = list; \ - list = p; \ - } + memset( p, 0 , sizeof( *p )); #define IVY_LIST_ADD_END(list, p ) \ - if ((p = (TYPEOF(p)) (malloc( sizeof( *p ))))) \ - { \ - TYPEOF(p) list_end; \ - memset( p, 0 , sizeof( *p ));\ - p->next = 0; \ - if ( list ) \ - {\ - list_end = list; \ - while ( list_end && list_end->next ) \ - list_end = list_end->next;\ - list_end->next = p; \ + p->next = list; \ + list = p; \ } \ - else list = p; \ + else \ + { \ + perror( "IVY LIST ADD malloc" ); \ + exit(0); \ } #define IVY_LIST_EACH( list, p ) \ for ( p = list ; p ; p = p -> next ) -#define IVY_LIST_EACH_SAFE( list, p, p_next )\ -for ( p = list ; (p_next = p ? p->next: p ),p ; p = p_next ) +#define IVY_LIST_EACH_SAFE( list, p, next )\ +for ( p = list ; (next = p ? p->next: p ),p ; p = next ) #define IVY_LIST_EMPTY( list ) \ { \ diff --git a/src/timer.c b/src/timer.c index 7efb3ce..4e38c52 100644 --- a/src/timer.c +++ b/src/timer.c @@ -6,7 +6,7 @@ * * Timers used in select based main loop * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * @@ -15,20 +15,16 @@ */ /* Module de gestion des timers autour d'un select */ - #include <stdio.h> #include <sys/types.h> #include <time.h> #include <stdlib.h> #include <memory.h> - #ifdef WIN32 -#include <crtdbg.h> #include <windows.h> #else #include <sys/time.h> #endif - #include "list.h" #include "timer.h" @@ -107,18 +103,16 @@ TimerId TimerRepeatAfter( int count, long time, TimerCb cb, void *user_data ) /* si y a rien a faire et ben on fait rien */ if ( cb == NULL ) return NULL; - IVY_LIST_ADD( timers, timer ) - if ( timer ) - { - timer->repeat = count; - timer->callback = cb; - timer->user_data = user_data; - stamp = currentTime(); - timer->period = time; - timer->when = stamp + time; - if ( (timer->when < nextTimeout) || (timeoutptr == NULL)) - SetNewTimeout( stamp, timer->when ); - } + IVY_LIST_ADD_START( timers, timer ) + timer->repeat = count; + timer->callback = cb; + timer->user_data = user_data; + stamp = currentTime(); + timer->period = time; + timer->when = stamp + time; + if ( (timer->when < nextTimeout) || (timeoutptr == NULL)) + SetNewTimeout( stamp, timer->when ); + IVY_LIST_ADD_END( timers, timer ) return timer; } void TimerRemove( TimerId timer ) @@ -143,6 +137,10 @@ void TimerModify( TimerId timer, long time ) struct timeval *TimerGetSmallestTimeout() { + unsigned long stamp; + /* recalcul du prochain timeout */ + stamp = currentTime(); + AdjTimeout( stamp ); return timeoutptr; } @@ -174,6 +172,5 @@ void TimerScan() } } } - /* recalcul du prochain timeout */ - AdjTimeout( stamp ); + } diff --git a/src/timer.h b/src/timer.h index c62b505..f8f21a5 100644 --- a/src/timer.h +++ b/src/timer.h @@ -6,7 +6,7 @@ * * Timers for select-based main loop * - * Authors: François-Régis Colin <fcolin@cena.fr> + * Authors: François-Régis Colin <fcolin@cena.dgac.fr> * * $Id$ * diff --git a/src/version.h b/src/version.h index 072a2fb..42d32fd 100644 --- a/src/version.h +++ b/src/version.h @@ -4,8 +4,8 @@ * Copyright (C) 1997-2004 * Centre d'Études de la Navigation Aérienne * - * Authors: François-Régis Colin <colin@cena.fr> - * Stéphane Chatty <chatty@cena.fr> + * Authors: François-Régis Colin <colin@cena.dgac.fr> + * Stéphane Chatty <chatty@cena.dgac.fr> * Yannick Jestin <jestin@cena.fr> * * $Id$ @@ -25,5 +25,5 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#define IVYMAJOR_VERSION 4 -#define IVYMINOR_VERSION 0 +#define IVYMAJOR_VERSION 3 +#define IVYMINOR_VERSION 9 |