From: Andreas Eversberg Date: Thu, 14 Jul 2011 12:25:42 +0000 (+0200) Subject: Merge branch 'develop' X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=da91d7d85fe092122e35ece52695f98345738359;hp=129a76d1411166176db646138b35e8f5ed9907a2 Merge branch 'develop' Conflicts: Makefile.in README chan_lcr.c configure gsm_bs.cpp gsm_ms.cpp interface.c route.c --- diff --git a/.gitignore b/.gitignore index f551c7f..570e576 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +core *.o *.po *.so @@ -6,10 +7,16 @@ stamp-h1 .deps/ Makefile -autom4te.cache/ config.h config.log config.status +*.in +aclocal.m4 +autom4te.cache/ +configure +depcomp +install-sh +missing genextension genrc gentones diff --git a/INSTALL b/INSTALL index 5458714..0894a83 100644 --- a/INSTALL +++ b/INSTALL @@ -44,6 +44,8 @@ of `autoconf'. The simplest way to compile this package is: + 0. If compile from GIT, run "./autogen.sh" first. + 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. diff --git a/Makefile.am b/Makefile.am index d8ba3bf..f047c56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,7 +51,7 @@ if ENABLE_GSM GSM_INCLUDE += -GSM_SOURCE += gsm_audio.c gsm.cpp gsm_conf.c +GSM_SOURCE += gsm_audio.c gsm.cpp GSM_LIB += /usr/lib/libgsm.a @@ -64,9 +64,7 @@ if ENABLE_GSM_BS GSM_INCLUDE += -DWITH_GSM_BS -I./openbsc/include -I./libosmocore/include -I./openbsc -GSM_SOURCE += gsm_bs.cpp openbsc/src/bsc_init.c openbsc/src/bsc_vty.c openbsc/src/vty_interface_layer3.c openbsc/src/bsc_api.c openbsc/src/bsc_version.c - -GSM_LIB += ./openbsc/src/libbsc.a ./openbsc/src/libmsc.a ./openbsc/src/libvty.a -losmovty -losmocore -ldbi -lcrypt +GSM_SOURCE += gsm_bs.cpp endif @@ -125,8 +123,8 @@ endif INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) -Wall $(INSTALLATION_DEFINES) -lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) select.c action.cpp mISDN.cpp tones.c \ - action_efi.cpp crypt.cpp mail.c trace.c \ +lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) select.c action.cpp mISDN.cpp \ + tones.c loop.c remote.c action_efi.cpp crypt.cpp mail.c trace.c \ action_vbox.cpp dss1.cpp main.c \ vbox.cpp alawulaw.c endpoint.cpp interface.c message.c \ apppbx.cpp endpointapp.cpp join.cpp options.c \ diff --git a/Makefile.in b/Makefile.in index 067dfe1..5930a8e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -33,17 +33,16 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : @ENABLE_GSM_TRUE@am__append_1 = -@ENABLE_GSM_TRUE@am__append_2 = gsm_audio.c gsm.cpp gsm_conf.c +@ENABLE_GSM_TRUE@am__append_2 = gsm_audio.c gsm.cpp @ENABLE_GSM_TRUE@am__append_3 = /usr/lib/libgsm.a #gsm_audio.po: gsm_audio.c gsm_audio.h # $(CC) -D_GNU_SOURCE -fPIC -c gsm_audio.c -o gsm_audio.po @ENABLE_GSM_BS_TRUE@am__append_4 = -DWITH_GSM_BS -I./openbsc/include -I./libosmocore/include -I./openbsc -@ENABLE_GSM_BS_TRUE@am__append_5 = gsm_bs.cpp openbsc/src/bsc_init.c openbsc/src/bsc_vty.c openbsc/src/vty_interface_layer3.c openbsc/src/bsc_api.c openbsc/src/bsc_version.c -@ENABLE_GSM_BS_TRUE@am__append_6 = ./openbsc/src/libbsc.a ./openbsc/src/libmsc.a ./openbsc/src/libvty.a -losmovty -losmocore -ldbi -lcrypt -@ENABLE_GSM_MS_TRUE@am__append_7 = -DPACKAGE_VERSION=0 -DWITH_GSM_MS -I./layer23/include -I./libosmocore/include -@ENABLE_GSM_MS_TRUE@am__append_8 = gsm_ms.cpp layer23/src/mobile/app_mobile.c -@ENABLE_GSM_MS_TRUE@am__append_9 = ./layer23/src/mobile/libmobile.a \ +@ENABLE_GSM_BS_TRUE@am__append_5 = gsm_bs.cpp +@ENABLE_GSM_MS_TRUE@am__append_6 = -DPACKAGE_VERSION=0 -DWITH_GSM_MS -I./layer23/include -I./libosmocore/include +@ENABLE_GSM_MS_TRUE@am__append_7 = gsm_ms.cpp layer23/src/mobile/app_mobile.c +@ENABLE_GSM_MS_TRUE@am__append_8 = ./layer23/src/mobile/libmobile.a \ @ENABLE_GSM_MS_TRUE@ ./layer23/src/common/liblayer23.a \ @ENABLE_GSM_MS_TRUE@ ./libosmocore/build-host/src/.libs/libosmocore.a \ @ENABLE_GSM_MS_TRUE@ ./libosmocore/build-host/src/vty/.libs/libosmovty.a \ @@ -92,23 +91,16 @@ gentones_LDADD = $(LDADD) genwave_SOURCES = genwave.c genwave_OBJECTS = genwave.$(OBJEXT) genwave_LDADD = $(LDADD) -am__lcr_SOURCES_DIST = gsm_audio.c gsm.cpp gsm_conf.c gsm_bs.cpp \ - openbsc/src/bsc_init.c openbsc/src/bsc_vty.c \ - openbsc/src/vty_interface_layer3.c openbsc/src/bsc_api.c \ - openbsc/src/bsc_version.c gsm_ms.cpp \ +am__lcr_SOURCES_DIST = gsm_audio.c gsm.cpp gsm_bs.cpp gsm_ms.cpp \ layer23/src/mobile/app_mobile.c ss5.cpp ss5_encode.c \ - ss5_decode.c select.c action.cpp mISDN.cpp tones.c \ - action_efi.cpp crypt.cpp mail.c trace.c action_vbox.cpp \ - dss1.cpp main.c vbox.cpp alawulaw.c endpoint.cpp interface.c \ - message.c apppbx.cpp endpointapp.cpp join.cpp options.c \ - extension.c joinpbx.cpp port.cpp callerid.c joinremote.cpp \ - route.c cause.c socket_server.c -@ENABLE_GSM_TRUE@am__objects_1 = gsm_audio.$(OBJEXT) gsm.$(OBJEXT) \ -@ENABLE_GSM_TRUE@ gsm_conf.$(OBJEXT) -@ENABLE_GSM_BS_TRUE@am__objects_2 = gsm_bs.$(OBJEXT) \ -@ENABLE_GSM_BS_TRUE@ bsc_init.$(OBJEXT) bsc_vty.$(OBJEXT) \ -@ENABLE_GSM_BS_TRUE@ vty_interface_layer3.$(OBJEXT) \ -@ENABLE_GSM_BS_TRUE@ bsc_api.$(OBJEXT) bsc_version.$(OBJEXT) + ss5_decode.c select.c action.cpp mISDN.cpp tones.c loop.c \ + remote.c action_efi.cpp crypt.cpp mail.c trace.c \ + action_vbox.cpp dss1.cpp main.c vbox.cpp alawulaw.c \ + endpoint.cpp interface.c message.c apppbx.cpp endpointapp.cpp \ + join.cpp options.c extension.c joinpbx.cpp port.cpp callerid.c \ + joinremote.cpp route.c cause.c socket_server.c +@ENABLE_GSM_TRUE@am__objects_1 = gsm_audio.$(OBJEXT) gsm.$(OBJEXT) +@ENABLE_GSM_BS_TRUE@am__objects_2 = gsm_bs.$(OBJEXT) @ENABLE_GSM_MS_TRUE@am__objects_3 = gsm_ms.$(OBJEXT) \ @ENABLE_GSM_MS_TRUE@ app_mobile.$(OBJEXT) am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3) @@ -116,22 +108,18 @@ am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3) @ENABLE_SS5_TRUE@ ss5_decode.$(OBJEXT) am_lcr_OBJECTS = $(am__objects_4) $(am__objects_5) select.$(OBJEXT) \ action.$(OBJEXT) mISDN.$(OBJEXT) tones.$(OBJEXT) \ - action_efi.$(OBJEXT) crypt.$(OBJEXT) mail.$(OBJEXT) \ - trace.$(OBJEXT) action_vbox.$(OBJEXT) dss1.$(OBJEXT) \ - main.$(OBJEXT) vbox.$(OBJEXT) alawulaw.$(OBJEXT) \ - endpoint.$(OBJEXT) interface.$(OBJEXT) message.$(OBJEXT) \ - apppbx.$(OBJEXT) endpointapp.$(OBJEXT) join.$(OBJEXT) \ - options.$(OBJEXT) extension.$(OBJEXT) joinpbx.$(OBJEXT) \ - port.$(OBJEXT) callerid.$(OBJEXT) joinremote.$(OBJEXT) \ - route.$(OBJEXT) cause.$(OBJEXT) socket_server.$(OBJEXT) + loop.$(OBJEXT) remote.$(OBJEXT) action_efi.$(OBJEXT) \ + crypt.$(OBJEXT) mail.$(OBJEXT) trace.$(OBJEXT) \ + action_vbox.$(OBJEXT) dss1.$(OBJEXT) main.$(OBJEXT) \ + vbox.$(OBJEXT) alawulaw.$(OBJEXT) endpoint.$(OBJEXT) \ + interface.$(OBJEXT) message.$(OBJEXT) apppbx.$(OBJEXT) \ + endpointapp.$(OBJEXT) join.$(OBJEXT) options.$(OBJEXT) \ + extension.$(OBJEXT) joinpbx.$(OBJEXT) port.$(OBJEXT) \ + callerid.$(OBJEXT) joinremote.$(OBJEXT) route.$(OBJEXT) \ + cause.$(OBJEXT) socket_server.$(OBJEXT) lcr_OBJECTS = $(am_lcr_OBJECTS) am__DEPENDENCIES_1 = -@ENABLE_GSM_BS_TRUE@am__DEPENDENCIES_2 = ./openbsc/src/libbsc.a \ -@ENABLE_GSM_BS_TRUE@ ./openbsc/src/libmsc.a \ -@ENABLE_GSM_BS_TRUE@ ./openbsc/src/libvty.a -am__DEPENDENCIES_3 = $(am__append_3) $(am__DEPENDENCIES_2) \ - $(am__append_9) -lcr_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) +lcr_DEPENDENCIES = $(am__DEPENDENCIES_1) $(GSM_LIB) am_lcradmin_OBJECTS = lcradmin.$(OBJEXT) cause.$(OBJEXT) \ options.$(OBJEXT) lcradmin_OBJECTS = $(am_lcradmin_OBJECTS) @@ -276,17 +264,17 @@ INSTALLATION_DEFINES = \ -DLOG_DIR="\"$(LOGdir)\"" \ -DEXTENSION_DATA="\"$(EXTENSIONdir)\"" -GSM_INCLUDE = $(am__append_1) $(am__append_4) $(am__append_7) -GSM_SOURCE = $(am__append_2) $(am__append_5) $(am__append_8) -GSM_LIB = $(am__append_3) $(am__append_6) $(am__append_9) +GSM_INCLUDE = $(am__append_1) $(am__append_4) $(am__append_6) +GSM_SOURCE = $(am__append_2) $(am__append_5) $(am__append_7) +GSM_LIB = $(am__append_3) $(am__append_8) @ENABLE_SS5_TRUE@SS5_INCLUDE = -DWITH_SS5 @ENABLE_SS5_TRUE@SS5_SOURCE = ss5.cpp ss5_encode.c ss5_decode.c @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_SOURCES = @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_LDFLAGS = -shared @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_LDADD = chan_lcr.po bchannel.po options.po callerid.po select.po INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) -Wall $(INSTALLATION_DEFINES) -lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) select.c action.cpp mISDN.cpp tones.c \ - action_efi.cpp crypt.cpp mail.c trace.c \ +lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) select.c action.cpp mISDN.cpp \ + tones.c loop.c remote.c action_efi.cpp crypt.cpp mail.c trace.c \ action_vbox.cpp dss1.cpp main.c \ vbox.cpp alawulaw.c endpoint.cpp interface.c message.c \ apppbx.cpp endpointapp.cpp join.cpp options.c \ @@ -474,10 +462,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alawulaw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/app_mobile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apppbx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsc_api.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsc_init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsc_version.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsc_vty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callerid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cause.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Po@am__quote@ @@ -492,19 +476,20 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_audio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_bs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_conf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_ms.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/join.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joinpbx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joinremote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lcradmin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mISDN.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_server.Po@am__quote@ @@ -514,7 +499,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tones.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vbox.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vty_interface_layer3.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -530,76 +514,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` -bsc_init.o: openbsc/src/bsc_init.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_init.o -MD -MP -MF $(DEPDIR)/bsc_init.Tpo -c -o bsc_init.o `test -f 'openbsc/src/bsc_init.c' || echo '$(srcdir)/'`openbsc/src/bsc_init.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_init.Tpo $(DEPDIR)/bsc_init.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_init.c' object='bsc_init.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_init.o `test -f 'openbsc/src/bsc_init.c' || echo '$(srcdir)/'`openbsc/src/bsc_init.c - -bsc_init.obj: openbsc/src/bsc_init.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_init.obj -MD -MP -MF $(DEPDIR)/bsc_init.Tpo -c -o bsc_init.obj `if test -f 'openbsc/src/bsc_init.c'; then $(CYGPATH_W) 'openbsc/src/bsc_init.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_init.c'; fi` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_init.Tpo $(DEPDIR)/bsc_init.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_init.c' object='bsc_init.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_init.obj `if test -f 'openbsc/src/bsc_init.c'; then $(CYGPATH_W) 'openbsc/src/bsc_init.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_init.c'; fi` - -bsc_vty.o: openbsc/src/bsc_vty.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_vty.o -MD -MP -MF $(DEPDIR)/bsc_vty.Tpo -c -o bsc_vty.o `test -f 'openbsc/src/bsc_vty.c' || echo '$(srcdir)/'`openbsc/src/bsc_vty.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_vty.Tpo $(DEPDIR)/bsc_vty.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_vty.c' object='bsc_vty.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_vty.o `test -f 'openbsc/src/bsc_vty.c' || echo '$(srcdir)/'`openbsc/src/bsc_vty.c - -bsc_vty.obj: openbsc/src/bsc_vty.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_vty.obj -MD -MP -MF $(DEPDIR)/bsc_vty.Tpo -c -o bsc_vty.obj `if test -f 'openbsc/src/bsc_vty.c'; then $(CYGPATH_W) 'openbsc/src/bsc_vty.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_vty.c'; fi` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_vty.Tpo $(DEPDIR)/bsc_vty.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_vty.c' object='bsc_vty.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_vty.obj `if test -f 'openbsc/src/bsc_vty.c'; then $(CYGPATH_W) 'openbsc/src/bsc_vty.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_vty.c'; fi` - -vty_interface_layer3.o: openbsc/src/vty_interface_layer3.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vty_interface_layer3.o -MD -MP -MF $(DEPDIR)/vty_interface_layer3.Tpo -c -o vty_interface_layer3.o `test -f 'openbsc/src/vty_interface_layer3.c' || echo '$(srcdir)/'`openbsc/src/vty_interface_layer3.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/vty_interface_layer3.Tpo $(DEPDIR)/vty_interface_layer3.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/vty_interface_layer3.c' object='vty_interface_layer3.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vty_interface_layer3.o `test -f 'openbsc/src/vty_interface_layer3.c' || echo '$(srcdir)/'`openbsc/src/vty_interface_layer3.c - -vty_interface_layer3.obj: openbsc/src/vty_interface_layer3.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vty_interface_layer3.obj -MD -MP -MF $(DEPDIR)/vty_interface_layer3.Tpo -c -o vty_interface_layer3.obj `if test -f 'openbsc/src/vty_interface_layer3.c'; then $(CYGPATH_W) 'openbsc/src/vty_interface_layer3.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/vty_interface_layer3.c'; fi` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/vty_interface_layer3.Tpo $(DEPDIR)/vty_interface_layer3.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/vty_interface_layer3.c' object='vty_interface_layer3.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vty_interface_layer3.obj `if test -f 'openbsc/src/vty_interface_layer3.c'; then $(CYGPATH_W) 'openbsc/src/vty_interface_layer3.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/vty_interface_layer3.c'; fi` - -bsc_api.o: openbsc/src/bsc_api.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_api.o -MD -MP -MF $(DEPDIR)/bsc_api.Tpo -c -o bsc_api.o `test -f 'openbsc/src/bsc_api.c' || echo '$(srcdir)/'`openbsc/src/bsc_api.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_api.Tpo $(DEPDIR)/bsc_api.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_api.c' object='bsc_api.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_api.o `test -f 'openbsc/src/bsc_api.c' || echo '$(srcdir)/'`openbsc/src/bsc_api.c - -bsc_api.obj: openbsc/src/bsc_api.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_api.obj -MD -MP -MF $(DEPDIR)/bsc_api.Tpo -c -o bsc_api.obj `if test -f 'openbsc/src/bsc_api.c'; then $(CYGPATH_W) 'openbsc/src/bsc_api.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_api.c'; fi` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_api.Tpo $(DEPDIR)/bsc_api.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_api.c' object='bsc_api.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_api.obj `if test -f 'openbsc/src/bsc_api.c'; then $(CYGPATH_W) 'openbsc/src/bsc_api.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_api.c'; fi` - -bsc_version.o: openbsc/src/bsc_version.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_version.o -MD -MP -MF $(DEPDIR)/bsc_version.Tpo -c -o bsc_version.o `test -f 'openbsc/src/bsc_version.c' || echo '$(srcdir)/'`openbsc/src/bsc_version.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_version.Tpo $(DEPDIR)/bsc_version.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_version.c' object='bsc_version.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_version.o `test -f 'openbsc/src/bsc_version.c' || echo '$(srcdir)/'`openbsc/src/bsc_version.c - -bsc_version.obj: openbsc/src/bsc_version.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bsc_version.obj -MD -MP -MF $(DEPDIR)/bsc_version.Tpo -c -o bsc_version.obj `if test -f 'openbsc/src/bsc_version.c'; then $(CYGPATH_W) 'openbsc/src/bsc_version.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_version.c'; fi` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/bsc_version.Tpo $(DEPDIR)/bsc_version.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='openbsc/src/bsc_version.c' object='bsc_version.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsc_version.obj `if test -f 'openbsc/src/bsc_version.c'; then $(CYGPATH_W) 'openbsc/src/bsc_version.c'; else $(CYGPATH_W) '$(srcdir)/openbsc/src/bsc_version.c'; fi` - app_mobile.o: layer23/src/mobile/app_mobile.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT app_mobile.o -MD -MP -MF $(DEPDIR)/app_mobile.Tpo -c -o app_mobile.o `test -f 'layer23/src/mobile/app_mobile.c' || echo '$(srcdir)/'`layer23/src/mobile/app_mobile.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/app_mobile.Tpo $(DEPDIR)/app_mobile.Po @@ -955,19 +869,19 @@ uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr.po: chan_lcr.c chan_lcr.h -@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) $(AST_CFLAGS) -D_GNU_SOURCE -fPIC -c chan_lcr.c -o chan_lcr.po +@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) $(AST_CFLAGS) $(CPPFLAGS) $(CFLAGS) -D_GNU_SOURCE -fPIC -c chan_lcr.c -o chan_lcr.po @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@bchannel.po: bchannel.c bchannel.h -@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE -fPIC -c bchannel.c -o bchannel.po +@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE $(CPPFLAGS) $(CFLAGS) -fPIC -c bchannel.c -o bchannel.po @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@callerid.po: callerid.c callerid.h -@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE -fPIC -c callerid.c -o callerid.po +@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE $(CPPFLAGS) $(CFLAGS) -fPIC -c callerid.c -o callerid.po @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@options.po: options.c options.h -@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE -fPIC -c options.c -o options.po +@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE $(CPPFLAGS) $(CFLAGS) -fPIC -c options.c -o options.po @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@select.po: select.c select.h -@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE -fPIC -c select.c -o select.po +@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ $(CC) $(INCLUDES) -D_GNU_SOURCE $(CPPFLAGS) $(CFLAGS) -fPIC -c select.c -o select.po @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@install-exec-hook: @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@ mkdir -p $(astmoddir) diff --git a/README b/README index 8515363..ffd2bdb 100644 --- a/README +++ b/README @@ -24,534 +24,3 @@ Read the documentation at http://www.linux-call-router.de Also you will find a quick howto there. -History: --------- - -Changes in Version 20021228 -- first release - -Changes in Version 20030111 (buggy and unuseable) -- support dtmf for callback and dtmf dialing mode (dial through via dtmf) -- bug fixes -- dialing improvement: dialing h323 now possible with port and alias -- other stuff -- new Makefile: make install will now install binaries and data on your system - -Changes in Version 20030118 (buggy and unuseable) -- information exchange between isdn/h323-ports, endpoints and calls are messages now - previousely using direct calls with pointers were dangerous -- removed bug since 200301011, which caued h323 calls to deadlock - -Changes in Version 20030120 -- login function -- callback authentication -- h323 audio bug. no h323 audio transmission sice version 20030111 -- some other bug fixes - -Changes in Version 20030206 (first beta release 1.0) -- callerid (CLIP/COLP) is now processed correctly with all features -- hold sound and active/inactive notification -- CD notification -- many callerid display function -- bug fixes -- documentation as word document (partly done) -- Note: This week I have my vakation, so there is no response to any question in the mailing list. - -Changes in Version 1.0 -- first release -- finished the first version of the documentation -- new style internet page with documentation in html -- all enities (port, endpoint, call) are now c++ objects, rather than structures -- tones may now be played and recorded using wave (8bit mono, 16bit mono, 16bit stereo) or law (alwa/ulaw mono) -- fixed corruption in wave-file creation -- now call forwad (cfb, cfnr) is implemented and working -- an answering machine with playback function is implemented. -- lots of bug fixes - -Changes in Version 1.1 -- option to fetch tones into memory, causing faster access, then from hard disk -- Memory is now locked using mlockall(), to prevent paging which causes jitter and interruption. -- Answering machine now works with keypad information. -- callback on internal port, if hangup with call on hold. -- A pocket calcularor with simple terms (*, /, +, -) and floating point is added. -- If a calls had more than two endpoints, any message has been ignored. - This caused not to receive the retreive notification, which caused the hold - music to continue to play. -- minor buf fixes -- Disconnect/release "causes" are now processed by priority, if a multipoint call is made. - -Changes in Version 1.2 -- bugfix: dialing of vbox-caller now works. -- bugfix: minor answering machine announcement bug -- fixed compiling error: h323_con.cpp (p_type not declared) thanx arne! -- added include definition for kernel api in Makefile. Hope it works... -- fix: dummyid is used for external calls when no caller id is available. the - dummy id is transmitted as restricted id. if the police is called, it will - see the dummyid rather than the pbx line id. this is used on forwarded calls - when the caller id is not available. -- doc: added a simple instruction to build a cross over cable. - -Changes in Version 2.0pre -- NEW ISDN DRIVER SUPPORT (Forget the HiSax, now use 'mISDN'.) -- NEW KERNEL REALTIME MODULE (mISDN_dsp.o) -- NEW NT-MODE LIBRARY SUPPORT (now MULTIPOINT!!!) -- NEW TE-MODE STACK SUPPORT -- support of call suspension and retrieval (switch between calls) -- call waiting on internal phone (calls when no bchannel is available) -- doc: Now headlines are moved to the next page if they are at the bottom of a - page. -- vbox: minor speech syntax bugfix -- up to 50 (compiler flag) dialed numbers can be recalled. -- up to 50 (compiler flag) received calls are listed and can be replied. -- Dialing informations are now queued by endpoint until port has received - setup acknowledge on the outgoing connection. -- Starting PBX without parameter gives a list of options. -- Query option for listing available ports/cards. -- CNIP (calling name) Some Simens switches and telephones support this. -- Extensions no have names. -- Timeouts can now be specified for different call states on ISDN phones. -- Tones/Announcements can now be overridden at different call states. -- isdn.cpp is completely reworked. -- Tones/Announcements can be played externally, if supported by the external - line. -- Commandline parameters must be given on startup of pbx. -- query option to check out the current isdn cards and protocolls. -- Debug flags can now be used to speciallize the debug output. -- vbox: Recorded calls can now be sent as attached sound file via email, or - just a notifaction mail without sound file can be sent. -- PBX now runs with highest prio (99) to get as much cpu as possible. -- CPU scheduler now runs PBX4Linux as real time process. -- Internal calls now use internal extension number as caller id. -- Rework of hold/conference. -- New option to allow an incoming h323-call to be connected at ringing state. -- New codecs supported with h323 (speex and law) -- COLP now works with h323 -- Answering machine now delays to avoid the dtmf tone when start recording -- Answering machine now adds the beep behind the announcement file. -- keypad facility dialing option -- Conference now really works using call hold feature in conjunction with - keypad feature -- Picking of an incoming call on isdn now really works. -- picking of a call forwarded to vbox -- I fixed a bug that did not queue the dialed digits correctly before getting - an external connecting. -- Logfiles of calls now show the correct year. -- Callback now rejects if no password is given or the given extension doesn't - exist. -- Incoming H.323 calls may now instantly connect using a special option. -- H323 compiles faster, because the H323 includes are only used for the H323 - code part. -- Using 'curses' for a state debugging. The current state of all instances - is displayed on the screen including calls, endpoints and ports. -- manny, manny more things that I forgot - -Changes in Version 2.0 -- fixed memory leak -- fixed COLP bug -- finally SUSPEND/RESUME (call parking), resume is allowed from any ISDN-port -- some CRITICAL bugfixes -- Fixed and reworked sample counting when playing tones. Now fast wind and - rewind works correctly. Also 8-bit recording can be played back now. - I hope it works now without problems. -- An internal phone without caller id will now be rejected rather than - treated as an extenal call. -- Fixed bug in rejecting an external call. -- Corrected handeling of 'inbandpatterns'. -- Data calls will not enable DTMF detection. -- Data calls will not use any audio transmission from user space. -- Forward to VBOX only if call is an audio call. -- Fixed library bug, that caused not to process keypad-information during - setup message. -- Fixed a 'release_complete' bug. -- Debug information now have the correct month. -- Fixed bug of wave-playback of voicebox recoding, caused by rework of the - audio routines. It caused a SEGMENTATION FAULT! -- Using threads now to send email and using libcrypto. -- Introducing encryption of external calls using Blowfish. -- Key exchange using RSA. -- Fixed a bug in dialing H323-IP with numerical digits. -- Fixed a bug that causes endpoint, which receives audio data, to crash when - no port is related to it. -- Fixed a bug that did not release endpoint, when it receives a disconnect - if it has no port (parked). -- Fixed a channel assignment bug when retrieving call. (second B-channel) -- Now COLP with H.323 works. No more crash! -- Park attribute was not set, which caused a crash. -- Conference now works correctly with dsp-module. -- Fixed a serious NT-mode process handling problem. (crash after some calls) -- Added log file which is also displayed on the 'state' screen. -- * Happy new year 2004 * - -Changes in Version 2.1 -- Fixed a bug that caused not to reply external calls (also VBOX). -- 'genrc' now supports loading HFC-4S, HFC-8S and HFC-E1 drivers -- Outgoing setup now expires after 8 seconds! -- Fixed a bug that causes mISDNuser to crash during cleanup. -- Fixed memory bug, thanx Paul! -- hfc-4s/8s driver support (mISDN) -- Improvement of isdn audio processing, hardware support. -- Fixed diplay callerid bug "anonymousunknown anon" -- Added more stable malloc (calloc) / free handling - -Changes in Version 2.2 -- PRI proof (2 MBit interface support when using HFC-E1) -- Fixed data call bug -- Improved display of PRI channels -- Now VBOX playback says "no messages" if the last message has been deleted - and will not play the last but one, unless the "previous" button has been - pressed. - -Changes in Version 2.3 -- Fixed HFC_MULTI driver activation problem (HW_RESET was not implemented) -- Fixed login prefix bug. Thanx Karsten V. -- MISDN: better layer 2 check -- Now facility informations are transfered during call to terminal - (finally advice of charge is displayed) MUST BE ENABLED BY SETTINGS! -- Fixed 'reply' dialing bug, that caused a crash. Thanx Karsten V. -- Added L1 activation for NT-Mode. Fixed problems with inactive links. -- Fixed a bug that caused subsequent data calls after a data call. Thanx JC. -- mISDN: layer 1 now works correct with E1 cards. - -Changes in Version 2.4 -- Fixed parallel ringing to multiple external numbers. -- Fixed login again (was still buggy). - -Changes in Version 2.5 -- Fixed callback bug. (International numbers were not detected.) -- Fixed typos (mostly "incoming") - thanx Lars. -- Fixed vbox-email bug - thanx Martin. (and also the compiler error) -- Fixed compiler bug, that caused compiling without crypto lib to fail. -- Fixed some mISDN crash problems. -- Now it should also compile with the original CVS tree. -- Fixed hfc_multi unloading bug - thanx Karsten! -- Now disabling DSP_MODULE really causes DSP to be disabled. -- Now disabling real time scheduling really works. -- mISDNuser (CVS) now compiles with the mISDN (CVS) -- Adding the outdial prefix to the caller ID is now possible. -- Fixed bug that caused echo test not to work. -- And finally hardware echo now works on HFC 4s/8s/E1 (hfc_multi) - For echo dial 993 (Test + 3) for standard configuration. -- Added new hfc_multi vendor IDs including "Beronet Cards". - -Changes in Version 2.6 -- Fixed hookflash bug in conjunction with prefix. Thanx Tobias! -- Fixed cleanup bug when loading of ISDN driver failed. -- Fixed mISDN bug that caused cards not to be found, if loaded in different - order as found by kernel. -- Fixed a bug that causes a segfault when a phone disconnects while - parallel ringing multiple phones/ports. -- Added capability for Point-To-Point in NT mode, including PRI. -- Added L1 link control for NT mode. -- Fixed bug in hfc_multi and mISDN driver that caused mISDN not to work - with kernel > 2.6.7. -- Fixed a but when detecting different cards with hfc_multi. -- Fixed timer bug that caused timers of multiple NT ports not to work - correctly. - -Changes in Version 2.7 -- Fixed lots of bugs. -- Now receive stream from mISDN is disabled when not needed. -- Added NT mode support for incoming "SETUP_ACKNOWLEDGE". - -Changes in Version 3.0 -- Advanced routing capability to replace the numbering_*.conf - (Don't worry, internal and external numbering is a feature of the routing - capability and is easy to convert.) -- Now correct cause location is generated and handled. -- New cause display feature. Location is displayed with the cause number. -- Many source cleanups. -- New interface (Unix socket) to administrate. Status informations are now - viewable without restarting PBX. Even may processes may view status info. - Starting / stopping state debugging, doesn't require to restart PBX. -- Status information now has selectable details. -- Better structure for debugging functions and better logging. (code) -- Dialing may also be done via command line interface. -- Now internel/external dialtone and ringing depends on internal/external call. -- Now endpoints (partys) can be released via command line (admin tool). -- Watchdog "pbxwatch" to automatically restart and even debug PBX4Linux. -- Removed problem with uninitialized variable in ISDNPort object causing to - crash. It did not happen very often.(only after some hundred/thousand calls) -- HFC-E1 cards did not correctly synchronize to external lines. -- dsp.o now allocates only one timeslot per call, as expected. -- mISDNuser now correctly connects PRI calls. -- PRI improvements and bugfixes. -- Support for conference rooms. -- Voice box is now able to play announcement before connecting the call. - A special feature on the external line is required to send audio before - answering the call. -- It is now possible to include seconds (time) in the connect message. This - might not be supported by all telephones, so it is an optional feature. -- Moved open and close of recording audio to the "Port" class, where it - belongs. The mixer will be more performant this way. -- Notify is now supported by mISDN and also correctly handled and queued - by PBX. -- Fixed bug that caused not to free broadcast process IDs in certain cases. - This would cause calls to internal phones (from extern or intern) not to - work after a while. -- Added HFC-S USB to 'genrc' tool. -- printisdn now shows corret month. - -Changes in Version 3.0-fix1 -- Rule for changing the forwarding now works. Enter "pbx rules forward" for - description. Also the example in "defaults/route.conf" is corrected. -- Forking now forks twice and suppresses debug output. Closing of shell is - possible. - -Changes in Version 3.0-fix2 -- Fixed memory leak bug in pbxadmin that caused to eat all memory and make it - stop. -- Fixed audio handling that cause forking calls to be mute. (Parallel - forwarding causes calls to fork to multiple destinations.) - -Changes in Version 3.0-fix3 -- Added "nopassword" parameter for login action. -- Fixed bolean condition bug. -- pbxadmin will not exit if terminal size changes. - -Changes in Version 3.1 -- Internal structure changed. "Endpoints" and "applications" are now two - linked classes. The code is now reusable for other projects than - "PBX4Linux". (No added features!) -- Some source cleanups. -- Now keypad must be enabled for each extension if required. (settings) -- Removed a new bug that caused remotely parked/holded calls not to be removed - from conference. The conference got disturbed by park/hold sound from - remote. -- Removed bug that caused printing of unset pointers. - -Changes in Version 3.2 -- PBX now works with mqueue branch. This is the latest CVS source: - * HFCmulti is ported - * HFC-PCI is ported - * DSP is ported - * nt-mode lib (libi4l) is ported - * source is now SMP (multiple processors or hyperthreading) save. -- Fixed bug that caused not to record if annoucement is missing -- A prefix may be specified with callback for predefined dialing after - callback. -- Now b-channels are displayed more compressed on admin tool. - -Changes in Version 3.3 -- * te-mode works -- * te-mode layer 1 and layer 2 control works (SHORTMESSAGE) - -Changes in Version 3.3-fix2 -- OpenH323 midas release compiles -- Fixed bug in MESSAGE_NOTIFY which cases display information not to dliver. -- OpenH323 midas release works currently only with law-codecs -- Dixed some dial string parsing for Openh323. - -Changes in Version 3.3-fix3 -- Rework of kernel audio briding. Much faster (less delay), dynamically - handles jitter. Ready for future RTP / ISDNoIP modules. - -Changes in Version 3.4 -- Removed DSP_MODULE switch, because it will be essential for PBX operation. -- Fixed pbxadmin offset bug. -- Added special feature "efi" to announce caller's ID. You call, and it tells - your caller ID. (if available) Sample set is not complete! -- Now caller ID and type can be given for external call rule. -- Now caller ID and type can be given for changing caller ID. -- Removed a display bug in pbxadmin, that caused busy channels to be omitted. -- Fixed layer 2 handling bug. -- Increased performance of pbx-status screen. Many interfaces/calls caused - lock up of machine. -- Timeout condition seems to work now. -- Timeout action seems to work now. - -New Verion for new name: LCR - -Changes in Version 0.1 -- Statefull b-channel open and closing -- Rebuild audio flow - Made much simpler - Preloading and keeping transmit buffer for seamless tones and patterns. - Recording of what is actually transmitted and received by party. -- Logging is replaced by trace -- New isdn interface and port structure with many features - Interfaces can be changed at runtime. - Interfaces can be loaded and unloaded at runtime. -- mISDN stack fixes -- DDI in and out on all stacks -- Layer 1 over IP supports interconnection via IP -- Rebuild line and b-channel hunting with individual lists -- Screen lists for changing caller IDs -- Multiplexing calls to multiple extensions -- Removed all VoIP stuff to make core fast and stable (Use Asterisk for VoIP.) -- Fixed a bug that caused some isdn connections to hang during disconnect -- Many bug fixes -- Many minor improvements -- New bugs of course... -- Rename of 'Call' instances to 'Join', because they join parties together. -- A new remote interface for external applications is integrated - -> Our first application is (-: *ASTERISK CHANNEL DRIVER* :-) - -Changes in Version 0.2 -- Fixed partyline handling -- Stall warning -- Audio recoriding still does not work. - -Changes in Version 0.3 -- Added join/release jingle options for partylines -- Fixed bug that did not release reserved channels, so interface run out of - channels. -- Bugfixes... -- Minor bugfixes -****** Major hfc_multi bugfix ******* -* no more crash with multiple cards * -************************************* -- Screening bug removed. (Thanx Martin) -- Wave files with FMT header > 16 now work. -- Added timeouts for testcall feature. (lcradmin) - -> You can run scripts, that generate testcalls of multiple destinations. -- Added origin flag to correctly process last_in and last_out call logging. -- Tones and annoucements are not overwritten if exist, during installation. -- Screening now also works for outgoing calls (to interface) -- Fixed VBox, also added trace debugging. -- Nice 'Beep' after the announcement. -- Special announcement recording without beep. -- Filters now work for interface.conf -- Fixed minor audio gain bug. -- Moved timeout setting from extension to interface.conf. - -Changes in Version 0.4 -- Complete set of EFI samples - -Changes in Version 0.5 -- Preperations for Asterisk channel driver (chan_lcr) -- Errors in information elements are now reported inside log/trace. -- Recover bchannel (de-)activation if message from mISDN got lost - -Changes in Version 1.0 -- Bugfixes -- Complete port to new mISDN V2 API (socket based). - -> Old mISDN will not work anymore. -- Interfaces mode (NT/TE PTP/PTMP) can now be changed at runtime. - -> No more module parameters must be given for cards. -- First Alpha release of chan_lcr - the Asterisk PBX channel link driver. - -> Use LCR in conjunction with Asterisk, or simply as ISDN frontend. - -Changes in Version 1.1 -- Fixed dtmf bug. -- Added more display infos -- Fixed b-channel check bug. (channel seemed busy, even if it was free) -- Forced proceeding, if "sending complete". -- Removed 'lcr query'. It is obsolete, because 'isdninfo' does it. -- Fixed lockinproblem with chan_lcr (hopefully). -- HDLC now works and is used for B-channels, if required. -- Briding for chan_lcr fixed, many other fixed for chan_lcr. Overlap dialing! -- Compiling and 64-bit issues fixed by Karsten. -- chan_lcr fixes and tests by Peter. -- LCR now runs as user, but still can be run as root. -- Ports can now be given with number or with name. - -Changes in Version 1.2 -- Changed isdninfo to misdn_info. -- Fixed some trace bugs. -- Fixed some layer2-link issues. -- special interface config option "te-special" to allow transmit of all IEs - in TE-mode. this is usefull to interconnect LCRs. -- Introduceing autoconf (./configure) with help of Joerg and Peter. - -> Default installation path remains /usr/local/lcr, so don't worry! - -Changes in Version 1.3 -- Finished autoconf. -- Obsolete "pbxwatch" is removed. - -Changes after Version 1.3 release -- fixes in chan_lcr, thanx to peter and gregor -- message pointer forwarding fix, thanx to bodo! -- capability fix, thanx to gregor -- processing of second caller id -- Dialing length can now be limited. EWSD allows only 20 digits at a time. - -> Multiple messages are sent to dial full string. -- Added alerting and proceeding to the goto rule. -- Added patch by gregory, asterisk should now use faxdetection with mISDN_dsp - disabled. - -Changes after Version 1.4 release -- Bugfix: When reloading interfaces, interface will not be reopened, if - interface was specified by name. -- Added PID file (thanx to Joerg) -- Added Callweaver support. (thanx to Kristijan) -- Bugfix on timeout rules. (thanx to Benjamin) -- Fixed dtmf detection of A-D. (thanx to Ralf) -- Fixed Notification messages in NT-mode - -> Notifications like diversions are now sent to terminal. -- Added l1hold feature (requires new mISDN and mISDNuser). -- chan_lcr: Fixed compile problem with newer versions. -- chan_lcr: Open b-channel if asterisk indicates "PROGRESS". - -> Also if tones are available, asterisk gets "PROGRESS" indication. -- lcradmin displays TEI values in NT-mode PTMP -- Added patch from Daniel - -> Improved forking - -> Execution action can now be done on call init or on call hangup. - -New release Version 1.5 -- Added GSM network support. - -> Requires OpenBSC, GSM codec, and a BS11 base station. - -> For more refer to www.linux-call-router.de. - -Changes after Version 1.5 -- Tones are restructured: - -> mISDN_dsp.ko tones must now be specified via 'tones_dir' parameter. - -> interface.conf has a tones_dir options for individual interfaces. - -> interface.conf has priority over tones_dir in options.conf. - -> exnsion's settings has pritority over other tones_dir setting. -- Debug option now works for GSM. -- Fixed some GSM information elements. -- OpenBSC api changes. -- Fixed disabling of DTMF using 'n' option of chan_lcr. -- Added GSM IMSI dialing by using dialing "imsi-". -- Applied API change of OpenBSC. -- Applied changes of OpenBSC main branch. LCR now works with OpenBSC main - branch. -- Minor fixes and source cleanups. -- Added patch by Kai Peter to complete screening indicators. Thanx! -- Join conference during alerting phase, so calls can be forwarded. -- Fixed conference release bug. - -New release Version 1.6 - -Changes after Version 1.6 -- Fixed bad call/conference bug in joinpbx.c -- External interfaces must now be specified using 'extern' keyword. - -> This prevents from selecting other interfaces when dialing out. - -> Just add 'extern' right below your external interface definition, or give - external interface name in routing.conf: ": extern interfaces=XXXXX" -- Added experimental CCITT No. 5 signalling system. (for educational purpose) -- Added socket owner/group options to options.conf -- Fixed/simplyfied config parser. The last digit of the last line was ignored. -- Added Keypad facility - -> New option for chan_lcr: 'k' - -> New dialing parameter for LCR: keypad -- Keep up with current OpenBSC API -- Fixed DTMF detection option with chan_lcr - -New release Version 1.7 - -Changes after Version 1.7 -- Added new option to interface.conf: "nonotify" to disable notify messages. -- Replaced polling main loop by event driven "select()" loop. -- Also replaced polling main loop by event driven "select()" loop on chan_lcr. -- Added "release" action and timeout to "execute" action. -- Added queue buffer for chan_lcr sending faxes without interruption. - -> Use options "t:q250" for disabling mISDN_dsp and adding a 250ms delay. -- Fixed HLC (higher layer capability) modification to LCR routing. -- Fixed chan_lcr fax queue buffer. Added LCR_TRANSFERCAPABILITY environment. -- Fixed compiler warnings when compiling with gcc 4.3.4. -- Fixed includes to latest mISDNuser structures. -- Fix by Peter: NULL pointer issue in asterisk frame. -- Fixes a locking bug in chan_lcr. Thanx to WIMPy for that report. -- Fixed forwarding of sending-complete information. -- Added progress messages (receive only). -- Fixed redirection info in chan_lcr. Thanx to Dennis for the fix. -- Added patch to play ringing tone when connected but the call is forwarded - and ringing again. Thanx to Jacek for this patch. -- Fixed LCR to work with the current API of OpenBSC. -- Splitted GSM support into BS (network) and MS (mobile) part. - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! there is no more update here, see "git log" !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - diff --git a/aclocal.m4 b/aclocal.m4 deleted file mode 100644 index 61989b2..0000000 --- a/aclocal.m4 +++ /dev/null @@ -1,964 +0,0 @@ -# generated automatically by aclocal 1.11.1 -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, -[m4_warning([this file was generated for autoconf 2.65. -You have another version of autoconf. It may work, but is not guaranteed to. -If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically `autoreconf'.])]) - -# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.11' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.1], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.1])dnl -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 9 - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -m4_define([_AM_COND_VALUE_$1], [$2])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 10 - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], UPC, [depcc="$UPC" am_compiler_list=], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - am__universal=false - m4_case([$1], [CC], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac], - [CXX], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac]) - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -#serial 5 - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[{ - # Autoconf 2.62 quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 16 - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.62])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) -AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl -]) -_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl -dnl The `parallel-tests' driver may need to know about EXEEXT, so add the -dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro -dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. -AC_CONFIG_COMMANDS_PRE(dnl -[m4_provide_if([_AM_COMPILER_EXEEXT], - [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl -]) - -dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not -dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further -dnl mangled by Autoconf and run in a shell conditional statement. -m4_define([_AC_COMPILER_EXEEXT], -m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_arg=$1 -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi -AC_SUBST(install_sh)]) - -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 6 - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) -fi -]) - -# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check for `mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# ------------------------------ -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) - -# _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 5 - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[[\\\"\#\$\&\'\`$am_lf]]*) - AC_MSG_ERROR([unsafe absolute working directory name]);; -esac -case $srcdir in - *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; -esac - -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT(yes)]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor `install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Public sister of _AM_SUBST_NOTMAKE. -AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) -m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir - -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - -m4_include([acinclude.m4]) diff --git a/action.cpp b/action.cpp index b7dfc58..352efb4 100644 --- a/action.cpp +++ b/action.cpp @@ -1976,9 +1976,11 @@ void EndpointAppPBX::action_execute(void) end_trace(); return; } +#if 0 argv[i++] = (char *)"/bin/sh"; argv[i++] = (char *)"-c"; argv[i++] = command; +#endif argv[i++] = command; if ((rparam = routeparam(e_action, PARAM_PARAM))) { argv[i++] = rparam->string_value; @@ -1999,7 +2001,7 @@ void EndpointAppPBX::action_execute(void) case 0: /* To be shure there are no zombies created double fork */ if ((pid2 = fork()) == 0) { - execve("/bin/sh", argv, environ); + execve(command, argv, environ); } else { /* Exit immediately and release the waiting parent. The subprocess falls to init because the parent died */ diff --git a/apppbx.cpp b/apppbx.cpp index f92f167..fff80ce 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -851,6 +851,7 @@ void EndpointAppPBX::out_setup(int cfnr) int channel = 0; int earlyb; int mode = B_MODE_TRANSPARENT; + struct admin_list *admin; /* set bchannel mode */ mode = e_capainfo.source_mode; @@ -989,6 +990,21 @@ void EndpointAppPBX::out_setup(int cfnr) port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode); else #endif + if (mISDNport->ifport->remote) { + admin = admin_first; + while(admin) { + if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app)) + break; + admin = admin->next; + } + if (!admin) { + trace_header("INTERFACE (remote not connected)", DIRECTION_NONE); + add_trace("application", NULL, "%s", mISDNport->ifport->remote_app); + end_trace(); + continue; + } + port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock); + } else port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode); if (!port) FATAL("Failed to create Port instance\n"); @@ -1208,6 +1224,21 @@ void EndpointAppPBX::out_setup(int cfnr) port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode); else #endif + if (mISDNport->ifport->remote) { + admin = admin_first; + while(admin) { + if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app)) + break; + admin = admin->next; + } + if (!admin) { + trace_header("INTERFACE (remote not connected)", DIRECTION_NONE); + add_trace("application", NULL, "%s", mISDNport->ifport->remote_app); + end_trace(); + continue; + } + port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock); + } else port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode); if (!port) FATAL("No memory for Port instance\n"); @@ -2048,10 +2079,8 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, /* other calls with no caller id (or not available for the extension) and force colp */ if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) { e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT; - if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT - || portlist->port_type==PORT_TYPE_DSS1_NT_OUT - || portlist->port_type==PORT_TYPE_GSM_BS_OUT - || portlist->port_type==PORT_TYPE_GSM_MS_OUT) { /* external extension answered */ + if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) { + /* external extension answered */ port = find_port_id(portlist->port_id); if (port) { SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international)); @@ -3530,10 +3559,7 @@ void EndpointAppPBX::pick_join(char *extensions) break; } } - if ((port->p_type==PORT_TYPE_DSS1_NT_OUT - || port->p_type==PORT_TYPE_DSS1_TE_OUT - || port->p_type==PORT_TYPE_GSM_BS_OUT - || port->p_type==PORT_TYPE_GSM_MS_OUT) + if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT && port->p_state==PORT_STATE_OUT_ALERTING) if (match_list(extensions, eapp->e_ext.number)) { found = eapp; diff --git a/chan_lcr.c b/chan_lcr.c index f4d8378..3904c9a 100644 --- a/chan_lcr.c +++ b/chan_lcr.c @@ -40,7 +40,7 @@ a new call reference (ref). The ref_was_assigned ist set to 1. Further dialing information is queued. After the new callref is received by special MESSAGE_NEWREF reply, new ref -is stored in the chan_call structure. +is stored in the chan_call structure. The setup information is sent to LCR using MESSAGE_SETUP. The state changes to CHAN_LCR_STATE_OUT_SETUP. @@ -207,8 +207,6 @@ int global_change = 0; int wake_global = 0; int wake_pipe[2]; struct lcr_fd wake_fd; - -int quit; int glob_channel = 0; @@ -247,7 +245,7 @@ void chan_lcr_log(int type, const char *file, int line, const char *function, st ast_text[sizeof(ast_text)-1] = '\0'; // ast_log(type, file, line, function, "[call=%s ast=%s] %s", call_text, ast_text, buffer); - printf("[call=%s ast=%s] %s", call_text, ast_text, buffer); + printf("[call=%s ast=%s line=%d] %s", call_text, ast_text, line, buffer); ast_mutex_unlock(&log_lock); } @@ -266,7 +264,7 @@ struct chan_call *find_call_ref(unsigned int ref) { struct chan_call *call = call_first; int assigned = (ref > 0); - + while(call) { if (call->ref == ref && call->ref_was_assigned == assigned) break; @@ -595,8 +593,8 @@ void apply_opt(struct chan_call *call, char *data) default: CERROR(call, call->ast, "Option '%s' unknown.\n", opt); } - } - + } + /* re-open, if bchannel is created */ if (call->bchannel && call->bchannel->b_sock > -1) { bchannel_destroy(call->bchannel); @@ -618,29 +616,40 @@ static void send_setup_to_lcr(struct chan_call *call) if (!call->ast || !call->ref) return; +#ifdef AST_1_8_OR_HIGHER + CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s, cid=%s)\n", call->interface, call->dialstring, call->callerinfo.id); +#else CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s, cid=%s)\n", call->interface, call->dialstring, call->cid_num); +#endif /* send setup message to LCR */ memset(&newparam, 0, sizeof(union parameter)); - newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN; - newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN; + newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN; + newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN; if (call->keypad) strncpy(newparam.setup.dialinginfo.keypad, call->dialstring, sizeof(newparam.setup.dialinginfo.keypad)-1); else strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1); - strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1); - newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN; - newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN; + if (!!strcmp(call->interface, "pbx")) + strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1); + newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN; + newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN; strncpy(newparam.setup.callerinfo.display, call->display, sizeof(newparam.setup.callerinfo.display)-1); call->display[0] = '\0'; + +#ifdef AST_1_8_OR_HIGHER + /* set stored call information */ + memcpy(&newparam.setup.callerinfo, &call->callerinfo, sizeof(struct caller_info)); + memcpy(&newparam.setup.redirinfo, &call->redirinfo, sizeof(struct redir_info)); +#else if (call->cid_num[0]) strncpy(newparam.setup.callerinfo.id, call->cid_num, sizeof(newparam.setup.callerinfo.id)-1); if (call->cid_name[0]) strncpy(newparam.setup.callerinfo.name, call->cid_name, sizeof(newparam.setup.callerinfo.name)-1); if (call->cid_rdnis[0]) { strncpy(newparam.setup.redirinfo.id, call->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1); - newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN; - newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN; + newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN; + newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN; } switch(ast->cid.cid_pres & AST_PRES_RESTRICTION) { case AST_PRES_RESTRICTED: @@ -666,6 +675,7 @@ static void send_setup_to_lcr(struct chan_call *call) default: newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN; } +#endif #warning DISABLED DUE TO DOUBLE LOCKING PROBLEM // tmp = pbx_builtin_getvar_helper(ast, "LCR_TRANSFERCAPABILITY"); // if (tmp && *tmp) @@ -697,7 +707,7 @@ static void send_dialque_to_lcr(struct chan_call *call) if (!call->ast || !call->ref || !call->dialque[0]) return; - + CDEBUG(call, call->ast, "Sending dial queue to LCR. (dialing=%s)\n", call->dialque); /* send setup message to LCR */ @@ -758,7 +768,7 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c exten = "s"; CDEBUG(call, ast, "Try to start pbx. (exten=%s context=%s complete=%s)\n", exten, ast->context, complete?"yes":"no"); - + if (complete) { /* if not match */ if (!ast_canmatch_extension(ast, ast->context, exten, 1, call->oad)) { @@ -822,16 +832,16 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c call->state = CHAN_LCR_STATE_RELEASE; ast_hangup(ast); // call will be destroyed here return; - + start: /* send setup to asterisk */ CDEBUG(call, ast, "Starting call to Asterisk due to matching extension.\n"); - #ifdef LCR_FOR_CALLWEAVER + #ifdef LCR_FOR_CALLWEAVER ast->type = "LCR"; snprintf(ast->name, sizeof(ast->name), "LCR/%s-%04x",ast->cid.cid_num, ast_random() & 0xffff); #endif - + ret = ast_pbx_start(ast); if (ret < 0) { cause = (ret==-2)?34:27; @@ -857,9 +867,13 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet #endif #ifdef LCR_FOR_ASTERISK +#ifdef AST_1_8_OR_HIGHER + ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", "", 0, "%s/%d", lcr_type, ++glob_channel); +#else ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel); +#endif #endif - + if (!ast) { /* release */ CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n"); @@ -873,7 +887,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet ast->tech_pvt = call; ast->tech = &lcr_tech; ast->fds[0] = call->pipe[0]; - + /* fill setup information */ if (param->setup.dialinginfo.id) strncpy(ast->exten, param->setup.dialinginfo.id, AST_MAX_EXTENSION-1); @@ -881,6 +895,139 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet strncpy(ast->context, param->setup.context, AST_MAX_CONTEXT-1); else strncpy(ast->context, param->setup.callerinfo.interface, AST_MAX_CONTEXT-1); + + + +#ifdef AST_1_8_OR_HIGHER + if (param->setup.callerinfo.id[0]) { + ast->caller.id.number.valid = 1; + ast->caller.id.number.str = strdup(param->setup.callerinfo.id); + if (!param->setup.callerinfo.id[0]) { + ast->caller.id.number.presentation = AST_PRES_RESTRICTED; + ast->caller.id.number.plan = (0 << 4) | 1; + } + switch (param->setup.callerinfo.present) { + case INFO_PRESENT_ALLOWED: + ast->caller.id.number.presentation = AST_PRES_ALLOWED; + break; + case INFO_PRESENT_RESTRICTED: + ast->caller.id.number.presentation = AST_PRES_RESTRICTED; + break; + default: + ast->caller.id.number.presentation = AST_PRES_UNAVAILABLE; + } + switch (param->setup.callerinfo.screen) { + case INFO_SCREEN_USER: + ast->caller.id.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED; + break; + case INFO_SCREEN_USER_VERIFIED_PASSED: + ast->caller.id.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN; + break; + case INFO_SCREEN_USER_VERIFIED_FAILED: + ast->caller.id.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN; + break; + default: + ast->caller.id.number.presentation |= AST_PRES_NETWORK_NUMBER; + } + switch (param->setup.callerinfo.ntype) { + case INFO_NTYPE_SUBSCRIBER: + ast->caller.id.number.plan = (4 << 4) | 1; + break; + case INFO_NTYPE_NATIONAL: + ast->caller.id.number.plan = (2 << 4) | 1; + break; + case INFO_NTYPE_INTERNATIONAL: + ast->caller.id.number.plan = (1 << 4) | 1; + break; + default: + ast->caller.id.number.plan = (0 << 4) | 1; + } + } + if (param->setup.callerinfo.id2[0]) { + ast->caller.ani.number.valid = 1; + ast->caller.ani.number.str = strdup(param->setup.callerinfo.id2); + switch (param->setup.callerinfo.present2) { + case INFO_PRESENT_ALLOWED: + ast->caller.ani.number.presentation = AST_PRES_ALLOWED; + break; + case INFO_PRESENT_RESTRICTED: + ast->caller.ani.number.presentation = AST_PRES_RESTRICTED; + break; + default: + ast->caller.ani.number.presentation = AST_PRES_UNAVAILABLE; + } + switch (param->setup.callerinfo.screen2) { + case INFO_SCREEN_USER: + ast->caller.ani.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED; + break; + case INFO_SCREEN_USER_VERIFIED_PASSED: + ast->caller.ani.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN; + break; + case INFO_SCREEN_USER_VERIFIED_FAILED: + ast->caller.ani.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN; + break; + default: + ast->caller.ani.number.presentation |= AST_PRES_NETWORK_NUMBER; + } + switch (param->setup.callerinfo.ntype2) { + case INFO_NTYPE_SUBSCRIBER: + ast->caller.ani.number.plan = (4 << 4) | 1; + break; + case INFO_NTYPE_NATIONAL: + ast->caller.ani.number.plan = (2 << 4) | 1; + break; + case INFO_NTYPE_INTERNATIONAL: + ast->caller.ani.number.plan = (1 << 4) | 1; + break; + default: + ast->caller.ani.number.plan = (0 << 4) | 1; + } + } + if (param->setup.callerinfo.name[0]) { + ast->caller.id.name.valid = 1; + ast->caller.id.name.str = strdup(param->setup.callerinfo.name); + } + if (param->setup.redirinfo.id[0]) { + ast->redirecting.from.number.valid = 1; + ast->redirecting.from.number.str = strdup(param->setup.redirinfo.id); + switch (param->setup.redirinfo.present) { + case INFO_PRESENT_ALLOWED: + ast->redirecting.from.number.presentation = AST_PRES_ALLOWED; + break; + case INFO_PRESENT_RESTRICTED: + ast->redirecting.from.number.presentation = AST_PRES_RESTRICTED; + break; + default: + ast->redirecting.from.number.presentation = AST_PRES_UNAVAILABLE; + } + switch (param->setup.redirinfo.screen) { + case INFO_SCREEN_USER: + ast->redirecting.from.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED; + break; + case INFO_SCREEN_USER_VERIFIED_PASSED: + ast->redirecting.from.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN; + break; + case INFO_SCREEN_USER_VERIFIED_FAILED: + ast->redirecting.from.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN; + break; + default: + ast->redirecting.from.number.presentation |= AST_PRES_NETWORK_NUMBER; + } + switch (param->setup.redirinfo.ntype) { + case INFO_NTYPE_SUBSCRIBER: + ast->redirecting.from.number.plan = (4 << 4) | 1; + break; + case INFO_NTYPE_NATIONAL: + ast->redirecting.from.number.plan = (2 << 4) | 1; + break; + case INFO_NTYPE_INTERNATIONAL: + ast->redirecting.from.number.plan = (1 << 4) | 1; + break; + default: + ast->redirecting.from.number.plan = (0 << 4) | 1; + } + } +#else memset(&ast->cid, 0, sizeof(ast->cid)); if (param->setup.callerinfo.id[0]) ast->cid.cid_num = strdup(param->setup.callerinfo.id); @@ -913,6 +1060,8 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet default: ast->cid.cid_ton = 0; } +#endif + ast->transfercapability = param->setup.capainfo.bearer_capa; /* enable hdlc if transcap is data */ if (param->setup.capainfo.source_mode == B_MODE_HDLC) @@ -1080,8 +1229,8 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param call->state = CHAN_LCR_STATE_RELEASE; /* copy release info */ if (!call->cause) { - call->cause = param->disconnectinfo.cause; - call->location = param->disconnectinfo.location; + call->cause = param->disconnectinfo.cause; + call->location = param->disconnectinfo.location; } /* if we have an asterisk instance, queue hangup, else we are done */ if (ast) { @@ -1099,7 +1248,7 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param } else { free_call(call); } - + } /* @@ -1110,7 +1259,7 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p struct ast_channel *ast = call->ast; CDEBUG(call, call->ast, "Incoming information from LCR. (dialing=%s)\n", param->information.id); - + if (!ast) return; /* pbx not started */ @@ -1120,14 +1269,14 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p lcr_start_pbx(call, ast, param->information.sending_complete); return; } - + /* change dailing state after setup */ if (call->state == CHAN_LCR_STATE_IN_SETUP) { CDEBUG(call, call->ast, "Changing from SETUP to DIALING state.\n"); call->state = CHAN_LCR_STATE_IN_DIALING; // ast_setstate(ast, AST_STATE_DIALING); } - + /* queue digits */ if (call->state == CHAN_LCR_STATE_IN_DIALING && param->information.id[0]) { if (!wake_global) { @@ -1303,6 +1452,10 @@ int receive_message(int message_type, unsigned int ref, union parameter *param) CDEBUG(call, call->ast, "Join bchannel, because call is already bridged.\n"); bchannel_join(bchannel, call->bridge_id); } + /* ignore all dsp features, if it is a loopback interface */ + if (param->bchannel.isloopback) + call->nodsp = 1; + /* create only, if call exists, othewhise it bchannel is freed below... */ if (bchannel_create(bchannel, ((call->nodsp || call->faxdetect > 0)?1:0) + ((call->hdlc)?2:0), call->nodsp_queue)) bchannel_activate(bchannel, 1); @@ -1333,7 +1486,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param) newparam.bchannel.type = BCHANNEL_REMOVE_ACK; newparam.bchannel.handle = param->bchannel.handle; send_message(MESSAGE_BCHANNEL, 0, &newparam); - + break; default: @@ -1344,7 +1497,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param) /* handle new ref */ if (message_type == MESSAGE_NEWREF) { - if (param->direction) { + if (param->newref.direction) { /* new ref from lcr */ CDEBUG(NULL, NULL, "Received new ref by LCR, due to incomming call. (ref=%ld)\n", ref); if (!ref || find_call_ref(ref)) { @@ -1367,8 +1520,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param) call = find_call_ref(0); if (!call) { /* send release, if ref does not exist */ - CDEBUG(NULL, NULL, "No call found, that requests a ref.\n"); - send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL); + CERROR(NULL, NULL, "No call found, that requests a ref.\n"); return 0; } /* store new ref */ @@ -1527,7 +1679,7 @@ static int handle_socket(struct lcr_fd *fd, unsigned int what, void *instance, i /* read from socket */ len = read(lcr_sock, &msg, sizeof(msg)); if (len == 0) { - CERROR(NULL, NULL, "Socket closed.\n"); + CERROR(NULL, NULL, "Socket closed.(read)\n"); error: CERROR(NULL, NULL, "Handling of socket failed - closing for some seconds.\n"); close_socket(); @@ -1560,7 +1712,7 @@ static int handle_socket(struct lcr_fd *fd, unsigned int what, void *instance, i admin = admin_first; len = write(lcr_sock, &admin->msg, sizeof(msg)); if (len == 0) { - CERROR(NULL, NULL, "Socket closed.\n"); + CERROR(NULL, NULL, "Socket closed.(write)\n"); goto error; } if (len > 0) { @@ -1638,7 +1790,7 @@ void close_socket(void) admin_first = NULL; /* close socket */ - if (lcr_sock >= 0) + if (lcr_sock >= 0) close(lcr_sock); lcr_sock = -1; global_change = 1; @@ -1706,7 +1858,7 @@ again: CDEBUG(call, ast, "Sending queued digit '%c' to Asterisk.\n", *p); /* send digit to asterisk */ memset(&fr, 0, sizeof(fr)); - + #ifdef LCR_FOR_ASTERISK fr.frametype = AST_FRAME_DTMF_BEGIN; #endif @@ -1714,16 +1866,20 @@ again: #ifdef LCR_FOR_CALLWEAVER fr.frametype = AST_FRAME_DTMF; #endif - + +#ifdef AST_1_8_OR_HIGHER + fr.subclass.integer = *p; +#else fr.subclass = *p; +#endif fr.delivery = ast_tv(0, 0); ast_queue_frame(ast, &fr); - + #ifdef LCR_FOR_ASTERISK fr.frametype = AST_FRAME_DTMF_END; ast_queue_frame(ast, &fr); #endif - + break; default: CDEBUG(call, ast, "Ignoring queued digit 0x%02x.\n", *p); @@ -1777,23 +1933,11 @@ static void *chan_thread(void *arg) ast_mutex_lock(&chan_lock); - while(!quit) { + while(1) { handle_queue(); select_main(0, &global_change, lock_chan, unlock_chan); } - close_socket(); - - del_timer(&socket_retry); - - unregister_fd(&wake_fd); - close(wake_pipe[0]); - close(wake_pipe[1]); - - CERROR(NULL, NULL, "Thread exit.\n"); - - ast_mutex_unlock(&chan_lock); - return NULL; } @@ -1801,11 +1945,15 @@ static void *chan_thread(void *arg) * new asterisk instance */ static +#ifdef AST_1_8_OR_HIGHER +struct ast_channel *lcr_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +#else struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause) +#endif { char exten[256], *dial, *interface, *opt; struct ast_channel *ast; - struct chan_call *call; + struct chan_call *call; ast_mutex_lock(&chan_lock); CDEBUG(NULL, NULL, "Received request from Asterisk. (data=%s)\n", (char *)data); @@ -1828,13 +1976,17 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c /* create asterisk channel instrance */ #ifdef LCR_FOR_ASTERISK +#ifdef AST_1_8_OR_HIGHER + ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, NULL, NULL, NULL, NULL, 0, "%s/%d", lcr_type, ++glob_channel); +#else ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel); +#endif #endif - + #ifdef LCR_FOR_CALLWEAVER ast = ast_channel_alloc(1); #endif - + if (!ast) { CERROR(NULL, NULL, "Failed to create Asterisk channel.\n"); free_call(call); @@ -1884,6 +2036,227 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c strncpy(call->dialstring, dial, sizeof(call->dialstring)-1); apply_opt(call, (char *)opt); +#ifdef AST_1_8_OR_HIGHER +// clone_variables(requestor, ast); + +#if 0 + ast->caller.ani.number.valid= requestor->caller.ani.number.valid; + if (requestor->caller.ani.number.valid) + if (requestor->caller.ani.number.str) + if (requestor->caller.ani.number.str[0]) + ast->caller.ani.number.str= strdup(requestor->caller.ani.number.str); + ast->caller.ani.number.plan= requestor->caller.ani.number.plan; + ast->caller.ani.number.presentation= requestor->caller.ani.number.presentation; + + ast->caller.ani.name.valid= requestor->caller.ani.name.valid; + if (requestor->caller.ani.name.valid) + if (requestor->caller.ani.name.str) + if (requestor->caller.ani.name.str[0]) + ast->caller.ani.name.str= strdup(requestor->caller.ani.name.str); + ast->caller.ani.name.presentation= requestor->caller.ani.name.presentation; + + ast->caller.ani.subaddress.valid= requestor->caller.ani.subaddress.valid; + if (requestor->caller.ani.subaddress.valid) + if (requestor->caller.ani.subaddress.str) + if (requestor->caller.ani.subaddress.str[0]) + ast->caller.ani.subaddress.str= strdup(requestor->caller.ani.subaddress.str); + ast->caller.ani.subaddress.type= requestor->caller.ani.subaddress.type; + + ast->caller.id.number.valid= requestor->caller.id.number.valid; + if (requestor->caller.id.number.valid) + if (requestor->caller.id.number.str) + if (requestor->caller.id.number.str[0]) + ast->caller.id.number.str= strdup(requestor->caller.id.number.str); + ast->caller.id.number.plan= requestor->caller.id.number.plan; + ast->caller.id.number.presentation= requestor->caller.id.number.presentation; + + ast->caller.id.name.valid= requestor->caller.id.name.valid; + if (requestor->caller.id.name.valid) + if (requestor->caller.id.name.str) + if (requestor->caller.id.name.str[0]) + ast->caller.id.name.str= strdup(requestor->caller.id.name.str); + ast->caller.id.name.presentation= requestor->caller.id.name.presentation; + + ast->caller.id.subaddress.valid= requestor->caller.id.subaddress.valid; + if (requestor->caller.id.subaddress.valid) + if (requestor->caller.id.subaddress.str) + if (requestor->caller.id.subaddress.str[0]) + ast->caller.id.subaddress.str= strdup(requestor->caller.id.subaddress.str); + ast->caller.id.subaddress.type= requestor->caller.id.subaddress.type; + + if (requestor->dialed.number.str) + if (requestor->dialed.number.str[0]) + ast->dialed.number.str= strdup(requestor->dialed.number.str); + ast->dialed.number.plan= requestor->dialed.number.plan; + + ast->dialed.subaddress.valid= requestor->dialed.subaddress.valid; + if (requestor->dialed.subaddress.valid) + if (requestor->dialed.subaddress.str) + if (requestor->dialed.subaddress.str[0]) + ast->dialed.subaddress.str= strdup(requestor->dialed.subaddress.str); + ast->dialed.subaddress.type= requestor->dialed.subaddress.type; + + ast->dialed.transit_network_select= requestor->dialed.transit_network_select; + ast->redirecting.count= requestor->redirecting.count; + ast->redirecting.reason= requestor->redirecting.reason; + + ast->redirecting.from.number.valid= requestor->redirecting.from.number.valid; + if (requestor->redirecting.from.number.valid) + if (requestor->redirecting.from.number.str) + if (requestor->redirecting.from.number.str[0]) + ast->redirecting.from.number.str= strdup(requestor->redirecting.from.number.str); + ast->redirecting.from.number.plan= requestor->redirecting.from.number.plan; + ast->redirecting.from.number.presentation= requestor->redirecting.from.number.presentation; + + ast->redirecting.to.number.valid= requestor->redirecting.to.number.valid; + if (requestor->redirecting.to.number.valid) + if (requestor->redirecting.to.number.str) + if (requestor->redirecting.to.number.str[0]) + ast->redirecting.to.number.str= strdup(requestor->redirecting.to.number.str); + ast->redirecting.to.number.plan= requestor->redirecting.to.number.plan; + ast->redirecting.to.number.presentation= requestor->redirecting.to.number.presentation; +#endif + /* store call information for setup */ + + /* caller ID */ + if (requestor->caller.id.number.valid) { + if (requestor->caller.id.number.str) + strncpy(call->callerinfo.id, requestor->caller.id.number.str, sizeof(call->callerinfo.id)-1); + switch(requestor->caller.id.number.presentation & AST_PRES_RESTRICTION) { + case AST_PRES_RESTRICTED: + call->callerinfo.present = INFO_PRESENT_RESTRICTED; + break; + case AST_PRES_UNAVAILABLE: + call->callerinfo.present = INFO_PRESENT_NOTAVAIL; + break; + case AST_PRES_ALLOWED: + default: + call->callerinfo.present = INFO_PRESENT_ALLOWED; + } + switch(requestor->caller.id.number.presentation & AST_PRES_NUMBER_TYPE) { + case AST_PRES_USER_NUMBER_UNSCREENED: + call->callerinfo.screen = INFO_SCREEN_USER; + break; + case AST_PRES_USER_NUMBER_PASSED_SCREEN: + call->callerinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED; + break; + case AST_PRES_USER_NUMBER_FAILED_SCREEN: + call->callerinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED; + break; + default: + call->callerinfo.screen = INFO_SCREEN_NETWORK; + } + switch((requestor->caller.id.number.plan >> 4) & 7) { + case 4: + call->callerinfo.ntype = INFO_NTYPE_SUBSCRIBER; + break; + case 2: + call->callerinfo.ntype = INFO_NTYPE_NATIONAL; + break; + case 1: + call->callerinfo.ntype = INFO_NTYPE_INTERNATIONAL; + break; + default: + call->callerinfo.ntype = INFO_NTYPE_UNKNOWN; + } + } else + call->callerinfo.present = INFO_PRESENT_NOTAVAIL; + + /* caller ID 2 */ + if (requestor->caller.ani.number.valid) { + if (requestor->caller.ani.number.str) + strncpy(call->callerinfo.id2, requestor->caller.ani.number.str, sizeof(call->callerinfo.id2)-1); + switch(requestor->caller.ani.number.presentation & AST_PRES_RESTRICTION) { + case AST_PRES_RESTRICTED: + call->callerinfo.present2 = INFO_PRESENT_RESTRICTED; + break; + case AST_PRES_UNAVAILABLE: + call->callerinfo.present2 = INFO_PRESENT_NOTAVAIL; + break; + case AST_PRES_ALLOWED: + default: + call->callerinfo.present2 = INFO_PRESENT_ALLOWED; + } + switch(requestor->caller.ani.number.presentation & AST_PRES_NUMBER_TYPE) { + case AST_PRES_USER_NUMBER_UNSCREENED: + call->callerinfo.screen2 = INFO_SCREEN_USER; + break; + case AST_PRES_USER_NUMBER_PASSED_SCREEN: + call->callerinfo.screen2 = INFO_SCREEN_USER_VERIFIED_PASSED; + break; + case AST_PRES_USER_NUMBER_FAILED_SCREEN: + call->callerinfo.screen2 = INFO_SCREEN_USER_VERIFIED_FAILED; + break; + default: + call->callerinfo.screen2 = INFO_SCREEN_NETWORK; + } + switch((requestor->caller.ani.number.plan >> 4) & 7) { + case 4: + call->callerinfo.ntype2 = INFO_NTYPE_SUBSCRIBER; + break; + case 2: + call->callerinfo.ntype2 = INFO_NTYPE_NATIONAL; + break; + case 1: + call->callerinfo.ntype2 = INFO_NTYPE_INTERNATIONAL; + break; + default: + call->callerinfo.ntype2 = INFO_NTYPE_UNKNOWN; + } + } else + call->callerinfo.present2 = INFO_PRESENT_NOTAVAIL; + + /* caller name */ + if (requestor->caller.id.name.valid) { + if (requestor->caller.id.name.str) + strncpy(call->callerinfo.name, requestor->caller.id.name.str, sizeof(call->callerinfo.name)-1); + } + + /* redir number */ + if (requestor->redirecting.from.number.valid) { + call->redirinfo.itype = INFO_ITYPE_CHAN; + if (requestor->redirecting.from.number.str) + strncpy(call->redirinfo.id, requestor->redirecting.from.number.str, sizeof(call->redirinfo.id)-1); + switch(requestor->redirecting.from.number.presentation & AST_PRES_RESTRICTION) { + case AST_PRES_RESTRICTED: + call->redirinfo.present = INFO_PRESENT_RESTRICTED; + break; + case AST_PRES_UNAVAILABLE: + call->redirinfo.present = INFO_PRESENT_NOTAVAIL; + break; + case AST_PRES_ALLOWED: + default: + call->redirinfo.present = INFO_PRESENT_ALLOWED; + } + switch(requestor->redirecting.from.number.presentation & AST_PRES_NUMBER_TYPE) { + case AST_PRES_USER_NUMBER_UNSCREENED: + call->redirinfo.screen = INFO_SCREEN_USER; + break; + case AST_PRES_USER_NUMBER_PASSED_SCREEN: + call->redirinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED; + break; + case AST_PRES_USER_NUMBER_FAILED_SCREEN: + call->redirinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED; + break; + default: + call->redirinfo.screen = INFO_SCREEN_NETWORK; + } + switch((requestor->redirecting.from.number.plan >> 4) & 7) { + case 4: + call->redirinfo.ntype = INFO_NTYPE_SUBSCRIBER; + break; + case 2: + call->redirinfo.ntype = INFO_NTYPE_NATIONAL; + break; + case 1: + call->redirinfo.ntype = INFO_NTYPE_INTERNATIONAL; + break; + default: + call->redirinfo.ntype = INFO_NTYPE_UNKNOWN; + } + } +#endif + ast_mutex_unlock(&chan_lock); return ast; } @@ -1894,16 +2267,16 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c static int lcr_call(struct ast_channel *ast, char *dest, int timeout) { union parameter newparam; - struct chan_call *call; + struct chan_call *call; ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; - - #ifdef LCR_FOR_CALLWEAVER - ast->type = "LCR"; - snprintf(ast->name, sizeof(ast->name), "LCR/%s-%04x",call->dialstring, ast_random() & 0xffff); - #endif - + call = ast->tech_pvt; + + #ifdef LCR_FOR_CALLWEAVER + ast->type = "LCR"; + snprintf(ast->name, sizeof(ast->name), "LCR/%s-%04x",call->dialstring, ast_random() & 0xffff); + #endif + if (!call) { CERROR(NULL, ast, "Received call from Asterisk, but call instance does not exist.\n"); ast_mutex_unlock(&chan_lock); @@ -1916,7 +2289,9 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout) call->pbx_started = 1; /* send MESSAGE_NEWREF */ memset(&newparam, 0, sizeof(union parameter)); - newparam.direction = 0; /* request from app */ + newparam.newref.direction = 0; /* request from app */ + if (!strcmp(call->interface, "pbx")) + newparam.newref.mode = 1; send_message(MESSAGE_NEWREF, 0, &newparam); /* set hdlc if capability requires hdlc */ @@ -1931,6 +2306,7 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout) && ast->transfercapability != INFO_BC_VIDEO) ast->transfercapability = INFO_BC_DATAUNRESTRICTED; +#ifndef AST_1_8_OR_HIGHER call->cid_num[0] = 0; call->cid_name[0] = 0; call->cid_rdnis[0] = 0; @@ -1938,51 +2314,51 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout) if (ast->cid.cid_num) if (ast->cid.cid_num[0]) strncpy(call->cid_num, ast->cid.cid_num, sizeof(call->cid_num)-1); - if (ast->cid.cid_name) if (ast->cid.cid_name[0]) - strncpy(call->cid_name, ast->cid.cid_name, + strncpy(call->cid_name, ast->cid.cid_name, sizeof(call->cid_name)-1); if (ast->cid.cid_rdnis) if (ast->cid.cid_rdnis[0]) - strncpy(call->cid_rdnis, ast->cid.cid_rdnis, + strncpy(call->cid_rdnis, ast->cid.cid_rdnis, sizeof(call->cid_rdnis)-1); +#endif ast_mutex_unlock(&chan_lock); - return 0; + return 0; } static void send_digit_to_chan(struct ast_channel * ast, char digit ) { - static const char* dtmf_tones[] = { - "!941+1336/100,!0/100", /* 0 */ - "!697+1209/100,!0/100", /* 1 */ - "!697+1336/100,!0/100", /* 2 */ - "!697+1477/100,!0/100", /* 3 */ - "!770+1209/100,!0/100", /* 4 */ - "!770+1336/100,!0/100", /* 5 */ - "!770+1477/100,!0/100", /* 6 */ - "!852+1209/100,!0/100", /* 7 */ - "!852+1336/100,!0/100", /* 8 */ - "!852+1477/100,!0/100", /* 9 */ - "!697+1633/100,!0/100", /* A */ - "!770+1633/100,!0/100", /* B */ - "!852+1633/100,!0/100", /* C */ - "!941+1633/100,!0/100", /* D */ - "!941+1209/100,!0/100", /* * */ - "!941+1477/100,!0/100" }; /* # */ - - if (digit >= '0' && digit <='9') - ast_playtones_start(ast,0,dtmf_tones[digit-'0'], 0); - else if (digit >= 'A' && digit <= 'D') - ast_playtones_start(ast,0,dtmf_tones[digit-'A'+10], 0); - else if (digit == '*') - ast_playtones_start(ast,0,dtmf_tones[14], 0); - else if (digit == '#') - ast_playtones_start(ast,0,dtmf_tones[15], 0); - else { - /* not handled */ + static const char* dtmf_tones[] = { + "!941+1336/100,!0/100", /* 0 */ + "!697+1209/100,!0/100", /* 1 */ + "!697+1336/100,!0/100", /* 2 */ + "!697+1477/100,!0/100", /* 3 */ + "!770+1209/100,!0/100", /* 4 */ + "!770+1336/100,!0/100", /* 5 */ + "!770+1477/100,!0/100", /* 6 */ + "!852+1209/100,!0/100", /* 7 */ + "!852+1336/100,!0/100", /* 8 */ + "!852+1477/100,!0/100", /* 9 */ + "!697+1633/100,!0/100", /* A */ + "!770+1633/100,!0/100", /* B */ + "!852+1633/100,!0/100", /* C */ + "!941+1633/100,!0/100", /* D */ + "!941+1209/100,!0/100", /* * */ + "!941+1477/100,!0/100" }; /* # */ + + if (digit >= '0' && digit <='9') + ast_playtones_start(ast,0,dtmf_tones[digit-'0'], 0); + else if (digit >= 'A' && digit <= 'D') + ast_playtones_start(ast,0,dtmf_tones[digit-'A'+10], 0); + else if (digit == '*') + ast_playtones_start(ast,0,dtmf_tones[14], 0); + else if (digit == '#') + ast_playtones_start(ast,0,dtmf_tones[15], 0); + else { + /* not handled */ CDEBUG(NULL, ast, "Unable to handle DTMF tone " "'%c' for '%s'\n", digit, ast->name); - } + } } #ifdef LCR_FOR_ASTERISK @@ -1992,7 +2368,7 @@ static int lcr_digit_begin(struct ast_channel *ast, char digit) static int lcr_digit(struct ast_channel *ast, char digit) #endif { - struct chan_call *call; + struct chan_call *call; union parameter newparam; char buf[]="x"; @@ -2005,7 +2381,7 @@ static int lcr_digit(struct ast_channel *ast, char digit) return 0; ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { CERROR(NULL, ast, "Received digit from Asterisk, but no call instance exists.\n"); ast_mutex_unlock(&chan_lock); @@ -2043,17 +2419,17 @@ static int lcr_digit(struct ast_channel *ast, char digit) static int lcr_digit_end(struct ast_channel *ast, char digit, unsigned int duration) { int inband_dtmf = 0; - struct chan_call *call; + struct chan_call *call; #endif ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { - CERROR(NULL, ast, - "Received digit from Asterisk, " - "but no call instance exists.\n"); + CERROR(NULL, ast, + "Received digit from Asterisk, " + "but no call instance exists.\n"); ast_mutex_unlock(&chan_lock); return -1; } @@ -2077,18 +2453,18 @@ static int lcr_digit_end(struct ast_channel *ast, char digit, unsigned int durat static int lcr_answer(struct ast_channel *ast) { union parameter newparam; - struct chan_call *call; + struct chan_call *call; ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n"); ast_mutex_unlock(&chan_lock); return -1; } - + CDEBUG(call, ast, "Received answer from Asterisk (maybe during lcr_bridge).\n"); - + /* copy connectinfo, if bridged */ if (call->bridge_call) memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info)); @@ -2110,20 +2486,20 @@ static int lcr_answer(struct ast_channel *ast) /* enable keypad */ // memset(&newparam, 0, sizeof(union parameter)); // send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam); - - ast_mutex_unlock(&chan_lock); - return 0; + + ast_mutex_unlock(&chan_lock); + return 0; } static int lcr_hangup(struct ast_channel *ast) { - struct chan_call *call; + struct chan_call *call; pthread_t tid = pthread_self(); if (!pthread_equal(tid, chan_tid)) { ast_mutex_lock(&chan_lock); } - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n"); if (!pthread_equal(tid, chan_tid)) { @@ -2165,7 +2541,7 @@ static int lcr_hangup(struct ast_channel *ast) call->state = CHAN_LCR_STATE_RELEASE; call->ast = NULL; } - } + } if (!pthread_equal(tid, chan_tid)) { ast_mutex_unlock(&chan_lock); } @@ -2174,23 +2550,35 @@ static int lcr_hangup(struct ast_channel *ast) static int lcr_write(struct ast_channel *ast, struct ast_frame *fr) { - struct chan_call *call; + struct chan_call *call; struct ast_frame * f = fr; +#ifdef AST_1_8_OR_HIGHER + if (!f->subclass.integer) +#else if (!f->subclass) +#endif CDEBUG(NULL, ast, "No subclass\n"); +#ifdef AST_1_8_OR_HIGHER + if (!(f->subclass.integer & ast->nativeformats)) { +#else if (!(f->subclass & ast->nativeformats)) { +#endif CDEBUG(NULL, ast, - "Unexpected format. " + "Unexpected format. " "Activating emergency conversion...\n"); +#ifdef AST_1_8_OR_HIGHER + ast_set_write_format(ast, f->subclass.integer); +#else ast_set_write_format(ast, f->subclass); +#endif f = (ast->writetrans) ? ast_translate( ast->writetrans, fr, 0) : fr; } ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { ast_mutex_unlock(&chan_lock); if (f != fr) { @@ -2210,11 +2598,11 @@ static int lcr_write(struct ast_channel *ast, struct ast_frame *fr) static struct ast_frame *lcr_read(struct ast_channel *ast) { - struct chan_call *call; + struct chan_call *call; int len = 0; ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { ast_mutex_unlock(&chan_lock); return NULL; @@ -2235,11 +2623,11 @@ static struct ast_frame *lcr_read(struct ast_channel *ast) #ifdef LCR_FOR_ASTERISK return &ast_null_frame; #endif - + #ifdef LCR_FOR_CALLWEAVER return &nullframe; #endif - + } if (len <= 0) { close(call->pipe[0]); @@ -2255,7 +2643,11 @@ static struct ast_frame *lcr_read(struct ast_channel *ast) } call->read_fr.frametype = AST_FRAME_VOICE; +#ifdef AST_1_8_OR_HIGHER + call->read_fr.subclass.integer = ast->nativeformats; +#else call->read_fr.subclass = ast->nativeformats; +#endif if (call->rebuffer) { call->read_fr.datalen = call->framepos; call->read_fr.samples = call->framepos; @@ -2274,20 +2666,20 @@ static struct ast_frame *lcr_read(struct ast_channel *ast) static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen) { union parameter newparam; - int res = 0; - struct chan_call *call; + int res = 0; + struct chan_call *call; const struct tone_zone_sound *ts = NULL; ast_mutex_lock(&chan_lock); - call = ast->tech_pvt; + call = ast->tech_pvt; if (!call) { CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n"); ast_mutex_unlock(&chan_lock); return -1; } - switch (cond) { - case AST_CONTROL_BUSY: + switch (cond) { + case AST_CONTROL_BUSY: CDEBUG(call, ast, "Received indicate AST_CONTROL_BUSY from Asterisk.\n"); ast_setstate(ast, AST_STATE_BUSY); if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) { @@ -2303,7 +2695,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz ts = ast_get_indication_tone(ast->zone, "busy"); } break; - case AST_CONTROL_CONGESTION: + case AST_CONTROL_CONGESTION: CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk. (cause %d)\n", ast->hangupcause); if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) { /* send message to lcr */ @@ -2318,7 +2710,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz ts = ast_get_indication_tone(ast->zone, "congestion"); } break; - case AST_CONTROL_PROCEEDING: + case AST_CONTROL_PROCEEDING: CDEBUG(call, ast, "Received indicate AST_CONTROL_PROCEEDING from Asterisk.\n"); if (call->state == CHAN_LCR_STATE_IN_SETUP || call->state == CHAN_LCR_STATE_IN_DIALING) { @@ -2329,7 +2721,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz call->state = CHAN_LCR_STATE_IN_PROCEEDING; } break; - case AST_CONTROL_RINGING: + case AST_CONTROL_RINGING: CDEBUG(call, ast, "Received indicate AST_CONTROL_RINGING from Asterisk.\n"); ast_setstate(ast, AST_STATE_RING); if (call->state == CHAN_LCR_STATE_IN_SETUP @@ -2355,35 +2747,35 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz send_message(MESSAGE_BCHANNEL, call->ref, &newparam); } break; - case -1: + case -1: CDEBUG(call, ast, "Received indicate -1.\n"); ast_playtones_stop(ast); - res = -1; + res = -1; break; - case AST_CONTROL_VIDUPDATE: + case AST_CONTROL_VIDUPDATE: CDEBUG(call, ast, "Received indicate AST_CONTROL_VIDUPDATE.\n"); - res = -1; - break; - case AST_CONTROL_HOLD: + res = -1; + break; + case AST_CONTROL_HOLD: CDEBUG(call, ast, "Received indicate AST_CONTROL_HOLD from Asterisk.\n"); /* send message to lcr */ memset(&newparam, 0, sizeof(union parameter)); newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD; send_message(MESSAGE_NOTIFY, call->ref, &newparam); - + /*start music onhold*/ #ifdef LCR_FOR_ASTERISK ast_moh_start(ast,data,ast->musicclass); #endif - + #ifdef LCR_FOR_CALLWEAVER ast_moh_start(ast, NULL); #endif - + call->on_hold = 1; - break; - case AST_CONTROL_UNHOLD: + break; + case AST_CONTROL_UNHOLD: CDEBUG(call, ast, "Received indicate AST_CONTROL_UNHOLD from Asterisk.\n"); /* send message to lcr */ memset(&newparam, 0, sizeof(union parameter)); @@ -2391,21 +2783,21 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz send_message(MESSAGE_NOTIFY, call->ref, &newparam); /*stop moh*/ - ast_moh_stop(ast); + ast_moh_stop(ast); call->on_hold = 0; - break; + break; #ifdef AST_CONTROL_SRCUPDATE - case AST_CONTROL_SRCUPDATE: + case AST_CONTROL_SRCUPDATE: #else - case 20: + case 20: #endif CDEBUG(call, ast, "Received AST_CONTROL_SRCUPDATE from Asterisk.\n"); - break; - default: + break; + default: CERROR(call, ast, "Received indicate from Asterisk with unknown condition %d.\n", cond); - res = -1; + res = -1; break; - } + } if (ts && ts->data[0]) { ast_playtones_start(ast, 0, ts->data, 1); @@ -2413,7 +2805,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz /* return */ ast_mutex_unlock(&chan_lock); - return res; + return res; } /* @@ -2421,7 +2813,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz */ static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast) { - struct chan_call *call; + struct chan_call *call; if (!ast) { return -1; @@ -2446,7 +2838,7 @@ static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast) */ static int lcr_send_text(struct ast_channel *ast, const char *text) { - struct chan_call *call; + struct chan_call *call; union parameter newparam; ast_mutex_lock(&chan_lock); @@ -2495,15 +2887,15 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, return AST_BRIDGE_COMPLETE; } - /* join, if both call instances uses dsp + /* join, if both call instances uses dsp ignore the case of fax detection here it may be benificial for ISDN fax machines or pass through. - */ + */ if (!call1->nodsp && !call2->nodsp) { CDEBUG(NULL, NULL, "Both calls use DSP, bridging via DSP.\n"); /* get bridge id and join */ bridge_id = new_bridge_id(); - + call1->bridge_id = bridge_id; if (call1->bchannel) bchannel_join(call1->bchannel, bridge_id); @@ -2557,9 +2949,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, call2->on_hold = 0; } - + ast_mutex_unlock(&chan_lock); - + while(1) { to = -1; who = ast_waitfor_n(carr, 2, &to); @@ -2569,7 +2961,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, break; } f = ast_read(who); - + if (!f || f->frametype == AST_FRAME_CONTROL) { if (!f) CDEBUG(NULL, NULL, "Got hangup.\n"); @@ -2580,14 +2972,14 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, *rc=who; break; } - + if ( f->frametype == AST_FRAME_DTMF ) { CDEBUG(NULL, NULL, "Got DTMF.\n"); *fo=f; *rc=who; break; } - + if (who == ast1) { ast_write(ast2,f); @@ -2595,9 +2987,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, else { ast_write(ast1,f); } - + } - + CDEBUG(NULL, NULL, "Releasing bridge.\n"); /* split channels */ @@ -2640,7 +3032,7 @@ static struct ast_channel_tech lcr_tech = { #endif .call = lcr_call, - .bridge = lcr_bridge, + .bridge = lcr_bridge, .hangup = lcr_hangup, .answer = lcr_answer, .read = lcr_read, @@ -2743,8 +3135,12 @@ static struct ast_cli_entry cli_port_unload = #ifdef LCR_FOR_ASTERISK +#ifdef AST_1_8_OR_HIGHER +static int lcr_config_exec(struct ast_channel *ast, const char *data) +#else static int lcr_config_exec(struct ast_channel *ast, void *data) #endif +#endif #ifdef LCR_FOR_CALLWEAVER static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv) @@ -2757,11 +3153,11 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv) #ifdef LCR_FOR_ASTERISK CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", (char *)data); #endif - + #ifdef LCR_FOR_CALLWEAVER CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", argv[0]); #endif - + /* find channel */ call = call_first; while(call) { @@ -2770,12 +3166,12 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv) call = call->next; } if (call) - + #ifdef LCR_FOR_ASTERISK apply_opt(call, (char *)data); - #endif - - #ifdef LCR_FOR_CALLWEAVER + #endif + + #ifdef LCR_FOR_CALLWEAVER apply_opt(call, (char *)argv[0]); #endif @@ -2804,12 +3200,12 @@ int load_module(void) #ifdef LCR_FOR_ASTERISK return AST_MODULE_LOAD_DECLINE; - #endif - + #endif + #ifdef LCR_FOR_CALLWEAVER return 0; #endif - + } ast_mutex_init(&chan_lock); @@ -2818,11 +3214,11 @@ int load_module(void) if (bchannel_initialize()) { CERROR(NULL, NULL, "Unable to open mISDN device\n"); close_socket(); - + #ifdef LCR_FOR_ASTERISK return AST_MODULE_LOAD_DECLINE; - #endif - + #endif + #ifdef LCR_FOR_CALLWEAVER return 0; #endif @@ -2837,29 +3233,29 @@ int load_module(void) #ifdef LCR_FOR_ASTERISK return AST_MODULE_LOAD_DECLINE; - #endif - + #endif + #ifdef LCR_FOR_CALLWEAVER return 0; #endif } ast_register_application("lcr_config", lcr_config_exec, "lcr_config", - + #ifdef LCR_FOR_ASTERISK "lcr_config(::...)\n" #endif - + #ifdef LCR_FOR_CALLWEAVER - "lcr_config(::...)\n", + "lcr_config(::...)\n", #endif - + "Sets LCR opts. and optargs\n" "\n" "The available options are:\n" " d - Send display text on called phone, text is the optarg.\n" " n - Don't detect dtmf tones on called channel.\n" - " h - Force data call (HDLC).\n" + " h - Force data call (HDLC).\n" " t - Disable mISDN_dsp features (required for fax application).\n" " q - Add queue to make fax stream seamless (required for fax app).\n" " Use queue size in miliseconds for optarg. (try 250)\n" @@ -2882,8 +3278,8 @@ int load_module(void) "options: \"n:t:q250\" for seamless audio transmission.\n" ); - -#if 0 + +#if 0 ast_cli_register(&cli_show_lcr); ast_cli_register(&cli_show_calls); ast_cli_register(&cli_reload_routing); @@ -2893,7 +3289,6 @@ int load_module(void) ast_cli_register(&cli_port_unload); #endif - quit = 0; if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0)) { /* failed to create thread */ bchannel_deinitialize(); @@ -2902,12 +3297,12 @@ int load_module(void) #ifdef LCR_FOR_ASTERISK return AST_MODULE_LOAD_DECLINE; - #endif - + #endif + #ifdef LCR_FOR_CALLWEAVER return 0; #endif - + } return 0; } @@ -2915,15 +3310,23 @@ int load_module(void) int unload_module(void) { /* First, take us out of the channel loop */ - CDEBUG(NULL, NULL, "-- Unregistering mISDN Channel Driver --\n"); + CDEBUG(NULL, NULL, "-- Unregistering Linux-Call-Router Channel Driver --\n"); - quit = 1; - pthread_join(chan_tid, NULL); - - ast_channel_unregister(&lcr_tech); + pthread_cancel(chan_tid); + + close_socket(); - ast_unregister_application("lcr_config"); + del_timer(&socket_retry); + + unregister_fd(&wake_fd); + close(wake_pipe[0]); + close(wake_pipe[1]); + +// ast_mutex_unlock(&chan_lock); + + ast_channel_unregister(&lcr_tech); + ast_unregister_application("lcr_config"); if (mISDN_created) { bchannel_deinitialize(); diff --git a/chan_lcr.h b/chan_lcr.h index e7ea0f5..8caa48e 100644 --- a/chan_lcr.h +++ b/chan_lcr.h @@ -29,6 +29,8 @@ struct chan_call { /* queue dialing prior setup ack */ char oad[64];/* caller id in number format */ + struct caller_info callerinfo; + struct redir_info redirinfo; struct connect_info connectinfo; /* store connectinfo form lcr */ int bridge_id; @@ -45,9 +47,11 @@ struct chan_call { /* LCR interface name for setup */ char dialstring[64]; /* cached dial string for setup */ +#ifndef AST_PARTY_CALLER char cid_num[64]; /* cached cid for setup */ char cid_name[64]; /* cached cid for setup */ char cid_rdnis[64]; /* cached cid for setup */ +#endif char display[128]; /* display for setup */ int dsp_dtmf; diff --git a/config.h.in b/config.h.in deleted file mode 100644 index b871dc3..0000000 --- a/config.h.in +++ /dev/null @@ -1,252 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the header file. */ -#undef HAVE_ASSERT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_ASTERISK_COMPILER_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_CTYPE_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if you have libcrypto */ -#undef HAVE_LIBCRYPTO - -/* Define to 1 if you have the `m' library (-lm). */ -#undef HAVE_LIBM - -/* Define to 1 if you have the `ncurses' library (-lncurses). */ -#undef HAVE_LIBNCURSES - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#undef HAVE_LIBPTHREAD - -/* Define to 1 if `lstat' has the bug that it succeeds when given the - zero-length file name argument. */ -#undef HAVE_LSTAT_EMPTY_STRING_BUG - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET - -/* Define to 1 if you have the header file. */ -#undef HAVE_MISDNUSER_MBUFFER_H - -/* Define to 1 if you have the `mkdir' function. */ -#undef HAVE_MKDIR - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RSA_H - -/* Define to 1 if you have the `socket' function. */ -#undef HAVE_SOCKET - -/* Define to 1 if stdbool.h conforms to C99. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strcasecmp' function. */ -#undef HAVE_STRCASECMP - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strncasecmp' function. */ -#undef HAVE_STRNCASECMP - -/* Define to 1 if you have the `strstr' function. */ -#undef HAVE_STRSTR - -/* Define to 1 if you have the `strtol' function. */ -#undef HAVE_STRTOL - -/* Define to 1 if you have the `strtoul' function. */ -#undef HAVE_STRTOUL - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_FILE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_IOCTL_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `vfork' function. */ -#undef HAVE_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_VFORK_H - -/* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF - -/* Define to 1 if `fork' works. */ -#undef HAVE_WORKING_FORK - -/* Define to 1 if `vfork' works. */ -#undef HAVE_WORKING_VFORK - -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - -/* Define to 1 if `lstat' dereferences a symlink specified with a trailing - slash. */ -#undef LSTAT_FOLLOWS_SLASHED_SYMLINK - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME - -/* Define to 1 if your declares `struct tm'. */ -#undef TM_IN_SYS_TIME - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - -/* Version number of package */ -#undef VERSION - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Define as `fork' if `vfork' does not work. */ -#undef vfork diff --git a/configure b/configure index 5ccc9cf..4c24728 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for lcr 1.7. +# Generated by GNU Autoconf 2.65 for lcr 1.8. # # Report bugs to . # @@ -552,8 +552,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='lcr' PACKAGE_TARNAME='lcr' -PACKAGE_VERSION='1.7' -PACKAGE_STRING='lcr 1.7' +PACKAGE_VERSION='1.8' +PACKAGE_STRING='lcr 1.8' PACKAGE_BUGREPORT='andreas@eversberg.eu' PACKAGE_URL='' @@ -1260,7 +1260,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures lcr 1.7 to adapt to many kinds of systems. +\`configure' configures lcr 1.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1326,7 +1326,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of lcr 1.7:";; + short | recursive ) echo "Configuration of lcr 1.8:";; esac cat <<\_ACEOF @@ -1430,7 +1430,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -lcr configure 1.7 +lcr configure 1.8 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -1893,7 +1893,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by lcr $as_me 1.7, which was +It was created by lcr $as_me 1.8, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -4022,7 +4022,7 @@ fi # Define the identity of the package. PACKAGE=lcr - VERSION=1.7 + VERSION=1.8 cat >>confdefs.h <<_ACEOF @@ -5326,6 +5326,7 @@ fi if test "x$with_asterisk" = "xyes"; then ast_tone_zone_sound= + ast_1_8_or_higher= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct tone_zone_sound in asterisk/indications.h" >&5 $as_echo_n "checking for struct tone_zone_sound in asterisk/indications.h... " >&6; } @@ -5392,7 +5393,35 @@ as_fn_error "No ast_tone_zone_sound, confused... See \`config.log' for more details." "$LINENO" 5; } fi - AST_CFLAGS="-Dtone_zone_sound=$ast_tone_zone_sound" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct ast_party_caller in asterisk/channel.h" >&5 +$as_echo_n "checking for struct ast_party_caller in asterisk/channel.h... " >&6; } + apc_test_result=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include , + #include +int +main () +{ +struct ast_party_caller * caller = NULL; (void) caller->id; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + apc_test_result=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $apc_test_result" >&5 +$as_echo "$apc_test_result" >&6; } + + if test "x$apc_test_result" = "xyes"; then + ast_1_8_or_higher="-DAST_1_8_OR_HIGHER" + fi + + AST_CFLAGS="-Dtone_zone_sound=$ast_tone_zone_sound $ast_1_8_or_higher" + fi @@ -7682,7 +7711,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by lcr $as_me 1.7, which was +This file was extended by lcr $as_me 1.8, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7748,7 +7777,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -lcr config.status 1.7 +lcr config.status 1.8 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 81eb404..5e01e41 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,7 @@ dnl Boston, MA 02110-1301, USA. dnl This keeps being the first instruction. dnl Change the 2nd argument if the version increases dnl 1st + 2nd argument is used for distribution package name -AC_INIT(lcr, 1.7, andreas@eversberg.eu) +AC_INIT(lcr, 1.8, andreas@eversberg.eu) AC_PREREQ(2.59) AC_CONFIG_SRCDIR([main.c]) AM_CONFIG_HEADER(config.h) @@ -33,7 +33,7 @@ AM_CONFIG_HEADER(config.h) # fix warnings from autoconf + automake AC_GNU_SOURCE # AC_USE_SYSTEM_EXTENSIONS -AM_INIT_AUTOMAKE(lcr,1.7) +AM_INIT_AUTOMAKE(lcr,1.8) @@ -71,6 +71,7 @@ AS_IF([test "x$with_asterisk" != xno], if test "x$with_asterisk" = "xyes"; then ast_tone_zone_sound= + ast_1_8_or_higher= AC_MSG_CHECKING([for struct tone_zone_sound in asterisk/indications.h]) tzs_test_result=no @@ -108,7 +109,22 @@ if test "x$with_asterisk" = "xyes"; then AC_MSG_FAILURE([No ast_tone_zone_sound, confused...]) fi - AST_CFLAGS="-Dtone_zone_sound=$ast_tone_zone_sound" + AC_MSG_CHECKING([for struct ast_party_caller in asterisk/channel.h]) + apc_test_result=no + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[#include ], + [#include ]], + [[struct ast_party_caller * caller = NULL; (void) caller->id;]])], + [apc_test_result=yes]) + AC_MSG_RESULT([$apc_test_result]) + + if test "x$apc_test_result" = "xyes"; then + ast_1_8_or_higher="-DAST_1_8_OR_HIGHER" + fi + + AST_CFLAGS="-Dtone_zone_sound=$ast_tone_zone_sound $ast_1_8_or_higher" + AC_SUBST([AST_CFLAGS]) fi diff --git a/default/gsm.conf b/default/gsm.conf deleted file mode 100644 index 148513b..0000000 --- a/default/gsm.conf +++ /dev/null @@ -1,39 +0,0 @@ -# LCR GSM options -################# - -# Two Loopback interfaces for audio transfer between OpenBSC and mISDN. -# They are also used for any Osmocom-BB interface, if exists. -# The first interface must provide B-channelis for each call mobile call. -# The seond interface links them to LCR. -# Use 30 B-channels unless you need more due to many TRXs or mobile stations. -# -> Load with: "modprobe mISDN_l1loop pri=1 nchannel=30" -# By default "mISDN_l1loop.1" and "mISDN_l1loop.2" is used. -#interface-bsc mISDN_l1loop.1 -#interface-lcr mISDN_l1loop.2 - -# Enable debugging of OpenBSC library. -# Refer to OpenBSC project for debugging options. -# By default, debugging is turned off. -#debug DRLL:DCC:DMM:DRR:DRSL:DNM:DSMS:DMNCC:DMNSMS:DPAG:DMUX:DMEAS - -# Give openbsc.cnf config file -# It will be located at /usr/local/lcr by default. -#config openbsc.cfg - -# Give database of Home Location Register (HLR) -# HLR stores all subscribers. It will be used to grant access to the network. -# It is an Sqlite3 database. Refer to OpenBSC project for handling. -# The database is located at /usr/local/lcr by default. -#hlr hlr.sqlite3 - -# To keep layer 2 connection to BS11 when quitting, use this option. -# It is only usefull for developing. TRX will stay on. -# Also changes in frequency, mcc, mnc, lac while keeping layer 2 will cause -# malefunction of BSC. -# Warning: Keeping layer 2 link may prevent emergency calls. (See below) -#keep-l2 - -# Write BTS-Link traffic to PCAP file. -#pcapfile pcap - - diff --git a/default/interface.conf b/default/interface.conf index 6e19538..004df59 100644 --- a/default/interface.conf +++ b/default/interface.conf @@ -180,7 +180,7 @@ # of LCR. The actual interface is defined in gsm.conf. # You may add 'extern' to make this interface the external line by default. #[GSM] -#gsm-ms 1 /tmp/osmocom_l2 +#gsm-ms 1 #layer1hold no #layer2hold no #tones no @@ -191,6 +191,20 @@ ##external +# Use chan_lcr (Asterisk PBX interface) as internal interface. +# The interface requires mISDN_l1loop.ko to be loaded: +# modprobe mISDN_l1loop nchannel=8 # use up to 8 b-channels +# The caller ID is used as extension, if "extension" parameter is given. +# Use "screen-in % xxx" to modify any caller id to xxx. +# An internal extension does not receive tones ("earlyb"), but sends them. +#[ast] +#remote asterisk +#extension +##screen-in % 209 +#earlyb no +#tones yes + + # Hint: Enter "lcr interface" for quick help on interface options. diff --git a/default/options.conf b/default/options.conf index e0e93a0..d1f4d6b 100644 --- a/default/options.conf +++ b/default/options.conf @@ -105,9 +105,8 @@ #socketgroup asterisk # Enable GSM network capability. -# This option turns LCR into a GSM network. Additional options are specified -# in 'gsm.conf'. You also need openbsc at compile time and of yourse - -# a base station transceiver. For more refer to LCR home page. +# This option turns LCR into a GSM network. +# For more refer to LCR home page and the OpenBSC page. # # !!! DANGER !!! # Running a GSM network may disturb other networks and may be prossecuted by @@ -120,3 +119,13 @@ # Enable polling in main loop. # This feature is temporarily for test purpose. Don't enable it #polling + +# Two Loopback interfaces for audio transfer between GSM/Asterisk and mISDN. +# The first interface must provide B-channels for each GSM call or channel +# instance, the seond interface links them to LCR. +# Use 30 B-channels unless you need more due to more instances. +# -> Load with: "modprobe mISDN_l1loop pri=1 nchannel=30" +# By default "mISDN_l1loop.1" and "mISDN_l1loop.2" is used. +#loopback-ext mISDN_l1loop.1 +#loopback-lcr mISDN_l1loop.2 + diff --git a/depcomp b/depcomp deleted file mode 100755 index ca5ea4e..0000000 --- a/depcomp +++ /dev/null @@ -1,584 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2006-10-15.18 - -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software -# Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - stat=$? - - if test -f "$tmpdepfile"; then : - else - stripped=`echo "$stripped" | sed 's,^.*/,,'` - tmpdepfile="$stripped.u" - fi - - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - outname="$stripped.o" - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want: - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. - sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. - "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/gsm.cpp b/gsm.cpp index 7245632..119f0f5 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -24,6 +24,167 @@ struct lcr_gsm *gsm = NULL; int new_callref = 1; +/* names of MNCC-SAP */ +static const struct _value_string { + int msg_type; + const char *name; +} mncc_names[] = { +#if defined(MNCC_SETUP_REQ) + { MNCC_SETUP_REQ, "MNCC_SETUP_REQ" }, +#endif +#if defined(MNCC_SETUP_IND) + { MNCC_SETUP_IND, "MNCC_SETUP_IND" }, +#endif +#if defined(MNCC_SETUP_RSP) + { MNCC_SETUP_RSP, "MNCC_SETUP_RSP" }, +#endif +#if defined(MNCC_SETUP_CNF) + { MNCC_SETUP_CNF, "MNCC_SETUP_CNF" }, +#endif +#if defined(MNCC_SETUP_COMPL_REQ) + { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" }, +#endif +#if defined(MNCC_SETUP_COMPL_IND) + { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" }, +#endif +#if defined(MNCC_CALL_CONF_IND) + { MNCC_CALL_CONF_IND, "MNCC_CALL_CONF_IND" }, +#endif +#if defined(MNCC_CALL_PROC_REQ) + { MNCC_CALL_PROC_REQ, "MNCC_CALL_PROC_REQ" }, +#endif +#if defined(MNCC_PROGRESS_REQ) + { MNCC_PROGRESS_REQ, "MNCC_PROGRESS_REQ" }, +#endif +#if defined(MNCC_ALERT_REQ) + { MNCC_ALERT_REQ, "MNCC_ALERT_REQ" }, +#endif +#if defined(MNCC_ALERT_IND) + { MNCC_ALERT_IND, "MNCC_ALERT_IND" }, +#endif +#if defined(MNCC_NOTIFY_REQ) + { MNCC_NOTIFY_REQ, "MNCC_NOTIFY_REQ" }, +#endif +#if defined(MNCC_NOTIFY_IND) + { MNCC_NOTIFY_IND, "MNCC_NOTIFY_IND" }, +#endif +#if defined(MNCC_DISC_REQ) + { MNCC_DISC_REQ, "MNCC_DISC_REQ" }, +#endif +#if defined(MNCC_DISC_IND) + { MNCC_DISC_IND, "MNCC_DISC_IND" }, +#endif +#if defined(MNCC_REL_REQ) + { MNCC_REL_REQ, "MNCC_REL_REQ" }, +#endif +#if defined(MNCC_REL_IND) + { MNCC_REL_IND, "MNCC_REL_IND" }, +#endif +#if defined(MNCC_REL_CNF) + { MNCC_REL_CNF, "MNCC_REL_CNF" }, +#endif +#if defined(MNCC_FACILITY_REQ) + { MNCC_FACILITY_REQ, "MNCC_FACILITY_REQ" }, +#endif +#if defined(MNCC_FACILITY_IND) + { MNCC_FACILITY_IND, "MNCC_FACILITY_IND" }, +#endif +#if defined(MNCC_START_DTMF_IND) + { MNCC_START_DTMF_IND, "MNCC_START_DTMF_IND" }, +#endif +#if defined(MNCC_START_DTMF_RSP) + { MNCC_START_DTMF_RSP, "MNCC_START_DTMF_RSP" }, +#endif +#if defined(MNCC_START_DTMF_REJ) + { MNCC_START_DTMF_REJ, "MNCC_START_DTMF_REJ" }, +#endif +#if defined(MNCC_STOP_DTMF_IND) + { MNCC_STOP_DTMF_IND, "MNCC_STOP_DTMF_IND" }, +#endif +#if defined(MNCC_STOP_DTMF_RSP) + { MNCC_STOP_DTMF_RSP, "MNCC_STOP_DTMF_RSP" }, +#endif +#if defined(MNCC_MODIFY_REQ) + { MNCC_MODIFY_REQ, "MNCC_MODIFY_REQ" }, +#endif +#if defined(MNCC_MODIFY_IND) + { MNCC_MODIFY_IND, "MNCC_MODIFY_IND" }, +#endif +#if defined(MNCC_MODIFY_RSP) + { MNCC_MODIFY_RSP, "MNCC_MODIFY_RSP" }, +#endif +#if defined(MNCC_MODIFY_CNF) + { MNCC_MODIFY_CNF, "MNCC_MODIFY_CNF" }, +#endif +#if defined(MNCC_MODIFY_REJ) + { MNCC_MODIFY_REJ, "MNCC_MODIFY_REJ" }, +#endif +#if defined(MNCC_HOLD_IND) + { MNCC_HOLD_IND, "MNCC_HOLD_IND" }, +#endif +#if defined(MNCC_HOLD_CNF) + { MNCC_HOLD_CNF, "MNCC_HOLD_CNF" }, +#endif +#if defined(MNCC_HOLD_REJ) + { MNCC_HOLD_REJ, "MNCC_HOLD_REJ" }, +#endif +#if defined(MNCC_RETRIEVE_IND) + { MNCC_RETRIEVE_IND, "MNCC_RETRIEVE_IND" }, +#endif +#if defined(MNCC_RETRIEVE_CNF) + { MNCC_RETRIEVE_CNF, "MNCC_RETRIEVE_CNF" }, +#endif +#if defined(MNCC_RETRIEVE_REJ) + { MNCC_RETRIEVE_REJ, "MNCC_RETRIEVE_REJ" }, +#endif +#if defined(MNCC_USERINFO_REQ) + { MNCC_USERINFO_REQ, "MNCC_USERINFO_REQ" }, +#endif +#if defined(MNCC_USERINFO_IND) + { MNCC_USERINFO_IND, "MNCC_USERINFO_IND" }, +#endif +#if defined(MNCC_REJ_REQ) + { MNCC_REJ_REQ, "MNCC_REJ_REQ" }, +#endif +#if defined(MNCC_REJ_IND) + { MNCC_REJ_IND, "MNCC_REJ_IND" }, +#endif +#if defined(MNCC_PROGRESS_IND) + { MNCC_PROGRESS_IND, "MNCC_PROGRESS_IND" }, +#endif +#if defined(MNCC_CALL_PROC_IND) + { MNCC_CALL_PROC_IND, "MNCC_CALL_PROC_IND" }, +#endif +#if defined(MNCC_CALL_CONF_REQ) + { MNCC_CALL_CONF_REQ, "MNCC_CALL_CONF_REQ" }, +#endif +#if defined(MNCC_START_DTMF_REQ) + { MNCC_START_DTMF_REQ, "MNCC_START_DTMF_REQ" }, +#endif +#if defined(MNCC_STOP_DTMF_REQ) + { MNCC_STOP_DTMF_REQ, "MNCC_STOP_DTMF_REQ" }, +#endif +#if defined(MNCC_HOLD_REQ) + { MNCC_HOLD_REQ, "MNCC_HOLD_REQ " }, +#endif +#if defined(MNCC_RETRIEVE_REQ) + { MNCC_RETRIEVE_REQ, "MNCC_RETRIEVE_REQ" }, +#endif + { 0, NULL } +}; + +const char *mncc_name(int value) +{ + int i = 0; + + while (mncc_names[i].name) { + if (mncc_names[i].msg_type == value) + return mncc_names[i].name; + i++; + } + return "unknown"; +} + /* * create and send mncc message */ @@ -38,14 +199,16 @@ struct gsm_mncc *create_mncc(int msg_type, unsigned int callref) } int send_and_free_mncc(void *instance, unsigned int msg_type, void *data) { - int ret; + int ret = 0; + if (instance) { #ifdef WITH_GSM_BS - ret = mncc_send((struct gsm_network *)instance, msg_type, data); + ret = mncc_send((struct gsm_network *)instance, msg_type, data); #endif #ifdef WITH_GSM_MS - ret = mncc_send((struct osmocom_ms *)instance, msg_type, data); + ret = mncc_send((struct osmocom_ms *)instance, msg_type, data); #endif + } free(data); return ret; @@ -119,7 +282,7 @@ void Pgsm::bchannel_close(void) static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index); -/* open bsc side bchannel */ +/* open external side bchannel */ int Pgsm::bchannel_open(int index) { int ret; @@ -145,7 +308,7 @@ int Pgsm::bchannel_open(int index) /* bind socket to bchannel */ addr.family = AF_ISDN; - addr.dev = gsm->gsm_port; + addr.dev = mISDNloop.port; addr.channel = index+1+(index>15); ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { @@ -257,13 +420,13 @@ void Pgsm::frame_receive(void *arg) /* * create trace - **/ + */ void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction) { char msgtext[64]; /* select message and primitive text */ - SCPY(msgtext, get_mncc_name(msg_type)); + SCPY(msgtext, mncc_name(msg_type)); /* add direction */ if (port) { @@ -295,70 +458,10 @@ void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned msgtext); } -/* select bchannel */ +/* select free bchannel from loopback interface */ int Pgsm::hunt_bchannel(void) { - int channel; - int i; - char map[p_m_mISDNport->b_num]; - struct interface *interface; - struct interface_port *ifport; - - chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE); - add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved); - if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan.. - add_trace("conclusion", NULL, "all channels are reserved"); - end_trace(); - return(-34); // no channel - } - - /* map all used ports of shared loopback interface */ - memset(map, 0, sizeof(map)); - interface = interface_first; - while(interface) { - ifport = interface->ifport; - while(ifport) { -#if defined WITH_GSM_BS && defined WITH_GSM_MS - if ((ifport->gsm_bs || ifport->gsm_ms) && ifport->mISDNport) { -#else -#ifdef WITH_GSM_BS - if (ifport->gsm_bs && ifport->mISDNport) { -#endif -#ifdef WITH_GSM_MS - if (ifport->gsm_ms && ifport->mISDNport) { -#endif -#endif - i = 0; - while(i < p_m_mISDNport->b_num) { - if (p_m_mISDNport->b_port[i]) - map[i] = 1; - i++; - } - } - ifport = ifport->next; - } - interface = interface->next; - } - - /* find channel */ - i = 0; - channel = 0; - while(i < p_m_mISDNport->b_num) { - if (!map[i]) { - channel = i+1+(i>=15); - break; - } - i++; - } - if (!channel) { - add_trace("conclusion", NULL, "no channel available"); - end_trace(); - return(-6); // channel unacceptable - } - add_trace("conclusion", NULL, "channel available"); - add_trace("connect", "channel", "%d", channel); - end_trace(); - return(channel); + return loop_hunt_bchannel(this, p_m_mISDNport); } /* PROCEEDING INDICATION */ @@ -884,87 +987,10 @@ static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int i return 0; } -static void gsm_sock_close(void) -{ - if (gsm->gsm_sock > -1) - close(gsm->gsm_sock); - gsm->gsm_sock = -1; -} - -static int gsm_sock_open(char *portname) -{ - int ret; - int cnt; - unsigned long on = 1; - struct sockaddr_mISDN addr; - struct mISDN_devinfo devinfo; - int pri, bri; - - /* check port counts */ - ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt); - if (ret < 0) { - fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret); - return(ret); - } - - if (cnt <= 0) { - PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n"); - return -EIO; - } - gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname); - if (gsm->gsm_port < 0) { - PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname); - return gsm->gsm_port; - } - /* get protocol */ - bri = pri = 0; - devinfo.id = gsm->gsm_port; - ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo); - if (ret < 0) { - PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret); - return ret; - } - if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) { - bri = 1; - } - if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) { - pri = 1; - } - if (!pri && !pri) { - PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port); - } - /* open socket */ - if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, (pri)?ISDN_P_TE_E1:ISDN_P_TE_S0)) < 0) { - PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port); - gsm_sock_close(); - return gsm->gsm_sock; - } - /* set nonblocking io */ - if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) { - PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port); - gsm_sock_close(); - return ret; - } - /* bind socket to dchannel */ - memset(&addr, 0, sizeof(addr)); - addr.family = AF_ISDN; - addr.dev = gsm->gsm_port; - addr.channel = 0; - if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) { - PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno); - gsm_sock_close(); - return (ret); - } - - return 0; -} - int gsm_exit(int rc) { /* free gsm instance */ if (gsm) { - if (gsm->gsm_sock > -1) - gsm_sock_close(); free(gsm); gsm = NULL; } @@ -974,31 +1000,11 @@ int gsm_exit(int rc) int gsm_init(void) { - char conf_error[256] = ""; - /* seed the PRNG */ srand(time(NULL)); /* create gsm instance */ gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm)); - gsm->gsm_sock = -1; - - /* parse options */ - if (!gsm_conf(&gsm->conf, conf_error)) { - PERROR("%s", conf_error); -#ifdef WITH_GSM_BS - gsm_bs_exit(-EINVAL); -#endif -#ifdef WITH_GSM_MS - gsm_ms_exit(-EINVAL); -#endif - return gsm_exit(-EINVAL); - } - - /* open gsm loop interface */ - if (gsm_sock_open(gsm->conf.interface_bsc)) { - return gsm_exit(-1); - } return 0; } diff --git a/gsm.h b/gsm.h index 71ed759..c12baa0 100644 --- a/gsm.h +++ b/gsm.h @@ -1,24 +1,22 @@ + +#include + extern int new_callref; -struct gsm_conf { - char debug[128]; /* debug info */ - char interface_bsc[64]; /* loopback interface BSC side */ - char interface_lcr[64]; /* loopback interface LCR side */ - char openbsc_cfg[128]; /* openbsc config file */ - char short_name[64]; /* short network name */ - char long_name[64]; /* long network name */ - char hlr[64]; /* database name */ - int allow_all; /* accept unknown subscribers */ - int keep_l2; /* keep layer 2 after exit */ - char pcapfile[128]; /* open capture file for BS11 links */ - int reject_cause; /* reject cause for unsubcribed IMSIs */ +struct mncc_q_entry { + struct mncc_q_entry *next; + unsigned int len; + char data[0]; /* struct gsm_mncc */ }; struct lcr_gsm { void *network; /* OpenBSC network handle */ - struct gsm_conf conf; /* gsm.conf options */ - int gsm_sock; /* loopback interface GSM side */ - int gsm_port; /* loopback interface port number */ + + struct lcr_fd mncc_lfd; /* Unix domain socket to OpenBSC MNCC */ + struct mncc_q_entry *mncc_q_hd; + struct mncc_q_entry *mncc_q_tail; + struct lcr_timer socket_retry; /* Timer to re-try connecting to BSC socket */ + struct sockaddr_un sun; /* Socket address of MNCC socket */ }; extern struct lcr_gsm *gsm; diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 584b7e2..22ac70c 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -16,75 +16,46 @@ #define _GNU_SOURCE #endif extern "C" { +#include #include -#include -#include -#include -#include -#include +#include +#include + #include #include -#include -//#include -struct gsm_network *bsc_gsmnet = 0; -extern int ipacc_rtp_direct; -extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *), - const char *cfg_file); -extern int bsc_shutdown_net(struct gsm_network *net); -void talloc_ctx_init(void); -void on_dso_load_token(void); -void on_dso_load_rrlp(void); -void on_dso_load_ho_dec(void); -int bts_model_unknown_init(void); -int bts_model_bs11_init(void); -int bts_model_nanobts_init(void); -static struct log_target *stderr_target; -extern const char *openbsc_copyright; - -/* timer to store statistics */ -#define DB_SYNC_INTERVAL 60, 0 -static struct timer_list db_sync_timer; - -/* FIXME: copied from the include file, because it will con compile with C++ */ -struct vty_app_info { - const char *name; - const char *version; - const char *copyright; - void *tall_ctx; - int (*go_parent_cb)(struct vty *vty); - int (*is_config_node)(struct vty *vty, int node); -}; - -extern int bsc_vty_go_parent(struct vty *vty); -extern int bsc_vty_is_config_node(struct vty *vty, int node); -static struct vty_app_info vty_info = { - "OpenBSC", - PACKAGE_VERSION, - NULL, - NULL, - bsc_vty_go_parent, - bsc_vty_is_config_node, -}; - -void vty_init(struct vty_app_info *app_info); -int bsc_vty_init(void); - } -/* timer handling */ -static int _db_store_counter(struct counter *counter, void *data) -{ - return db_store_counter(counter); -} +#define SOCKET_RETRY_TIMER 5 + +/* + * DTMF stuff + */ +unsigned char dtmf_samples[16][8000]; +static int dtmf_x[4] = { 1209, 1336, 1477, 1633 }; +static int dtmf_y[4] = { 697, 770, 852, 941 }; -static void db_sync_timer_cb(void *data) +void generate_dtmf(void) { - /* store counters to database and re-schedule */ - counters_for_each(_db_store_counter, NULL); - bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL); + double fx, fy, sample; + int i, x, y; + unsigned char *law; + + for (y = 0; y < 4; y++) { + fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0; + for (x = 0; x < 4; x++) { + fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0; + law = dtmf_samples[y << 2 | x]; + for (i = 0; i < 8000; i++) { + sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */ + sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */ + *law++ = audio_s16_to_law[(int)sample & 0xffff]; + } + } + } } + /* * DTMF stuff */ @@ -150,6 +121,7 @@ void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct add_trace("keypad", NULL, "%c", mncc->keypad); end_trace(); resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref); + resp->fields |= MNCC_F_KEYPAD; resp->keypad = mncc->keypad; send_and_free_mncc(p_m_g_instance, resp->msg_type, resp); @@ -620,6 +592,20 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); + /* no GSM MNCC connection */ + if (gsm->mncc_lfd.fd < 0) { + gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); + add_trace("failure", NULL, "No MNCC connection."); + end_trace(); + message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; // temp. unavail. + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + new_state(PORT_STATE_RELEASE); + trigger_work(&p_m_g_delete); + return; + } + /* no number */ if (!p_dialinginfo.id[0]) { gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); @@ -838,6 +824,7 @@ int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parame int gsm_bs_exit(int rc) { +#if 0 /* free gsm instance */ if (gsm) { /* shutdown network */ @@ -848,110 +835,211 @@ int gsm_bs_exit(int rc) // free((struct gsm_network *)gsm->network); /* TBD */ // } } - +#endif return(rc); } -int gsm_bs_init(void) +extern "C" { + +static int mncc_q_enqueue(struct gsm_mncc *mncc, unsigned int len) { - char hlr[128], cfg[128], filename[128]; - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - int pcapfd, rc; - - vty_info.copyright = openbsc_copyright; - - log_init(&log_info); - tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc"); - talloc_ctx_init(); - on_dso_load_token(); - on_dso_load_rrlp(); - on_dso_load_ho_dec(); - stderr_target = log_target_create_stderr(); - log_add_target(stderr_target); - - bts_model_unknown_init(); - bts_model_bs11_init(); - bts_model_nanobts_init(); - - /* enable filters */ - log_set_all_filter(stderr_target, 1); - - /* Init VTY (need to preceed options) */ - vty_init(&vty_info); - bsc_vty_init(); - - /* set debug */ - if (gsm->conf.debug[0]) - log_parse_category_mask(stderr_target, gsm->conf.debug); - - /* open pcap file */ - if (gsm->conf.pcapfile[0]) { - if (gsm->conf.pcapfile[0] == '/') - SCPY(filename, gsm->conf.pcapfile); - else - SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile); - pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode); - if (pcapfd < 0) { - PERROR("Failed to open file for pcap\n"); - return gsm_exit(-1); - } - e1_set_pcap_fd(pcapfd); - } + struct mncc_q_entry *qe; - /* use RTP proxy for audio streaming */ - ipacc_rtp_direct = 0; + qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len); + if (!qe) + return -ENOMEM; - /* bootstrap network */ - if (gsm->conf.openbsc_cfg[0] == '/') - SCPY(cfg, gsm->conf.openbsc_cfg); - else - SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg); - rc = bsc_bootstrap_network(&message_bsc, cfg); - if (rc < 0) { - PERROR("Failed to bootstrap GSM network.\n"); - return gsm_exit(-1); + qe->next = NULL; + qe->len = len; + memcpy(qe->data, mncc, len); + + /* in case of empty list ... */ + if (!gsm->mncc_q_hd && !gsm->mncc_q_tail) { + /* the list head and tail both point to the new qe */ + gsm->mncc_q_hd = gsm->mncc_q_tail = qe; + } else { + /* append to tail of list */ + gsm->mncc_q_tail->next = qe; + gsm->mncc_q_tail = qe; } - bsc_api_init(bsc_gsmnet, msc_bsc_api()); - gsm->network = bsc_gsmnet; - /* init database */ - if (gsm->conf.hlr[0] == '/') - SCPY(hlr, gsm->conf.hlr); - else - SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr); - if (db_init(hlr)) { - PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr); - return gsm_exit(-1); + gsm->mncc_lfd.when |= LCR_FD_WRITE; + + return 0; +} + +static struct mncc_q_entry *mncc_q_dequeue(void) +{ + struct mncc_q_entry *qe = gsm->mncc_q_hd; + if (!qe) + return NULL; + + /* dequeue the successfully sent message */ + gsm->mncc_q_hd = qe->next; + if (!qe) + return NULL; + if (qe == gsm->mncc_q_tail) + gsm->mncc_q_tail = NULL; + + return qe; +} + +/* routine called by LCR code if it wants to send a message to OpenBSC */ +int mncc_send(struct gsm_network *instance, int msg_type, void *data) +{ + int len = 0; + + /* FIXME: the caller should provide this */ + switch (msg_type) { + case GSM_TCHF_FRAME: + len = sizeof(struct gsm_data_frame) + 33; + break; + default: + len = sizeof(struct gsm_mncc); + break; } - printf("DB: Database initialized.\n"); - if (db_prepare()) { - PERROR("GSM DB: Failed to prepare database.\n"); - return gsm_exit(-1); + + return mncc_q_enqueue((struct gsm_mncc *)data, len); +} + +} // extern "C" + +/* close MNCC socket */ +static int mncc_fd_close(struct lcr_fd *lfd) +{ + class Port *port; + class Pgsm_bs *pgsm_bs = NULL; + struct lcr_msg *message; + + PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER); + close(lfd->fd); + unregister_fd(lfd); + lfd->fd = -1; + + /* free all the calls that were running through the MNCC interface */ + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) { + pgsm_bs = (class Pgsm_bs *)port; + message = message_create(pgsm_bs->p_serial, ACTIVE_EPOINT(pgsm_bs->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; // temp. unavail. + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + pgsm_bs->new_state(PORT_STATE_RELEASE); + trigger_work(&pgsm_bs->p_m_g_delete); + } + port = port->next; } - printf("DB: Database prepared.\n"); - /* setup the timer */ - db_sync_timer.cb = db_sync_timer_cb; - db_sync_timer.data = NULL; - bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL); + /* flush the queue */ + while (mncc_q_dequeue()) + ; + + /* start the re-connect timer */ + schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0); generate_dtmf(); return 0; } -/* - * handles bsc select function within LCR's main loop - */ -int handle_gsm_bs(void) +/* read from OpenBSC via MNCC socket */ +static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx) +{ + struct mncc_q_entry *qe, *qe2; + int rc; + + while (1) { + qe = gsm->mncc_q_hd; + if (!qe) { + lfd->when &= ~LCR_FD_WRITE; + break; + } + rc = write(lfd->fd, qe->data, qe->len); + if (rc == 0) + return mncc_fd_close(lfd); + if (rc < 0) + return rc; + if (rc < (int)qe->len) + return -1; + /* dequeue the successfully sent message */ + qe2 = mncc_q_dequeue(); + assert(qe == qe2); + free(qe); + } + return 0; +} + +/* read from OpenBSC via MNCC socket */ +static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx) +{ + int rc; + static char buf[sizeof(struct gsm_mncc)+1024]; + struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf; + + memset(buf, 0, sizeof(buf)); + rc = recv(lfd->fd, buf, sizeof(buf), 0); + if (rc == 0) + return mncc_fd_close(lfd); + if (rc < 0) + return rc; + + /* Hand the MNCC message into LCR */ + return message_bsc(NULL, mncc_prim->msg_type, mncc_prim); +} + +/* file descriptor callback if we can read or write form MNCC socket */ +static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *instance, int idx) +{ + int rc = 0; + + if (what & LCR_FD_READ) + rc = mncc_fd_read(lfd, instance, idx); + if (rc < 0) + return rc; + + if (what & LCR_FD_WRITE) + rc = mncc_fd_write(lfd, instance, idx); + + return rc; +} + +static int socket_retry_cb(struct lcr_timer *timer, void *instance, int index) { - int ret1, ret2; + int fd, rc; + + fd = socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { + PERROR("Cannot create SEQPACKET socket, giving up!\n"); + return fd; + } + + rc = connect(fd, (struct sockaddr *) &gsm->sun, + sizeof(gsm->sun)); + if (rc < 0) { + PERROR("Could not connect to MNCC socket, " + "retrying in %u seconds\n", SOCKET_RETRY_TIMER); + close(fd); + schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0); + } else { + PDEBUG(DEBUG_GSM, "Connected to MNCC socket!\n"); + gsm->mncc_lfd.fd = fd; + register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0); + } - ret1 = bsc_upqueue((struct gsm_network *)gsm->network); - log_reset_context(); - ret2 = bsc_select_main(1); /* polling */ - if (ret1 || ret2) - return 1; return 0; } +int gsm_bs_init(void) +{ + gsm->sun.sun_family = AF_UNIX; + SCPY(gsm->sun.sun_path, "/tmp/bsc_mncc"); + + memset(&gsm->socket_retry, 0, sizeof(gsm->socket_retry)); + add_timer(&gsm->socket_retry, socket_retry_cb, NULL, 0); + + /* do the initial connect */ + socket_retry_cb(&gsm->socket_retry, NULL, 0); + + return 0; +} diff --git a/gsm_bs.h b/gsm_bs.h index fd56efe..8a55213 100644 --- a/gsm_bs.h +++ b/gsm_bs.h @@ -25,3 +25,7 @@ int handle_gsm_bs(void); int gsm_bs_conf(struct gsm_conf *gsm_conf, char *conf_error); int gsm_bs_exit(int rc); int gsm_bs_init(void); + +extern "C" { +int mncc_send(struct gsm_network *instance, int msg_type, void *data); +}; diff --git a/gsm_conf.c b/gsm_conf.c deleted file mode 100644 index a64f2ff..0000000 --- a/gsm_conf.c +++ /dev/null @@ -1,170 +0,0 @@ -/*****************************************************************************\ -** ** -** PBX4Linux ** -** ** -**---------------------------------------------------------------------------** -** Copyright: Andreas Eversberg ** -** ** -** reading options.conf and filling structure ** -** ** -\*****************************************************************************/ - -#include "main.h" - - -/* read options - * - * read options from options.conf - */ -int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error) -{ - FILE *fp=NULL; - char filename[128]; - char *p; - char option[32]; - char params[11][256]; - int pnum; - unsigned int line,i; - char buffer[256]; - - /* set defaults */ - SCPY(gsm_conf->debug, ""); - SCPY(gsm_conf->interface_bsc, "mISDN_l1loop.1"); - SCPY(gsm_conf->interface_lcr, "mISDN_l1loop.2"); - SCPY(gsm_conf->hlr, "hlr.sqlite3"); - SCPY(gsm_conf->openbsc_cfg, "openbsc.cfg"); - gsm_conf->reject_cause = 0; - gsm_conf->keep_l2 = 0; - - SPRINT(filename, "%s/gsm.conf", CONFIG_DATA); - - if (!(fp=fopen(filename,"r"))) { - UPRINT(conf_error, "Cannot open %s\n",filename); - return(0); - } - - line=0; - while((GETLINE(buffer, fp))) { - line++; - p=buffer; - - while(*p <= 32) { /* skip spaces */ - if (*p == 0) - break; - p++; - } - if (*p==0 || *p=='#') /* ignore comments and empty line */ - continue; - - option[0]=0; - i=0; /* read option */ - while(*p > 32) { - if (i+1 >= sizeof(option)) { - UPRINT(conf_error, "Error in %s (line %d): option too long.\n",filename,line); - goto error; - } - option[i+1] = '\0'; - option[i++] = *p++; - } - - while(*p <= 32) { /* skip spaces */ - if (*p == 0) - break; - p++; - } - - params[0][0] = 0; - pnum = 0; - while(*p!=0 && *p!='#' && pnum < 10) { /* param */ - i=0; /* read param */ - while(*p > 32) { - if (i+1 >= sizeof(params[pnum])) { - UPRINT(conf_error, "Error in %s (line %d): param too long.\n",filename,line); - goto error; - } - params[pnum][i+1] = '\0'; - params[pnum][i++] = *p++; - } - while(*p <= 32) { /* skip spaces */ - if (*p == 0) - break; - p++; - } - pnum++; - params[pnum][0] = 0; - } - - /* at this point we have option and param */ - - /* check option */ - if (!strcmp(option,"debug")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option); - goto error; - } - SCPY(gsm_conf->debug, params[0]); - - } else - if (!strcmp(option,"interface-bsc")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); - goto error; - } - SCPY(gsm_conf->interface_bsc, params[0]); - - } else - if (!strcmp(option,"interface-lcr")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); - goto error; - } - SCPY(gsm_conf->interface_lcr, params[0]); - - } else - if (!strcmp(option,"config")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); - goto error; - } - SCPY(gsm_conf->openbsc_cfg, params[0]); - - } else - if (!strcmp(option,"hlr")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); - goto error; - } - SCPY(gsm_conf->hlr, params[0]); - - } else - if (!strcmp(option,"reject-cause")) { - UPRINT(conf_error, "Option '%s' in gsm.conf has moved to openbsc.cfg", option); - goto error; - } else - if (!strcmp(option,"allow-all")) { - gsm_conf->allow_all = 1; - } else - if (!strcmp(option,"keep-l2")) { - gsm_conf->keep_l2 = 1; - - } else - if (!strcmp(option,"pcapfile")) { - if (params[0][0]==0) { - UPRINT(conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); - goto error; - } - SCPY(gsm_conf->pcapfile, params[0]); - } else { - UPRINT(conf_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option); - goto error; - } - } - - if (fp) fclose(fp); - return(1); -error: - if (fp) fclose(fp); - return(0); -} - - diff --git a/gsm_ms.cpp b/gsm_ms.cpp index 551fcad..c8292f9 100644 --- a/gsm_ms.cpp +++ b/gsm_ms.cpp @@ -16,24 +16,26 @@ #endif extern "C" { #include +#include #include #include +#include #include #include #include -#include +#include } -const char *openbsc_copyright = ""; +static const char *config_file = "/etc/osmocom/osmocom.cfg"; short vty_port = 4247; struct llist_head ms_list; struct log_target *stderr_target; void *l23_ctx = NULL; -int (*l23_app_work) (struct osmocom_ms *ms) = NULL; -int (*l23_app_exit) (struct osmocom_ms *ms) = NULL; + +static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index); static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index); @@ -54,8 +56,11 @@ Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct p } } - if (!p_m_g_instance) - FATAL("MS name %s does not exists. Please fix!"); + p_m_g_dtmf_state = DTMF_ST_IDLE; + p_m_g_dtmf_index = 0; + p_m_g_dtmf[0] = '\0'; + memset(&p_m_g_dtmf_timer, 0, sizeof(p_m_g_dtmf_timer)); + add_timer(&p_m_g_dtmf_timer, dtmf_timeout, this, 0); p_m_g_dtmf_state = DTMF_ST_IDLE; p_m_g_dtmf_index = 0; @@ -391,7 +396,31 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg) struct mISDNport *mISDNport; /* Special messages */ - if (msg_type) { + switch (msg_type) { + case MS_NEW: + PDEBUG(DEBUG_GSM, "MS %s comes available\n", ms->name); + return 0; + case MS_DELETE: + PDEBUG(DEBUG_GSM, "MS %s is removed\n", ms->name); + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) { + pgsm_ms = (class Pgsm_ms *)port; + if (pgsm_ms->p_m_g_instance == ms) { + struct lcr_msg *message; + + pgsm_ms->p_m_g_instance = 0; + message = message_create(pgsm_ms->p_serial, ACTIVE_EPOINT(pgsm_ms->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + pgsm_ms->new_state(PORT_STATE_RELEASE); + trigger_work(&pgsm_ms->p_m_g_delete); + } + } + port = port->next; + } + return 0; } /* find callref */ @@ -508,6 +537,20 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); + /* no instance */ + if (!p_m_g_instance) { + gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); + add_trace("failure", NULL, "MS %s instance is unavailable", p_m_mISDNport->ifport->gsm_ms_name); + end_trace(); + message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + new_state(PORT_STATE_RELEASE); + trigger_work(&p_m_g_delete); + return; + } + /* no number */ if (!p_dialinginfo.id[0]) { gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); @@ -782,6 +825,7 @@ int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parame int gsm_ms_exit(int rc) { + l23_app_exit(); return(rc); } @@ -796,50 +840,40 @@ int gsm_ms_init(void) l23_ctx = talloc_named_const(NULL, 1, "layer2 context"); - return 0; -} - -/* add a new GSM mobile instance */ -int gsm_ms_new(const char *name, const char *socket_path) -{ - struct osmocom_ms *ms = NULL; - int rc; - - PDEBUG(DEBUG_GSM, "GSM: creating new instance '%s' on '%s'\n", name, socket_path); + log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM"); + log_set_log_level(stderr_target, LOGL_INFO); - ms = talloc_zero(l23_ctx, struct osmocom_ms); - if (!ms) { - FATAL("Failed to allocate MS\n"); +#if 0 + if (gsmtap_ip) { + rc = gsmtap_init(gsmtap_ip); + if (rc < 0) { + fprintf(stderr, "Failed during gsmtap_init()\n"); + exit(1); + } } - /* must add here, because other init processes may search in the list */ - llist_add_tail(&ms->entity, &ms_list); - +#endif - SPRINT(ms->name, name); + l23_app_init(message_ms, config_file, vty_port); - rc = layer2_open(ms, socket_path); - if (rc < 0) { - FATAL("Failed during layer2_open()\n"); - } - - lapdm_init(&ms->l2_entity.lapdm_dcch, ms); - lapdm_init(&ms->l2_entity.lapdm_acch, ms); + return 0; +} - rc = l23_app_init(ms); - if (rc < 0) { - FATAL("Failed to init layer23\n"); - } - ms->mncc_entity.mncc_recv = message_ms; +/* add a new GSM mobile instance */ +int gsm_ms_new(const char *name) +{ + PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is up\n", name); return 0; } int gsm_ms_delete(const char *name) { - struct osmocom_ms *ms = NULL; + struct osmocom_ms *ms; int found = 0; + class Port *port; + class Pgsm_ms *pgsm_ms = NULL; - PDEBUG(DEBUG_GSM, "GSM: destroying instance '%s'\n", name); + PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is down\n", name); llist_for_each_entry(ms, &ms_list, entity) { if (!strcmp(ms->name, name)) { @@ -848,15 +882,29 @@ int gsm_ms_delete(const char *name) } } - if (!found) { - FATAL("Failed delete layer23, instance '%s' not found\n", name); - } - - l23_app_exit(ms); - lapdm_exit(&ms->l2_entity.lapdm_dcch); - lapdm_exit(&ms->l2_entity.lapdm_acch); + if (!found) + return 0; - llist_del(&ms->entity); + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) { + pgsm_ms = (class Pgsm_ms *)port; + if (pgsm_ms->p_m_g_instance == ms && pgsm_ms->p_m_g_callref) { + struct gsm_mncc *rej; + + rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref); + rej->fields |= MNCC_F_CAUSE; + rej->cause.coding = 3; + rej->cause.location = 1; + rej->cause.value = 27; + gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT); + add_trace("cause", "coding", "%d", rej->cause.coding); + add_trace("cause", "location", "%d", rej->cause.location); + add_trace("cause", "value", "%d", rej->cause.value); + end_trace(); + } + } + } return 0; } @@ -864,18 +912,17 @@ int gsm_ms_delete(const char *name) /* * handles bsc select function within LCR's main loop */ -int handle_gsm_ms(void) +int handle_gsm_ms(int *_quit) { - struct osmocom_ms *ms = NULL; - int work = 0; - - llist_for_each_entry(ms, &ms_list, entity) { - if (l23_app_work(ms)) - work = 1; -// debug_reset_context(); - if (bsc_select_main(1)) /* polling */ - work = 1; - } + int work = 0, quit = 0; + + if (l23_app_work(&quit)) + work = 1; + if (quit && llist_empty(&ms_list)) + *_quit = 1; +// debug_reset_context(); + if (bsc_select_main(1)) /* polling */ + work = 1; return work; } diff --git a/gsm_ms.h b/gsm_ms.h index 3e9794f..822f0a6 100644 --- a/gsm_ms.h +++ b/gsm_ms.h @@ -23,10 +23,10 @@ class Pgsm_ms : public Pgsm int message_epoint(unsigned int epoint_id, int message_id, union parameter *param); }; -int handle_gsm_ms(void); +int handle_gsm_ms(int *quit); int gsm_ms_conf(struct gsm_conf *gsm_conf, char *conf_error); int gsm_ms_exit(int rc); int gsm_ms_init(void); -int gsm_ms_new(const char *name, const char *socket_path); +int gsm_ms_new(const char *name); int gsm_ms_delete(const char *name); diff --git a/install-sh b/install-sh deleted file mode 100755 index 4fbbae7..0000000 --- a/install-sh +++ /dev/null @@ -1,507 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2006-10-14.15 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -posix_glob= -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chmodcmd=$chmodprog -chowncmd= -chgrpcmd= -stripcmd= -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src= -dst= -dir_arg= -dstarg= -no_target_directory= - -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - shift - shift - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t) dstarg=$2 - shift - shift - continue;; - - -T) no_target_directory=true - shift - continue;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac -done - -if test $# -ne 0 && test -z "$dir_arg$dstarg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src ;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dstarg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix=/ ;; - -*) prefix=./ ;; - *) prefix= ;; - esac - - case $posix_glob in - '') - if (set -f) 2>/dev/null; then - posix_glob=true - else - posix_glob=false - fi ;; - esac - - oIFS=$IFS - IFS=/ - $posix_glob && set -f - set fnord $dstdir - shift - $posix_glob && set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dst"; then - $doit $rmcmd -f "$dst" 2>/dev/null \ - || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ - && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ - || { - echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - } || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/interface.c b/interface.c index 09e0067..4e432af 100644 --- a/interface.c +++ b/interface.c @@ -325,11 +325,9 @@ static int inter_portname(struct interface *interface, char *filename, int line, ifport = ifport->next; } - /* check for port already assigned, but not for shared gsm interface */ + /* check for port already assigned, but not for shared loop interface */ searchif = interface_newlist; -#if defined WITH_GSM_BS || defined WITH_GSM_MS - if (options.gsm && !strcmp(value, gsm->conf.interface_lcr)) -#endif + if (!!strcmp(value, options.loopback_lcr)) { while(searchif) { ifport = searchif->ifport; @@ -918,7 +916,7 @@ static int inter_gsm_bs(struct interface *interface, char *filename, int line, c } /* set portname */ - if (inter_portname(interface, filename, line, (char *)"portname", gsm->conf.interface_lcr)) + if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr)) return(-1); /* goto end of chain again to set gsmflag */ @@ -947,7 +945,7 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c } /* set portname */ - if (inter_portname(interface, filename, line, (char *)"portname", gsm->conf.interface_lcr)) + if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr)) return(-1); /* goto end of chain again to set gsmflag and socket */ @@ -963,21 +961,15 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c return(-1); } SCPY(ifport->gsm_ms_name, element); - element = strsep(&value, " "); - if (!element || !element[0]) { - SPRINT(interface_error, "Error in %s (line %d): Missing socket name after MS name.\n", filename, line); - return(-1); - } - SCPY(ifport->gsm_ms_socket, element); - /* check if socket is used multiple times */ + /* check if name is used multiple times */ searchif = interface_newlist; while(searchif) { searchifport = searchif->ifport; while(searchifport) { if (searchifport != ifport - && !strcmp(searchifport->gsm_ms_socket, ifport->gsm_ms_socket)) { - SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given socket '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_socket); + && !strcmp(searchifport->gsm_ms_name, ifport->gsm_ms_name)) { + SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_name); return(-1); } searchifport = searchifport->next; @@ -1054,6 +1046,42 @@ static int inter_ss5(struct interface *interface, char *filename, int line, char return(0); } #endif +static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value) +{ + struct interface_port *ifport; + struct interface *searchif; + + if (!value[0]) { + SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter); + return(-1); + } + searchif = interface_newlist; + while(searchif) { + ifport = searchif->ifport; + while(ifport) { + if (ifport->remote && !strcmp(ifport->remote_app, value)) { + SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses remote application '%s'.\n", filename, line, ifport->portname, value); + return(-1); + } + ifport = ifport->next; + } + searchif = searchif->next; + } + + /* set portname */ + if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr)) + return(-1); + + /* goto end of chain again to set application name */ + ifport = interface->ifport; + while(ifport->next) + ifport = ifport->next; + ifport->remote = 1; + SCPY(ifport->remote_app, value); + + + return(0); +} /* @@ -1215,6 +1243,10 @@ struct interface_param interface_param[] = { " suppress - Suppress received tones, as they will be recognized."}, #endif + {"remote", &inter_remote, "", + "Sets up an interface that communicates with the remote application.\n" + "Use \"asterisk\" to use chan_lcr as remote application."}, + {NULL, NULL, NULL, NULL} }; @@ -1551,7 +1583,7 @@ void load_port(struct interface_port *ifport) mISDNport_static(mISDNport); #ifdef WITH_GSM_MS if (ifport->gsm_ms) - gsm_ms_new(ifport->gsm_ms_name, ifport->gsm_ms_socket); + gsm_ms_new(ifport->gsm_ms_name); #endif } else { ifport->block = 2; /* not available */ diff --git a/interface.h b/interface.h index d1bea04..f271080 100644 --- a/interface.h +++ b/interface.h @@ -57,10 +57,10 @@ struct interface_port { #ifdef WITH_GSM_MS int gsm_ms; /* interface is an GSM MS interface */ char gsm_ms_name[32]; /* name of ms */ - char gsm_ms_socket[128]; /* layer1 socket name */ - char gsm_ms_service; /* see GSM_SERVICE_* */ #endif unsigned int ss5; /* set, if SS5 signalling enabled, also holds feature bits */ + int remote; /* interface is a remote app interface */ + char remote_app[32]; /* name of remote application */ int channel_force; /* forces channel by protocol */ int nodtmf; /* disables DTMF */ struct select_channel *out_channel; /* list of channels to select */ diff --git a/joinremote.cpp b/joinremote.cpp index 167bbce..c02de8e 100644 --- a/joinremote.cpp +++ b/joinremote.cpp @@ -14,6 +14,7 @@ //#define __u16 unsigned short //#define __u32 unsigned int +extern unsigned int new_remote; /* * constructor for a new join @@ -27,6 +28,7 @@ JoinRemote::JoinRemote(unsigned int serial, char *remote_name, int remote_id) : SCPY(j_remote_name, remote_name); j_remote_id = remote_id; j_type = JOIN_TYPE_REMOTE; + j_remote_ref = new_remote++; j_epoint_id = serial; /* this is the endpoint, if created by epoint */ if (j_epoint_id) @@ -35,9 +37,8 @@ JoinRemote::JoinRemote(unsigned int serial, char *remote_name, int remote_id) : /* send new ref to remote socket */ memset(¶m, 0, sizeof(union parameter)); if (serial) - param.direction = 1; /* new ref from lcr */ - /* the j_serial is assigned by Join() parent. this is sent as new ref */ - if (admin_message_from_join(j_remote_id, j_serial, MESSAGE_NEWREF, ¶m)<0) + param.newref.direction = 1; /* new ref from lcr */ + if (admin_message_from_lcr(j_remote_id, j_remote_ref, MESSAGE_NEWREF, ¶m)<0) FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", j_remote_name); } @@ -56,7 +57,7 @@ void JoinRemote::message_epoint(unsigned int epoint_id, int message_type, union return; /* look for Remote's interface */ - if (admin_message_from_join(j_remote_id, j_serial, message_type, param)<0) { + if (admin_message_from_lcr(j_remote_id, j_remote_ref, message_type, param)<0) { PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all joins.\n", j_remote_name); return; } @@ -100,25 +101,5 @@ void JoinRemote::message_remote(int message_type, union parameter *param) } } -void message_bchannel_to_remote(unsigned int remote_id, unsigned int ref, int type, unsigned int handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type) -{ - union parameter param; - - memset(¶m, 0, sizeof(union parameter)); - param.bchannel.type = type; - param.bchannel.handle = handle; - param.bchannel.tx_gain = tx_gain; - param.bchannel.rx_gain = rx_gain; - if (pipeline) - SCPY(param.bchannel.pipeline, pipeline); - if (crypt_len) - memcpy(param.bchannel.crypt, crypt, crypt_len); - param.bchannel.crypt_type = crypt_type; - if (admin_message_from_join(remote_id, ref, MESSAGE_BCHANNEL, ¶m)<0) { - PERROR("No socket with remote id %d found, this happens, if the socket is closed before all bchannels are imported.\n", remote_id); - return; - } -} - diff --git a/joinremote.h b/joinremote.h index 1582133..a933466 100644 --- a/joinremote.h +++ b/joinremote.h @@ -17,10 +17,10 @@ class JoinRemote : public Join void message_epoint(unsigned int epoint_id, int message, union parameter *param); void message_remote(int message_type, union parameter *param); + unsigned int j_remote_ref; int j_remote_id; char j_remote_name[32]; unsigned int j_epoint_id; }; -void message_bchannel_to_remote(unsigned int remote_id, unsigned int ref, int type, unsigned int handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type); diff --git a/loop.c b/loop.c new file mode 100644 index 0000000..cbd82e5 --- /dev/null +++ b/loop.c @@ -0,0 +1,153 @@ +/*****************************************************************************\ +** ** +** LCR ** +** ** +**---------------------------------------------------------------------------** +** Copyright: Andreas Eversberg ** +** ** +** loopback interface functions ** +** ** +\*****************************************************************************/ + +#include "main.h" + +struct mISDNloop mISDNloop = { -1, 0 }; + +void mISDNloop_close(void) +{ + if (mISDNloop.sock > -1) + close(mISDNloop.sock); + mISDNloop.sock = -1; +} + +int mISDNloop_open() +{ + int ret; + int cnt; + unsigned long on = 1; + struct sockaddr_mISDN addr; + struct mISDN_devinfo devinfo; + int pri, bri; + + /* already open */ + if (mISDNloop.sock > -1) + return 0; + + PDEBUG(DEBUG_PORT, "Open external interface of loopback.\n"); + + /* check port counts */ + ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt); + if (ret < 0) { + fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret); + return(ret); + } + + if (cnt <= 0) { + PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n"); + return -EIO; + } + mISDNloop.port = mISDN_getportbyname(mISDNsocket, cnt, options.loopback_ext); + if (mISDNloop.port < 0) { + PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface?.\n", options.loopback_ext); + return mISDNloop.port; + } + /* get protocol */ + bri = pri = 0; + devinfo.id = mISDNloop.port; + ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo); + if (ret < 0) { + PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", mISDNloop.port, ret); + return ret; + } + if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) { + bri = 1; + } + if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) { + pri = 1; + } + if (!bri && !pri) { + PERROR_RUNTIME("loop port %d does not support TE PRI or TE BRI.\n", mISDNloop.port); + } + /* open socket */ + if ((mISDNloop.sock = socket(PF_ISDN, SOCK_DGRAM, (pri)?ISDN_P_TE_E1:ISDN_P_TE_S0)) < 0) { + PERROR_RUNTIME("loop port %d failed to open socket.\n", mISDNloop.port); + mISDNloop_close(); + return mISDNloop.sock; + } + /* set nonblocking io */ + if ((ret = ioctl(mISDNloop.sock, FIONBIO, &on)) < 0) { + PERROR_RUNTIME("loop port %d failed to set socket into nonblocking io.\n", mISDNloop.port); + mISDNloop_close(); + return ret; + } + /* bind socket to dchannel */ + memset(&addr, 0, sizeof(addr)); + addr.family = AF_ISDN; + addr.dev = mISDNloop.port; + addr.channel = 0; + if ((ret = bind(mISDNloop.sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) { + PERROR_RUNTIME("loop port %d failed to bind socket. (name = %s errno=%d)\n", mISDNloop.port, options.loopback_ext, errno); + mISDNloop_close(); + return (ret); + } + + return 0; +} + +int loop_hunt_bchannel(class PmISDN *port, struct mISDNport *mISDNport) +{ + int channel; + int i; + char map[mISDNport->b_num]; + struct interface *interface; + struct interface_port *ifport; + + chan_trace_header(mISDNport, port, "CHANNEL SELECTION (setup)", DIRECTION_NONE); + add_trace("channel", "reserved", "%d", mISDNport->b_reserved); + if (mISDNport->b_reserved >= mISDNport->b_num) { // of out chan.. + add_trace("conclusion", NULL, "all channels are reserved"); + end_trace(); + return(-34); // no channel + } + + /* map all used ports of shared loopback interface */ + memset(map, 0, sizeof(map)); + interface = interface_first; + while(interface) { + ifport = interface->ifport; + while(ifport) { + if (!strcmp(ifport->portname, options.loopback_lcr)) { + i = 0; + while(i < mISDNport->b_num) { + if (mISDNport->b_port[i]) + map[i] = 1; + i++; + } + } + ifport = ifport->next; + } + interface = interface->next; + } + + /* find channel */ + i = 0; + channel = 0; + while(i < mISDNport->b_num) { + if (!map[i]) { + channel = i+1+(i>=15); + break; + } + i++; + } + if (!channel) { + add_trace("conclusion", NULL, "no channel available"); + end_trace(); + return(-6); // channel unacceptable + } + add_trace("conclusion", NULL, "channel available"); + add_trace("connect", "channel", "%d", channel); + end_trace(); + return(channel); +} + + diff --git a/loop.h b/loop.h new file mode 100644 index 0000000..cb2ad05 --- /dev/null +++ b/loop.h @@ -0,0 +1,12 @@ + +struct mISDNloop { + int sock; /* loopback interface external side */ + int port; /* port number for external side */ +}; + +extern mISDNloop mISDNloop; + +void mISDNloop_close(void); +int mISDNloop_open(); +int loop_hunt_bchannel(class PmISDN *port, struct mISDNport *mISDNport); + diff --git a/mISDN.cpp b/mISDN.cpp index ee50bf1..50746ec 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -33,21 +33,6 @@ int __af_isdn = MISDN_AF_ISDN; #define B_TIMER_ACTIVATING 1 // seconds #define B_TIMER_DEACTIVATING 1 // seconds -/* GSM condition */ -#if defined WITH_GSM_BS && defined WITH_GSM_MS - #define MISDNPORT_GSM (mISDNport->gsm_bs || mISDNport->gsm_ms) -#else - #ifdef WITH_GSM_BS - #define MISDNPORT_GSM (mISDNport->gsm_bs) - #endif - #ifdef WITH_GSM_MS - #define MISDNPORT_GSM (mISDNport->gsm_ms) - #endif -#endif -#ifndef MISDNPORT_GSM - #define MISDNPORT_GSM (0) -#endif - /* list of mISDN ports */ struct mISDNport *mISDNport_first; @@ -671,7 +656,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_STATE_IDLE: if (p_m_remote_ref) { /* export bchannel */ - message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type); + message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "assign"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -719,7 +704,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) /* in case, the bchannel is exported right after seize_bchannel */ /* export bchannel */ /* p_m_remote_id is set, when this event happens. */ - message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type); + message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "assign"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -774,7 +759,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_STATE_REMOTE: /* bchannel is exported, so we re-import */ - message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0); + message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "remove"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -825,7 +810,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) * OR bchannel is not used anymore * OR bchannel has been exported to an obsolete ref, * so reimport, to later export to new remote */ - message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0); + message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "remove"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -861,7 +846,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_STATE_REMOTE: /* bchannel is exported, so we re-import */ - message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0); + message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "remove"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -892,7 +877,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) if (b_port) { /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */ if (p_m_remote_ref) { - message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type); + message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "assign"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -924,7 +909,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) if (b_port) { /* bchannel is now imported, but is requied by Port class, so we reactivate / export */ if (p_m_remote_ref) { - message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type); + message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0); chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); add_trace("type", NULL, "assign"); add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); @@ -1382,7 +1367,11 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) { chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN); add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK); + if (!p_m_dtmf) + add_trace("info", NULL, "DTMF is disabled"); end_trace(); + if (!p_m_dtmf) + return; message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF); message->param.dtmf = cont & DTMF_TONE_MASK; PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c'\n", p_name, message->param.dtmf); @@ -1856,7 +1845,7 @@ static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, i mISDNport = mISDNport_first; while(mISDNport) { /* handle queued up-messages (d-channel) */ - if (!MISDNPORT_GSM) { + if (!mISDNport->isloopback) { while ((mb = mdequeue(&mISDNport->upqueue))) { l3m = &mb->l3; switch(l3m->type) { @@ -1932,7 +1921,7 @@ static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, i if (!mISDNport->ntmode || mISDNport->ptp) mISDNport->l2link = 0; } - if (!MISDNPORT_GSM && (!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) { + if (!mISDNport->isloopback && (!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) { if (!mISDNport->l2establish.active && mISDNport->l2hold) { PDEBUG(DEBUG_ISDN, "set timer and establish.\n"); schedule_timer(&mISDNport->l2establish, 5, 0); @@ -1959,7 +1948,7 @@ static int l2establish_timeout(struct lcr_timer *timer, void *instance, int i) { struct mISDNport *mISDNport = (struct mISDNport *)instance; - if (!MISDNPORT_GSM && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) { + if (!mISDNport->isloopback && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) { // PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum); mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL); schedule_timer(&mISDNport->l2establish, 5, 0); /* 5 seconds */ @@ -2119,7 +2108,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) int force_nt = ifport->nt; int l1hold = ifport->l1hold; int l2hold = ifport->l2hold; - int gsm = 0; + int loop = 0; int ss5 = ifport->ss5; int i, cnt; int pri, bri, pots; @@ -2129,15 +2118,23 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) unsigned int protocol, prop; #if defined WITH_GSM_BS && defined WITH_GSM_MS - gsm = ifport->gsm_ms | ifport->gsm_bs; + loop = ifport->gsm_ms | ifport->gsm_bs; #else #ifdef WITH_GSM_BS - gsm = ifport->gsm_bs; + loop = ifport->gsm_bs; #endif #ifdef WITH_GSM_MS - gsm = ifport->gsm_ms; + loop = ifport->gsm_ms; #endif #endif +//printf("%s == %s\n", ifport->portname, options.loopback_int); + if (!strcmp(ifport->portname, options.loopback_lcr)) + loop = 1; + + if (loop) { + if (mISDNloop_open()) + return NULL; + } /* check port counts */ ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt); @@ -2153,8 +2150,8 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) if (port < 0) { port = mISDN_getportbyname(mISDNsocket, cnt, ifport->portname); if (port < 0) { - if (gsm) - PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", ifport->portname); + if (loop) + PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface?.\n", ifport->portname); else PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", ifport->portname); return(NULL); @@ -2270,8 +2267,8 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) mISDNportp = &((*mISDNportp)->next); mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport)); add_timer(&mISDNport->l2establish, l2establish_timeout, mISDNport, 0); - if (gsm | ss5) { - /* gsm/ss5 link is always active */ + if (loop | ss5) { + /* loop/ss5 link is always active */ mISDNport->l1link = 1; mISDNport->l2link = 1; } else { @@ -2284,6 +2281,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) #ifdef WITH_GSM_MS mISDNport->gsm_ms = ifport->gsm_ms; #endif + mISDNport->isloopback = loop; pmemuse++; *mISDNportp = mISDNport; @@ -2325,25 +2323,24 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) if (l2hold) // supports layer 2 hold prop |= (1 << MISDN_FLG_L2_HOLD); /* open layer 3 and init upqueue */ - if (gsm) { -#if defined WITH_GSM_BS || defined WITH_GSM_MS + if (loop) { unsigned long on = 1; struct sockaddr_mISDN addr; if (devinfo.nrbchan < 8) { - PERROR_RUNTIME("GSM port %d must have at least 8 b-channels.\n", port); - mISDNport_close(mISDNport); - return(NULL); + printf("loop port %d has a low number of bchannels. (only %d) remember that all interfaces that requires a loopback could run out of channels\n", port, devinfo.nrbchan); +// mISDNport_close(mISDNport); +// return(NULL); } - if ((mISDNport->lcr_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_NT_S0)) < 0) { - PERROR_RUNTIME("GSM port %d failed to open socket.\n", port); + if ((mISDNport->lcr_sock = socket(PF_ISDN, SOCK_DGRAM, (bri) ? ISDN_P_TE_S0 : ISDN_P_TE_E1)) < 0) { + PERROR_RUNTIME("loop port %d failed to open socket.\n", port); mISDNport_close(mISDNport); return(NULL); } /* set nonblocking io */ if (ioctl(mISDNport->lcr_sock, FIONBIO, &on) < 0) { - PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", port); + PERROR_RUNTIME("loop port %d failed to set socket into nonblocking io.\n", port); mISDNport_close(mISDNport); return(NULL); } @@ -2353,11 +2350,10 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) addr.dev = port; addr.channel = 0; if (bind(mISDNport->lcr_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - PERROR_RUNTIME("GSM port %d failed to bind socket. (errno %d)\n", port, errno); + PERROR_RUNTIME("loop port %d failed to bind socket. (errno %d)\n", port, errno); mISDNport_close(mISDNport); return(NULL); } -#endif } else { /* queue must be initializes, because l3-thread may send messages during open_layer3() */ mqueue_init(&mISDNport->upqueue); @@ -2398,7 +2394,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport) } /* if ptp, pull up the link */ - if (!MISDNPORT_GSM && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) { + if (!mISDNport->isloopback && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) { mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL); l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT); add_trace("tei", NULL, "%d", 0); @@ -2511,19 +2507,17 @@ void mISDNport_close(struct mISDNport *mISDNport) del_timer(&mISDNport->l2establish); /* close layer 3, if open */ - if (!MISDNPORT_GSM && mISDNport->ml3) { + if (!mISDNport->isloopback && mISDNport->ml3) { close_layer3(mISDNport->ml3); } -#if defined WITH_GSM_BS || defined WITH_GSM_MS /* close gsm socket, if open */ - if (MISDNPORT_GSM && mISDNport->lcr_sock > -1) { + if (mISDNport->isloopback && mISDNport->lcr_sock > -1) { close(mISDNport->lcr_sock); } -#endif /* purge upqueue */ - if (!MISDNPORT_GSM) + if (!mISDNport->isloopback) mqueue_purge(&mISDNport->upqueue); /* remove from list */ diff --git a/mISDN.h b/mISDN.h index 644658b..de223c8 100644 --- a/mISDN.h +++ b/mISDN.h @@ -71,9 +71,8 @@ struct mISDNport { #ifdef WITH_GSM_MS int gsm_ms; /* this is the an GSM MS interface */ #endif -#if defined WITH_GSM_BS || defined WITH_GSM_MS int lcr_sock; /* socket of loopback on LCR side */ -#endif + int isloopback; /* will be set on open, in case it is a loopback if */ /* ss5 */ unsigned int ss5; /* set, if SS5 signalling enabled, also holds feature bits */ diff --git a/mail.c b/mail.c index 445e268..0e34b77 100644 --- a/mail.c +++ b/mail.c @@ -99,7 +99,8 @@ static void *mail_child(void *arg) fprintf(ph, "\n * date: %s %d %d %d:%02d\n\n", months[mon], mday, year+1900, hour, min); /* attach audio file */ - if ((filename[0]) && ((fh = open(filename, O_RDONLY)))) { + if (filename[0]) { + if ((fh = open(filename, O_RDONLY))) { while(strchr(filename, '/')) filename = strchr(filename, '/')+1; fprintf(ph, "--next_part\n"); @@ -144,11 +145,12 @@ static void *mail_child(void *arg) fprintf(ph, "\n\n"); close(fh); - } else { + } else { SPRINT(buffer, "-Error- Failed to read audio file: '%s'.\n\n", filename); fprintf(ph, "%s", buffer); PERROR("%s", buffer); - } + } + } /* finish mail */ fprintf(ph, ".\n"); diff --git a/main.c b/main.c index d293f7f..1aa2d8b 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,11 @@ #include "main.h" #include "config.h" +#ifdef WITH_GSM_MS +extern "C" { +#include +} +#endif //MESSAGES @@ -138,11 +143,23 @@ void _printerror(const char *function, int line, const char *fmt, ...) void sighandler(int sigset) { struct sched_param schedp; +#ifdef WITH_GSM_MS + int wait_ms = 0; +#endif if (sigset == SIGHUP) return; if (sigset == SIGPIPE) return; + fprintf(stderr, "LCR: Signal received: %d\n", sigset); + PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset); +#ifdef WITH_GSM_MS + if (!wait_ms) { + wait_ms = 1; + dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); + return; + } +#endif if (!quit) { quit = sigset; /* set scheduler & priority */ @@ -151,8 +168,6 @@ void sighandler(int sigset) schedp.sched_priority = 0; sched_setscheduler(0, SCHED_OTHER, &schedp); } - fprintf(stderr, "LCR: Signal received: %d\n", sigset); - PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset); } } @@ -469,12 +484,8 @@ int main(int argc, char *argv[]) if (options.gsm) { if (handle_gsm()) all_idle = 0; -#ifdef WITH_GSM_BS - if (handle_gsm_bs()) - all_idle = 0; -#endif #ifdef WITH_GSM_MS - if (handle_gsm_ms()) + if (handle_gsm_ms(&quit)) all_idle = 0; #endif } @@ -602,6 +613,10 @@ free: #endif } + /* close loopback, if used by GSM or remote */ + if (mISDNloop.sock > -1) + mISDNloop_close(); + /* display memory leak */ #define MEMCHECK(a, b) \ if (b) { \ diff --git a/main.h b/main.h index 8e45581..7aad3c2 100644 --- a/main.h +++ b/main.h @@ -148,6 +148,8 @@ extern "C" { #include "port.h" #include "mISDN.h" #include "dss1.h" +#include "loop.h" +#include "remote.h" #if defined WITH_GSM_BS || defined WITH_GSM_MS #include "gsm.h" #endif diff --git a/message.h b/message.h index 471e2c8..c2076af 100644 --- a/message.h +++ b/message.h @@ -324,6 +324,7 @@ struct param_hello { struct param_bchannel { int type; /* BCHANNEL_* */ unsigned int handle; /* bchannel stack/portid */ + int isloopback; /* in this case the application behaves like an interface, dsp should not be used */ int tx_gain, rx_gain; char pipeline[256]; unsigned char crypt[128]; @@ -331,6 +332,11 @@ struct param_bchannel { int crypt_type; /* 1 = blowfish */ }; +struct param_newref { + int direction; /* who requests a refe? */ + int mode; /* 0 = direct-mode, 1 = PBX mode */ +}; + /* structure of message parameter */ union parameter { struct param_tone tone; /* MESSAGE_TONE */ @@ -355,7 +361,7 @@ union parameter { struct param_crypt crypt; /* MESSAGE_CRYPT */ struct param_hello hello; /* MESSAGE_HELLO */ struct param_bchannel bchannel; /* MESSAGE_BCHANNEL */ - int direction; /* MESSAGE_NEWREF */ + struct param_newref newref; /* MESSAGE_NEWREF */ }; enum { /* message flow */ @@ -428,6 +434,7 @@ enum { /* messages between entities */ "MESSAGE_RELEASE", \ "MESSAGE_TIMEOUT", \ "MESSAGE_NOTIFY", \ + "MESSAGE_PROGRESS", \ "MESSAGE_FACILITY", \ "MESSAGE_SUSPEND", \ "MESSAGE_RESUME", \ diff --git a/missing b/missing deleted file mode 100755 index 1c8ff70..0000000 --- a/missing +++ /dev/null @@ -1,367 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. - -scriptversion=2006-05-10.23 - -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - -esac - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). -case $1 in - lex|yacc) - # Not GNU programs, they don't have --version. - ;; - - tar) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $1 in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - tar) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/options.c b/options.c index 88f6424..7fb9bcb 100644 --- a/options.c +++ b/options.c @@ -36,7 +36,9 @@ struct options options = { -1, /* socket user (-1= no change) */ -1, /* socket group (-1= no change) */ 0, /* enable gsm */ - 1 /* use polling of main loop */ + 1, /* use polling of main loop */ + "mISDN_l1loop.1", /* GSM/Asterisk side */ + "mISDN_l1loop.2", /* LCR side */ }; char options_error[256]; @@ -239,6 +241,22 @@ int read_options(char *options_error) } else if (!strcmp(option,"polling")) { options.polling = 1; + } else + if (!strcmp(option,"loopback-ext")) { + if (param[0]==0) { + UPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); + goto error; + } + SCPY(options.loopback_ext, param); + + } else + if (!strcmp(option,"loopback-lcr")) { + if (param[0]==0) { + UPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option); + goto error; + } + SCPY(options.loopback_lcr, param); + } else { UPRINT(options_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option); goto error; diff --git a/options.h b/options.h index c13ee2c..c7f9f8f 100644 --- a/options.h +++ b/options.h @@ -31,6 +31,8 @@ struct options { int socketgroup; /* socket chgrp to this group */ int gsm; /* enable gsm support */ int polling; + char loopback_ext[64]; /* loopback interface GSM side */ + char loopback_lcr[64]; /* loopback interface LCR side */ }; extern struct options options; diff --git a/port.h b/port.h index d7c0580..a4da7de 100644 --- a/port.h +++ b/port.h @@ -22,10 +22,14 @@ #define PORT_CLASS_GSM_BS 0x1210 #define PORT_CLASS_GSM_MS 0x1220 #define PORT_CLASS_SS5 0x1300 +#define PORT_CLASS_REMOTE 0x1400 #define PORT_CLASS_MASK 0xf000 #define PORT_CLASS_mISDN_MASK 0xff00 #define PORT_CLASS_DSS1_MASK 0xfff0 #define PORT_CLASS_GSM_MASK 0xfff0 +#define PORT_CLASS_DIR_MASK 0x000f +#define PORT_CLASS_DIR_IN 0x0001 +#define PORT_CLASS_DIR_OUT 0x0002 /* nt-mode */ #define PORT_TYPE_DSS1_NT_IN 0x1111 #define PORT_TYPE_DSS1_NT_OUT 0x1112 @@ -41,6 +45,9 @@ #define PORT_TYPE_SS5_IN 0x1311 #define PORT_TYPE_SS5_OUT 0x1312 #define PORT_TYPE_SS5_IDLE 0x1313 + /* remote */ +#define PORT_TYPE_REMOTE_IN 0x1411 +#define PORT_TYPE_REMOTE_OUT 0x1412 /* answering machine */ #define PORT_TYPE_VBOX_OUT 0x3111 diff --git a/remote.cpp b/remote.cpp new file mode 100644 index 0000000..e14c8e3 --- /dev/null +++ b/remote.cpp @@ -0,0 +1,221 @@ +/*****************************************************************************\ +** ** +** LCR ** +** ** +**---------------------------------------------------------------------------** +** Copyright: Andreas Eversberg ** +** ** +** mISDN remote ** +** ** +\*****************************************************************************/ + +#include "main.h" + +unsigned int new_remote = 0x00000001; + +/* + * constructor + */ +Premote::Premote(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, int remote_id) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode) +{ + union parameter param; + + p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN; + p_m_r_ref = new_remote++; + SCPY(p_m_r_remote_app, mISDNport->ifport->remote_app); + p_m_r_handle = 0; + + /* send new ref to remote socket */ + memset(¶m, 0, sizeof(union parameter)); + if (type == PORT_TYPE_REMOTE_OUT) + param.newref.direction = 1; /* new ref from lcr */ + p_m_r_remote_id = remote_id; + if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_NEWREF, ¶m) < 0) + FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", mISDNport->ifport->remote_app); + + PDEBUG(DEBUG_GSM, "Created new RemotePort(%s).\n", portname); + +} + +/* + * destructor + */ +Premote::~Premote() +{ + /* need to remote (import) external channel from remote application */ + if (p_m_r_handle) { + message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, p_m_r_handle, 0, 0, 0, 0, 0, 0, 1); + chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); + add_trace("type", NULL, "remove"); + add_trace("channel", NULL, "%d.%d", p_m_r_handle>>8, p_m_r_handle&0xff); + end_trace(); + } + + PDEBUG(DEBUG_GSM, "Destroyed Remote process(%s).\n", p_name); + +} + +/* + * endpoint sends messages to the port + */ +int Premote::message_epoint(unsigned int epoint_id, int message_type, union parameter *param) +{ + struct lcr_msg *message; + int channel; + int ret; + struct epoint_list *epointlist; + + if (PmISDN::message_epoint(epoint_id, message_type, param)) + return 1; + + if (message_type == MESSAGE_SETUP) { + ret = channel = hunt_bchannel(); + if (ret < 0) + goto no_channel; + /* open channel */ + ret = seize_bchannel(channel, 1); + if (ret < 0) { + no_channel: + message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 34; + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + new_state(PORT_STATE_RELEASE); + delete this; + return 0; + } + bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE); + + /* attach only if not already */ + epointlist = p_epointlist; + while(epointlist) { + if (epointlist->epoint_id == epoint_id) + break; + epointlist = epointlist->next; + } + if (!epointlist) + epointlist_new(epoint_id); + + /* set context to pbx */ + SCPY(param->setup.context, "pbx"); + } + + /* look for Remote's interface */ + if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, message_type, param)<0) { + PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_m_mISDNport->ifport->remote_app); + return 0; + } + + /* enable audio path */ + if (message_type == MESSAGE_SETUP) { + union parameter newparam; + memset(&newparam, 0, sizeof(union parameter)); + admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam); + newparam.audiopath = 1; + admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam); + } + + if (message_type == MESSAGE_RELEASE) { + new_state(PORT_STATE_RELEASE); + delete this; + return 0; + } + + return 0; +} + +void Premote::message_remote(int message_type, union parameter *param) +{ + class Endpoint *epoint; + struct lcr_msg *message; + int channel; + int ret; + + if (message_type == MESSAGE_SETUP) { + /* enable audio path */ + union parameter newparam; + memset(&newparam, 0, sizeof(union parameter)); + admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam); + newparam.audiopath = 1; + admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam); + + /* set source interface */ + param->setup.callerinfo.itype = p_callerinfo.itype; + param->setup.callerinfo.isdn_port = p_m_portnum; + SCPY(param->setup.callerinfo.interface, p_m_mISDNport->ifport->interface->name); + + ret = channel = hunt_bchannel(); + if (ret < 0) + goto no_channel; + + /* open channel */ + ret = seize_bchannel(channel, 1); + if (ret < 0) { + no_channel: + message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 34; + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + new_state(PORT_STATE_RELEASE); + delete this; + return; + } + bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE); + + /* create endpoint */ + if (p_epointlist) + FATAL("Incoming call but already got an endpoint.\n"); + if (!(epoint = new Endpoint(p_serial, 0))) + FATAL("No memory for Endpoint instance\n"); + if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming + FATAL("No memory for Endpoint Application instance\n"); + + epointlist_new(epoint->ep_serial); + } + + /* set serial on bchannel message + * also ref is given, so we send message with ref */ + if (message_type == MESSAGE_BCHANNEL) { + int i = p_m_b_index; + unsigned int portid = (mISDNloop.port<<8) + i+1+(i>=15); + switch (param->bchannel.type) { + case BCHANNEL_REQUEST: + p_m_r_handle = portid; + message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_ASSIGN, portid, 0, 0, 0, 0, 0, 0, 1); + chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); + add_trace("type", NULL, "assign"); + add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); + end_trace(); + break; + case BCHANNEL_RELEASE: + p_m_r_handle = 0; + message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, portid, 0, 0, 0, 0, 0, 0, 1); + chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE); + add_trace("type", NULL, "remove"); + add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff); + end_trace(); + break; + } + return; + } + + /* cannot just forward, because param is not of container "struct lcr_msg" */ + message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type); + memcpy(&message->param, param, sizeof(message->param)); + message_put(message); + + if (message_type == MESSAGE_RELEASE) { + new_state(PORT_STATE_RELEASE); + delete this; + return; + } +} + +/* select free bchannel from loopback interface */ +int Premote::hunt_bchannel(void) +{ + return loop_hunt_bchannel(this, p_m_mISDNport); +} + + + diff --git a/remote.h b/remote.h new file mode 100644 index 0000000..f39245b --- /dev/null +++ b/remote.h @@ -0,0 +1,20 @@ + +/* GSM port class */ +class Premote : public PmISDN +{ + public: + Premote(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, int remote_id); + ~Premote(); + + unsigned int p_m_r_ref; + int p_m_r_remote_id; /* remote instance (socket) */ + char p_m_r_remote_app[32]; + unsigned int p_m_r_handle; /* 0, if no bchannel is exported */ + + int message_epoint(unsigned int epoint_id, int message_id, union parameter *param); + void message_remote(int message_type, union parameter *param); + + int hunt_bchannel(void); +}; + + diff --git a/route.c b/route.c index f72d6b0..8217ff1 100644 --- a/route.c +++ b/route.c @@ -1902,6 +1902,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) struct admin_list *admin; time_t now; struct tm *now_tm; + int pid2; /* reset timeout action */ e_match_to_action = NULL; @@ -2071,9 +2072,11 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) case MATCH_EXECUTE: j = 0; +#if 0 argv[j++] = (char *)"/bin/sh"; argv[j++] = (char *)"-c"; argv[j++] = cond->string_value; +#endif argv[j++] = cond->string_value; argv[j++] = e_extdialing; argv[j++] = (char *)numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international); @@ -2083,8 +2086,11 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) argv[j++] = isdn_port; argv[j++] = e_callerinfo.imsi; argv[j++] = NULL; /* check also number of args above */ - if (execve("/bin/sh", argv, environ) == 0) - istrue = 1; + if (fork() == 0) { + if ((pid2 = fork()) == 0) { + execve(cond->string_value, argv, environ); + } + } break; case MATCH_DEFAULT: diff --git a/socket_server.c b/socket_server.c index e84fa5e..32c6e71 100644 --- a/socket_server.c +++ b/socket_server.c @@ -84,6 +84,8 @@ void free_connection(struct admin_list *admin) struct mISDNport *mISDNport; int i, ii; struct admin_list **adminp; + class Port *port, *portnext; + class Premote *remote; /* free remote joins */ if (admin->remote_name[0]) { @@ -126,6 +128,22 @@ void free_connection(struct admin_list *admin) } join = joinnext; } + /* release remote port */ + port = port_first; + while(port) { + portnext = port->next; + if ((port->p_type & PORT_CLASS_MASK) == PORT_CLASS_REMOTE) { + remote = (class Premote *) port; + if (remote->p_m_r_remote_id == admin->sock) { + memset(¶m, 0, sizeof(param)); + param.disconnectinfo.cause = CAUSE_OUTOFORDER; + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + remote->message_remote(MESSAGE_RELEASE, ¶m); + /* port is now destroyed, so we go to next join */ + } + } + port = portnext; + } } if (admin->sock >= 0) { @@ -586,9 +604,13 @@ void admin_call_response(int adminid, int message, const char *connected, int ca /* * send data to the remote socket join instance */ -int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin) +int admin_message_to_lcr(struct admin_msg *msg, struct admin_list *admin) { + struct mISDNport *mISDNport; class Join *join; + class JoinRemote *joinremote = NULL; /* make GCC happy */ + class Port *port; + class Premote *remote = NULL; /* make GCC happy */ struct admin_list *temp; /* hello message */ @@ -629,13 +651,44 @@ int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin) return(-1); } - /* new join */ + /* new join. the reply (NEWREF assignment) is sent from constructor */ if (msg->type == MESSAGE_NEWREF) { - /* create new join instance */ - join = new JoinRemote(0, admin->remote_name, admin->sock); // must have no serial, because no endpoint is connected - if (!join) { - FATAL("No memory for remote join instance\n"); - return(-1); + if (msg->param.newref.mode) { + char name[32]; + /* find remote port */ + mISDNport = mISDNport_first; + while(mISDNport) { + if (mISDNport->ifport->remote && !strcmp(mISDNport->ifport->remote_app, admin->remote_name)) + break; + mISDNport = mISDNport->next; + } + if (!mISDNport) { + union parameter param; + + /* create new join instance */ + join = joinremote = new JoinRemote(0, admin->remote_name, admin->sock); // must have no serial, because no endpoint is connected + if (!join) { + FATAL("No memory for remote join instance\n"); + return(-1); + } + memset(¶m, 0, sizeof(union parameter)); + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + param.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL; + admin_message_from_lcr(joinremote->j_remote_id, joinremote->j_remote_ref, MESSAGE_RELEASE, ¶m); + return 0; + } + /* creating port object, transparent until setup with hdlc */ + SPRINT(name, "%s-%s-in", mISDNport->ifport->interface->name, mISDNport->ifport->remote_app); + if (!(remote = new Premote(PORT_TYPE_REMOTE_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT, admin->sock))) + + FATAL("Cannot create Port instance.\n"); + } else { + /* create new join instance */ + join = new JoinRemote(0, admin->remote_name, admin->sock); // must have no serial, because no endpoint is connected + if (!join) { + FATAL("No memory for remote join instance\n"); + return(-1); + } } return(0); } @@ -660,36 +713,56 @@ int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin) /* find join instance */ join = join_first; while(join) { - if (join->j_serial == msg->ref) - break; + if (join->j_type == JOIN_TYPE_REMOTE) { + joinremote = (class JoinRemote *)join; + if (joinremote->j_remote_ref == msg->ref) + break; + } join = join->next; } - if (!join) { - PDEBUG(DEBUG_LOG, "No join found with serial %d. (May have been already released.)\n", msg->ref); + if (join) { + if (admin->sock != joinremote->j_remote_id) { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, joinremote->j_remote_name, admin->remote_name); + return(-1); + } + /* send message */ + joinremote->message_remote(msg->type, &msg->param); + return(0); } - /* check application */ - if (join->j_type != JOIN_TYPE_REMOTE) { - PERROR("Ref %d does not belong to a remote join instance.\n", msg->ref); - return(-1); - } - if (admin->sock != ((class JoinRemote *)join)->j_remote_id) { - PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote_name, admin->remote_name); - return(-1); + /* find port instance */ + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_REMOTE) { + remote = (class Premote *) port; + if (remote->p_m_r_ref == msg->ref) + break; + } + port = port->next; } + if (port) { + if (admin->sock != remote->p_m_r_remote_id) { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, remote->p_m_r_remote_app, admin->remote_name); + return(-1); + } + + /* send message */ + remote->message_remote(msg->type, &msg->param); - /* send message */ - ((class JoinRemote *)join)->message_remote(msg->type, &msg->param); + return(0); + } + PDEBUG(DEBUG_LOG, "No remote instance found with ref %d. (May have been already released.)\n", msg->ref); return(0); + } /* * this function is called for every message to remote socket */ -int admin_message_from_join(int remote_id, unsigned int ref, int message_type, union parameter *param) +int admin_message_from_lcr(int remote_id, unsigned int ref, int message_type, union parameter *param) { struct admin_list *admin; struct admin_queue **responsep; /* response pointer */ @@ -1234,7 +1307,7 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i break; case ADMIN_MESSAGE: - if (admin_message_to_join(&msg.u.msg, admin) < 0) { + if (admin_message_to_lcr(&msg.u.msg, admin) < 0) { PERROR("Failed to deliver message for socket %d.\n", admin->sock); goto response_error; } @@ -1281,3 +1354,24 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i return 0; } +void message_bchannel_to_remote(unsigned int remote_id, unsigned int ref, int type, unsigned int handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type, int isloopback) +{ + union parameter param; + + memset(¶m, 0, sizeof(union parameter)); + param.bchannel.isloopback = isloopback; + param.bchannel.type = type; + param.bchannel.handle = handle; + param.bchannel.tx_gain = tx_gain; + param.bchannel.rx_gain = rx_gain; + if (pipeline) + SCPY(param.bchannel.pipeline, pipeline); + if (crypt_len) + memcpy(param.bchannel.crypt, crypt, crypt_len); + param.bchannel.crypt_type = crypt_type; + if (admin_message_from_lcr(remote_id, ref, MESSAGE_BCHANNEL, ¶m)<0) { + PERROR("No socket with remote id %d found, this happens, if the socket is closed before all bchannels are imported.\n", remote_id); + return; + } +} + diff --git a/socket_server.h b/socket_server.h index b3ea89a..9a31b10 100644 --- a/socket_server.h +++ b/socket_server.h @@ -33,8 +33,9 @@ extern struct admin_list *admin_first; int admin_init(void); void admin_cleanup(void); void admin_call_response(int adminid, int message, const char *connected, int cause, int location, int notify); -int admin_message_to_join(struct admin_message *msg, int remote_id); -int admin_message_from_join(int remote_id, unsigned int ref, int message_type, union parameter *param); +int admin_message_to_lcr(struct admin_message *msg, int remote_id); +int admin_message_from_lcr(int remote_id, unsigned int ref, int message_type, union parameter *param); +void message_bchannel_to_remote(unsigned int remote_id, unsigned int ref, int type, unsigned int handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type, int isloopback);