diff --git a/BUGS b/BUGS index 86fbb76fd..624459ea5 100644 --- a/BUGS +++ b/BUGS @@ -4,7 +4,7 @@ Asterisk Bug Tracking Information To learn about and report Asterisk bugs, please visit the official Asterisk Bug Tracker at: - https://issues.asterisk.org + https://issues.asterisk.org/jira For more information on using the bug tracker, or to learn how you can contribute by acting as a bug marshal diff --git a/CHANGES b/CHANGES index 53587b598..869f2d0e4 100644 --- a/CHANGES +++ b/CHANGES @@ -9,7 +9,7 @@ ============================================================================== ------------------------------------------------------------------------------ ---- Functionality changes from Asterisk 1.8 to Asterisk 1.10 ----------------- +--- Functionality changes from Asterisk 1.8 to Asterisk 10 ------------------- ------------------------------------------------------------------------------ Text Messaging @@ -75,6 +75,11 @@ CODECS -------------------------- * Ability to define custom SILK formats in codecs.conf. * Addition of speex32 audio format with translation. + * CELT codec pass-through support and ability to define + custom CELT formats in codecs.conf. + * Ability to read raw signed linear files with sample rates + ranging from 8khz - 192khz. The new file extensions introduced + are .sln12, .sln24, .sln32, .sln44, .sln48, .sln96, .sln192. ConfBridge -------------------------- @@ -82,11 +87,14 @@ ConfBridge mixing audio at sample rates ranging from 8khz-96khz. * CONFBRIDGE dialplan function capable of creating dynamic ConfBridge user and bridge profiles on a channel. - * CONFBRIDGE_INFO dialplan function capable of retreiving information + * CONFBRIDGE_INFO dialplan function capable of retrieving information about a conference such as locked status and number of parties, admins, and marked users. * Addition of video_mode option in confbridge.conf for adding video support into a bridge profile. + * Addition of the follow_talker video_mode in confbridge.conf. This video + mode dynamically switches the video feed to always display the loudest talker + supplying video in the conference. Dialplan Variables ------------------ @@ -148,7 +156,7 @@ pbx_lua in the sample extensions.lua file for syntax details. * Applications that perform jumps in the dialplan such as Goto will now execute properly. When pbx_lua detects that the context, extension, or - priority we are executing on has changed it will immediatly return control + priority we are executing on has changed it will immediately return control to the asterisk PBX engine. Currently the engine cannot detect a Goto to the priority after the currently executing priority. * An autoservice is now started by default for pbx_lua channels. It can be @@ -188,6 +196,19 @@ Applications * Added ability to include '@parkinglot' to ParkedCall extension in order to specify a specific parkinglot on which to search the extension. +Asterisk Database +----------------- + * The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + +Asterisk Modules +---------------- + * Modules marked as deprecated are no longer marked as building by default. Enabling + these modules is still available via menuselect. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.6.2 to Asterisk 1.8 ---------------- ------------------------------------------------------------------------------ diff --git a/Makefile b/Makefile index 0615d60c8..87139c118 100644 --- a/Makefile +++ b/Makefile @@ -467,9 +467,9 @@ datafiles: _all doc/core-en_US.xml # improved a lot. I'll put it here for now. for x in static-http/*; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/static-http" ; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/static-http ; \ done - $(INSTALL) -m 644 doc/core-en_US.xml "$(DESTDIR)$(ASTDATADIR)/static-http"; + $(INSTALL) -m 644 doc/core-en_US.xml $(DESTDIR)$(ASTDATADIR)/static-http; if [ -d doc/tex/asterisk ] ; then \ $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/static-http/docs" ; \ for n in doc/tex/asterisk/* ; do \ @@ -477,7 +477,7 @@ datafiles: _all doc/core-en_US.xml done \ fi for x in images/*.jpg; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/images" ; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/images ; \ done $(MAKE) -C sounds install @@ -576,21 +576,21 @@ bininstall: _all installdirs $(SUBDIRS_INSTALL) rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\ fi - $(INSTALL) -m 644 doc/core-*.xml "$(DESTDIR)$(ASTDATADIR)/documentation" - $(INSTALL) -m 644 doc/appdocsxml.dtd "$(DESTDIR)$(ASTDATADIR)/documentation" - $(INSTALL) -m 644 doc/asterisk.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/astgenkey.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/autosupport.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 "$(DESTDIR)$(ASTMANDIR)/man8" + $(INSTALL) -m 644 doc/core-*.xml $(DESTDIR)$(ASTDATADIR)/documentation + $(INSTALL) -m 644 doc/appdocsxml.dtd $(DESTDIR)$(ASTDATADIR)/documentation + $(INSTALL) -m 644 doc/asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/astgenkey.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/autosupport.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 if [ -f contrib/firmware/iax/iaxy.bin ] ; then \ - $(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin "$(DESTDIR)$(ASTDATADIR)/firmware/iax/iaxy.bin"; \ + $(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTDATADIR)/firmware/iax/iaxy.bin; \ fi $(SUBDIRS_INSTALL): +@DESTDIR="$(DESTDIR)" ASTSBINDIR="$(ASTSBINDIR)" $(SUBMAKE) -C $(@:-install=) install NEWMODS:=$(foreach d,$(MOD_SUBDIRS),$(notdir $(wildcard $(d)/*.so))) -OLDMODS=$(filter-out $(NEWMODS),$(notdir $(wildcard "$(DESTDIR)$(MODULES_DIR)/*.so"))) +OLDMODS=$(filter-out $(NEWMODS),$(notdir $(wildcard $(DESTDIR)$(MODULES_DIR)/*.so))) oldmodcheck: @if [ -n "$(OLDMODS)" ]; then \ @@ -698,33 +698,33 @@ samples: adsi rm -f $(DESTDIR)$(ASTCONFPATH).tmp ; \ fi ; \ $(INSTALL) -d $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX - build_tools/make_sample_voicemail "$(DESTDIR)$(ASTDATADIR)" "$(DESTDIR)$(ASTSPOOLDIR)" + build_tools/make_sample_voicemail $(DESTDIR)/$(ASTDATADIR) $(DESTDIR)/$(ASTSPOOLDIR) @for x in phoneprov/*; do \ dst="$(DESTDIR)$(ASTDATADIR)/$$x" ; \ - if [ -f "$${dst}" ]; then \ + if [ -f $${dst} ]; then \ if [ "$(OVERWRITE)" = "y" ]; then \ - if cmp -s "$${dst}" $$x ; then \ + if cmp -s $${dst} $$x ; then \ echo "Config file $$x is unchanged"; \ continue; \ fi ; \ - mv -f "$${dst}" "$${dst}.old" ; \ + mv -f $${dst} $${dst}.old ; \ else \ echo "Skipping config file $$x"; \ continue; \ fi ;\ fi ; \ echo "Installing file $$x"; \ - $(INSTALL) -m 644 $$x "$${dst}" ;\ + $(INSTALL) -m 644 $$x $${dst} ;\ done webvmail: @[ -d $(DESTDIR)$(HTTP_DOCSDIR)/ ] || ( printf "http docs directory not found.\nUpdate assignment of variable HTTP_DOCSDIR in Makefile!\n" && exit 1 ) @[ -d $(DESTDIR)$(HTTP_CGIDIR) ] || ( printf "cgi-bin directory not found.\nUpdate assignment of variable HTTP_CGIDIR in Makefile!\n" && exit 1 ) - $(INSTALL) -m 4755 contrib/scripts/vmail.cgi "$(DESTDIR)$(HTTP_CGIDIR)/vmail.cgi" + $(INSTALL) -m 4755 contrib/scripts/vmail.cgi $(DESTDIR)$(HTTP_CGIDIR)/vmail.cgi $(INSTALL) -d $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk for x in images/*.gif; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(HTTP_DOCSDIR)/_asterisk/"; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk/; \ done @echo " +--------- Asterisk Web Voicemail ----------+" @echo " + +" @@ -838,17 +838,18 @@ sounds: cleantest: @cmp -s .cleancount .lastclean || $(MAKE) clean + @[ -f "$(DESTDIR)$(ASTDBDIR)/astdb.sqlite3" ] || [ ! -f "$(DESTDIR)$(ASTDBDIR)/astdb" ] || [ ! -f menuselect.makeopts ] || grep -q MENUSELECT_UTILS=.*astdb2sqlite3 menuselect.makeopts || (sed -i.orig -e's/MENUSELECT_UTILS=\(.*\)/MENUSELECT_UTILS=\1 astdb2sqlite3/' menuselect.makeopts && echo "Updating menuselect.makeopts to include astdb2sqlite3" && echo "Original version backed up to menuselect.makeopts.orig") $(SUBDIRS_UNINSTALL): +@$(SUBMAKE) -C $(@:-uninstall=) uninstall _uninstall: $(SUBDIRS_UNINSTALL) - rm -f "$(DESTDIR)$(MODULES_DIR)/*" + rm -f $(DESTDIR)$(MODULES_DIR)/* rm -f $(DESTDIR)$(ASTSBINDIR)/*asterisk* rm -f $(DESTDIR)$(ASTSBINDIR)/astgenkey rm -f $(DESTDIR)$(ASTSBINDIR)/autosupport rm -rf $(DESTDIR)$(ASTHEADERDIR) - rm -rf "$(DESTDIR)$(ASTDATADIR)/firmware" + rm -rf $(DESTDIR)$(ASTDATADIR)/firmware rm -f $(DESTDIR)$(ASTMANDIR)/man8/asterisk.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/astgenkey.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/autosupport.8 @@ -870,12 +871,12 @@ uninstall: _uninstall @echo " +-------------------------------------------+" uninstall-all: _uninstall - rm -rf "$(DESTDIR)$(ASTLIBDIR)" - rm -rf "$(DESTDIR)$(ASTVARLIBDIR)" - rm -rf "$(DESTDIR)$(ASTDATADIR)" - rm -rf "$(DESTDIR)$(ASTSPOOLDIR)" - rm -rf "$(DESTDIR)$(ASTETCDIR)" - rm -rf "$(DESTDIR)$(ASTLOGDIR)" + rm -rf $(DESTDIR)$(ASTLIBDIR) + rm -rf $(DESTDIR)$(ASTVARLIBDIR) + rm -rf $(DESTDIR)$(ASTDATADIR) + rm -rf $(DESTDIR)$(ASTSPOOLDIR) + rm -rf $(DESTDIR)$(ASTETCDIR) + rm -rf $(DESTDIR)$(ASTLOGDIR) menuconfig: menuselect diff --git a/Makefile.moddir_rules b/Makefile.moddir_rules index b0bc148ac..b883548af 100644 --- a/Makefile.moddir_rules +++ b/Makefile.moddir_rules @@ -122,7 +122,7 @@ clean:: install:: all @echo "Installing modules from `basename $(CURDIR)`..." - @for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x "$(DESTDIR)$(MODULES_DIR)" ; done + @for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done uninstall:: diff --git a/UPGRADE-1.8.txt b/UPGRADE-1.8.txt index 5d40e2eb1..b70ff07f6 100644 --- a/UPGRADE-1.8.txt +++ b/UPGRADE-1.8.txt @@ -20,6 +20,8 @@ From 1.6.2 to 1.8: +* Asterisk now requires libpri 1.4.11+ for PRI support. + * A couple of CLI commands in res_ais were changed back to their original form: "ais show clm members" --> "ais clm show members" "ais show evt event channels" --> "ais evt show event channels" diff --git a/UPGRADE-10.txt b/UPGRADE-10.txt new file mode 100644 index 000000000..c5d927b51 --- /dev/null +++ b/UPGRADE-10.txt @@ -0,0 +1,81 @@ +=========================================================== +=== +=== Information for upgrading between Asterisk versions +=== +=== These files document all the changes that MUST be taken +=== into account when upgrading between the Asterisk +=== versions listed below. These changes may require that +=== you modify your configuration files, dialplan or (in +=== some cases) source code if you have your own Asterisk +=== modules or patches. These files also include advance +=== notice of any functionality that has been marked as +=== 'deprecated' and may be removed in a future release, +=== along with the suggested replacement functionality. +=== +=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2 +=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 +=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 +=== UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 +=== +=========================================================== + +From 1.8 to 10: + +cel_pgsql: + - This module now expects an 'extra' column in the database for data added + using the CELGenUserEvent() application. + +ConfBridge + - ConfBridge's dialplan arguments have changed and are not + backwards compatible. + +File Interpreters + - The format interpreter formats/format_sln16.c for the file extension + '.sln16' has been removed. The '.sln16' file interpreter now exists + in the formats/format_sln.c module along with new support for sln12, + sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. + +HTTP: + - A bindaddr must be specified in order for the HTTP server + to run. Previous versions would default to 0.0.0.0 if no + bindaddr was specified. + +Gtalk: + - The default value for 'context' and 'parkinglots' in gtalk.conf has + been changed to 'default', previously they were empty. + +chan_dahdi: + - The mohinterpret=passthrough setting is deprecated in favor of + moh_signaling=notify. + +pbx_lua: + - Execution no longer continues after applications that do dialplan jumps + (such as app.goto). Now when an application such as app.goto() is called, + control is returned back to the pbx engine and the current extension + function stops executing. + - the autoservice now defaults to being on by default + - autoservice_start() and autoservice_start() no longer return a value. + +Queue: + - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members + - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. + +Asterisk Database: + - The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + +Module Support Level + - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, + formats, funcs, pbx, and res have been updated to include MODULEINFO data + that includes tags with a value of core, extended, or deprecated. + More information is available on the Asterisk wiki at + https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States + + Deprecated modules are now marked to not build by default and must be explicitly + enabled in menuselect. + +=========================================================== +=========================================================== diff --git a/UPGRADE.txt b/UPGRADE.txt index dfa85684e..d7803b4d3 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -16,10 +16,15 @@ === UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 === UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 === UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 +=== UPGRADE-10.txt -- Upgrade info for 1.8 to 10 === =========================================================== -From 1.8 to 1.10: +From 10 to 12: + +* No significant changes as of yet. + +From 1.8 to 10: cel_pgsql: - This module now expects an 'extra' column in the database for data added @@ -29,6 +34,12 @@ ConfBridge - ConfBridge's dialplan arguments have changed and are not backwards compatible. +File Interpreters + - The format interpreter formats/format_sln16.c for the file extension + '.sln16' has been removed. The '.sln16' file interpreter now exists + in the formats/format_sln.c module along with new support for sln12, + sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. + HTTP: - A bindaddr must be specified in order for the HTTP server to run. Previous versions would default to 0.0.0.0 if no @@ -54,5 +65,22 @@ Queue: - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. +Asterisk Database: + - The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + +Module Support Level + - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, + formats, funcs, pbx, and res have been updated to include MODULEINFO data + that includes tags with a value of core, extended, or deprecated. + More information is available on the Asterisk wiki at + https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States + + Deprecated modules are now marked to not build by default and must be explicitly + enabled in menuselect. + =========================================================== =========================================================== diff --git a/addons/app_mysql.c b/addons/app_mysql.c index 589b23823..5649166a7 100644 --- a/addons/app_mysql.c +++ b/addons/app_mysql.c @@ -26,6 +26,8 @@ /*** MODULEINFO mysqlclient no + deprecated + func_odbc ***/ #include "asterisk.h" diff --git a/addons/app_saycountpl.c b/addons/app_saycountpl.c index 915779899..b4441f24f 100644 --- a/addons/app_saycountpl.c +++ b/addons/app_saycountpl.c @@ -22,6 +22,8 @@ /*** MODULEINFO no + deprecated + say.conf ***/ #include "asterisk.h" diff --git a/addons/cdr_mysql.c b/addons/cdr_mysql.c index 60abae2d9..ecdfaea0b 100644 --- a/addons/cdr_mysql.c +++ b/addons/cdr_mysql.c @@ -36,6 +36,8 @@ /*** MODULEINFO mysqlclient no + deprecated + cdr_adaptive_odbc ***/ #include "asterisk.h" diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c index 5495c7f22..7c1492729 100644 --- a/addons/chan_mobile.c +++ b/addons/chan_mobile.c @@ -28,6 +28,7 @@ /*** MODULEINFO bluetooth no + extended ***/ #include "asterisk.h" diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index 5c2131c93..32d1cf7d4 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -19,11 +19,48 @@ /*** MODULEINFO no + extended ***/ #include "chan_ooh323.h" #include +/*** DOCUMENTATION + + + Allow Setting / Reading OOH323 Settings + + + + + + Fax Detect [R/W] + Returns 0 or 1 + Write yes or no + + + + + t38support [R/W] + Returns 0 or 1 + Write yes or no + + + + + Returns h323id [R] + + + + + + Read and set channel parameters in the dialplan. + name is one of the above only those with a [W] can be writen to. + + + +***/ + #define FORMAT_STRING_SIZE 512 /* Defaults */ @@ -49,6 +86,9 @@ #define T38_ENABLED 1 #define T38_FAXGW 1 +#define FAXDETECT_CNG 1 +#define FAXDETECT_T38 2 + /* Channel description */ static const char type[] = "OOH323"; static const char tdesc[] = "Objective Systems H323 Channel Driver"; @@ -138,6 +178,8 @@ static struct ooh323_pvt { struct ast_rtp_instance *vrtp; /* Placeholder for now */ int t38support; /* T.38 mode - disable, transparent, faxgw */ + int faxdetect; + int faxdetected; int rtptimeout; struct ast_udptl *udptl; int faxmode; @@ -199,25 +241,26 @@ AST_MUTEX_DEFINE_STATIC(iflock); /* Profile of H.323 user registered with PBX*/ struct ooh323_user{ ast_mutex_t lock; - char name[256]; - char context[AST_MAX_EXTENSION]; - int incominglimit; - unsigned inUse; - char accountcode[20]; - int amaflags; + char name[256]; + char context[AST_MAX_EXTENSION]; + int incominglimit; + unsigned inUse; + char accountcode[20]; + int amaflags; struct ast_format_cap *cap; struct ast_codec_pref prefs; - int dtmfmode; - int dtmfcodec; - int t38support; - int rtptimeout; - int mUseIP; /* Use IP address or H323-ID to search user */ - char mIP[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ - struct OOH323Regex *rtpmask; - char rtpmaskstr[120]; - int rtdrcount, rtdrinterval; - int faststart, h245tunneling; - int g729onlyA; + int dtmfmode; + int dtmfcodec; + int faxdetect; + int t38support; + int rtptimeout; + int mUseIP; /* Use IP address or H323-ID to search user */ + char mIP[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ + struct OOH323Regex *rtpmask; + char rtpmaskstr[120]; + int rtdrcount, rtdrinterval; + int faststart, h245tunneling; + int g729onlyA; struct ooh323_user *next; }; @@ -233,6 +276,7 @@ struct ooh323_peer{ int amaflags; int dtmfmode; int dtmfcodec; + int faxdetect; int t38support; int mFriend; /* indicates defined as friend */ char ip[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ @@ -295,6 +339,7 @@ static struct ast_format_cap *gCap; static struct ast_codec_pref gPrefs; static int gDTMFMode = H323_DTMF_RFC2833; static int gDTMFCodec = 101; +static int gFAXdetect = FAXDETECT_CNG; static int gT38Support = T38_FAXGW; static char gGatekeeper[100]; static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper; @@ -343,10 +388,12 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL; static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, - const char *host, struct ast_format_cap *cap, const char *linkedid) + const char *host, struct ast_format_cap *cap, const char *linkedid) { struct ast_channel *ch = NULL; struct ast_format tmpfmt; + int features = 0; + if (gH323Debug) ast_verbose("--- ooh323_new - %s\n", host); @@ -388,16 +435,27 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, ast_module_ref(myself); /* Allocate dsp for in-band DTMF support */ - if (i->dtmfmode & H323_DTMF_INBAND) { + if ((i->dtmfmode & H323_DTMF_INBAND) || (i->faxdetect & FAXDETECT_CNG)) { i->vad = ast_dsp_new(); - ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT); - ast_dsp_set_features(i->vad, - DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT); - ast_dsp_set_faxmode(i->vad, - DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED); + } - if (i->dtmfmode & H323_DTMF_INBANDRELAX) + /* inband DTMF*/ + if (i->dtmfmode & H323_DTMF_INBAND) { + features |= DSP_FEATURE_DIGIT_DETECT; + if (i->dtmfmode & H323_DTMF_INBANDRELAX) { ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); + } + } + + /* fax detection*/ + if (i->faxdetect & FAXDETECT_CNG) { + features |= DSP_FEATURE_FAX_DETECT; + ast_dsp_set_faxmode(i->vad, + DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED); + } + + if (features) { + ast_dsp_set_features(i->vad, features); } ast_mutex_lock(&usecnt_lock); @@ -484,6 +542,9 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) ast_mutex_lock(&pvt->lock); pvt->faxmode = 0; + pvt->chmodepend = 0; + pvt->faxdetected = 0; + pvt->faxdetect = gFAXdetect; pvt->t38support = gT38Support; pvt->rtptimeout = gRTPTimeout; pvt->rtdrinterval = gRTDRInterval; @@ -610,6 +671,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca p->g729onlyA = peer->g729onlyA; p->dtmfmode |= peer->dtmfmode; p->dtmfcodec = peer->dtmfcodec; + p->faxdetect = peer->faxdetect; p->t38support = peer->t38support; p->rtptimeout = peer->rtptimeout; p->faststart = peer->faststart; @@ -639,6 +701,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca p->g729onlyA = g729onlyA; p->dtmfmode = gDTMFMode; p->dtmfcodec = gDTMFCodec; + p->faxdetect = gFAXdetect; p->t38support = gT38Support; p->rtptimeout = gRTPTimeout; ast_format_cap_copy(p->cap, gCap); @@ -828,17 +891,7 @@ static int ooh323_digit_begin(struct ast_channel *chan, char digit) } ast_mutex_lock(&p->lock); - - if (digit == 'e' && !p->faxmode && p->t38support != T38_DISABLED) { - if (!p->chmodepend) { - if (gH323Debug) - ast_verbose("request to change %s to t.38 because fax cng\n", - p->callToken); - p->chmodepend = 1; - ooRequestChangeMode(p->callToken, 1); - } - - } else if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) { + if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) { ast_rtp_instance_dtmf_begin(p->rtp, digit); } else if (((p->dtmfmode & H323_DTMF_Q931) || (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) || @@ -1270,27 +1323,50 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d (int)sizeof(enum ast_control_t38), (int)datalen); } else { const struct ast_control_t38_parameters *parameters = data; + struct ast_control_t38_parameters our_parameters; enum ast_control_t38 message = parameters->request_response; switch (message) { + case AST_T38_NEGOTIATED: + if (p->faxmode) { + res = 0; + break; + } case AST_T38_REQUEST_NEGOTIATE: - if (!p->chmodepend && !p->faxmode) { - ooRequestChangeMode(p->callToken, 1); + if (p->faxmode) { + /* T.38 already negotiated */ + our_parameters.request_response = AST_T38_NEGOTIATED; + our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); + our_parameters.rate = AST_T38_RATE_14400; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + } else if (!p->chmodepend) { p->chmodepend = 1; + ooRequestChangeMode(p->callToken, 1); res = 0; } break; case AST_T38_REQUEST_TERMINATE: - if (!p->chmodepend && p->faxmode) { - ooRequestChangeMode(p->callToken, 0); + if (!p->faxmode) { + /* T.38 already terminated */ + our_parameters.request_response = AST_T38_TERMINATED; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + } else if (!p->chmodepend) { p->chmodepend = 1; + ooRequestChangeMode(p->callToken, 0); res = 0; } break; + case AST_T38_REQUEST_PARMS: + our_parameters.request_response = AST_T38_REQUEST_PARMS; + our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); + our_parameters.rate = AST_T38_RATE_14400; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + res = AST_T38_REQUEST_PARMS; + break; default: ; @@ -1336,17 +1412,18 @@ static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, i case AST_OPTION_T38_STATE: if (*datalen != sizeof(enum ast_t38_state)) { - ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option." + ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option." " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); break; } - if (p->t38support != T38_DISABLED) - state = T38_STATE_UNKNOWN; - if (p->faxmode) - state = (p->chmodepend) ? T38_STATE_UNKNOWN : T38_STATE_NEGOTIATED; - else if (p->chmodepend) - state = T38_STATE_NEGOTIATING; + if (p->t38support != T38_DISABLED) { + if (p->faxmode) { + state = (p->chmodepend) ? T38_STATE_NEGOTIATING : T38_STATE_NEGOTIATED; + } else { + state = T38_STATE_UNKNOWN; + } + } *((enum ast_t38_state *) data) = state; res = 0; @@ -1762,6 +1839,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg) memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref)); p->dtmfmode |= user->dtmfmode; p->dtmfcodec = user->dtmfcodec; + p->faxdetect = user->faxdetect; p->t38support = user->t38support; p->rtptimeout = user->rtptimeout; p->h245tunneling = user->h245tunneling; @@ -2202,6 +2280,7 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) user->rtptimeout = gRTPTimeout; user->dtmfmode = gDTMFMode; user->dtmfcodec = gDTMFCodec; + user->faxdetect = gFAXdetect; user->t38support = gT38Support; user->faststart = gFastStart; user->h245tunneling = gTunneling; @@ -2279,7 +2358,27 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { user->dtmfcodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + user->faxdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + user->faxdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + user->faxdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + user->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + user->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) user->t38support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2322,11 +2421,12 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, peer->amaflags = gAMAFLAGS; peer->dtmfmode = gDTMFMode; peer->dtmfcodec = gDTMFCodec; + peer->faxdetect = gFAXdetect; peer->t38support = gT38Support; peer->faststart = gFastStart; peer->h245tunneling = gTunneling; peer->g729onlyA = g729onlyA; - peer->port = 1720; + peer->port = 1720; if (0 == friend_type) { peer->mFriend = 1; } @@ -2426,7 +2526,27 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { peer->dtmfcodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + peer->faxdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + peer->faxdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + peer->faxdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + peer->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + peer->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) peer->t38support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2548,6 +2668,7 @@ int reload_config(int reload) memset(&gPrefs, 0, sizeof(struct ast_codec_pref)); gDTMFMode = H323_DTMF_RFC2833; gDTMFCodec = 101; + gFAXdetect = FAXDETECT_CNG; gT38Support = T38_FAXGW; gTRCLVL = OOTRCLVLERR; gRasGkMode = RasNoGatekeeper; @@ -2751,7 +2872,27 @@ int reload_config(int reload) gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { gDTMFCodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + gFAXdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + gFAXdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + gFAXdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + gFAXdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + gFAXdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) gT38Support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2838,14 +2979,13 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc if (a->argc != 4) return CLI_SHOWUSAGE; - ast_mutex_lock(&peerl.lock); peer = peerl.peers; while (peer) { ast_mutex_lock(&peer->lock); - if(!strcmp(peer->name, a->argv[3])) + if (!strcmp(peer->name, a->argv[3])) { break; - else { + } else { prev = peer; peer = peer->next; ast_mutex_unlock(&prev->lock); @@ -2853,53 +2993,64 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc } if (peer) { - sprintf(ip_port, "%s:%d", peer->ip, peer->port); - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); - ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no", + sprintf(ip_port, "%s:%d", peer->ip, peer->port); + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); + ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no", peer->h245tunneling?"yes":"no"); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &peer->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &peer->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (peer->dtmfmode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); } else if (peer->dtmfmode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); - } else if (peer->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (peer->dtmfmode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else - ast_cli(a->fd, "%s\n", "unknown"); + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + } else if (peer->dtmfmode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (peer->dtmfmode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { + ast_cli(a->fd, "%s\n", "unknown"); + } + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (peer->t38support == T38_DISABLED) { + ast_cli(a->fd, "%s\n", "disabled"); + } else if (peer->t38support == T38_FAXGW) { + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (peer->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (peer->faxdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (peer->faxdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - ast_cli(a->fd,"%-15s", "T.38 Mode: "); - if (peer->t38support == T38_DISABLED) - ast_cli(a->fd, "%s\n", "disabled"); - else if (peer->t38support == T38_FAXGW) - ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); - - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", - ast_cdr_flags2str(peer->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port); - ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); - if (peer->rtpmaskstr[0]) - ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr); - if (peer->rtdrcount && peer->rtdrinterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval); - ast_mutex_unlock(&peer->lock); + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(peer->amaflags)); + ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port); + ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); + if (peer->rtpmaskstr[0]) { + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr); + } + if (peer->rtdrcount && peer->rtdrinterval) { + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval); + } + ast_mutex_unlock(&peer->lock); } else { - ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&peerl.lock); @@ -2989,9 +3140,9 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc user = userl.users; while (user) { ast_mutex_lock(&user->lock); - if(!strcmp(user->name, a->argv[3])) { + if (!strcmp(user->name, a->argv[3])) { break; - } else { + } else { prev = user; user = user->next; ast_mutex_unlock(&prev->lock); @@ -2999,53 +3150,64 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc } if (user) { - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); - ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no", + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); + ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no", user->h245tunneling?"yes":"no"); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &user->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &user->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (user->dtmfmode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); } else if (user->dtmfmode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); - } else if (user->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (user->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (user->dtmfmode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else - ast_cli(a->fd, "%s\n", "unknown"); + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + } else if (user->dtmfmode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (user->dtmfmode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (user->dtmfmode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { + ast_cli(a->fd, "%s\n", "unknown"); + } + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (user->t38support == T38_DISABLED) { + ast_cli(a->fd, "%s\n", "disabled"); + } else if (user->t38support == T38_FAXGW) { + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (user->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (user->faxdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (user->faxdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - ast_cli(a->fd,"%-15s", "T.38 Mode: "); - if (user->t38support == T38_DISABLED) - ast_cli(a->fd, "%s\n", "disabled"); - else if (user->t38support == T38_FAXGW) - ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); - - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", - ast_cdr_flags2str(user->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); - ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); - ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); - if (user->rtpmaskstr[0]) - ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(user->amaflags)); + ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); + ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); + ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); + if (user->rtpmaskstr[0]) { + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); + } ast_mutex_unlock(&user->lock); - if (user->rtdrcount && user->rtdrinterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval); + if (user->rtdrcount && user->rtdrinterval) { + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval); + } } else { - ast_cli(a->fd, "User %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "User %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&userl.lock); @@ -3144,91 +3306,93 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str if (a->argc != 3) return CLI_SHOWUSAGE; - - - ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); + ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); snprintf(value, sizeof(value), "%s:%d", gIP, gPort); - ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); - ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", - ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd); - ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); - ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", - gMediaWaitForConnect?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); + ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd); + ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); + ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect?"yes":"no"); #if (0) extern OOH323EndPoint gH323ep; - ast_cli(a->fd, "%-20s%s\n", "FASTSTART", - (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "TUNNELING", - (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", - (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "FASTSTART", + (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "TUNNELING", + (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", + (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no"); #endif - if (gRasGkMode == RasNoGatekeeper) + if (gRasGkMode == RasNoGatekeeper) { snprintf(value, sizeof(value), "%s", "No Gatekeeper"); - else if (gRasGkMode == RasDiscoverGatekeeper) + } else if (gRasGkMode == RasDiscoverGatekeeper) { snprintf(value, sizeof(value), "%s", "Discover"); - else + } else { snprintf(value, sizeof(value), "%s", gGatekeeper); - - ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); - - ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); - - ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); - - ast_cli(a->fd, "%-20s%s\n", "Capability:", - ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap)); - - ast_cli(a->fd, "%-20s", "DTMF Mode: "); + } + ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); + ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); + ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); + ast_cli(a->fd, "%-20s%s\n", "Capability:", + ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap)); + ast_cli(a->fd, "%-20s", "DTMF Mode: "); if (gDTMFMode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec); } else if (gDTMFMode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); - } else if (gDTMFMode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (gDTMFMode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (gDTMFMode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec); + } else if (gDTMFMode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (gDTMFMode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (gDTMFMode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { ast_cli(a->fd, "%s\n", "unknown"); + } - ast_cli(a->fd,"%-20s", "T.38 Mode: "); - if (gT38Support == T38_DISABLED) + ast_cli(a->fd,"%-20s", "T.38 Mode: "); + if (gT38Support == T38_DISABLED) { ast_cli(a->fd, "%s\n", "disabled"); - else if (gT38Support == T38_FAXGW) + } else if (gT38Support == T38_FAXGW) { ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (gFAXdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (gFAXdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (gFAXdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - if (gRTDRCount && gRTDRInterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval); + if (gRTDRCount && gRTDRInterval) { + ast_cli(a->fd, "%-20.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval); + } - ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); - ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); - - ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); + ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); + ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); + ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); pAlias = gAliasList; - if(pAlias) { - ast_cli(a->fd, "%-20s\n", "Aliases: "); - } + if(pAlias) { + ast_cli(a->fd, "%-20s\n", "Aliases: "); + } while (pAlias) { pAliasNext = pAlias->next; if (pAliasNext) { - ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value); + ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value); pAlias = pAliasNext->next; - } - else{ - ast_cli(a->fd,"\t%-30s\n",pAlias->value); + } else { + ast_cli(a->fd,"\t%-30s\n",pAlias->value); pAlias = pAlias->next; } } @@ -3245,6 +3409,115 @@ static struct ast_cli_entry cli_ooh323[] = { AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config") }; +/*! \brief OOH323 Dialplan function - reads ooh323 settings */ +static int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + struct ooh323_pvt *p = chan->tech_pvt; + + ast_channel_lock(chan); + if (!p) { + ast_channel_unlock(chan); + return -1; + } + + if (strcmp(chan->tech->type, "OOH323")) { + ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", chan->tech->type); + ast_channel_unlock(chan); + return -1; + } + + ast_mutex_lock(&p->lock); + if (!strcasecmp(data, "faxdetect")) { + ast_copy_string(buf, p->faxdetect ? "1" : "0", len); + } else if (!strcasecmp(data, "t38support")) { + ast_copy_string(buf, p->t38support ? "1" : "0", len); + } else if (!strcasecmp(data, "caller_h323id")) { + ast_copy_string(buf, p->caller_h323id, len); + } else if (!strcasecmp(data, "caller_dialeddigits")) { + ast_copy_string(buf, p->caller_dialedDigits, len); + } else if (!strcasecmp(data, "caller_email")) { + ast_copy_string(buf, p->caller_email, len); + } else if (!strcasecmp(data, "h323id_url")) { + ast_copy_string(buf, p->caller_url, len); + } else if (!strcasecmp(data, "callee_h323id")) { + ast_copy_string(buf, p->callee_h323id, len); + } else if (!strcasecmp(data, "callee_dialeddigits")) { + ast_copy_string(buf, p->callee_dialedDigits, len); + } else if (!strcasecmp(data, "callee_email")) { + ast_copy_string(buf, p->callee_email, len); + } else if (!strcasecmp(data, "callee_url")) { + ast_copy_string(buf, p->callee_url, len); + } + ast_mutex_unlock(&p->lock); + + ast_channel_unlock(chan); + return 0; +} + +/*! \brief OOH323 Dialplan function - writes ooh323 settings */ +static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) +{ + struct ooh323_pvt *p = chan->tech_pvt; + int res = -1; + + ast_channel_lock(chan); + if (!p) { + ast_channel_unlock(chan); + return -1; + } + + if (strcmp(chan->tech->type, "OOH323")) { + ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", chan->tech->type); + ast_channel_unlock(chan); + return -1; + } + + ast_mutex_lock(&p->lock); + if (!strcasecmp(data, "faxdetect")) { + if (ast_true(value)) { + p->faxdetect = 1; + res = 0; + } else if (ast_false(value)) { + p->faxdetect = 0; + res = 0; + } else { + char *buf = ast_strdupa(value); + char *word, *next = buf; + p->faxdetect = 0; + res = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + p->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + p->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s'.\n", word); + res = -1; + } + } + + } + } else if (!strcasecmp(data, "t38support")) { + if (ast_true(value)) { + p->t38support = 1; + res = 0; + } else { + p->t38support = 0; + res = 0; + } + } + ast_mutex_unlock(&p->lock); + ast_channel_unlock(chan); + + return res; +} + +/*! \brief Structure to declare a dialplan function: OOH323 */ +static struct ast_custom_function ooh323_function = { + .name = "OOH323", + .read = function_ooh323_read, + .write = function_ooh323_write, +}; static int load_module(void) { @@ -3414,6 +3687,9 @@ static int load_module(void) restart_monitor(); } + /* Register dialplan functions */ + ast_custom_function_register(&ooh323_function); + return 0; } @@ -3689,7 +3965,7 @@ int delete_users() ast_mutex_unlock(&userl.lock); return 0; } - + static int unload_module(void) { struct ooh323_pvt *p; @@ -3804,8 +4080,11 @@ static int unload_module(void) } ooH323EpDestroy(); + /* Unregister dial plan functions */ + ast_custom_function_unregister(&ooh323_function); + if (gH323Debug) { - ast_verbose("+++ ooh323 unload_module \n"); + ast_verbose("+++ ooh323 unload_module \n"); } gCap = ast_format_cap_destroy(gCap); @@ -4310,6 +4589,7 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) { /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ struct ast_frame *f; + struct ast_frame *dfr = NULL; static struct ast_frame null_frame = { AST_FRAME_NULL, }; switch (ast->fdno) { case 0: @@ -4336,25 +4616,59 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) f = &null_frame; } - if (p->owner) { + if (p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) { /* We already hold the channel lock */ - if (f->frametype == AST_FRAME_VOICE && !p->faxmode) { - if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { - ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format)); - ast_format_cap_set(p->owner->nativeformats, &f->subclass.format); - ast_set_read_format(p->owner, &p->owner->readformat); - ast_set_write_format(p->owner, &p->owner->writeformat); - } + if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { + ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(p->owner->nativeformats, &f->subclass.format); + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); + } + if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad && + (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW || + f->subclass.format.id == AST_FORMAT_ULAW)) { + dfr = ast_frdup(f); + dfr = ast_dsp_process(p->owner, p->vad, dfr); + } + } else { + return f; + } - if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad && - (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW || - f->subclass.format.id == AST_FORMAT_ULAW)) { - f = ast_dsp_process(p->owner, p->vad, f); - if (f && (f->frametype == AST_FRAME_DTMF)) { - ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); + /* process INBAND DTMF*/ + if (dfr && (dfr->frametype == AST_FRAME_DTMF) && ((dfr->subclass.integer == 'f') || (dfr->subclass.integer == 'e'))) { + ast_debug(1, "* Detected FAX Tone %s\n", (dfr->subclass.integer == 'e') ? "CED" : "CNG"); + /* Switch to T.38 ON CED*/ + if (!p->faxmode && !p->chmodepend && (dfr->subclass.integer == 'e') && (p->t38support != T38_DISABLED)) { + if (gH323Debug) + ast_verbose("request to change %s to t.38 because fax ced\n", p->callToken); + p->chmodepend = 1; + p->faxdetected = 1; + ooRequestChangeMode(p->callToken, 1); + } else if ((dfr->subclass.integer == 'f') && !p->faxdetected) { + const char *target_context = S_OR(p->owner->macrocontext, p->owner->context); + if ((strcmp(p->owner->exten, "fax")) && + (ast_exists_extension(p->owner, target_context, "fax", 1, + S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL)))) { + ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", p->owner->name); + pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); + if (ast_async_goto(p->owner, target_context, "fax", 1)) { + ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name,target_context); } + p->faxdetected = 1; + if (dfr) { + ast_frfree(dfr); + } + return &ast_null_frame; } } + } else if (dfr && dfr->frametype == AST_FRAME_DTMF) { + ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); + ast_frfree(f); + return dfr; + } + + if (dfr) { + ast_frfree(dfr); } return f; } @@ -4377,6 +4691,7 @@ void onModeChanged(ooCallData *call, int t38mode) { if (gH323Debug) ast_debug(1, "mode for %s is already %d\n", call->callToken, t38mode); + p->chmodepend = 0; ast_mutex_unlock(&p->lock); return; } @@ -4387,11 +4702,13 @@ void onModeChanged(ooCallData *call, int t38mode) { DEADLOCK_AVOIDANCE(&p->lock); } if (!p->owner) { + p->chmodepend = 0; ast_mutex_unlock(&p->lock); ast_log(LOG_ERROR, "Channel has no owner\n"); return; } } else { + p->chmodepend = 0; ast_mutex_unlock(&p->lock); ast_log(LOG_ERROR, "Channel has no owner\n"); return; @@ -4401,10 +4718,26 @@ void onModeChanged(ooCallData *call, int t38mode) { if (p->t38support == T38_ENABLED) { + struct ast_control_t38_parameters parameters = { .request_response = 0 }; + + if ((p->faxdetect & FAXDETECT_T38) && !p->faxdetected) { + const char *target_context; + ast_debug(1, "* Detected T.38 Request\n"); + target_context = S_OR(p->owner->macrocontext, p->owner->context); + if ((strcmp(p->owner->exten, "fax")) && + (ast_exists_extension(p->owner, target_context, "fax", 1, + S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL)))) { + ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", p->owner->name); + pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); + if (ast_async_goto(p->owner, target_context, "fax", 1)) { + ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name,target_context); + } + } + p->faxdetected = 1; + } /* AST_T38_CONTROL mode */ - struct ast_control_t38_parameters parameters = { .request_response = 0 }; parameters.request_response = AST_T38_REQUEST_NEGOTIATE; if (call->T38FarMaxDatagram) { ast_udptl_set_far_max_datagram(p->udptl, call->T38FarMaxDatagram); @@ -4420,6 +4753,7 @@ void onModeChanged(ooCallData *call, int t38mode) { ¶meters, sizeof(parameters)); p->faxmode = 1; + } } else { if (p->t38support == T38_ENABLED) { @@ -4431,6 +4765,7 @@ void onModeChanged(ooCallData *call, int t38mode) { ¶meters, sizeof(parameters)); } p->faxmode = 0; + p->faxdetected = 0; p->t38_init = 0; } diff --git a/addons/format_mp3.c b/addons/format_mp3.c index d59411d6c..5584f3e06 100644 --- a/addons/format_mp3.c +++ b/addons/format_mp3.c @@ -29,6 +29,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/addons/ooh323c/src/ooGkClient.c b/addons/ooh323c/src/ooGkClient.c index 04359998a..33d7df019 100644 --- a/addons/ooh323c/src/ooGkClient.c +++ b/addons/ooh323c/src/ooGkClient.c @@ -1211,8 +1211,11 @@ int ooGkClientHandleRegistrationConfirm if(pGkClient->regTimeout > DEFAULT_TTL_OFFSET) regTTL = pGkClient->regTimeout - DEFAULT_TTL_OFFSET; - else - regTTL = pGkClient->regTimeout; + else { + regTTL = pGkClient->regTimeout - 1; /* -1 due to some ops expire us few earlier */ + if (regTTL <= 0) + regTTL = 1; + } cbData = (ooGkClientTimerCb*) memAlloc (&pGkClient->ctxt, sizeof(ooGkClientTimerCb)); @@ -1260,7 +1263,6 @@ int ooGkClientHandleRegistrationConfirm memFreePtr(&pGkClient->ctxt, pTimer->cbData); ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); OOTRACEDBGA1("Deleted RRQ Timer.\n"); - break; } } pGkClient->state = GkClientRegistered; @@ -1505,8 +1507,10 @@ int ooGkClientSendURQ(ooGkClient *pGkClient, ooAliases *aliases) int ooGkClientHandleUnregistrationRequest (ooGkClient *pGkClient, H225UnregistrationRequest * punregistrationRequest) { - int iRet=0; - + int iRet=0, x; + OOTimer *pTimer = NULL; + DListNode *pNode = NULL; + /* Lets first send unregistration confirm message back to gatekeeper*/ ooGkClientSendUnregistrationConfirm(pGkClient, punregistrationRequest->requestSeqNum); @@ -1528,6 +1532,24 @@ int ooGkClientHandleUnregistrationRequest pGkClient->rrqRetries = 0; pGkClient->state = GkClientDiscovered; + + /* delete the corresponding RRQ & REG timers */ + pNode = NULL; + for(x=0; xtimerList.count; x++) { + pNode = dListFindByIndex(&pGkClient->timerList, x); + pTimer = (OOTimer*)pNode->data; + if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_RRQ_TIMER) { + memFreePtr(&pGkClient->ctxt, pTimer->cbData); + ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); + OOTRACEDBGA1("Deleted RRQ Timer.\n"); + } + if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_REG_TIMER) { + memFreePtr(&pGkClient->ctxt, pTimer->cbData); + ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); + OOTRACEDBGA1("Deleted REG Timer.\n"); + } + } + iRet = ooGkClientSendRRQ(pGkClient, 0); if(iRet != OO_OK) { diff --git a/addons/res_config_mysql.c b/addons/res_config_mysql.c index eaf7209f9..d393de6c1 100644 --- a/addons/res_config_mysql.c +++ b/addons/res_config_mysql.c @@ -25,6 +25,7 @@ /*** MODULEINFO mysqlclient no + extended ***/ #include "asterisk.h" diff --git a/agi/eagi-test.c b/agi/eagi-test.c index dc2d7fa1a..7f24d1f23 100644 --- a/agi/eagi-test.c +++ b/agi/eagi-test.c @@ -5,6 +5,10 @@ * with no warranty of any kind */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #define AUDIO_FILENO (STDERR_FILENO + 1) diff --git a/apps/app_adsiprog.c b/apps/app_adsiprog.c index c138f0429..430d8258d 100644 --- a/apps/app_adsiprog.c +++ b/apps/app_adsiprog.c @@ -27,6 +27,7 @@ /*** MODULEINFO res_adsi + extended ***/ #include "asterisk.h" diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c index 6936cb5a0..1a4f9220f 100644 --- a/apps/app_alarmreceiver.c +++ b/apps/app_alarmreceiver.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_amd.c b/apps/app_amd.c index 7c4e2a47a..35c5005f7 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -26,6 +26,9 @@ * \author Claude Klimos (claude.klimos@aheeva.com) */ +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_authenticate.c b/apps/app_authenticate.c index 416ea432d..8b5fa11a6 100644 --- a/apps/app_authenticate.c +++ b/apps/app_authenticate.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_cdr.c b/apps/app_cdr.c index 70036ad82..2f227b049 100644 --- a/apps/app_cdr.c +++ b/apps/app_cdr.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c index 5dd4a1f60..86ce34177 100644 --- a/apps/app_chanisavail.c +++ b/apps/app_chanisavail.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_channelredirect.c b/apps/app_channelredirect.c index 57c9234ef..8fe543dab 100644 --- a/apps/app_channelredirect.c +++ b/apps/app_channelredirect.c @@ -23,6 +23,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index c90a7907a..92e0ba513 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index d046c489f..4897d065e 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -28,6 +28,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -632,10 +636,10 @@ static int play_prompt_to_channel(struct conference_bridge *conference_bridge, s return res; } -static void handle_video_on_join(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) +static void handle_video_on_join(struct conference_bridge *conference_bridge, struct ast_channel *chan, int marked) { - /* only automatically set video source for marked users */ - if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) { + /* Right now, only marked users are automatically set as the single src of video.*/ + if (!marked) { return; } @@ -645,7 +649,7 @@ static void handle_video_on_join(struct conference_bridge *conference_bridge, st ao2_lock(conference_bridge); /* see if anyone is already the video src */ AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { - if (tmp_user == conference_bridge_user) { + if (tmp_user->chan == chan) { continue; } if (ast_bridge_is_video_src(conference_bridge->bridge, tmp_user->chan)) { @@ -655,24 +659,31 @@ static void handle_video_on_join(struct conference_bridge *conference_bridge, st } ao2_unlock(conference_bridge); if (set) { - ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); } } else if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) { /* we joined and are video capable, we override anyone else that may have already been the video feed */ - ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); } } -static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) +static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct ast_channel *chan) { struct conference_bridge_user *tmp_user = NULL; /* if this isn't a video source, nothing to update */ - if (!ast_bridge_is_video_src(conference_bridge->bridge, conference_bridge_user->chan)) { + if (!ast_bridge_is_video_src(conference_bridge->bridge, chan)) { return; } - ast_bridge_remove_video_src(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_remove_video_src(conference_bridge->bridge, chan); + + /* If in follow talker mode, make sure to restore this mode on the + * bridge when a source is removed. It is possible this channel was + * only set temporarily as a video source by an AMI or DTMF action. */ + if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) { + ast_bridge_set_talker_src_video_mode(conference_bridge->bridge); + } /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */ if (!ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) && @@ -680,10 +691,10 @@ static void handle_video_on_exit(struct conference_bridge *conference_bridge, st return; } - /* Make the next avaliable marked user the video src. */ + /* Make the next available marked user the video src. */ ao2_lock(conference_bridge); AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { - if (tmp_user == conference_bridge_user) { + if (tmp_user->chan == chan) { continue; } if (ast_test_flag(&tmp_user->u_profile, USER_OPT_MARKEDUSER)) { @@ -1454,7 +1465,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) } } - handle_video_on_join(conference_bridge, &conference_bridge_user); + /* See if we need to automatically set this user as a video source or not */ + handle_video_on_join(conference_bridge, conference_bridge_user.chan, ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_MARKEDUSER)); /* Join our conference bridge for real */ send_join_event(conference_bridge_user.chan, conference_bridge->name); @@ -1465,8 +1477,15 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) &conference_bridge_user.tech_args); send_leave_event(conference_bridge_user.chan, conference_bridge->name); + /* if we're shutting down, don't attempt to do further processing */ + if (ast_shutting_down()) { + leave_conference_bridge(conference_bridge, &conference_bridge_user); + conference_bridge = NULL; + goto confbridge_cleanup; + } - handle_video_on_exit(conference_bridge, &conference_bridge_user); + /* If this user was a video source, we need to clean up and possibly pick a new source. */ + handle_video_on_exit(conference_bridge, conference_bridge_user.chan); /* if this user has a intro, play it when leaving */ if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) { @@ -1775,6 +1794,9 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge, ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan); ao2_unlock(conference_bridge); break; + case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC: + handle_video_on_exit(conference_bridge, bridge_channel->chan); + break; } } return res; diff --git a/apps/app_controlplayback.c b/apps/app_controlplayback.c index bbeea3037..1e2e6fbc2 100644 --- a/apps/app_controlplayback.c +++ b/apps/app_controlplayback.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_dahdibarge.c b/apps/app_dahdibarge.c index 082405e80..bb0120cbc 100644 --- a/apps/app_dahdibarge.c +++ b/apps/app_dahdibarge.c @@ -33,6 +33,9 @@ /*** MODULEINFO dahdi + no + deprecated + app_chanspy ***/ #include "asterisk.h" diff --git a/apps/app_dahdiras.c b/apps/app_dahdiras.c index b467b16b8..fbaf98450 100644 --- a/apps/app_dahdiras.c +++ b/apps/app_dahdiras.c @@ -27,6 +27,7 @@ /*** MODULEINFO dahdi + extended ***/ #include "asterisk.h" diff --git a/apps/app_db.c b/apps/app_db.c index 99679e71b..1fa24088e 100644 --- a/apps/app_db.c +++ b/apps/app_db.c @@ -28,6 +28,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_dial.c b/apps/app_dial.c index d3b8009de..65f5666f2 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -27,6 +27,7 @@ /*** MODULEINFO chan_local + core ***/ @@ -2408,7 +2409,8 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast * datastore again, causing a crash */ ast_channel_lock(chan); - if (!ast_channel_datastore_remove(chan, datastore)) { + datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); /* make sure we weren't cleaned up already */ + if (datastore && !ast_channel_datastore_remove(chan, datastore)) { ast_datastore_free(datastore); } ast_channel_unlock(chan); diff --git a/apps/app_dictate.c b/apps/app_dictate.c index 5bf439d16..b50fbb044 100644 --- a/apps/app_dictate.c +++ b/apps/app_dictate.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index 63a7621ff..1b47d011a 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -76,9 +80,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Pickup a ringing channel. - - - + + + + +