summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile193
-rwxr-xr-xsrc/Makefile.mingw2
-rwxr-xr-xsrc/Makefile.win3249
-rwxr-xr-xsrc/hash.c665
-rwxr-xr-xsrc/hash.h29
-rw-r--r--src/intervalRegexp.c432
-rw-r--r--src/intervalRegexp.h14
-rw-r--r--src/ivy.c1045
-rw-r--r--src/ivy.h71
-rwxr-xr-xsrc/ivyargument.c180
-rwxr-xr-xsrc/ivyargument.h35
-rw-r--r--src/ivybind.c249
-rw-r--r--src/ivybind.h22
-rw-r--r--src/ivybuffer.c82
-rw-r--r--src/ivybuffer.h39
-rw-r--r--src/ivychannel.h19
-rw-r--r--src/ivydebug.h30
-rw-r--r--src/ivyglibloop.c26
-rw-r--r--src/ivyglibloop.h3
-rwxr-xr-xsrc/ivyglutloop.c28
-rwxr-xr-xsrc/ivyglutloop.h6
-rw-r--r--src/ivyloop.c66
-rw-r--r--src/ivyloop.h37
-rwxr-xr-xsrc/ivyperf.c71
-rw-r--r--src/ivyprobe.c333
-rw-r--r--src/ivysocket.c408
-rw-r--r--src/ivysocket.h31
-rwxr-xr-xsrc/ivytcl.c21
-rwxr-xr-xsrc/ivytcl.h6
-rw-r--r--src/ivyxtloop.c29
-rw-r--r--src/ivyxtloop.h8
-rw-r--r--src/libIvy.def28
-rw-r--r--src/list.h42
-rw-r--r--src/timer.c35
-rw-r--r--src/timer.h2
-rw-r--r--src/version.h8
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
diff --git a/src/ivy.c b/src/ivy.c
index 63de4b4..5231f0d 100644
--- a/src/ivy.c
+++ b/src/ivy.c
@@ -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;
+ }
+}
diff --git a/src/ivy.h b/src/ivy.h
index 889e86b..0ee4542 100644
--- a/src/ivy.h
+++ b/src/ivy.h
@@ -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(&regexp, expression, REGCOMP_OPT|REG_EXTENDED);
@@ -138,38 +107,26 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr
else
{
regerror (reg, &regexp, 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(&reg,arg,REG_ICASE|REG_EXTENDED)!=0) {
- char errbuf[4096];
- regerror (err, &reg, 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
diff --git a/src/list.h b/src/list.h
index ff01f13..968f619 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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