[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/.version
|
@@ -1 +1 @@
-1.6.0.1
+1.6.1.0
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/ChangeLog
^
|
@@ -1,14 +1,115 @@
+2009-04-28 Leif Madsen <lmadsen@digium.com>
+
+ * Release Asterisk-Addons 1.6.1.0
+
+2009-03-19 Leif Madsen <lmadsen@digium.com>
+
+ * Release Asterisk-Addons 1.6.1.0-rc3
+
+2009-02-20 22:01 +0000 [r788] Tilghman Lesher <tlesher@digium.com>
+
+ * cdr/cdr_addon_mysql.c: Only add the column if the value is
+ non-NULL.
+
+2009-01-21 19:07 +0000 [r728-732] Matthew Nicholson <mnicholson@digium.com>
+
+ * /, configs/mobile.conf.sample: Merged revisions 730 via svnmerge
+ from https://origsvn.digium.com/svn/asterisk-addons/trunk
+ ........ r730 | mnicholson | 2009-01-21 13:06:42 -0600 (Wed, 21
+ Jan 2009) | 2 lines Fixed a typo in configs/mobile.conf.sample,
+ found by mmichelson ........
+
+ * channels/chan_mobile.c, /, configs/mobile.conf.sample: Merged
+ revisions 725-726 via svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/trunk ........
+ r725 | mnicholson | 2009-01-21 12:09:44 -0600 (Wed, 21 Jan 2009)
+ | 7 lines Add a 'blackberry' option for devices in chan_mobile to
+ support blackberry devices' non standard HFP behavior. (closes
+ issue #13744) Reported by: ciaranm Tested by: ciaranm, davidste,
+ mnicholson, jongerenchaos ........ r726 | mnicholson | 2009-01-21
+ 12:22:33 -0600 (Wed, 21 Jan 2009) | 2 lines Added an example for
+ the new blackberry option in mobile.conf.sample ........
+
+2009-01-13 17:38 +0000 [r724] Tilghman Lesher <tlesher@digium.com>
+
+ * cdr/cdr_addon_mysql.c: Last commit didn't quite merge correctly
+ (Closes issue #14229) Reported by: sergee Patches:
+ cdr-mysql-r721.diff uploaded by sergee (license 138)
+
+2009-01-08 21:59 +0000 [r721] Tilghman Lesher <tlesher@digium.com>
+
+ * cdr/cdr_addon_mysql.c, /: Merged revisions 719 via svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/trunk ........
+ r719 | tilghman | 2009-01-08 15:55:12 -0600 (Thu, 08 Jan 2009) |
+ 2 lines Prevent a possible race between a reload event and
+ logging a CDR ........
+
+2008-12-22 17:01 +0000 [r717] Russell Bryant <russell@digium.com>
+
+ * channels/ooh323c/src/ooCmdChannel.c, /: Merged revisions 715 via
+ svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/trunk
+ ................ r715 | russell | 2008-12-22 11:00:07 -0600 (Mon,
+ 22 Dec 2008) | 15 lines Merged revisions 714 via svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/branches/1.4
+ ........ r714 | russell | 2008-12-22 10:59:46 -0600 (Mon, 22 Dec
+ 2008) | 7 lines Fix a bogus pthread_mutex_init() (closes issue
+ #14116) Reported by: junky Patches: mutex_init.diff uploaded by
+ junky (license 177) ........ ................
+
+2008-12-16 00:00 +0000 [r712] Tilghman Lesher <tlesher@digium.com>
+
+ * res/res_config_mysql.c, /: Merged revisions 711 via svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/trunk ........
+ r711 | tilghman | 2008-12-15 17:54:39 -0600 (Mon, 15 Dec 2008) |
+ 2 lines Convert addons to use ast_str opacity, fixing some bugs
+ along the way. ........
+
+2008-12-11 21:18 +0000 [r709] Tilghman Lesher <tlesher@digium.com>
+
+ * configs/cdr_mysql.conf.sample, cdr/cdr_addon_mysql.c, /: Merged
+ revisions 707 via svnmerge from
+ https://origsvn.digium.com/svn/asterisk-addons/trunk ........
+ r707 | tilghman | 2008-12-11 15:16:11 -0600 (Thu, 11 Dec 2008) |
+ 6 lines Allow setting the MySQL character set on each connect.
+ (closes issue #13775) Reported by: sergee Patches:
+ cdr_mysql_charset-r679-v2.diff uploaded by sergee (license 138)
+ ........
+
+2008-12-04 19:54 +0000 [r705] Tilghman Lesher <tlesher@digium.com>
+
+ * /: Initialized merge tracking via "svnmerge" with revisions
+ "1-690" from https://origsvn.digium.com/svn/asterisk-addons/trunk
+
2008-12-01 Tilghman Lesher <tlesher@digium.com>
- * Asterisk-Addons 1.6.0.1 released
+ * Asterisk-Addons 1.6.1-rc2 released
+
+2008-11-13 18:39 +0000 [r691-693] Tilghman Lesher <tlesher@digium.com>
+
+ * apps/app_saycountpl.c: Revert XML in this branch, since the XML
+ isn't in Asterisk-1.6.1
+
+ * res/res_config_mysql.c: Remove portions of API that aren't in
+ Asterisk-1.6.1
+
+ * / (added): Since the API can potentially change in 1.6.x, we need
+ an -addons to match for Asterisk 1.6.1
+
+2008-10-31 Tilghman Lesher <tlesher@digium.com>
+
+ * Asterisk-Addons 1.6.1-rc1 released
+
+2008-10-14 00:12 +0000 [r677] Tilghman Lesher <tlesher@digium.com>
+
+ * res/res_config_mysql.c: Merge branch for -addons, relating to the
+ realtime_update2 branch. See commit number 148570 on the asterisk
+ repository for more information.
-2008-11-10 20:25 +0000 [r690] Tilghman Lesher <tlesher@digium.com>
+2008-10-08 22:01 +0000 [r673] Michiel van Baak <michiel@vanbaak.info>
- * configs/res_mysql.conf.sample, res/res_config_mysql.c: Fix
- specification of different databases in extconfig.conf when using
- MySQL backend. This fixes a regression. (closes issue #13603)
- Reported by: atis Patches: multi_db.patch uploaded by atis
- (license 242)
+ * res/res_config_mysql.c: replace PostgreSQL with MySQL in
+ res_config_mysql.c
2008-10-01 Russell Bryant <russell@digium.com>
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/Makefile
^
|
@@ -58,10 +58,20 @@
ifeq ($(OSARCH),SunOS)
ASTETCDIR=/var/etc/asterisk
ASTLIBDIR=/opt/asterisk/lib
+ ASTVARLIBDIR=/var/opt/asterisk
else
ASTETCDIR=$(sysconfdir)/asterisk
ASTLIBDIR=$(libdir)/asterisk
+ifneq ($(findstring BSD,$(OSARCH)),)
+ ASTVARLIBDIR=$(prefix)/share/asterisk
+else
+ ASTVARLIBDIR=$(localstatedir)/lib/asterisk
+endif
+endif
+ifeq ($(ASTDATADIR),)
+ ASTDATADIR:=$(ASTVARLIBDIR)
endif
+
MODULES_DIR=$(ASTLIBDIR)/modules
#MOD_SUBDIRS:=channels pbx apps codecs formats cdr funcs tests main res $(LOCAL_MOD_SUBDIRS)
@@ -114,7 +124,7 @@
@echo " + $(mK) install +"
@echo " +-------------------------------------------+"
-_all: cleantest makeopts $(SUBDIRS)
+_all: cleantest makeopts $(SUBDIRS) doc/addons-en_US.xml
makeopts: configure
@echo "****"
@@ -162,7 +172,7 @@
@echo "****"
@exit 1
-install: _all $(SUBDIRS_INSTALL)
+install: _all $(SUBDIRS_INSTALL) install-xmldoc
@echo " +---- Asterisk-Addons Installation Complete ----+"
@echo " + +"
@echo " + Addons has successfully been installed. +"
@@ -173,6 +183,10 @@
@echo " + $(MAKE) samples +"
@echo " +-----------------------------------------------+"
+install-xmldoc: doc/addons-en_US.xml
+ @echo "Installing XML documentation"
+ @$(INSTALL) -m 644 doc/addons-*.xml $(ASTDATADIR)/documentation
+
cleantest:
$(SUBDIRS_INSTALL):
@@ -218,6 +232,29 @@
$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ;\
done
+doc/addons-en_US.xml: $(foreach dir,$(MOD_SUBDIRS),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cc))
+ @echo -n "Building Documentation For: "
+ @echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
+ @echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@
+ @echo "<docs>" >> $@
+ @for x in $(MOD_SUBDIRS); do \
+ echo -n "$$x " ; \
+ for i in $$x/*.c; do \
+ $(AWK) -f build_tools/get_documentation $$i >> $@ ; \
+ done ; \
+ done
+ @echo
+ @echo "</docs>" >> $@
+
+validate-docs: install-xmldoc
+ifeq ($(XMLSTARLET),:)
+ @echo "---------------------------------------------------------------"
+ @echo "--- Please install xmlstarlet to validate the documentation ---"
+ @echo "---------------------------------------------------------------"
+else
+ @$(XMLSTARLET) val -E $(ASTDATADIR)/documentation/addons-en_US.xml
+endif
+
update:
@if [ -d .svn ]; then \
echo "Updating from Subversion..." ; \
@@ -292,4 +329,4 @@
@for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SUBMAKE) -C $${dir} SUBDIR=$${dir} makeopts >> $@; done
@echo "</menu>" >> $@
-.PHONY: menuselect clean dist-clean distclean all cleantest uninstall _uninstall uninstall-all dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS)
+.PHONY: menuselect clean dist-clean distclean all cleantest install-xmldoc uninstall _uninstall uninstall-all dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS)
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/UPGRADE.txt
^
|
@@ -1,3 +1,10 @@
+res_config_mysql
+================
+ - A greater variation of database handles has been made available, such that
+ you can now configure realtime mysql to connect to multiple hosts and
+ separate read queries from write queries. Please familiarize yourself with
+ the sample res_config_mysql.conf, as the new behavior is now specified there.
+
cdr_addon_mysql
===============
- Module has been completely revamped, with some options in the config file no
|
[-]
[+]
|
Added |
asterisk-addons-1.6.1.0.tar.bz2/asterisk-addons-1.6.1.0-summary.html
^
|
@@ -0,0 +1,119 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Release Summary - asterisk-addons-1.6.1.0</title></head>
+<body>
+<h1 align="center"><a name="top">Release Summary</a></h1>
+<h3 align="center">asterisk-addons-1.6.1.0</h3>
+<h3 align="center">Date: 2009-04-28</h3>
+<h3 align="center"><asteriskteam@digium.com></h3>
+<hr/>
+<h2 align="center">Table of Contents</h2>
+<ol>
+ <li><a href="#summary">Summary</a></li>
+ <li><a href="#contributors">Contributors</a></li>
+ <li><a href="#issues">Closed Issues</a></li>
+ <li><a href="#commits">Other Changes</a></li>
+ <li><a href="#diffstat">Diffstat</a></li>
+</ol>
+<hr/>
+<a name="summary"><h2 align="center">Summary</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This release includes new features. For a list of new features that have been included with this release, please see the CHANGES file inside the source package. Since this is new major release, users are encouraged to do extended testing before upgrading to this version in a production environment.</p>
+<p>The data in this summary reflects changes that have been made since the previous release, asterisk-addons-1.6.0.</p>
+<hr/>
+<a name="contributors"><h2 align="center">Contributors</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were closed by commits that went into this release.</p>
+<table width="100%" border="0">
+<tr>
+<td width="33%"><h3>Coders</h3></td>
+<td width="33%"><h3>Testers</h3></td>
+<td width="33%"><h3>Reporters</h3></td>
+</tr>
+<tr valign="top">
+<td>
+7 tilghman<br/>
+2 mnicholson<br/>
+2 sergee<br/>
+1 eliel<br/>
+1 junky<br/>
+1 kpfleming<br/>
+</td>
+<td>
+1 ciaranm<br/>
+1 davidste<br/>
+1 jongerenchaos<br/>
+1 mnicholson<br/>
+</td>
+<td>
+2 sergee<br/>
+1 ciaranm<br/>
+1 junky<br/>
+1 tzafrir<br/>
+</td>
+</tr>
+</table>
+<hr/>
+<a name="issues"><h2 align="center">Closed Issues</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p>
+<h3>Category: Addons/General</h3><br/>
+<a href="http://bugs.digium.com/view.php?id=14701">#14701</a>: [patch] missing DESTDIR in addons install-xmldoc<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=827">827</a><br/>
+Reporter: tzafrir<br/>
+Coders: eliel<br/>
+<br/>
+<h3>Category: Addons/cdr_addon_mysql</h3><br/>
+<a href="http://bugs.digium.com/view.php?id=13775">#13775</a>: [patch] New option to specify mysql charset<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=709">709</a><br/>
+Reporter: sergee<br/>
+Coders: sergee<br/>
+<br/>
+<a href="http://bugs.digium.com/view.php?id=14229">#14229</a>: [patch] Asterisk exits when trying to load cdr_addon_mysql.so<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=724">724</a><br/>
+Reporter: sergee<br/>
+Coders: sergee<br/>
+<br/>
+<h3>Category: Addons/chan_mobile</h3><br/>
+<a href="http://bugs.digium.com/view.php?id=13744">#13744</a>: Blackberry Pearl (8100) rarely initialises<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=728">728</a><br/>
+Reporter: ciaranm<br/>
+Testers: ciaranm, davidste, mnicholson, jongerenchaos<br/>
+Coders: mnicholson<br/>
+<br/>
+<h3>Category: Addons/chan_ooh323</h3><br/>
+<a href="http://bugs.digium.com/view.php?id=14116">#14116</a>: [patch] wrong phtread_mutex_init<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=717">717</a><br/>
+Reporter: junky<br/>
+Coders: junky<br/>
+<br/>
+<hr/>
+<a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all changes that went into this release that did not directly close an issue from the issue tracker. The commits may have been marked as being related to an issue. If that is the case, the issue numbers are listed here, as well.</p>
+<table width="100%" border="1">
+<tr><td><b>Revision</b></td><td><b>Author</b></td><td><b>Summary</b></td><td><b>Issues Referenced</b></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=691">691</a></td><td>tilghman</td><td>Since the API can potentially change in 1.6.x, we need an -addons to match for Asterisk 1.6.1</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=692">692</a></td><td>tilghman</td><td>Remove portions of API that aren't in Asterisk-1.6.1</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=693">693</a></td><td>tilghman</td><td>Revert XML in this branch, since the XML isn't in Asterisk-1.6.1</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=705">705</a></td><td>tilghman</td><td>Initialized merge tracking via "svnmerge" with revisions "1-690" from</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=712">712</a></td><td>tilghman</td><td>Convert addons to use ast_str opacity, fixing some bugs along the way.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=721">721</a></td><td>tilghman</td><td>Prevent a possible race between a reload event and logging a CDR</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=732">732</a></td><td>mnicholson</td><td>Fixed a typo in configs/mobile.conf.sample, found by mmichelson</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=788">788</a></td><td>tilghman</td><td>Only add the column if the value is non-NULL.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk-addons/branches/1.6.1?view=revision&revision=889">889</a></td><td>kpfleming</td><td>Incorporate autoconf 2.63 related fixes to configure script</td>
+<td></td></tr></table>
+<hr/>
+<a name="diffstat"><h2 align="center">Diffstat Results</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p>
+<pre>
+UPGRADE.txt | 7
+acinclude.m4 | 16
+aclocal.m4 | 2
+cdr/cdr_addon_mysql.c | 63 ++
+channels/chan_mobile.c | 53 +-
+channels/ooh323c/src/ooCmdChannel.c | 2
+configs/cdr_mysql.conf.sample | 5
+configs/mobile.conf.sample | 8
+configs/res_mysql.conf.sample | 33 -
+res/res_config_mysql.c | 855 +++++++++++++++++++-----------------
+10 files changed, 597 insertions(+), 447 deletions(-)
+</pre><br/>
+<hr/>
+</body>
+</html>
|
[-]
[+]
|
Added |
asterisk-addons-1.6.1.0.tar.bz2/asterisk-addons-1.6.1.0-summary.txt
^
|
@@ -0,0 +1,169 @@
+ Release Summary
+
+ asterisk-addons-1.6.1.0
+
+ Date: 2009-04-28
+
+ <asteriskteam@digium.com>
+
+ ----------------------------------------------------------------------
+
+ Table of Contents
+
+ 1. Summary
+ 2. Contributors
+ 3. Closed Issues
+ 4. Other Changes
+ 5. Diffstat
+
+ ----------------------------------------------------------------------
+
+ Summary
+
+ [Back to Top]
+
+ This release includes new features. For a list of new features that have
+ been included with this release, please see the CHANGES file inside the
+ source package. Since this is new major release, users are encouraged to
+ do extended testing before upgrading to this version in a production
+ environment.
+
+ The data in this summary reflects changes that have been made since the
+ previous release, asterisk-addons-1.6.0.
+
+ ----------------------------------------------------------------------
+
+ Contributors
+
+ [Back to Top]
+
+ This table lists the people who have submitted code, those that have
+ tested patches, as well as those that reported issues on the issue tracker
+ that were resolved in this release. For coders, the number is how many of
+ their patches (of any size) were committed into this release. For testers,
+ the number is the number of times their name was listed as assisting with
+ testing a patch. Finally, for reporters, the number is the number of
+ issues that they reported that were closed by commits that went into this
+ release.
+
+ Coders Testers Reporters
+ 7 tilghman 1 ciaranm 2 sergee
+ 2 mnicholson 1 davidste 1 ciaranm
+ 2 sergee 1 jongerenchaos 1 junky
+ 1 eliel 1 mnicholson 1 tzafrir
+ 1 junky
+ 1 kpfleming
+
+ ----------------------------------------------------------------------
+
+ Closed Issues
+
+ [Back to Top]
+
+ This is a list of all issues from the issue tracker that were closed by
+ changes that went into this release.
+
+ Category: Addons/General
+
+ #14701: [patch] missing DESTDIR in addons install-xmldoc
+ Revision: 827
+ Reporter: tzafrir
+ Coders: eliel
+
+ Category: Addons/cdr_addon_mysql
+
+ #13775: [patch] New option to specify mysql charset
+ Revision: 709
+ Reporter: sergee
+ Coders: sergee
+
+ #14229: [patch] Asterisk exits when trying to load cdr_addon_mysql.so
+ Revision: 724
+ Reporter: sergee
+ Coders: sergee
+
+ Category: Addons/chan_mobile
+
+ #13744: Blackberry Pearl (8100) rarely initialises
+ Revision: 728
+ Reporter: ciaranm
+ Testers: ciaranm, davidste, mnicholson, jongerenchaos
+ Coders: mnicholson
+
+ Category: Addons/chan_ooh323
+
+ #14116: [patch] wrong phtread_mutex_init
+ Revision: 717
+ Reporter: junky
+ Coders: junky
+
+ ----------------------------------------------------------------------
+
+ Commits Not Associated with an Issue
+
+ [Back to Top]
+
+ This is a list of all changes that went into this release that did not
+ directly close an issue from the issue tracker. The commits may have been
+ marked as being related to an issue. If that is the case, the issue
+ numbers are listed here, as well.
+
+ +------------------------------------------------------------------------+
+ | Revision | Author | Summary | Issues |
+ | | | | Referenced |
+ |----------+------------+-----------------------------------+------------|
+ | | | Since the API can potentially | |
+ | 691 | tilghman | change in 1.6.x, we need an | |
+ | | | -addons to match for Asterisk | |
+ | | | 1.6.1 | |
+ |----------+------------+-----------------------------------+------------|
+ | 692 | tilghman | Remove portions of API that | |
+ | | | aren't in Asterisk-1.6.1 | |
+ |----------+------------+-----------------------------------+------------|
+ | 693 | tilghman | Revert XML in this branch, since | |
+ | | | the XML isn't in Asterisk-1.6.1 | |
+ |----------+------------+-----------------------------------+------------|
+ | | | Initialized merge tracking via | |
+ | 705 | tilghman | "svnmerge" with revisions "1-690" | |
+ | | | from | |
+ |----------+------------+-----------------------------------+------------|
+ | | | Convert addons to use ast_str | |
+ | 712 | tilghman | opacity, fixing some bugs along | |
+ | | | the way. | |
+ |----------+------------+-----------------------------------+------------|
+ | 721 | tilghman | Prevent a possible race between a | |
+ | | | reload event and logging a CDR | |
+ |----------+------------+-----------------------------------+------------|
+ | | | Fixed a typo in | |
+ | 732 | mnicholson | configs/mobile.conf.sample, found | |
+ | | | by mmichelson | |
+ |----------+------------+-----------------------------------+------------|
+ | 788 | tilghman | Only add the column if the value | |
+ | | | is non-NULL. | |
+ |----------+------------+-----------------------------------+------------|
+ | 889 | kpfleming | Incorporate autoconf 2.63 related | |
+ | | | fixes to configure script | |
+ +------------------------------------------------------------------------+
+
+ ----------------------------------------------------------------------
+
+ Diffstat Results
+
+ [Back to Top]
+
+ This is a summary of the changes to the source code that went into this
+ release that was generated using the diffstat utility.
+
+ UPGRADE.txt | 7
+ acinclude.m4 | 16
+ aclocal.m4 | 2
+ cdr/cdr_addon_mysql.c | 63 ++
+ channels/chan_mobile.c | 53 +-
+ channels/ooh323c/src/ooCmdChannel.c | 2
+ configs/cdr_mysql.conf.sample | 5
+ configs/mobile.conf.sample | 8
+ configs/res_mysql.conf.sample | 33 -
+ res/res_config_mysql.c | 855 +++++++++++++++++++-----------------
+ 10 files changed, 597 insertions(+), 447 deletions(-)
+
+ ----------------------------------------------------------------------
|
[-]
[+]
|
Added |
asterisk-addons-1.6.1.0.tar.bz2/build_tools/get_documentation
^
|
@@ -0,0 +1,3 @@
+/\/\*\*\* DOCUMENTATION/ {printit=1; next}
+/\*\*\*\// {if (printit) exit}
+// {if (printit) print}
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/cdr/cdr_addon_mysql.c
^
|
@@ -59,7 +59,7 @@
static char *name = "mysql";
static char *config = "cdr_mysql.conf";
-static struct ast_str *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *dbsock = NULL, *dbtable = NULL;
+static struct ast_str *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *dbsock = NULL, *dbtable = NULL, *dbcharset = NULL;
static struct ast_str *ssl_ca = NULL, *ssl_cert = NULL, *ssl_key = NULL;
@@ -185,6 +185,11 @@
connected = 1;
connect_time = time(NULL);
records = 0;
+ if (dbcharset) {
+ snprintf(sql1, sizeof(sql1), "SET NAMES '%s'", dbcharset->str);
+ mysql_real_query(&mysql, sql1, strlen(sql1));
+ ast_debug(1, "SQL command as follows: %s\n", sql1);
+ }
} else {
ast_log(LOG_ERROR, "Cannot connect to database server %s: (%d) %s\n", hostname->str, mysql_errno(&mysql), mysql_error(&mysql));
connected = 0;
@@ -247,11 +252,6 @@
}
/* Construct SQL */
- if (column_count++) {
- strcat(sql1, ",");
- strcat(sql2, "','");
- }
-
if (strlen(sql1) + 2 + strlen(entry->name) > sql1size) {
char *tmp = ast_realloc(sql1, sql1size * 2);
if (!tmp)
@@ -259,7 +259,6 @@
sql1size *= 2;
sql1 = tmp;
}
- strcat(sql1, entry->name);
/* Need the type and value to determine if we want the raw value or not */
if ((!strcmp(cdrname, "start") ||
@@ -286,6 +285,13 @@
sql2 = tmp;
}
if (value) {
+ if (column_count++) {
+ strcat(sql1, ",");
+ strcat(sql2, "','");
+ }
+
+ strcat(sql1, entry->name);
+
/*!\note We're manually escaping here, to ensure that we know exactly
* how much space is used. Since we only accept ASCII strings at this
* point in time, there is no danger in this simplistic escape method,
@@ -332,7 +338,7 @@
return 0;
}
-static int my_unload_module(void)
+static int my_unload_module(int reload)
{
struct unload_string *us;
struct column *entry;
@@ -352,11 +358,15 @@
}
AST_LIST_UNLOCK(&unload_strings);
- AST_RWLIST_WRLOCK(&columns);
+ if (!reload) {
+ AST_RWLIST_WRLOCK(&columns);
+ }
while ((entry = AST_RWLIST_REMOVE_HEAD(&columns, list))) {
ast_free(entry);
}
- AST_RWLIST_UNLOCK(&columns);
+ if (!reload) {
+ AST_RWLIST_UNLOCK(&columns);
+ }
dbport = 0;
ast_cdr_unregister(name);
@@ -425,24 +435,31 @@
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
return AST_MODULE_LOAD_SUCCESS;
- if (reload)
- my_unload_module();
+ if (reload) {
+ AST_RWLIST_WRLOCK(&columns);
+ my_unload_module(1);
+ }
var = ast_variable_browse(cfg, "global");
if (!var) {
/* nothing configured */
+ if (reload) {
+ AST_RWLIST_UNLOCK(&columns);
+ }
return AST_MODULE_LOAD_SUCCESS;
}
res = 0;
- res |= my_load_config_string(cfg, "global", "hostname", &hostname, "localhost");
+ res |= my_load_config_string(cfg, "global", "hostname", &hostname, "localhost");
res |= my_load_config_string(cfg, "global", "dbname", &dbname, "astriskcdrdb");
res |= my_load_config_string(cfg, "global", "user", &dbuser, "root");
res |= my_load_config_string(cfg, "global", "sock", &dbsock, "");
res |= my_load_config_string(cfg, "global", "table", &dbtable, "cdr");
res |= my_load_config_string(cfg, "global", "password", &password, "");
+ res |= my_load_config_string(cfg, "global", "charset", &dbcharset, "");
+
res |= my_load_config_string(cfg, "global", "ssl_ca", &ssl_ca, "");
res |= my_load_config_string(cfg, "global", "ssl_cert", &ssl_cert, "");
res |= my_load_config_string(cfg, "global", "ssl_key", &ssl_key, "");
@@ -456,11 +473,18 @@
calldate_compat = 0;
}
- if (res < 0)
+ if (res < 0) {
+ if (reload) {
+ AST_RWLIST_UNLOCK(&columns);
+ }
return AST_MODULE_LOAD_FAILURE;
+ }
/* Check for any aliases */
- AST_RWLIST_WRLOCK(&columns);
+ if (!reload) {
+ /* Lock, if not already */
+ AST_RWLIST_WRLOCK(&columns);
+ }
while ((entry = AST_LIST_REMOVE_HEAD(&columns, list))) {
ast_free(entry);
}
@@ -475,6 +499,10 @@
ast_debug(1, "Got password of %s\n", password->str);
ast_debug(1, "%sunning in calldate compatibility mode\n", calldate_compat ? "R" : "Not r");
+ if (dbcharset) {
+ ast_debug(1, "Got DB charste of %s\n", dbcharset->str);
+ }
+
mysql_init(&mysql);
if (timeout && mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout) != 0) {
@@ -501,6 +529,11 @@
connected = 1;
records = 0;
connect_time = time(NULL);
+ if (dbcharset) {
+ snprintf(sqldesc, sizeof(sqldesc), "SET NAMES '%s'", dbcharset->str);
+ mysql_real_query(&mysql, sqldesc, strlen(sqldesc));
+ ast_debug(1, "SQL command as follows: %s\n", sqldesc);
+ }
/* Get table description */
snprintf(sqldesc, sizeof(sqldesc), "DESC %s", dbtable ? dbtable->str : "cdr");
@@ -583,14 +616,14 @@
static int unload_module(void)
{
- return my_unload_module();
+ return my_unload_module(0);
}
static int reload(void)
{
int ret;
- ast_mutex_lock(&mysql_lock);
+ ast_mutex_lock(&mysql_lock);
ret = my_load_module(1);
ast_mutex_unlock(&mysql_lock);
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/channels/chan_mobile.c
^
|
@@ -31,7 +31,7 @@
#include <asterisk.h>
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 584 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 728 $")
#include <stdio.h>
#include <string.h>
@@ -123,7 +123,7 @@
AST_LIST_ENTRY(adapter_pvt) entry;
};
-static AST_LIST_HEAD_STATIC(adapters, adapter_pvt);
+static AST_RWLIST_HEAD_STATIC(adapters, adapter_pvt);
struct mbl_pvt {
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
@@ -160,6 +160,7 @@
unsigned int do_alignment_detection:1;
unsigned int alignment_detection_triggered:1;
unsigned int do_hangup:1;
+ unsigned int blackberry:1;
short alignment_samples[4];
int alignment_count;
char sms_txt[160];
@@ -171,7 +172,7 @@
AST_LIST_ENTRY(mbl_pvt) entry;
};
-static AST_LIST_HEAD_STATIC(devices, mbl_pvt);
+static AST_RWLIST_HEAD_STATIC(devices, mbl_pvt);
/* CLI stuff */
static char *handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
@@ -267,13 +268,15 @@
return CLI_SHOWUSAGE;
ast_cli(a->fd, FORMAT1, "ID", "Address", "Group", "Adapter", "Connected", "State", "SMS");
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
ba2str(&pvt->addr, bdaddr);
snprintf(group, 5, "%d", pvt->group);
ast_cli(a->fd, FORMAT1, pvt->id, bdaddr, group, pvt->adapter->id, pvt->connected ? "Yes" : "No",
(pvt->state == MBL_STATE_IDLE) ? "Free" : (pvt->state < MBL_STATE_IDLE) ? "Init" : "Busy",
(pvt->has_sms) ? "Yes" : "No");
}
+ AST_RWLIST_UNLOCK(&devices);
#undef FORMAT1
@@ -308,10 +311,12 @@
return CLI_SHOWUSAGE;
/* find a free adapter */
- AST_LIST_TRAVERSE(&adapters, adapter, entry) {
+ AST_RWLIST_RDLOCK(&adapters);
+ AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
if (!adapter->inuse)
break;
}
+ AST_RWLIST_UNLOCK(&adapters);
if (!adapter) {
ast_cli(a->fd, "All Bluetooth adapters are in use at this time.\n");
@@ -368,10 +373,12 @@
if (a->argc != 4)
return CLI_SHOWUSAGE;
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!strcmp(pvt->id, a->argv[2]))
break;
}
+ AST_RWLIST_UNLOCK(&devices);
if (!pvt || !pvt->connected) {
ast_cli(a->fd, "Device %s not found.\n", a->argv[2]);
@@ -415,10 +422,12 @@
stat = 1;
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!strcmp(pvt->id, args.device))
break;
}
+ AST_RWLIST_UNLOCK(&devices);
if (pvt) {
if (pvt->connected)
@@ -468,10 +477,12 @@
return -1;
}
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!strcmp(pvt->id, args.device))
break;
}
+ AST_RWLIST_UNLOCK(&devices);
if (!pvt) {
ast_log(LOG_ERROR,"Bluetooth device %s wasn't found in the list -- SMS will not be sent.\n", args.device);
@@ -558,7 +569,7 @@
struct mbl_pvt *pvt;
char *dest_dev = NULL;
char *dest_num = NULL;
- int oldformat, group;
+ int oldformat, group = -1;
if (!data) {
ast_log(LOG_WARNING, "Channel requested with no data\n");
@@ -580,16 +591,20 @@
if (dest_num)
*dest_num++ = 0x00;
- /* Find requested device and make sure its connected. */
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
- if (((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) && ((dest_dev[1] >= '0') && (dest_dev[1] <= '9'))) {
- group = atoi(dest_dev+1);
- if (pvt->group == group)
- break;
+ if (((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) && ((dest_dev[1] >= '0') && (dest_dev[1] <= '9'))) {
+ group = atoi(&dest_dev[1]);
+ }
+
+ /* Find requested device and make sure it's connected. */
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
+ if (group > -1 && pvt->group == group && pvt->connected && !pvt->owner) {
+ break;
} else if (!strcmp(pvt->id, dest_dev)) {
break;
}
}
+ AST_RWLIST_UNLOCK(&devices);
if (!pvt || !pvt->connected || pvt->owner) {
ast_log(LOG_WARNING, "Request to call on device %s which is not connected / already in use.\n", dest_dev);
*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
@@ -597,14 +612,14 @@
}
if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
- ast_log(LOG_WARNING, "Cant determine destination number.\n");
+ ast_log(LOG_WARNING, "Can't determine destination number.\n");
*cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
return NULL;
}
chn = mbl_new(AST_STATE_DOWN, pvt, NULL);
if (!chn) {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ ast_log(LOG_WARNING, "Unable to allocate channel structure.\n");
*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
return NULL;
}
@@ -775,9 +790,9 @@
pvt->fr.mallocd = 0;
pvt->fr.delivery.tv_sec = 0;
pvt->fr.delivery.tv_usec = 0;
- pvt->fr.data = pvt->io_buf + AST_FRIENDLY_OFFSET;
+ pvt->fr.data.ptr = pvt->io_buf + AST_FRIENDLY_OFFSET;
- if ((r = read(pvt->io_pipe[0], pvt->fr.data, CHANNEL_FRAME_SIZE)) != CHANNEL_FRAME_SIZE) {
+ if ((r = read(pvt->io_pipe[0], pvt->fr.data.ptr, CHANNEL_FRAME_SIZE)) != CHANNEL_FRAME_SIZE) {
if (r == -1) {
ast_log(LOG_ERROR, "read error %d\n", errno);
return &ast_null_frame;
@@ -813,7 +828,7 @@
io_need = 0;
if (pvt->io_save_len > 0) {
io_need = DEVICE_FRAME_SIZE - pvt->io_save_len;
- memcpy(pvt->io_save_buf + pvt->io_save_len, frame->data, io_need);
+ memcpy(pvt->io_save_buf + pvt->io_save_len, frame->data.ptr, io_need);
sco_write(pvt->sco_socket, pvt->io_save_buf, DEVICE_FRAME_SIZE);
if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE))) {
if (pvt->do_alignment_detection)
@@ -824,7 +839,7 @@
}
num_frames = (frame->datalen - io_need) / DEVICE_FRAME_SIZE;
- pfr = frame->data + io_need;
+ pfr = frame->data.ptr + io_need;
for (i=0; i<num_frames; i++) {
sco_write(pvt->sco_socket, pfr, DEVICE_FRAME_SIZE);
@@ -869,10 +884,12 @@
ast_debug(1, "Checking device state for device %s\n", device);
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!strcmp(pvt->id, device))
break;
}
+ AST_RWLIST_UNLOCK(&devices);
if (pvt) {
if (pvt->connected) {
@@ -1334,8 +1351,13 @@
pvt->state++;
nsmode = 1;
} else if (strstr(buf, "OK") && brsf) {
- rfcomm_write(pvt, "AT+CIND=?\r");
- pvt->state++;
+ if (pvt->blackberry) {
+ rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
+ pvt->state = MBL_STATE_INIT3;
+ } else {
+ rfcomm_write(pvt, "AT+CIND=?\r");
+ pvt->state++;
+ }
}
break;
case MBL_STATE_INIT1:
@@ -1380,14 +1402,24 @@
monitor = 0;
}
} else if (strstr(buf, "OK")) {
- rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
- pvt->state++;
+ if (pvt->blackberry) {
+ rfcomm_write(pvt, "AT+CLIP=1\r");
+ pvt->state = MBL_STATE_INIT4;
+ } else {
+ rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
+ pvt->state++;
+ }
}
break;
case MBL_STATE_INIT3:
if (strstr(buf, "OK")) {
- rfcomm_write(pvt, "AT+CLIP=1\r");
- pvt->state++;
+ if (pvt->blackberry) {
+ rfcomm_write(pvt, "AT+CIND=?\r");
+ pvt->state = MBL_STATE_INIT1;
+ } else {
+ rfcomm_write(pvt, "AT+CLIP=1\r");
+ pvt->state++;
+ }
}
break;
case MBL_STATE_INIT4:
@@ -1771,9 +1803,11 @@
struct mbl_pvt *pvt;
for (;;) {
- AST_LIST_TRAVERSE(&adapters, adapter, entry) {
+ AST_RWLIST_RDLOCK(&adapters);
+ AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
if (!adapter->inuse) {
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!adapter->inuse && !pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
pvt->state = 0;
@@ -1787,8 +1821,10 @@
}
}
}
+ AST_RWLIST_UNLOCK(&devices);
}
}
+ AST_RWLIST_UNLOCK(&adapters);
/* Go to sleep */
sleep(discovery_interval);
}
@@ -1843,10 +1879,12 @@
ast_debug(1, "Incoming Audio Connection from device %s MTU is %d\n", saddr, so.mtu);
pvt = NULL;
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ AST_RWLIST_RDLOCK(&devices);
+ AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
if (!bacmp(&pvt->addr, &addr.sco_bdaddr))
break;
}
+ AST_RWLIST_UNLOCK(&devices);
if (pvt) {
if (pvt->sco_socket != -1)
close(pvt->sco_socket);
@@ -1874,7 +1912,7 @@
struct ast_config *cfg = NULL;
char *cat = NULL;
struct ast_variable *var;
- const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master, *nocallsetup, *aligndetect;
+ const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master, *nocallsetup, *aligndetect, *blackberry;
struct mbl_pvt *pvt;
struct adapter_pvt *adapter;
uint16_t vs;
@@ -1929,7 +1967,9 @@
hci_close_dev(adapter->hci_socket);
ast_free(adapter);
} else {
- AST_LIST_INSERT_HEAD(&adapters, adapter, entry);
+ AST_RWLIST_WRLOCK(&adapters);
+ AST_RWLIST_INSERT_HEAD(&adapters, adapter, entry);
+ AST_RWLIST_UNLOCK(&adapters);
nadapters++;
}
}
@@ -1959,12 +1999,15 @@
skip = ast_variable_retrieve(cfg, cat, "dtmfskip");
group = ast_variable_retrieve(cfg, cat, "group");
nocallsetup = ast_variable_retrieve(cfg, cat, "nocallsetup");
+ blackberry = ast_variable_retrieve(cfg, cat, "blackberry");
if (!ast_strlen_zero(address) && !ast_strlen_zero(port) && !ast_strlen_zero(useadapter)) {
/* find the adapter */
- AST_LIST_TRAVERSE(&adapters, adapter, entry) {
+ AST_RWLIST_RDLOCK(&adapters);
+ AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
if (!strcmp(adapter->id, useadapter))
break;
}
+ AST_RWLIST_UNLOCK(&adapters);
if (!adapter) {
ast_log(LOG_ERROR, "Device %s configured to use unknown adapter %s. It won't be enabled.\n", cat, useadapter);
break;
@@ -1974,6 +2017,10 @@
pvt->type = MBL_TYPE_HEADSET;
else
pvt->type = MBL_TYPE_PHONE;
+
+ if (blackberry)
+ pvt->blackberry = ast_true(blackberry);
+
ast_copy_string(pvt->id, cat, sizeof(pvt->id));
str2ba(address, &pvt->addr);
ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
@@ -1997,10 +2044,12 @@
pvt->dtmf_skip = 200;
} else
pvt->dtmf_skip = 200;
- ast_dsp_set_features(pvt->dsp, DSP_FEATURE_DTMF_DETECT);
- ast_dsp_digitmode(pvt->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
+ ast_dsp_set_features(pvt->dsp, DSP_FEATURE_DIGIT_DETECT);
+ ast_dsp_set_digitmode(pvt->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
pvt->adapter = adapter;
- AST_LIST_INSERT_HEAD(&devices, pvt, entry);
+ AST_RWLIST_WRLOCK(&devices);
+ AST_RWLIST_INSERT_HEAD(&devices, pvt, entry);
+ AST_RWLIST_UNLOCK(&devices);
}
} else {
ast_log(LOG_ERROR, "Device %s has no address/port/adapter configured. It won't be enabled.\n", cat);
@@ -2031,7 +2080,8 @@
}
/* Destroy the device list */
- while ((pvt = AST_LIST_REMOVE_HEAD(&devices, entry))) {
+ AST_RWLIST_WRLOCK(&devices);
+ while ((pvt = AST_RWLIST_REMOVE_HEAD(&devices, entry))) {
if (pvt->monitor_thread != AST_PTHREADT_NULL) {
pthread_cancel(pvt->monitor_thread);
pthread_join(pvt->monitor_thread, NULL);
@@ -2052,12 +2102,15 @@
ast_dsp_free(pvt->dsp);
ast_free(pvt);
}
+ AST_RWLIST_UNLOCK(&devices);
/* Destroy the adapter list */
- while ((adapter = AST_LIST_REMOVE_HEAD(&adapters, entry))) {
+ AST_RWLIST_WRLOCK(&adapters);
+ while ((adapter = AST_RWLIST_REMOVE_HEAD(&adapters, entry))) {
hci_close_dev(adapter->hci_socket);
ast_free(adapter);
}
+ AST_RWLIST_UNLOCK(&adapters);
if (sdp_session)
sdp_close(sdp_session);
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/channels/chan_ooh323.c
^
|
@@ -50,8 +50,7 @@
static struct ast_frame *ooh323_read(struct ast_channel *ast);
static int ooh323_write(struct ast_channel *ast, struct ast_frame *f);
static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
-static int ooh323_fixup
- (struct ast_channel *oldchan, struct ast_channel *newchan);
+static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
@@ -65,68 +64,68 @@
#endif
static const struct ast_channel_tech ooh323_tech = {
- .type = type,
- .description = tdesc,
- .capabilities = -1,
- .requester = ooh323_request,
- .send_digit_begin = ooh323_digit_begin,
- .send_digit_end = ooh323_digit_end,
- .call = ooh323_call,
- .hangup = ooh323_hangup,
- .answer = ooh323_answer,
- .read = ooh323_read,
- .write = ooh323_write,
- .exception = ooh323_read,
- .indicate = ooh323_indicate,
- .fixup = ooh323_fixup,
- .send_html = 0,
- .bridge = ast_rtp_bridge,
+ .type = type,
+ .description = tdesc,
+ .capabilities = -1,
+ .requester = ooh323_request,
+ .send_digit_begin = ooh323_digit_begin,
+ .send_digit_end = ooh323_digit_end,
+ .call = ooh323_call,
+ .hangup = ooh323_hangup,
+ .answer = ooh323_answer,
+ .read = ooh323_read,
+ .write = ooh323_write,
+ .exception = ooh323_read,
+ .indicate = ooh323_indicate,
+ .fixup = ooh323_fixup,
+ .send_html = 0,
+ .bridge = ast_rtp_bridge,
};
static struct ast_rtp_protocol ooh323_rtp = {
- .type = type,
- .get_rtp_info = ooh323_get_rtp_peer,
- .get_vrtp_info = ooh323_get_vrtp_peer,
- .set_rtp_peer = ooh323_set_rtp_peer
+ .type = type,
+ .get_rtp_info = ooh323_get_rtp_peer,
+ .get_vrtp_info = ooh323_get_vrtp_peer,
+ .set_rtp_peer = ooh323_set_rtp_peer
};
/* H.323 channel private structure */
static struct ooh323_pvt {
- ast_mutex_t lock; /* Channel private lock */
- struct ast_rtp *rtp;
- struct ast_rtp *vrtp; /* Placeholder for now */
- struct ast_channel *owner; /* Master Channel */
- time_t lastrtptx;
- time_t lastrtprx;
- unsigned int flags;
- unsigned int call_reference;
- char *callToken;
- char *username;
- char *host;
- char *callerid_name;
- char *callerid_num;
- char caller_h323id[AST_MAX_EXTENSION];
- char caller_dialedDigits[AST_MAX_EXTENSION];
- char caller_email[AST_MAX_EXTENSION];
- char caller_url[256];
- char callee_h323id[AST_MAX_EXTENSION];
- char callee_dialedDigits[AST_MAX_EXTENSION];
- char callee_email[AST_MAX_EXTENSION];
- char callee_url[AST_MAX_EXTENSION];
+ ast_mutex_t lock; /* Channel private lock */
+ struct ast_rtp *rtp;
+ struct ast_rtp *vrtp; /* Placeholder for now */
+ struct ast_channel *owner; /* Master Channel */
+ time_t lastrtptx;
+ time_t lastrtprx;
+ unsigned int flags;
+ unsigned int call_reference;
+ char *callToken;
+ char *username;
+ char *host;
+ char *callerid_name;
+ char *callerid_num;
+ char caller_h323id[AST_MAX_EXTENSION];
+ char caller_dialedDigits[AST_MAX_EXTENSION];
+ char caller_email[AST_MAX_EXTENSION];
+ char caller_url[256];
+ char callee_h323id[AST_MAX_EXTENSION];
+ char callee_dialedDigits[AST_MAX_EXTENSION];
+ char callee_email[AST_MAX_EXTENSION];
+ char callee_url[AST_MAX_EXTENSION];
- int port;
- int readformat; /* negotiated read format */
- int writeformat; /* negotiated write format */
- int capability;
- struct ast_codec_pref prefs;
- int dtmfmode;
- char exten[AST_MAX_EXTENSION]; /* Requested extension */
- char context[AST_MAX_EXTENSION]; /* Context where to start */
- char accountcode[256]; /* Account code */
- int nat;
- int amaflags;
- struct ast_dsp *vad;
- struct ooh323_pvt *next; /* Next entity */
+ int port;
+ int readformat; /* negotiated read format */
+ int writeformat; /* negotiated write format */
+ int capability;
+ struct ast_codec_pref prefs;
+ int dtmfmode;
+ char exten[AST_MAX_EXTENSION]; /* Requested extension */
+ char context[AST_MAX_EXTENSION]; /* Context where to start */
+ char accountcode[256]; /* Account code */
+ int nat;
+ int amaflags;
+ struct ast_dsp *vad;
+ struct ooh323_pvt *next; /* Next entity */
} *iflist = NULL;
/* Protect the channel/interface list (ooh323_pvt) */
@@ -134,62 +133,62 @@
/* 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;
- int capability;
- struct ast_codec_pref prefs;
- int dtmfmode;
- int rtptimeout;
- int mUseIP; /* Use IP address or H323-ID to search user */
- char mIP[20];
- struct ooh323_user *next;
+ ast_mutex_t lock;
+ char name[256];
+ char context[AST_MAX_EXTENSION];
+ int incominglimit;
+ unsigned inUse;
+ char accountcode[20];
+ int amaflags;
+ int capability;
+ struct ast_codec_pref prefs;
+ int dtmfmode;
+ int rtptimeout;
+ int mUseIP; /* Use IP address or H323-ID to search user */
+ char mIP[20];
+ struct ooh323_user *next;
};
/* Profile of valid asterisk peers */
struct ooh323_peer{
- ast_mutex_t lock;
- char name[256];
- unsigned outgoinglimit;
- unsigned outUse;
- int capability;
- struct ast_codec_pref prefs;
- char accountcode[20];
- int amaflags;
- int dtmfmode;
- int mFriend; /* indicates defined as friend */
- char ip[20];
- int port;
- char *h323id; /* H323-ID alias, which asterisk will register with gk to reach this peer*/
- char *email; /* Email alias, which asterisk will register with gk to reach this peer*/
- char *url; /* url alias, which asterisk will register with gk to reach this peer*/
- char *e164; /* e164 alias, which asterisk will register with gk to reach this peer*/
- int rtptimeout;
- struct ooh323_peer *next;
+ ast_mutex_t lock;
+ char name[256];
+ unsigned outgoinglimit;
+ unsigned outUse;
+ int capability;
+ struct ast_codec_pref prefs;
+ char accountcode[20];
+ int amaflags;
+ int dtmfmode;
+ int mFriend; /* indicates defined as friend */
+ char ip[20];
+ int port;
+ char *h323id; /* H323-ID alias, which asterisk will register with gk to reach this peer*/
+ char *email; /* Email alias, which asterisk will register with gk to reach this peer*/
+ char *url; /* url alias, which asterisk will register with gk to reach this peer*/
+ char *e164; /* e164 alias, which asterisk will register with gk to reach this peer*/
+ int rtptimeout;
+ struct ooh323_peer *next;
};
/* List of H.323 users known to PBX */
static struct ast_user_list {
- struct ooh323_user *users;
- ast_mutex_t lock;
+ struct ooh323_user *users;
+ ast_mutex_t lock;
} userl;
static struct ast_peer_list {
- struct ooh323_peer *peers;
- ast_mutex_t lock;
-}peerl;
+ struct ooh323_peer *peers;
+ ast_mutex_t lock;
+} peerl;
/* Mutex to protect H.323 reload process */
static int h323_reloading = 0;
AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
/* Mutex to protect usage counter */
-static int usecnt =0;
+static int usecnt = 0;
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
AST_MUTEX_DEFINE_STATIC(ooh323c_cmd_lock);
@@ -228,7 +227,7 @@
{
int mTCPPortStart;
int mTCPPortEnd;
-}ooconfig;
+} ooconfig;
/** Asterisk RTP stuff*/
static struct sched_context *sched;
@@ -247,218 +246,181 @@
static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
const char *host)
{
- struct ast_channel *ch = NULL;
- int fmt;
- if(gH323Debug)
- ast_verbose("--- ooh323_new - %s\n", host);
-
-
- /* Don't hold a h323 pvt lock while we allocate a channel */
- ast_mutex_unlock(&i->lock);
- ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, i->accountcode, i->exten, i->context, i->amaflags, "OOH323/%s-%04x", host, rand() & 0xffff);
- ast_mutex_lock(&i->lock);
-
- if(ch)
- {
- ast_channel_lock(ch);
- ch->tech = &ooh323_tech;
-
- ch->nativeformats = i->capability;
-
-
- fmt = ast_best_codec(ch->nativeformats);
-
- ch->fds[0] = ast_rtp_fd(i->rtp);
- ch->fds[1] = ast_rtcp_fd(i->rtp);
-
- if (state == AST_STATE_RING)
- ch->rings = 1;
-
- ch->adsicpe = AST_ADSI_UNAVAILABLE;
- ch->writeformat = fmt;
- ch->rawwriteformat = fmt;
- ch->readformat = fmt;
- ch->rawreadformat = fmt;
- ch->tech_pvt = i;
- i->owner = ch;
-
- /* Allocate dsp for in-band DTMF support */
- if(i->dtmfmode & H323_DTMF_INBAND) {
- i->vad = ast_dsp_new();
- ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
- }
-
- ast_mutex_lock(&usecnt_lock);
- usecnt++;
- ast_mutex_unlock(&usecnt_lock);
-
- /* Notify the module monitors that use count for resource has changed*/
- ast_update_use_count();
-
- strncpy(ch->context, i->context, sizeof(ch->context)-1);
- ch->context[sizeof(ch->context)-1] = '\0';
- strncpy(ch->exten, i->exten, sizeof(ch->exten)-1);
- ch->exten[sizeof(ch->exten)-1] = '\0';
-
- ch->priority = 1;
- if (i->callerid_name)
- {
- ch->cid.cid_name = strdup(i->callerid_name);
- }
- if(i->callerid_num){
-
- ch->cid.cid_num = strdup(i->callerid_num);
- }
-
- if(!ast_test_flag(i, H323_OUTGOING))
- {
-
- if (!ast_strlen_zero(i->caller_h323id)) {
- pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
-
- }
- if (!ast_strlen_zero(i->caller_dialedDigits)) {
- pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS",
- i->caller_dialedDigits);
- }
- if (!ast_strlen_zero(i->caller_email)) {
- pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL",
- i->caller_email);
- }
- if (!ast_strlen_zero(i->caller_url)) {
- pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url);
- }
- }
-
- if (!ast_strlen_zero(i->accountcode))
- ast_string_field_set(ch, accountcode, i->accountcode);
-
- if (i->amaflags)
- ch->amaflags = i->amaflags;
-
- ast_setstate(ch, state);
- if (state != AST_STATE_DOWN) {
- if (ast_pbx_start(ch)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
- ast_channel_unlock(ch);
- ast_hangup(ch);
- ch = NULL;
- }
- }
- } else
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ struct ast_channel *ch = NULL;
+ int fmt;
+ if (gH323Debug)
+ ast_verbose("--- ooh323_new - %s\n", host);
+
+
+ /* Don't hold a h323 pvt lock while we allocate a channel */
+ ast_mutex_unlock(&i->lock);
+ ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, i->accountcode, i->exten, i->context, i->amaflags, "OOH323/%s-%08x", host, i);
+ ast_mutex_lock(&i->lock);
+
+ if (ch) {
+ ast_channel_lock(ch);
+ ch->tech = &ooh323_tech;
+
+ ch->nativeformats = i->capability;
+
+ fmt = ast_best_codec(ch->nativeformats);
+
+ ch->fds[0] = ast_rtp_fd(i->rtp);
+ ch->fds[1] = ast_rtcp_fd(i->rtp);
+
+ if (state == AST_STATE_RING)
+ ch->rings = 1;
+
+ ch->adsicpe = AST_ADSI_UNAVAILABLE;
+ ch->writeformat = fmt;
+ ch->rawwriteformat = fmt;
+ ch->readformat = fmt;
+ ch->rawreadformat = fmt;
+ ch->tech_pvt = i;
+ i->owner = ch;
+
+ /* Allocate dsp for in-band DTMF support */
+ if (i->dtmfmode & H323_DTMF_INBAND) {
+ i->vad = ast_dsp_new();
+ ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
+ }
+
+ ast_mutex_lock(&usecnt_lock);
+ usecnt++;
+ ast_mutex_unlock(&usecnt_lock);
+
+ /* Notify the module monitors that use count for resource has changed*/
+ ast_update_use_count();
+
+ ast_copy_string(ch->context, i->context, sizeof(ch->context));
+ ast_copy_string(ch->exten, i->exten, sizeof(ch->exten));
+
+ ch->priority = 1;
+ if (i->callerid_name) {
+ ch->cid.cid_name = strdup(i->callerid_name);
+ }
+ if (i->callerid_num) {
+ ch->cid.cid_num = strdup(i->callerid_num);
+ }
- if(ch) ast_channel_unlock(ch);
+ if (!ast_test_flag(i, H323_OUTGOING)) {
+
+ if (!ast_strlen_zero(i->caller_h323id)) {
+ pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
+
+ }
+ if (!ast_strlen_zero(i->caller_dialedDigits)) {
+ pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS",
+ i->caller_dialedDigits);
+ }
+ if (!ast_strlen_zero(i->caller_email)) {
+ pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL",
+ i->caller_email);
+ }
+ if (!ast_strlen_zero(i->caller_url)) {
+ pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url);
+ }
+ }
+
+ if (!ast_strlen_zero(i->accountcode))
+ ast_string_field_set(ch, accountcode, i->accountcode);
+
+ if (i->amaflags)
+ ch->amaflags = i->amaflags;
+
+ ast_setstate(ch, state);
+ if (state != AST_STATE_DOWN) {
+ if (ast_pbx_start(ch)) {
+ ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
+ ast_channel_unlock(ch);
+ ast_hangup(ch);
+ ch = NULL;
+ }
+ }
+ } else
+ ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
- if(gH323Debug)
- ast_verbose("+++ h323_new\n");
- return ch;
+ if (ch)
+ ast_channel_unlock(ch);
+
+ if (gH323Debug)
+ ast_verbose("+++ h323_new\n");
+
+ return ch;
}
static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
{
- struct ooh323_pvt *pvt = NULL;
- struct in_addr ipAddr;
- if(gH323Debug)
- ast_verbose("--- ooh323_alloc\n");
-
- pvt = (struct ooh323_pvt*) malloc(sizeof(struct ooh323_pvt));
- if(!pvt)
- {
- ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
- return NULL;
- }
-
- memset(pvt, 0, sizeof(struct ooh323_pvt));
- ast_mutex_init(&pvt->lock);
- ast_mutex_lock(&pvt->lock);
-
-
- pvt->caller_h323id[0]='\0';
- pvt->caller_dialedDigits[0]='\0';
- pvt->caller_email[0]='\0';
- pvt->caller_url[0]='\0';
- pvt->vrtp = NULL;
- pvt->callee_h323id[0]='\0';
- pvt->callee_dialedDigits[0]='\0';
- pvt->callee_email[0] = '\0';
- pvt->callee_url[0] = '\0';
-
- pvt->host = NULL;
- pvt->callToken = NULL;
- pvt->port = 0;
- pvt->vad = NULL;
- pvt->next = NULL;
- pvt->owner = NULL;
- pvt->callerid_name = NULL;
- pvt->callerid_num = NULL;
- pvt->flags = 0;
- if(!inet_aton(gIP, &ipAddr))
- {
- ast_log(LOG_ERROR, "Invalid OOH323 driver ip address\n");
- ast_mutex_unlock(&pvt->lock);
- ast_mutex_destroy(&pvt->lock);
- free(pvt);
- return NULL;
- }
-
-
- pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr);
-
- if (!pvt->rtp)
- {
- ast_log(LOG_WARNING, "Unable to create RTP session: %s\n",
- strerror(errno));
- ast_mutex_unlock(&pvt->lock);
- ast_mutex_destroy(&pvt->lock);
- free(pvt);
- return NULL;
- }
-
- ast_rtp_setqos(pvt->rtp, gTOS, 0, "ooh323");
+ struct ooh323_pvt *pvt = NULL;
+ struct in_addr ipAddr;
+ if (gH323Debug)
+ ast_verbose("--- ooh323_alloc\n");
+
+ if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
+ ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
+ return NULL;
+ }
+ ast_mutex_init(&pvt->lock);
+ ast_mutex_lock(&pvt->lock);
- pvt->call_reference = callref;
- if(callToken)
- pvt->callToken = strdup(callToken);
+ if (!inet_aton(gIP, &ipAddr)) {
+ ast_log(LOG_ERROR, "Invalid OOH323 driver ip address\n");
+ ast_mutex_unlock(&pvt->lock);
+ ast_mutex_destroy(&pvt->lock);
+ free(pvt);
+ return NULL;
+ }
- /* whether to use gk for this call */
- if(gRasGkMode == RasNoGatekeeper)
- OO_SETFLAG(pvt->flags, H323_DISABLEGK);
+ if (!(pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr))) {
+ ast_log(LOG_WARNING, "Unable to create RTP session: %s\n",
+ strerror(errno));
+ ast_mutex_unlock(&pvt->lock);
+ ast_mutex_destroy(&pvt->lock);
+ free(pvt);
+ return NULL;
+ }
+
+ ast_rtp_setqos(pvt->rtp, gTOS, 0, "ooh323");
- pvt->dtmfmode = gDTMFMode;
- strncpy(pvt->context, gContext, sizeof(pvt->context)-1);
- pvt->exten[0]='\0';
- strncpy(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode)-1);
- pvt->amaflags = gAMAFLAGS;
- pvt->capability = gCapability;
- memcpy(&pvt->prefs, &gPrefs, sizeof(struct ast_codec_pref));
+ pvt->call_reference = callref;
+ if (callToken)
+ pvt->callToken = strdup(callToken);
+ /* whether to use gk for this call */
+ if (gRasGkMode == RasNoGatekeeper)
+ OO_SETFLAG(pvt->flags, H323_DISABLEGK);
- ast_mutex_unlock(&pvt->lock);
- /* Add to interface list */
- ast_mutex_lock(&iflock);
- pvt->next = iflist;
- iflist = pvt;
- ast_mutex_unlock(&iflock);
+ pvt->dtmfmode = gDTMFMode;
+ ast_copy_string(pvt->context, gContext, sizeof(pvt->context));
+ ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
+ pvt->amaflags = gAMAFLAGS;
+ pvt->capability = gCapability;
+ memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
+
+ ast_mutex_unlock(&pvt->lock);
+ /* Add to interface list */
+ ast_mutex_lock(&iflock);
+ pvt->next = iflist;
+ iflist = pvt;
+ ast_mutex_unlock(&iflock);
- if(gH323Debug)
- ast_verbose("+++ ooh323_alloc\n");
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_alloc\n");
- return pvt;
+ return pvt;
}
/*
- Possible data values - peername, exten/peername, exten@ip
+ Possible data values - peername, exten/peername, exten@ip
*/
static struct ast_channel *ooh323_request(const char *type, int format,
- void *data, int *cause)
-
+ void *data, int *cause)
{
struct ast_channel *chan = NULL;
struct ooh323_pvt *p = NULL;
@@ -470,658 +432,618 @@
int oldformat;
int port = 0;
- if(gH323Debug)
- ast_verbose("--- ooh323_request - data %s format %s\n", (char*)data,
- ast_getformatname_multiple(formats,512,format) );
-
- oldformat = format;
- format &= AST_FORMAT_AUDIO_MASK;
- if (!format) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format "
- "'%d'\n", format);
- return NULL;
- }
-
- p = ooh323_alloc(0,0); /* Initial callRef is zero */
-
- if(!p)
- {
- ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char*)data);
- return NULL;
- }
- ast_mutex_lock(&p->lock);
-
- /* This is an outgoing call, since ooh323_request is called */
- ast_set_flag(p, H323_OUTGOING);
-
-
- strncpy(tmp, (char*)data, sizeof(tmp)-1);
-
- dest = strchr(tmp, '/');
-
- if(dest)
- {
- *dest = '\0';
- dest++;
- ext = tmp;
- }
- else if((dest = strchr(tmp, '@'))) {
- *dest = '\0';
- dest++;
- ext = tmp;
- }
- else {
- dest = tmp;
- ext = NULL;
- }
-
- /*if((sport = strchr(dest, ':'))) {
- *sport = '\0';
- sport++;
- port = atoi(sport);
- }*/
-
- if(dest) {
- peer = find_peer(dest, port);
- }
- else{
- ast_log(LOG_ERROR, "Destination format is not supported\n");
- return NULL;
- }
-
- if(peer)
- {
- p->username = strdup(peer->name);
- p->host = strdup(peer->ip);
- p->port = peer->port;
- /* Disable gk as we are going to call a known peer*/
- OO_SETFLAG(p->flags, H323_DISABLEGK);
-
- if(ext)
- strncpy(p->exten, ext, sizeof(p->exten)-1);
-
- if(peer->capability & format)
- p->capability = peer->capability & format;
- else{
- p->capability = peer->capability;
- }
- memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
- p->dtmfmode = peer->dtmfmode;
- strncpy(p->accountcode, peer->accountcode, sizeof(p->accountcode)-1);
- p->amaflags = peer->amaflags;
- }
- else {
- p->dtmfmode = gDTMFMode;
- p->capability = gCapability;
-
- memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
- p->username = strdup(dest);
-
-
- p->host = strdup(dest);
- if(port > 0) {
- p->port = port;
- }
- if(ext) {
- strncpy(p->exten, ext, sizeof(p->exten)-1);
- }
- }
-
-
- chan = ooh323_new(p, AST_STATE_DOWN, p->username);
-
- ast_mutex_unlock(&p->lock);
-
- if (!chan)
- {
- ast_mutex_lock(&iflock);
- ooh323_destroy(p);
- ast_mutex_unlock(&iflock);
- }
-
- restart_monitor();
- if(gH323Debug)
- ast_verbose("+++ ooh323_request\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_request - data %s format %s\n", (char*)data,
+ ast_getformatname_multiple(formats,512,format));
+
+ oldformat = format;
+ format &= AST_FORMAT_AUDIO_MASK;
+ if (!format) {
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format "
+ "'%d'\n", format);
+ return NULL;
+ }
+
+ p = ooh323_alloc(0,0); /* Initial callRef is zero */
+
+ if (!p) {
+ ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char*)data);
+ return NULL;
+ }
+ ast_mutex_lock(&p->lock);
+
+ /* This is an outgoing call, since ooh323_request is called */
+ ast_set_flag(p, H323_OUTGOING);
+
+ ast_copy_string(tmp, data, sizeof(data));
+
+ dest = strchr(tmp, '/');
+
+ if (dest) {
+ *dest = '\0';
+ dest++;
+ ext = tmp;
+ } else if ((dest = strchr(tmp, '@'))) {
+ *dest = '\0';
+ dest++;
+ ext = tmp;
+ } else {
+ dest = tmp;
+ ext = NULL;
+ }
+
+#if 0
+ if ((sport = strchr(dest, ':'))) {
+ *sport = '\0';
+ sport++;
+ port = atoi(sport);
+ }
+#endif
+
+ if (dest) {
+ peer = find_peer(dest, port);
+ } else{
+ ast_log(LOG_ERROR, "Destination format is not supported\n");
+ return NULL;
+ }
+
+ if (peer) {
+ p->username = strdup(peer->name);
+ p->host = strdup(peer->ip);
+ p->port = peer->port;
+ /* Disable gk as we are going to call a known peer*/
+ OO_SETFLAG(p->flags, H323_DISABLEGK);
+
+ if (ext)
+ ast_copy_string(p->exten, ext, sizeof(p->exten));
+
+ if (peer->capability & format) {
+ p->capability = peer->capability & format;
+ } else {
+ p->capability = peer->capability;
+ }
+ memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
+ p->dtmfmode = peer->dtmfmode;
+ ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
+ p->amaflags = peer->amaflags;
+ } else {
+ p->dtmfmode = gDTMFMode;
+ p->capability = gCapability;
- return chan;
+ memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
+ p->username = strdup(dest);
+
+ p->host = strdup(dest);
+ if (port > 0) {
+ p->port = port;
+ }
+ if (ext) {
+ ast_copy_string(p->exten, ext, sizeof(p->exten));
+ }
+ }
+
+
+ chan = ooh323_new(p, AST_STATE_DOWN, p->username);
+
+ ast_mutex_unlock(&p->lock);
+
+ if (!chan) {
+ ast_mutex_lock(&iflock);
+ ooh323_destroy(p);
+ ast_mutex_unlock(&iflock);
+ }
+
+ restart_monitor();
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_request\n");
+
+ return chan;
}
static struct ooh323_pvt* find_call(ooCallData *call)
{
- struct ooh323_pvt *p=NULL;
+ struct ooh323_pvt *p;
- if(gH323Debug)
- ast_verbose("--- find_call\n");
+ if (gH323Debug)
+ ast_verbose("--- find_call\n");
- p = iflist;
- ast_mutex_lock(&iflock);
+ ast_mutex_lock(&iflock);
- while(p)
- {
- if(p->callToken && !strcmp(p->callToken, call->callToken))
- {
- break;
- }
- p = p->next;
-
- }
- ast_mutex_unlock(&iflock);
+ for (p = iflist; p; p = p->next) {
+ if (p->callToken && !strcmp(p->callToken, call->callToken)) {
+ break;
+ }
+ }
+ ast_mutex_unlock(&iflock);
- if(gH323Debug)
- ast_verbose("+++ find_call\n");
+ if (gH323Debug)
+ ast_verbose("+++ find_call\n");
- return p;
+ return p;
}
struct ooh323_user *find_user(const char * name, const char* ip)
{
- struct ooh323_user *user=NULL;
+ struct ooh323_user *user;
- if(gH323Debug)
- ast_verbose("--- find_user\n");
+ if (gH323Debug)
+ ast_verbose("--- find_user\n");
- user = userl.users;
- ast_mutex_lock(&userl.lock);
- while(user)
- {
- if(ip && user->mUseIP && !strcmp(user->mIP, ip)) {
- break;
- }
- if(name && !strcmp(user->name, name)) {
- break;
- }
- user = user->next;
- }
- ast_mutex_unlock(&userl.lock);
+ ast_mutex_lock(&userl.lock);
+ for (user = userl.users; user; user = user->next) {
+ if (ip && user->mUseIP && !strcmp(user->mIP, ip)) {
+ break;
+ }
+ if (name && !strcmp(user->name, name)) {
+ break;
+ }
+ }
+ ast_mutex_unlock(&userl.lock);
- if(gH323Debug)
- ast_verbose("+++ find_user\n");
+ if (gH323Debug)
+ ast_verbose("+++ find_user\n");
- return user;
+ return user;
}
struct ooh323_peer *find_friend(const char *name, int port)
{
- struct ooh323_peer *peer=NULL;
+ struct ooh323_peer *peer;
- if(gH323Debug)
- ast_verbose("--- find_friend \"%s\"\n", name);
+ if (gH323Debug)
+ ast_verbose("--- find_friend \"%s\"\n", name);
- peer = peerl.peers;
- ast_mutex_lock(&peerl.lock);
- while(peer)
- {
- if(gH323Debug) {
- ast_verbose(" comparing with \"%s\"\n", peer->ip);
- }
- if(!strcmp(peer->ip, name)) {
- if(port > 0 && peer->port == port) { break; }
- else if (port <= 0) { break; }
- }
- peer = peer->next;
- }
- ast_mutex_unlock(&peerl.lock);
-
- if(gH323Debug) {
- if(peer) {
- ast_verbose(" found matching friend\n");
- }
- ast_verbose("+++ find_friend \"%s\"\n", name);
- }
+ ast_mutex_lock(&peerl.lock);
+ for (peer = peerl.peers; peer; peer = peer->next) {
+ if (gH323Debug) {
+ ast_verbose(" comparing with \"%s\"\n", peer->ip);
+ }
+ if (!strcmp(peer->ip, name)) {
+ if (port <= 0 || (port > 0 && peer->port == port)) {
+ break;
+ }
+ }
+ }
+ ast_mutex_unlock(&peerl.lock);
- return peer;
+ if (gH323Debug) {
+ if (peer) {
+ ast_verbose(" found matching friend\n");
+ }
+ ast_verbose("+++ find_friend \"%s\"\n", name);
+ }
+
+ return peer;
}
struct ooh323_peer *find_peer(const char * name, int port)
{
- struct ooh323_peer *peer=NULL;
+ struct ooh323_peer *peer;
- if(gH323Debug)
- ast_verbose("--- find_peer \"%s\"\n", name);
+ if (gH323Debug)
+ ast_verbose("--- find_peer \"%s\"\n", name);
+ ast_mutex_lock(&peerl.lock);
+ for (peer = peerl.peers; peer; peer = peer->next) {
+ if (gH323Debug) {
+ ast_verbose(" comparing with \"%s\"\n", peer->ip);
+ }
+ if (!strcasecmp(peer->name, name))
+ break;
+ if (peer->h323id && !strcasecmp(peer->h323id, name))
+ break;
+ if (peer->e164 && !strcasecmp(peer->e164, name))
+ break;
+ /*
+ if (!strcmp(peer->ip, name)) {
+ if (port > 0 && peer->port == port) { break; }
+ else if (port <= 0) { break; }
+ }
+ */
+ }
+ ast_mutex_unlock(&peerl.lock);
- peer = peerl.peers;
- ast_mutex_lock(&peerl.lock);
- while(peer)
- {
- if(gH323Debug) {
- ast_verbose(" comparing with \"%s\"\n", peer->ip);
- }
- if(!strcasecmp(peer->name, name))
- break;
- if(peer->h323id && !strcasecmp(peer->h323id, name))
- break;
- if(peer->e164 && !strcasecmp(peer->e164, name))
- break;
- /*
- if(!strcmp(peer->ip, name)) {
- if(port > 0 && peer->port == port) { break; }
- else if (port <= 0) { break; }
- }
- */
- peer = peer->next;
- }
- ast_mutex_unlock(&peerl.lock);
-
- if(gH323Debug) {
- if(peer) {
- ast_verbose(" found matching peer\n");
- }
- ast_verbose("+++ find_peer \"%s\"\n", name);
- }
+ if (gH323Debug) {
+ if (peer) {
+ ast_verbose(" found matching peer\n");
+ }
+ ast_verbose("+++ find_peer \"%s\"\n", name);
+ }
- return peer;
+ return peer;
}
static int ooh323_digit_begin(struct ast_channel *chan, char digit)
{
- char dtmf[2];
- struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
-
- if(gH323Debug)
- ast_verbose("--- ooh323_digit_begin\n");
-
- if(!p){
- ast_log(LOG_ERROR, "No private structure for call\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
- ast_rtp_senddigit_begin(p->rtp, digit);
- }
- else if (((p->dtmfmode & H323_DTMF_Q931) ||
- (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) ||
- (p->dtmfmode & H323_DTMF_H245SIGNAL))){
- dtmf[0]= digit;
- dtmf[1]='\0';
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooSendDTMFDigit(p->callToken, dtmf);
- ast_mutex_unlock(&ooh323c_cmd_lock);
- }
- ast_mutex_unlock(&p->lock);
- if(gH323Debug)
- ast_verbose("+++ ooh323_digit_begin\n");
+ char dtmf[2];
+ struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323_digit_begin\n");
+
+ if (!p) {
+ ast_log(LOG_ERROR, "No private structure for call\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
+ ast_rtp_senddigit_begin(p->rtp, digit);
+ } else if (((p->dtmfmode & H323_DTMF_Q931) ||
+ (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) ||
+ (p->dtmfmode & H323_DTMF_H245SIGNAL))) {
+ dtmf[0] = digit;
+ dtmf[1] = '\0';
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooSendDTMFDigit(p->callToken, dtmf);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+ }
+ ast_mutex_unlock(&p->lock);
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_digit_begin\n");
- return 0;
+ return 0;
}
static int ooh323_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
{
- struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
+ struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
- if(gH323Debug)
- ast_verbose("--- ooh323_digit_end\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_digit_end\n");
- if(!p){
- ast_log(LOG_ERROR, "No private structure for call\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833))
- ast_rtp_senddigit_end(p->rtp, digit);
-
- ast_mutex_unlock(&p->lock);
- if(gH323Debug)
- ast_verbose("+++ ooh323_digit_end\n");
+ if (!p) {
+ ast_log(LOG_ERROR, "No private structure for call\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833))
+ ast_rtp_senddigit_end(p->rtp, digit);
+
+ ast_mutex_unlock(&p->lock);
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_digit_end\n");
- return 0;
+ return 0;
}
static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
{
- struct ooh323_pvt *p = ast->tech_pvt;
- char destination[256];
- int res=0;
- const char *val=NULL;
- ooCallOptions opts = {
- .fastStart = TRUE,
- .tunneling = TRUE,
- .disableGk = TRUE,
- .callMode = OO_CALLMODE_AUDIOCALL
- };
- if(gH323Debug)
- ast_verbose("--- ooh323_call- %s\n", dest);
-
-
- if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED))
- {
- ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
- "reserved\n", ast->name);
- return -1;
- }
- ast_mutex_lock(&p->lock);
- ast_set_flag(p, H323_OUTGOING);
- if (ast->cid.cid_num) {
- if(p->callerid_num) free(p->callerid_num);
- p->callerid_num = strdup(ast->cid.cid_num);
- }
-
- if(ast->cid.cid_name) {
- if(p->callerid_name) free(p->callerid_name);
- p->callerid_name = strdup(ast->cid.cid_name);
- }
- else{
- ast->cid.cid_name = strdup(gCallerID);
- if(p->callerid_name) free(p->callerid_name);
- p->callerid_name = strdup(ast->cid.cid_name);
- }
-
- /* Retrieve vars */
-
-
- val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID");
- if(val){
- strncpy(p->caller_h323id, val, sizeof(p->caller_h323id)-1);
- }
-
- val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS");
- if(val){
- strncpy(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits)-1);
- if(!p->callerid_num) p->callerid_num = strdup(val);
-
- }
-
- val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL");
- if(val)
- strncpy(p->caller_email, val, sizeof(p->caller_email)-1);
-
- val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL");
- if(val)
- strncpy(p->caller_url, val, sizeof(p->caller_url)-1);
-
-
- p->callToken = (char*)malloc(AST_MAX_EXTENSION);
- if(!p->callToken)
- {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
- return -1; /* TODO: need to clean/hangup?? */
- }
-
- if(p->host && p->port != 0)
- sprintf(destination, "%s:%d", p->host, p->port);
- else if(p->host)
- sprintf(destination, "%s", p->host);
- else
- strncpy(destination, dest, sizeof(destination)-1);
-
- destination[sizeof(destination)-1]='\0';
-
- ast_mutex_lock(&ooh323c_cmd_lock);
- if(OO_TESTFLAG(p->flags, H323_DISABLEGK))
- res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
- else
- res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
- ast_mutex_unlock(&ooh323c_cmd_lock);
-
- ast_mutex_unlock(&p->lock);
- if(res != OO_OK)
- {
- ast_log(LOG_ERROR,"Failed to make call\n");
- return -1; /* ToDO: cleanup */
- }
- if(gH323Debug)
- ast_verbose("+++ ooh323_call\n");
+ struct ooh323_pvt *p = ast->tech_pvt;
+ char destination[256];
+ int res = 0;
+ const char *val = NULL;
+ ooCallOptions opts = {
+ .fastStart = TRUE,
+ .tunneling = TRUE,
+ .disableGk = TRUE,
+ .callMode = OO_CALLMODE_AUDIOCALL
+ };
+ if (gH323Debug)
+ ast_verbose("--- ooh323_call- %s\n", dest);
+
+ if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
+ ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
+ "reserved\n", ast->name);
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ ast_set_flag(p, H323_OUTGOING);
+ if (ast->cid.cid_num) {
+ if (p->callerid_num) {
+ free(p->callerid_num);
+ }
+ p->callerid_num = strdup(ast->cid.cid_num);
+ }
+
+ if (ast->cid.cid_name) {
+ if (p->callerid_name) {
+ free(p->callerid_name);
+ }
+ p->callerid_name = strdup(ast->cid.cid_name);
+ }
+ else{
+ ast->cid.cid_name = strdup(gCallerID);
+ if (p->callerid_name) {
+ free(p->callerid_name);
+ }
+ p->callerid_name = strdup(ast->cid.cid_name);
+ }
+
+ /* Retrieve vars */
+
+
+ if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
+ ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
+ }
+
+ if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
+ ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
+ if (!p->callerid_num) {
+ p->callerid_num = strdup(val);
+ }
+ }
+
+ if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
+ ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
+ }
+
+ if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
+ ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
+ }
+
+
+ if (!(p->callToken = (char*)malloc(AST_MAX_EXTENSION))) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
+ return -1; /* TODO: need to clean/hangup?? */
+ }
+
+ if (p->host && p->port != 0)
+ snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
+ else if (p->host)
+ snprintf(destination, sizeof(destination), "%s", p->host);
+ else
+ ast_copy_string(destination, dest, sizeof(destination));
+
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ if (OO_TESTFLAG(p->flags, H323_DISABLEGK))
+ res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
+ else
+ res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+
+ ast_mutex_unlock(&p->lock);
+ if (res != OO_OK) {
+ ast_log(LOG_ERROR, "Failed to make call\n");
+ return -1; /* TODO: cleanup */
+ }
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_call\n");
return 0;
}
static int ooh323_hangup(struct ast_channel *ast)
{
- struct ooh323_pvt *p = ast->tech_pvt;
+ struct ooh323_pvt *p = ast->tech_pvt;
- if(gH323Debug)
- ast_verbose("--- ooh323_hangup\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_hangup\n");
- if(p)
- {
- ast_mutex_lock(&p->lock);
-
- if(gH323Debug)
- ast_verbose(" hanging %s\n", p->username);
- ast->tech_pvt = NULL;
- if(!ast_test_flag(p, H323_ALREADYGONE)) {
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(p->callToken,
- ooh323_convert_hangupcause_asteriskToH323(p->owner->hangupcause));
- ast_mutex_unlock(&ooh323c_cmd_lock);
- ast_set_flag(p, H323_ALREADYGONE);
- /* ast_mutex_unlock(&p->lock); */
- }
- else {
- ast_set_flag(p, H323_NEEDDESTROY);
- }
- /* detach channel here */
- if(p->owner)
- {
- p->owner->tech_pvt = NULL;
- p->owner = NULL;
- }
-
- ast_mutex_unlock(&p->lock);
- ast_mutex_lock(&usecnt_lock);
- usecnt--;
- ast_mutex_unlock(&usecnt_lock);
-
- /* Notify the module monitors that use count for resource has changed */
- ast_update_use_count();
-
- }
-
-
- else {
- ast_log(LOG_ERROR, "No call to hangup\n" );
- return -1;
- }
-
- if(gH323Debug)
- ast_verbose("+++ ooh323_hangup\n");
+ if (p) {
+ ast_mutex_lock(&p->lock);
+
+ if (gH323Debug)
+ ast_verbose(" hanging %s\n", p->username);
+ ast->tech_pvt = NULL;
+ if (!ast_test_flag(p, H323_ALREADYGONE)) {
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooHangCall(p->callToken,
+ ooh323_convert_hangupcause_asteriskToH323(p->owner->hangupcause));
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+ ast_set_flag(p, H323_ALREADYGONE);
+ /* ast_mutex_unlock(&p->lock); */
+ } else {
+ ast_set_flag(p, H323_NEEDDESTROY);
+ }
+ /* detach channel here */
+ if (p->owner) {
+ p->owner->tech_pvt = NULL;
+ p->owner = NULL;
+ }
+
+ ast_mutex_unlock(&p->lock);
+ ast_mutex_lock(&usecnt_lock);
+ usecnt--;
+ ast_mutex_unlock(&usecnt_lock);
+
+ /* Notify the module monitors that use count for resource has changed */
+ ast_update_use_count();
+
+ } else {
+ ast_log(LOG_ERROR, "No call to hangup\n" );
+ return -1;
+ }
+
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_hangup\n");
return 0;
}
static int ooh323_answer(struct ast_channel *ast)
{
- struct ooh323_pvt *p = ast->tech_pvt;
+ struct ooh323_pvt *p = ast->tech_pvt;
- if(gH323Debug)
- ast_verbose("--- ooh323_answer\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_answer\n");
- ast_mutex_lock(&p->lock);
- if(ast->_state != AST_STATE_UP)
- {
- ast_channel_lock(ast);
- ast_setstate(ast, AST_STATE_UP);
- ast_debug(1, "ooh323_answer(%s)\n", ast->name);
- ast_channel_unlock(ast);
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooAnswerCall(p->callToken);
- ast_mutex_unlock(&ooh323c_cmd_lock);
- }
- ast_mutex_unlock(&p->lock);
+ ast_mutex_lock(&p->lock);
+ if (ast->_state != AST_STATE_UP) {
+ ast_channel_lock(ast);
+ ast_setstate(ast, AST_STATE_UP);
+ ast_debug(1, "ooh323_answer(%s)\n", ast->name);
+ ast_channel_unlock(ast);
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooAnswerCall(p->callToken);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+ }
+ ast_mutex_unlock(&p->lock);
- if(gH323Debug)
- ast_verbose("+++ ooh323_answer\n");
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_answer\n");
return 0;
}
static struct ast_frame *ooh323_read(struct ast_channel *ast)
{
- struct ast_frame *fr;
- static struct ast_frame null_frame = { AST_FRAME_NULL, };
- struct ooh323_pvt *p = ast->tech_pvt;
-
- ast_mutex_lock(&p->lock);
- if(p->rtp)
- fr = ooh323_rtp_read(ast, p);
- else
- fr = &null_frame;
- /* time(&p->lastrtprx); */
- ast_mutex_unlock(&p->lock);
- return fr;
+ struct ast_frame *fr;
+ static struct ast_frame null_frame = { AST_FRAME_NULL, };
+ struct ooh323_pvt *p = ast->tech_pvt;
+
+ ast_mutex_lock(&p->lock);
+ if (p->rtp)
+ fr = ooh323_rtp_read(ast, p);
+ else
+ fr = &null_frame;
+ /* time(&p->lastrtprx); */
+ ast_mutex_unlock(&p->lock);
+ return fr;
}
static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
{
- struct ooh323_pvt *p = ast->tech_pvt;
- int res = 0;
+ struct ooh323_pvt *p = ast->tech_pvt;
+ int res = 0;
- if(f->frametype == AST_FRAME_VOICE)
- {
- if(!(f->subclass & ast->nativeformats))
- {
- ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native "
- "formats is %d (read/write = %d/%d)\n",
- f->subclass, ast->nativeformats, ast->readformat,
- ast->writeformat);
- return 0;
- }
- if(p){
- ast_mutex_lock(&p->lock);
- if(p->rtp)
- res = ast_rtp_write(p->rtp, f);
- ast_mutex_unlock(&p->lock);
- }
- }
- else if (f->frametype == AST_FRAME_IMAGE) {
- return 0;
- }
- else {
- ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n",
- f->frametype);
- return 0;
- }
+ if (f->frametype == AST_FRAME_VOICE) {
+ if (!(f->subclass & ast->nativeformats)) {
+ ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native "
+ "formats is %d (read/write = %d/%d)\n",
+ f->subclass, ast->nativeformats, ast->readformat,
+ ast->writeformat);
+ return 0;
+ }
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->rtp)
+ res = ast_rtp_write(p->rtp, f);
+ ast_mutex_unlock(&p->lock);
+ }
+ } else if (f->frametype == AST_FRAME_IMAGE) {
+ return 0;
+ } else {
+ ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n",
+ f->frametype);
+ return 0;
+ }
- return res;
+ return res;
}
static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
{
- struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
- char *callToken = (char *)NULL;
+ struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
+ char *callToken = (char *)NULL;
+
+ ast_mutex_lock(&p->lock);
+ callToken = (p->callToken ? strdup(p->callToken) : NULL);
+ ast_mutex_unlock(&p->lock);
+
+ if (!callToken) {
+ if (gH323Debug)
+ ast_verbose(" ooh323_indicate - No callToken\n");
+ return -1;
+ }
+
+ if (gH323Debug)
+ ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken);
+
+
+ switch (condition) {
+ case AST_CONTROL_CONGESTION:
+ if (!ast_test_flag(p, H323_ALREADYGONE)) {
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+ ast_set_flag(p, H323_ALREADYGONE);
+ }
+ break;
+ case AST_CONTROL_BUSY:
+ if (!ast_test_flag(p, H323_ALREADYGONE)) {
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooHangCall(callToken, OO_REASON_LOCAL_BUSY);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
+ ast_set_flag(p, H323_ALREADYGONE);
+ }
+ break;
+ case AST_CONTROL_HOLD:
+ ast_moh_start(ast, data, NULL);
+ break;
+ case AST_CONTROL_UNHOLD:
+ ast_moh_stop(ast);
+ break;
+ case AST_CONTROL_PROCEEDING:
+ case AST_CONTROL_RINGING:
+ case AST_CONTROL_PROGRESS:
+ case -1:
+ break;
+ default:
+ ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
+ condition, callToken);
+ }
+
+ if (gH323Debug)
+ ast_verbose("++++ ooh323_indicate %d on %s\n", condition, callToken);
+
+
+ return -1;
+}
+
+static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+{
+ struct ooh323_pvt *p = newchan->tech_pvt;
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323c ooh323_fixup\n");
- ast_mutex_lock(&p->lock);
- callToken = (p->callToken ? strdup(p->callToken) : NULL);
- ast_mutex_unlock(&p->lock);
-
- if(!callToken)
- {
- if(gH323Debug)
- ast_verbose(" ooh323_indicate - No callToken\n");
- return -1;
- }
-
- if(gH323Debug)
- ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken);
-
-
- switch(condition) {
- case AST_CONTROL_CONGESTION:
- if(!ast_test_flag(p, H323_ALREADYGONE)){
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED);
- ast_mutex_unlock(&ooh323c_cmd_lock);
- ast_set_flag(p, H323_ALREADYGONE);
- }
- break;
- case AST_CONTROL_BUSY:
- if(!ast_test_flag(p, H323_ALREADYGONE)){
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(callToken, OO_REASON_LOCAL_BUSY);
- ast_mutex_unlock(&ooh323c_cmd_lock);
- ast_set_flag(p, H323_ALREADYGONE);
- }
- break;
- case AST_CONTROL_HOLD:
- ast_moh_start(ast, data, NULL);
- break;
- case AST_CONTROL_UNHOLD:
- ast_moh_stop(ast);
- break;
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_RINGING:
- case AST_CONTROL_PROGRESS:
- case -1:
- break;
- default:
- ast_log(LOG_WARNING,"Don't know how to indicate condition %d on %s\n",
- condition, callToken);
- }
-
- if(gH323Debug)
- ast_verbose("++++ ooh323_indicate %d on %s\n", condition, callToken);
-
-
- return -1;
-}
-
-static int ooh323_fixup
- (struct ast_channel *oldchan, struct ast_channel *newchan)
-{
- struct ooh323_pvt *p = newchan->tech_pvt;
-
- if(gH323Debug)
- ast_verbose("--- ooh323c ooh323_fixup\n");
-
- ast_mutex_lock(&p->lock);
- if (p->owner != oldchan) {
- ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
- ast_mutex_unlock(&p->lock);
- return -1;
- }
-
- if (p->owner == oldchan) {
- p->owner = newchan;
- }
- else {
- p->owner = oldchan;
- }
+ ast_mutex_lock(&p->lock);
+ if (p->owner != oldchan) {
+ ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
+ ast_mutex_unlock(&p->lock);
+ return -1;
+ }
- ast_mutex_unlock(&p->lock);
+ if (p->owner == oldchan) {
+ p->owner = newchan;
+ } else {
+ p->owner = oldchan;
+ }
- if(gH323Debug)
- ast_verbose("+++ ooh323c ooh323_fixup \n");
+ ast_mutex_unlock(&p->lock);
- return 0;
+ if (gH323Debug)
+ ast_verbose("+++ ooh323c ooh323_fixup \n");
+
+ return 0;
}
void ooh323_set_write_format(ooCallData *call, int fmt)
{
#if 0
- struct ooh323_pvt *p = NULL;
- char formats[512];
+ struct ooh323_pvt *p = NULL;
+ char formats[512];
#ifdef print_debug
- printf("--- ooh323_update_writeformat %s\n",
- ast_getformatname_multiple(formats,512, fmt));
+ printf("--- ooh323_update_writeformat %s\n",
+ ast_getformatname_multiple(formats,512, fmt));
#endif
-
- p = find_call(call);
- if(!p)
- {
- ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
- return;
- }
-
- ast_mutex_lock(&p->lock);
-
- p->writeformat = fmt;
- ast_mutex_unlock(&p->lock);
-
- if(p->owner){
- printf("Writeformat before update %s\n",
- ast_getformatname_multiple(formats,512, p->owner->writeformat));
- ast_set_write_format(p->owner, fmt);
- }
- else
- ast_log(LOG_ERROR, "No owner found\n");
+
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
+ return;
+ }
+
+ ast_mutex_lock(&p->lock);
+
+ p->writeformat = fmt;
+ ast_mutex_unlock(&p->lock);
+
+ if (p->owner) {
+ printf("Writeformat before update %s\n",
+ ast_getformatname_multiple(formats,512, p->owner->writeformat));
+ ast_set_write_format(p->owner, fmt);
+ }
+ else
+ ast_log(LOG_ERROR, "No owner found\n");
#ifdef print_debug
@@ -1134,25 +1056,24 @@
void ooh323_set_read_format(ooCallData *call, int fmt)
{
#if 0
- struct ooh323_pvt *p = NULL;
- char formats[512];
+ struct ooh323_pvt *p = NULL;
+ char formats[512];
#ifdef print_debug
- printf("--- ooh323_update_readformat %s\n",
- ast_getformatname_multiple(formats,512, fmt));
+ printf("--- ooh323_update_readformat %s\n",
+ ast_getformatname_multiple(formats,512, fmt));
#endif
- p = find_call(call);
- if(!p)
- {
- ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
- return;
- }
-
- ast_mutex_lock(&p->lock);
- p->readformat = fmt;
- ast_mutex_unlock(&p->lock);
- ast_set_read_format(p->owner, fmt);
-
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
+ return;
+ }
+
+ ast_mutex_lock(&p->lock);
+ p->readformat = fmt;
+ ast_mutex_unlock(&p->lock);
+ ast_set_read_format(p->owner, fmt);
+
#ifdef print_debug
printf("+++ ooh323_update_readformat\n");
#endif
@@ -1161,50 +1082,42 @@
int onAlerting(ooCallData *call)
{
- struct ooh323_pvt *p=NULL;
- struct ast_channel *c = NULL;
-
- if(gH323Debug)
- ast_verbose("--- onAlerting %s\n", call->callToken);
+ struct ooh323_pvt *p = NULL;
+ struct ast_channel *c = NULL;
- p = find_call(call);
+ if (gH323Debug)
+ ast_verbose("--- onAlerting %s\n", call->callToken);
- if(!p)
- {
- ast_log(LOG_ERROR, "No matching call found\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- if(!ast_test_flag(p, H323_OUTGOING))
- {
- c = ooh323_new(p, AST_STATE_RING, p->username);
- if(!c)
- {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Could not create ast_channel\n");
- return -1;
- }
- ast_mutex_unlock(&p->lock);
- }
- else {
- if (!p->owner) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return 0;
- }
- c = p->owner;
- ast_mutex_unlock(&p->lock);
- ast_channel_lock(c);
- ast_setstate(c, AST_STATE_RINGING);
- ast_channel_unlock(c);
- ast_queue_control(c, AST_CONTROL_RINGING);
- }
-
+ if (!(p = find_call(call))) {
+ ast_log(LOG_ERROR, "No matching call found\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (!ast_test_flag(p, H323_OUTGOING)) {
+ if (!(c = ooh323_new(p, AST_STATE_RING, p->username))) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Could not create ast_channel\n");
+ return -1;
+ }
+ ast_mutex_unlock(&p->lock);
+ } else {
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
+ }
+ c = p->owner;
+ ast_mutex_unlock(&p->lock);
+ ast_channel_lock(c);
+ ast_setstate(c, AST_STATE_RINGING);
+ ast_channel_unlock(c);
+ ast_queue_control(c, AST_CONTROL_RINGING);
+ }
- if(gH323Debug)
- ast_verbose("+++ onAlerting %s\n", call->callToken);
+ if (gH323Debug)
+ ast_verbose("+++ onAlerting %s\n", call->callToken);
- return OO_OK;
+ return OO_OK;
}
/**
@@ -1213,637 +1126,571 @@
*/
int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
{
- struct ooh323_pvt *p=NULL;
- struct ast_frame f;
- int res;
-
- ast_debug(1, "Received Digit: %c\n", digit[0]);
- p = find_call(call);
- if(!p) {
- ast_log(LOG_ERROR, "Failed to find a matching call.\n");
- return -1;
- }
- if(!p->owner) {
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- memset(&f, 0, sizeof(f));
- f.frametype = AST_FRAME_DTMF;
- f.subclass = digit[0];
- f.datalen = 0;
- f.samples = 800;
- f.offset = 0;
- f.data = NULL;
- f.mallocd = 0;
- f.src = "SEND_DIGIT";
- ast_mutex_unlock(&p->lock);
- res = ast_queue_frame(p->owner, &f);
- return res;
+ struct ooh323_pvt *p = NULL;
+ struct ast_frame f;
+ int res;
+
+ ast_debug(1, "Received Digit: %c\n", digit[0]);
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "Failed to find a matching call.\n");
+ return -1;
+ }
+ if (!p->owner) {
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ memset(&f, 0, sizeof(f));
+ f.frametype = AST_FRAME_DTMF;
+ f.subclass = digit[0];
+ f.datalen = 0;
+ f.samples = 800;
+ f.offset = 0;
+ f.data.ptr = NULL;
+ f.mallocd = 0;
+ f.src = "SEND_DIGIT";
+ ast_mutex_unlock(&p->lock);
+ res = ast_queue_frame(p->owner, &f);
+ return res;
}
int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
{
- struct ooh323_pvt *p=NULL;
- struct ooh323_user *user=NULL;
- ooAliases *alias=NULL;
- char *at=NULL;
- char number [OO_MAX_NUMBER_LENGTH];
-
- if(gH323Debug)
- ast_verbose("--- ooh323_onReceivedSetup %s\n", call->callToken);
-
-
- p = ooh323_alloc(call->callReference, call->callToken);
- if(!p)
- {
- ast_log(LOG_ERROR, "Failed to create a new call.\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- ast_clear_flag(p, H323_OUTGOING);
+ struct ooh323_pvt *p = NULL;
+ struct ooh323_user *user = NULL;
+ ooAliases *alias = NULL;
+ char *at = NULL;
+ char number [OO_MAX_NUMBER_LENGTH];
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323_onReceivedSetup %s\n", call->callToken);
+
+
+ if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
+ ast_log(LOG_ERROR, "Failed to create a new call.\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ ast_clear_flag(p, H323_OUTGOING);
- if(call->remoteDisplayName){
- p->callerid_name = strdup(call->remoteDisplayName);
- }
-
- if(ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK)
- {
- p->callerid_num = strdup(number);
- }
-
- if(call->remoteAliases)
- {
- alias = call->remoteAliases;
- while(alias)
- {
- if(alias->type == T_H225AliasAddress_h323_ID)
- {
- if(!p->callerid_name){
- p->callerid_name = strdup(alias->value);
- }
- strncpy(p->caller_h323id, alias->value, sizeof(p->caller_h323id)-1);
- }
- else if(alias->type == T_H225AliasAddress_dialedDigits)
- {
- if(!p->callerid_num)
- p->callerid_num = strdup(alias->value);
- strncpy(p->caller_dialedDigits, alias->value,
- sizeof(p->caller_dialedDigits)-1);
- }
- else if(alias->type == T_H225AliasAddress_email_ID)
- {
- strncpy(p->caller_email, alias->value, sizeof(p->caller_email)-1);
- }
- else if(alias->type == T_H225AliasAddress_url_ID)
- {
- strncpy(p->caller_url, alias->value, sizeof(p->caller_url)-1);
- }
- alias = alias->next;
- }
- }
-
- number[0]='\0';
- if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK)
- {
- strncpy(p->exten, number, sizeof(p->exten)-1);
- }
- else{
- update_our_aliases(call, p);
- if(!ast_strlen_zero(p->callee_dialedDigits)){
- strncpy(p->exten, p->callee_dialedDigits, sizeof(p->exten)-1);
- }
- else if(!ast_strlen_zero(p->callee_h323id)){
- strncpy(p->exten, p->callee_h323id, sizeof(p->exten)-1);
- }
- else if(!ast_strlen_zero(p->callee_email)){
- strncpy(p->exten, p->callee_email, sizeof(p->exten)-1);
- if((at=strchr(p->exten, '@'))) {
- *at='\0';
- }
- }
- }
-
- /* if no extension found, set to default 's' */
- if(ast_strlen_zero(p->exten))
- {
- p->exten[0]='s';
- p->exten[1]='\0';
- }
-
- if(!p->callerid_name)
- {
- p->callerid_name = strdup(call->remoteIP);
- }
-
- if(p->callerid_name)
- {
- user = find_user(p->callerid_name, call->remoteIP);
- if(user)
- {
- ast_mutex_lock(&user->lock);
- p->username = strdup(user->name);
- strncpy(p->context, user->context, sizeof(p->context)-1);
- strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode)-1);
- p->amaflags = user->amaflags;
- p->capability = user->capability;
- memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
- p->dtmfmode = user->dtmfmode;
- /* Since, call is coming from a pbx user, no need to use gk */
- OO_SETFLAG(p->flags, H323_DISABLEGK);
- OO_SETFLAG(call->flags, OO_M_DISABLEGK);
- ast_mutex_unlock(&user->lock);
- }
- }
-
-
- ooh323c_set_capability_for_call(call, &p->prefs, p->capability,p->dtmfmode);
- configure_local_rtp(p, call);
-
- ast_mutex_unlock(&p->lock);
-
- if(gH323Debug)
- ast_verbose("+++ ooh323_onReceivedSetup - Determined context %s, "
- "extension %s\n", p->context, p->exten);
+ if (call->remoteDisplayName) {
+ p->callerid_name = strdup(call->remoteDisplayName);
+ }
+
+ if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
+ p->callerid_num = strdup(number);
+ }
+
+ if (call->remoteAliases) {
+ for (alias = call->remoteAliases; alias; alias = alias->next) {
+ if (alias->type == T_H225AliasAddress_h323_ID) {
+ if (!p->callerid_name) {
+ p->callerid_name = strdup(alias->value);
+ }
+ ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
+ } else if (alias->type == T_H225AliasAddress_dialedDigits) {
+ if (!p->callerid_num) {
+ p->callerid_num = strdup(alias->value);
+ }
+ ast_copy_string(p->caller_dialedDigits, alias->value,
+ sizeof(p->caller_dialedDigits));
+ } else if (alias->type == T_H225AliasAddress_email_ID) {
+ ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
+ } else if (alias->type == T_H225AliasAddress_url_ID) {
+ ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
+ }
+ }
+ }
- return OO_OK;
+ number[0] = '\0';
+ if (ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
+ ast_copy_string(p->exten, number, sizeof(p->exten));
+ } else {
+ update_our_aliases(call, p);
+ if (!ast_strlen_zero(p->callee_dialedDigits)) {
+ ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
+ } else if (!ast_strlen_zero(p->callee_h323id)) {
+ ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
+ } else if (!ast_strlen_zero(p->callee_email)) {
+ ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
+ if ((at = strchr(p->exten, '@'))) {
+ *at = '\0';
+ }
+ }
+ }
+
+ /* if no extension found, set to default 's' */
+ if (ast_strlen_zero(p->exten)) {
+ ast_copy_string(p->exten, "s", sizeof(p->exten));
+ }
+
+ if (!p->callerid_name) {
+ p->callerid_name = strdup(call->remoteIP);
+ }
+
+ if (p->callerid_name) {
+ if ((user = find_user(p->callerid_name, call->remoteIP))) {
+ ast_mutex_lock(&user->lock);
+ p->username = strdup(user->name);
+ ast_copy_string(p->context, user->context, sizeof(p->context));
+ ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
+ p->amaflags = user->amaflags;
+ p->capability = user->capability;
+ memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
+ p->dtmfmode = user->dtmfmode;
+ /* Since, call is coming from a pbx user, no need to use gk */
+ OO_SETFLAG(p->flags, H323_DISABLEGK);
+ OO_SETFLAG(call->flags, OO_M_DISABLEGK);
+ ast_mutex_unlock(&user->lock);
+ }
+ }
+
+
+ ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
+ configure_local_rtp(p, call);
+
+ ast_mutex_unlock(&p->lock);
+
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_onReceivedSetup - Determined context %s, "
+ "extension %s\n", p->context, p->exten);
+
+ return OO_OK;
}
int onNewCallCreated(ooCallData *call)
{
- struct ooh323_pvt *p = NULL;
- int i=0;
+ struct ooh323_pvt *p = NULL;
+ int i = 0;
- if(gH323Debug)
- ast_verbose("--- onNewCallCreated %s\n", call->callToken);
+ if (gH323Debug)
+ ast_verbose("--- onNewCallCreated %s\n", call->callToken);
- if(!strcmp(call->callType, "outgoing"))
- {
- p = find_call(call);
- if(!p)
- {
- ast_log(LOG_ERROR, "No matching call found for outgoing call\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- if(p->callerid_name){
- ooCallSetCallerId(call, p->callerid_name);
- }
- if(p->callerid_num)
- {
- i=0;
- while(*(p->callerid_num+i) != '\0')
- {
- if(!isdigit(*(p->callerid_num+i))) { break; }
- i++;
- }
- if(*(p->callerid_num+i) == '\0')
- ooCallSetCallingPartyNumber(call, p->callerid_num);
- else{
- if(!p->callerid_name)
- ooCallSetCallerId(call, p->callerid_num);
- }
- }
-
- if(!ast_strlen_zero(p->caller_h323id))
- ooCallAddAliasH323ID(call, p->caller_h323id);
-
- if(!ast_strlen_zero(p->caller_dialedDigits)){
- if(gH323Debug) {
- ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
- }
- ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
- }
- else if(p->callerid_num) {
- if(ooIsDailedDigit(p->callerid_num)) {
- if(gH323Debug) {
- ast_verbose("setting callid number %s\n", p->callerid_num);
- }
- ooCallAddAliasDialedDigits(call, p->callerid_num);
- }
- else if(ast_strlen_zero(p->caller_h323id)) {
- ooCallAddAliasH323ID(call, p->callerid_num);
- }
- }
+ if (!strcmp(call->callType, "outgoing")) {
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "No matching call found for outgoing call\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (p->callerid_name) {
+ ooCallSetCallerId(call, p->callerid_name);
+ }
+ if (p->callerid_num) {
+ i = 0;
+ while (*(p->callerid_num + i) != '\0') {
+ if (!isdigit(*(p->callerid_num + i))) {
+ break;
+ }
+ i++;
+ }
+ if (*(p->callerid_num + i) == '\0') {
+ ooCallSetCallingPartyNumber(call, p->callerid_num);
+ } else {
+ if (!p->callerid_name) {
+ ooCallSetCallerId(call, p->callerid_num);
+ }
+ }
+ }
+
+ if (!ast_strlen_zero(p->caller_h323id))
+ ooCallAddAliasH323ID(call, p->caller_h323id);
+
+ if (!ast_strlen_zero(p->caller_dialedDigits)) {
+ if (gH323Debug) {
+ ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
+ }
+ ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
+ } else if (p->callerid_num) {
+ if (ooIsDailedDigit(p->callerid_num)) {
+ if (gH323Debug) {
+ ast_verbose("setting callid number %s\n", p->callerid_num);
+ }
+ ooCallAddAliasDialedDigits(call, p->callerid_num);
+ } else if (ast_strlen_zero(p->caller_h323id)) {
+ ooCallAddAliasH323ID(call, p->callerid_num);
+ }
+ }
- if(!ast_strlen_zero(p->exten))
- {
- if(ooIsDailedDigit(p->exten)) {
- ooCallSetCalledPartyNumber(call, p->exten);
- ooCallAddRemoteAliasDialedDigits(call, p->exten);
- }
- else {
- ooCallAddRemoteAliasH323ID(call, p->exten);
- }
- }
-
- if(gH323Debug)
- {
- char prefsBuf[256];
- ast_codec_pref_string(&p->prefs, prefsBuf, 256);
- ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n",
- p->username?p->username:"NULL", call->callToken, prefsBuf);
- }
-
- ooh323c_set_capability_for_call(call, &p->prefs, p->capability,
- p->dtmfmode);
-
- configure_local_rtp(p, call);
- ast_mutex_unlock(&p->lock);
- }
- if(gH323Debug)
- ast_verbose("+++ onNewCallCreated %s\n", call->callToken);
+ if (!ast_strlen_zero(p->exten)) {
+ if (ooIsDailedDigit(p->exten)) {
+ ooCallSetCalledPartyNumber(call, p->exten);
+ ooCallAddRemoteAliasDialedDigits(call, p->exten);
+ } else {
+ ooCallAddRemoteAliasH323ID(call, p->exten);
+ }
+ }
+
+ if (gH323Debug) {
+ char prefsBuf[256];
+ ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
+ ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n",
+ p->username?p->username:"NULL", call->callToken, prefsBuf);
+ }
+
+ ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
+
+ configure_local_rtp(p, call);
+ ast_mutex_unlock(&p->lock);
+ }
+ if (gH323Debug)
+ ast_verbose("+++ onNewCallCreated %s\n", call->callToken);
- return OO_OK;
+ return OO_OK;
}
int onCallEstablished(ooCallData *call)
{
- struct ooh323_pvt *p = NULL;
+ struct ooh323_pvt *p = NULL;
- if(gH323Debug)
- ast_verbose("--- onCallEstablished %s\n", call->callToken);
+ if (gH323Debug)
+ ast_verbose("--- onCallEstablished %s\n", call->callToken);
- p = find_call(call);
- if(!p) {
- ast_log(LOG_ERROR, "Failed to find a matching call.\n");
- return -1;
- }
- ast_mutex_lock(&p->lock);
- if (!p->owner) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return -1;
- }
-
- while(ast_channel_trylock(p->owner))
- {
- ast_debug(1,"Failed to grab lock, trying again\n");
- ast_mutex_unlock(&p->lock);
- usleep(1);
- ast_mutex_lock(&p->lock);
- }
- if(p->owner->_state != AST_STATE_UP)
- {
- ast_setstate(p->owner, AST_STATE_UP);
- }
- ast_channel_unlock(p->owner);
- if(ast_test_flag(p, H323_OUTGOING)) {
- struct ast_channel* c = p->owner;
- ast_mutex_unlock(&p->lock);
- ast_queue_control(c, AST_CONTROL_ANSWER);
- }
- else { ast_mutex_unlock(&p->lock); }
+ if (!(p = find_call(call))) {
+ ast_log(LOG_ERROR, "Failed to find a matching call.\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return -1;
+ }
+
+ while (ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ ast_mutex_unlock(&p->lock);
+ usleep(1);
+ ast_mutex_lock(&p->lock);
+ }
+ if (p->owner->_state != AST_STATE_UP) {
+ ast_setstate(p->owner, AST_STATE_UP);
+ }
+ ast_channel_unlock(p->owner);
+ if (ast_test_flag(p, H323_OUTGOING)) {
+ struct ast_channel* c = p->owner;
+ ast_mutex_unlock(&p->lock);
+ ast_queue_control(c, AST_CONTROL_ANSWER);
+ } else {
+ ast_mutex_unlock(&p->lock);
+ }
- if(gH323Debug)
- ast_verbose("+++ onCallEstablished %s\n", call->callToken);
+ if (gH323Debug)
+ ast_verbose("+++ onCallEstablished %s\n", call->callToken);
- return OO_OK;
+ return OO_OK;
}
int onCallCleared(ooCallData *call)
{
- struct ooh323_pvt *p = NULL;
- int ownerLock = 0;
+ struct ooh323_pvt *p = NULL;
+ int ownerLock = 0;
- if(gH323Debug)
- ast_verbose("--- onCallCleared %s \n", call->callToken);
+ if (gH323Debug)
+ ast_verbose("--- onCallCleared %s \n", call->callToken);
- p = find_call(call);
- if (!p) { return 0; }
- ast_mutex_lock(&p->lock);
+ p = find_call(call);
+ if (!p) {
+ return 0;
+ }
+ ast_mutex_lock(&p->lock);
- while(p->owner) {
- if(ast_channel_trylock(p->owner)) {
- ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
- ast_debug(1,"Failed to grab lock, trying again\n");
- ast_mutex_unlock(&p->lock);
- usleep(1);
- ast_mutex_lock(&p->lock);
- }
- else {
- ownerLock = 1; break;
- }
- }
-
- if(ownerLock) {
- if(!ast_test_flag(p, H323_ALREADYGONE)) {
-
- /* NOTE: Channel is not detached yet */
- ast_set_flag(p, H323_ALREADYGONE);
- p->owner->hangupcause =
- ooh323_convert_hangupcause_h323ToAsterisk(call->callEndReason);
- p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- ast_channel_unlock(p->owner);
- ast_queue_hangup(p->owner);
- ast_mutex_unlock(&p->lock);
- return OO_OK;
- }
- ast_channel_unlock(p->owner);
- }
- ast_set_flag(p, H323_NEEDDESTROY);
- ast_mutex_unlock(&p->lock);
+ while (p->owner) {
+ if (ast_channel_trylock(p->owner)) {
+ ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ ast_mutex_unlock(&p->lock);
+ usleep(1);
+ ast_mutex_lock(&p->lock);
+ } else {
+ ownerLock = 1;
+ break;
+ }
+ }
+
+ if (ownerLock) {
+ if (!ast_test_flag(p, H323_ALREADYGONE)) {
- if(gH323Debug)
- ast_verbose("+++ onCallCleared\n");
+ /* NOTE: Channel is not detached yet */
+ ast_set_flag(p, H323_ALREADYGONE);
+ p->owner->hangupcause =
+ ooh323_convert_hangupcause_h323ToAsterisk(call->callEndReason);
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ ast_channel_unlock(p->owner);
+ ast_queue_hangup(p->owner);
+ ast_mutex_unlock(&p->lock);
+ return OO_OK;
+ }
+ ast_channel_unlock(p->owner);
+ }
+ ast_set_flag(p, H323_NEEDDESTROY);
+ ast_mutex_unlock(&p->lock);
- return OO_OK;
+ if (gH323Debug)
+ ast_verbose("+++ onCallCleared\n");
+
+ return OO_OK;
}
#if 0
static void ooh323_delete_user(struct ooh323_user *user)
{
- struct ooh323_user *prev=NULL, *cur=NULL;
+ struct ooh323_user *prev = NULL, *cur = NULL;
- if(gH323Debug)
- ast_verbose("--- ooh323_delete_user\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_delete_user\n");
- if(user)
- {
- cur = userl.users;
- ast_mutex_lock(&userl.lock);
- while(cur)
- {
- if(cur==user) break;
- prev = cur;
- cur = cur->next;
- }
-
- if(cur)
- {
- if(prev)
- prev->next = cur->next;
- else
- userl.users = cur->next;
- }
- ast_mutex_unlock(&userl.lock);
+ if (user) {
+ cur = userl.users;
+ ast_mutex_lock(&userl.lock);
+ while (cur) {
+ if (cur == user) break;
+ prev = cur;
+ cur = cur->next;
+ }
- free(user);
- }
+ if (cur) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ userl.users = cur->next;
+ }
+ ast_mutex_unlock(&userl.lock);
- if(gH323Debug)
- ast_verbose("+++ ooh323_delete_user\n");
+ free(user);
+ }
+
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_delete_user\n");
}
#endif
void ooh323_delete_peer(struct ooh323_peer *peer)
{
- struct ooh323_peer *prev=NULL, *cur=NULL;
+ struct ooh323_peer *prev = NULL, *cur = NULL;
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323_delete_peer\n");
- if(gH323Debug)
- ast_verbose("--- ooh323_delete_peer\n");
+ if (peer) {
+ ast_mutex_lock(&peerl.lock);
+ for (cur = peerl.peers; cur; prev = cur, cur = cur->next) {
+ if (cur == peer) {
+ break;
+ }
+ }
- if(peer)
- {
- cur = peerl.peers;
- ast_mutex_lock(&peerl.lock);
- while(cur)
- {
- if(cur==peer) break;
- prev = cur;
- cur = cur->next;
- }
-
- if(cur)
- {
- if(prev)
- prev->next = cur->next;
- else
- peerl.peers = cur->next;
- }
- ast_mutex_unlock(&peerl.lock);
-
- if(peer->h323id) free(peer->h323id);
- if(peer->email) free(peer->email);
- if(peer->url) free(peer->url);
- if(peer->e164) free(peer->e164);
+ if (cur) {
+ if (prev) {
+ prev->next = cur->next;
+ } else {
+ peerl.peers = cur->next;
+ }
+ }
+ ast_mutex_unlock(&peerl.lock);
- free(peer);
- }
+ if (peer->h323id)
+ free(peer->h323id);
+ if (peer->email)
+ free(peer->email);
+ if (peer->url)
+ free(peer->url);
+ if (peer->e164)
+ free(peer->e164);
- if(gH323Debug)
- ast_verbose("+++ ooh323_delete_peer\n");
+ free(peer);
+ }
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_delete_peer\n");
}
static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
{
- struct ooh323_user *user=NULL;
+ struct ooh323_user *user = NULL;
- if(gH323Debug)
- ast_verbose("--- build_user\n");
+ if (gH323Debug)
+ ast_verbose("--- build_user\n");
- user = (struct ooh323_user *)malloc(sizeof(struct ooh323_user));
- if (user) {
- memset(user, 0, sizeof(struct ooh323_user));
- ast_mutex_init(&user->lock);
- strncpy(user->name, name, sizeof(user->name)-1);
- user->capability = gCapability;
- memcpy(&user->prefs, &gPrefs, sizeof(struct ast_codec_pref));
- user->rtptimeout = gRTPTimeout;
- user->dtmfmode = gDTMFMode;
- /* set default context */
- strncpy(user->context, gContext, sizeof(user->context)-1);
- strncpy(user->accountcode, gAccountcode, sizeof(user->accountcode)-1);
- user->amaflags = gAMAFLAGS;
-
- while(v) {
- if (!strcasecmp(v->name, "context")) {
- strncpy(user->context, v->value, sizeof(user->context) - 1);
- }
- else if (!strcasecmp(v->name, "incominglimit")) {
- user->incominglimit = atoi(v->value);
- if (user->incominglimit < 0)
- user->incominglimit = 0;
- }
- else if (!strcasecmp(v->name, "accountcode")) {
- strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1);
- }
- else if (!strcasecmp(v->name, "rtptimeout")) {
- user->rtptimeout = atoi(v->value);
- if(user->rtptimeout < 0)
- user->rtptimeout = gRTPTimeout;
- }
- else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&user->prefs, &user->capability,
- v->value, 0);
- }
- else if (!strcasecmp(v->name, "allow")) {
- const char* tcodecs = v->value;
- if(!strcasecmp(v->value, "all")) {
- tcodecs = "ulaw,alaw,g729,g723,gsm";
- }
- ast_parse_allow_disallow(&user->prefs, &user->capability,
- tcodecs, 1);
- }
- else if (!strcasecmp(v->name, "amaflags")) {
- user->amaflags = ast_cdr_amaflags2int(v->value);
- }
- else if (!strcasecmp(v->name, "ip")) {
- strncpy(user->mIP, v->value, sizeof(user->mIP)-1);
- user->mUseIP = 1;
- }
- else if (!strcasecmp(v->name, "dtmfmode")) {
- if(!strcasecmp(v->value, "rfc2833"))
- user->dtmfmode = H323_DTMF_RFC2833;
- else if(!strcasecmp(v->value, "q931keypad"))
- user->dtmfmode = H323_DTMF_Q931;
- else if(!strcasecmp(v->value, "h245alphanumeric"))
- user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
- else if(!strcasecmp(v->value, "h245signal"))
- user->dtmfmode = H323_DTMF_H245SIGNAL;
- }
- v = v->next;
- }
- }
+ user = ast_calloc(1, sizeof(*user));
+ if (user) {
+ ast_mutex_init(&user->lock);
+ ast_copy_string(user->name, name, sizeof(user->name));
+ user->capability = gCapability;
+ memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
+ user->rtptimeout = gRTPTimeout;
+ user->dtmfmode = gDTMFMode;
+ /* set default context */
+ ast_copy_string(user->context, gContext, sizeof(user->context));
+ ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode));
+ user->amaflags = gAMAFLAGS;
+
+ while (v) {
+ if (!strcasecmp(v->name, "context")) {
+ ast_copy_string(user->context, v->value, sizeof(user->context));
+ } else if (!strcasecmp(v->name, "incominglimit")) {
+ user->incominglimit = atoi(v->value);
+ if (user->incominglimit < 0)
+ user->incominglimit = 0;
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
+ } else if (!strcasecmp(v->name, "rtptimeout")) {
+ user->rtptimeout = atoi(v->value);
+ if (user->rtptimeout < 0)
+ user->rtptimeout = gRTPTimeout;
+ } else if (!strcasecmp(v->name, "disallow")) {
+ ast_parse_allow_disallow(&user->prefs, &user->capability,
+ v->value, 0);
+ } else if (!strcasecmp(v->name, "allow")) {
+ const char* tcodecs = v->value;
+ if (!strcasecmp(v->value, "all")) {
+ tcodecs = "ulaw,alaw,g729,g723,gsm";
+ }
+ ast_parse_allow_disallow(&user->prefs, &user->capability,
+ tcodecs, 1);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+ user->amaflags = ast_cdr_amaflags2int(v->value);
+ } else if (!strcasecmp(v->name, "ip")) {
+ ast_copy_string(user->mIP, v->value, sizeof(user->mIP));
+ user->mUseIP = 1;
+ } else if (!strcasecmp(v->name, "dtmfmode")) {
+ if (!strcasecmp(v->value, "rfc2833"))
+ user->dtmfmode = H323_DTMF_RFC2833;
+ else if (!strcasecmp(v->value, "q931keypad"))
+ user->dtmfmode = H323_DTMF_Q931;
+ else if (!strcasecmp(v->value, "h245alphanumeric"))
+ user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
+ else if (!strcasecmp(v->value, "h245signal"))
+ user->dtmfmode = H323_DTMF_H245SIGNAL;
+ }
+ v = v->next;
+ }
+ }
- if(gH323Debug)
- ast_verbose("+++ build_user\n");
+ if (gH323Debug)
+ ast_verbose("+++ build_user\n");
- return user;
+ return user;
}
static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, int friend_type)
{
- struct ooh323_peer *peer=NULL;
+ struct ooh323_peer *peer = NULL;
- if(gH323Debug)
- ast_verbose("--- build_peer\n");
+ if (gH323Debug)
+ ast_verbose("--- build_peer\n");
- peer = (struct ooh323_peer *)malloc(sizeof(struct ooh323_peer));
- if (peer) {
- memset(peer, 0, sizeof(struct ooh323_peer));
- ast_mutex_init(&peer->lock);
- strncpy(peer->name, name, sizeof(peer->name)-1);
- peer->capability = gCapability;
- memcpy(&peer->prefs, &gPrefs, sizeof(struct ast_codec_pref));
- peer->rtptimeout = gRTPTimeout;
- strncpy(peer->accountcode, gAccountcode, sizeof(peer->accountcode)-1);
- peer->amaflags = gAMAFLAGS;
- peer->dtmfmode = gDTMFMode;
- if(0 == friend_type) {
- peer->mFriend = 1;
- }
-
- while(v) {
- if (!strcasecmp(v->name, "h323id")) {
- peer->h323id = (char*)malloc(strlen(v->value)+1);
- if(!peer->h323id)
- {
- ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
- "peer %s\n", name);
- ooh323_delete_peer(peer);
- return NULL;
- }
- strcpy(peer->h323id, v->value);
- }
- else if (!strcasecmp(v->name, "e164")) {
- peer->e164 = (char*)malloc(strlen(v->value)+1);
- if(!peer->e164)
- {
- ast_log(LOG_ERROR, "Could not allocate memory for e164 of "
- "peer %s\n", name);
- ooh323_delete_peer(peer);
- return NULL;
- }
- strcpy(peer->e164, v->value);
- }
- else if (!strcasecmp(v->name, "email")) {
- peer->email = (char*)malloc(strlen(v->value)+1);
- if(!peer->email)
- {
- ast_log(LOG_ERROR, "Could not allocate memory for email of "
- "peer %s\n", name);
- ooh323_delete_peer(peer);
- return NULL;
- }
- strcpy(peer->email, v->value);
- }
- else if (!strcasecmp(v->name, "url")) {
- peer->url = (char*)malloc(strlen(v->value)+1);
- if(!peer->url)
- {
- ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
- "peer %s\n", name);
- ooh323_delete_peer(peer);
- return NULL;
- }
- strcpy(peer->url, v->value);
- }
- else if (!strcasecmp(v->name, "port")) {
- peer->port = atoi(v->value);
- }
- else if (!strcasecmp(v->name, "ip")) {
- strncpy(peer->ip, v->value, sizeof(peer->ip)-1);
- }
- else if (!strcasecmp(v->name, "outgoinglimit")) {
- peer->outgoinglimit = atoi(v->value);
- if (peer->outgoinglimit < 0)
- peer->outgoinglimit = 0;
- }
- else if (!strcasecmp(v->name, "accountcode")) {
- strncpy(peer->accountcode, v->value, sizeof(peer->accountcode)-1);
- }
- else if (!strcasecmp(v->name, "rtptimeout")) {
- peer->rtptimeout = atoi(v->value);
- if(peer->rtptimeout < 0)
- peer->rtptimeout = gRTPTimeout;
- }
- else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&peer->prefs, &peer->capability,
- v->value, 0);
- }
- else if (!strcasecmp(v->name, "allow")) {
- const char* tcodecs = v->value;
- if(!strcasecmp(v->value, "all")) {
- tcodecs = "ulaw,alaw,g729,g723,gsm";
- }
- ast_parse_allow_disallow(&peer->prefs, &peer->capability,
- tcodecs, 1);
- }
- else if (!strcasecmp(v->name, "amaflags")) {
- peer->amaflags = ast_cdr_amaflags2int(v->value);
- }
- else if (!strcasecmp(v->name, "dtmfmode")) {
- if(!strcasecmp(v->value, "rfc2833"))
- peer->dtmfmode = H323_DTMF_RFC2833;
- else if(!strcasecmp(v->value, "q931keypad"))
- peer->dtmfmode = H323_DTMF_Q931;
- else if(!strcasecmp(v->value, "h245alphanumeric"))
- peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
- else if(!strcasecmp(v->value, "h245signal"))
- peer->dtmfmode = H323_DTMF_H245SIGNAL;
- }
- v = v->next;
- }
- }
+ peer = ast_calloc(1, sizeof(*peer));
+ if (peer) {
+ memset(peer, 0, sizeof(struct ooh323_peer));
+ ast_mutex_init(&peer->lock);
+ ast_copy_string(peer->name, name, sizeof(peer->name));
+ peer->capability = gCapability;
+ memcpy(&peer->prefs, &gPrefs, sizeof(struct ast_codec_pref));
+ peer->rtptimeout = gRTPTimeout;
+ ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
+ peer->amaflags = gAMAFLAGS;
+ peer->dtmfmode = gDTMFMode;
+ if (0 == friend_type) {
+ peer->mFriend = 1;
+ }
+
+ while (v) {
+ if (!strcasecmp(v->name, "h323id")) {
+ if (!(peer->h323id = ast_strdup(v->value))) {
+ ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
+ "peer %s\n", name);
+ ooh323_delete_peer(peer);
+ return NULL;
+ }
+ } else if (!strcasecmp(v->name, "e164")) {
+ if (!(peer->e164 = ast_strdup(v->value))) {
+ ast_log(LOG_ERROR, "Could not allocate memory for e164 of "
+ "peer %s\n", name);
+ ooh323_delete_peer(peer);
+ return NULL;
+ }
+ } else if (!strcasecmp(v->name, "email")) {
+ if (!(peer->email = ast_strdup(v->value))) {
+ ast_log(LOG_ERROR, "Could not allocate memory for email of "
+ "peer %s\n", name);
+ ooh323_delete_peer(peer);
+ return NULL;
+ }
+ } else if (!strcasecmp(v->name, "url")) {
+ if (!(peer->url = ast_strdup(v->value))) {
+ ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
+ "peer %s\n", name);
+ ooh323_delete_peer(peer);
+ return NULL;
+ }
+ } else if (!strcasecmp(v->name, "port")) {
+ peer->port = atoi(v->value);
+ } else if (!strcasecmp(v->name, "ip")) {
+ ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
+ } else if (!strcasecmp(v->name, "outgoinglimit")) {
+ if ((peer->outgoinglimit = atoi(v->value)) < 0) {
+ peer->outgoinglimit = 0;
+ }
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
+ } else if (!strcasecmp(v->name, "rtptimeout")) {
+ if ((peer->rtptimeout = atoi(v->value)) < 0) {
+ peer->rtptimeout = gRTPTimeout;
+ }
+ } else if (!strcasecmp(v->name, "disallow")) {
+ ast_parse_allow_disallow(&peer->prefs, &peer->capability,
+ v->value, 0);
+ } else if (!strcasecmp(v->name, "allow")) {
+ const char* tcodecs = v->value;
+ if (!strcasecmp(v->value, "all")) {
+ tcodecs = "ulaw,alaw,g729,g723,gsm";
+ }
+ ast_parse_allow_disallow(&peer->prefs, &peer->capability,
+ tcodecs, 1);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+ peer->amaflags = ast_cdr_amaflags2int(v->value);
+ } else if (!strcasecmp(v->name, "dtmfmode")) {
+ if (!strcasecmp(v->value, "rfc2833"))
+ peer->dtmfmode = H323_DTMF_RFC2833;
+ else if (!strcasecmp(v->value, "q931keypad"))
+ peer->dtmfmode = H323_DTMF_Q931;
+ else if (!strcasecmp(v->value, "h245alphanumeric"))
+ peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
+ else if (!strcasecmp(v->value, "h245signal"))
+ peer->dtmfmode = H323_DTMF_H245SIGNAL;
+ }
+ v = v->next;
+ }
+ }
- if(gH323Debug)
- ast_verbose("+++ build_peer\n");
+ if (gH323Debug)
+ ast_verbose("+++ build_peer\n");
- return peer;
+ return peer;
}
static int ooh323_do_reload(void)
{
- if(gH323Debug) {
- ast_verbose("--- ooh323_do_reload\n");
- }
+ if (gH323Debug) {
+ ast_verbose("--- ooh323_do_reload\n");
+ }
- reload_config(1);
+ reload_config(1);
- if(gH323Debug) {
- ast_verbose("+++ ooh323_do_reload\n");
- }
+ if (gH323Debug) {
+ ast_verbose("+++ ooh323_do_reload\n");
+ }
- return 0;
+ return 0;
}
#if 0
@@ -1851,322 +1698,281 @@
static int ooh323_reload(int fd, int argc, char *argv[])
{
- if(gH323Debug)
- ast_verbose("--- ooh323_reload\n");
+ if (gH323Debug)
+ ast_verbose("--- ooh323_reload\n");
- ast_mutex_lock(&h323_reload_lock);
- if (h323_reloading) {
- ast_verbose("Previous OOH323 reload not yet done\n");
- }
- else {
- h323_reloading = 1;
- }
- ast_mutex_unlock(&h323_reload_lock);
- restart_monitor();
+ ast_mutex_lock(&h323_reload_lock);
+ if (h323_reloading) {
+ ast_verbose("Previous OOH323 reload not yet done\n");
+ }
+ else {
+ h323_reloading = 1;
+ }
+ ast_mutex_unlock(&h323_reload_lock);
+ restart_monitor();
- if(gH323Debug)
- ast_verbose("+++ ooh323_reload\n");
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_reload\n");
- return 0;
+ return 0;
}
#endif
#if 0
static int reload(void *mod)
{
- return ooh323_reload(0, 0, NULL);
+ return ooh323_reload(0, 0, NULL);
}
#endif
int reload_config(int reload)
{
- int format;
- struct ooAliases *pNewAlias = NULL;
- struct ast_config *cfg;
- struct ast_variable *v;
- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
- struct ooh323_user *user = NULL;
- struct ooh323_peer *peer = NULL;
- char *cat;
- const char *utype;
-
- if(gH323Debug)
- ast_verbose("--- reload_config\n");
-
- cfg = ast_config_load((char*)config, config_flags);
-
- /* We *must* have a config file otherwise stop immediately */
- if (!cfg) {
- ast_log(LOG_NOTICE, "Unable to load config %s, OOH323 disabled\n",config);
- return 1;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
- return RESULT_SUCCESS;
-
- if (reload) {
- delete_users();
- delete_peers();
- }
-
- /* Inintialize everything to default */
- strcpy(gLogFile, DEFAULT_LOGFILE);
- gPort = 1720;
- gIP[0]='\0';
- strcpy(gCallerID, DEFAULT_H323ID);
- gCapability = AST_FORMAT_ULAW;
- memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
- gDTMFMode = H323_DTMF_RFC2833;
- gRasGkMode = RasNoGatekeeper;
- gGatekeeper[0] = '\0';
- gRTPTimeout = 60;
- strcpy(gAccountcode, DEFAULT_H323ACCNT);
- gFastStart = 1;
- gTunneling = 1;
- gTOS = 0;
- strcpy(gContext, DEFAULT_CONTEXT);
- gAliasList = NULL;
- gMediaWaitForConnect = 0;
- ooconfig.mTCPPortStart = 12030;
- ooconfig.mTCPPortEnd = 12230;
-
- v = ast_variable_browse(cfg, "general");
- while(v) {
-
- if (!strcasecmp(v->name, "port")) {
- gPort = (int)strtol(v->value, NULL, 10);
- }
- else if (!strcasecmp(v->name, "bindaddr")) {
- strncpy(gIP, v->value, sizeof(gIP)-1);
- }
- else if (!strcasecmp(v->name, "h225portrange")) {
- char* endlimit = 0;
- char temp[512];
- strncpy(temp, v->value, sizeof(temp) - 1);
- /* char *temp = ast_strdupa(v->value); */
- endlimit = strchr(temp, ',');
- if (endlimit) {
- *endlimit = '\0';
- endlimit++;
- ooconfig.mTCPPortStart = atoi(temp);
- ooconfig.mTCPPortEnd = atoi(endlimit);
-
- if(ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart,
- ooconfig.mTCPPortEnd) == OO_FAILED) {
- ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
- }
- }
- else {
- ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
- }
- }
- else if (!strcasecmp(v->name, "gateway")) {
- gIsGateway = ast_true(v->value);
- }
- else if (!strcasecmp(v->name, "faststart")) {
- gFastStart = ast_true(v->value);
- if(gFastStart)
- ooH323EpEnableFastStart();
- else
- ooH323EpDisableFastStart();
- }
- else if (!strcasecmp(v->name, "mediawaitforconnect")) {
- gMediaWaitForConnect = ast_true(v->value);
- if(gMediaWaitForConnect)
- ooH323EpEnableMediaWaitForConnect();
- else
- ooH323EpDisableMediaWaitForConnect();
- }
- else if (!strcasecmp(v->name, "h245tunneling")) {
- gTunneling = ast_true(v->value);
- if(gTunneling)
- ooH323EpEnableH245Tunneling();
- else
- ooH323EpDisableH245Tunneling();
- }
- else if (!strcasecmp(v->name, "h323id")) {
- pNewAlias = malloc(sizeof(struct ooAliases));
- if(!pNewAlias){
- ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
- return 1;
- }
- pNewAlias->type = T_H225AliasAddress_h323_ID;
- pNewAlias->value = strdup(v->value);
- pNewAlias->next = gAliasList;
- gAliasList = pNewAlias;
- pNewAlias = NULL;
- }
- else if (!strcasecmp(v->name, "e164")) {
- pNewAlias = malloc(sizeof(struct ooAliases));
- if(!pNewAlias){
- ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
- return 1;
- }
- pNewAlias->type = T_H225AliasAddress_dialedDigits;
- pNewAlias->value = strdup(v->value);
- pNewAlias->next = gAliasList;
- gAliasList = pNewAlias;
- pNewAlias = NULL;
- }
- else if (!strcasecmp(v->name, "email")) {
- pNewAlias = malloc(sizeof(struct ooAliases));
- if(!pNewAlias){
- ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
- return 1;
- }
- pNewAlias->type = T_H225AliasAddress_email_ID;
- pNewAlias->value = strdup(v->value);
- pNewAlias->next = gAliasList;
- gAliasList = pNewAlias;
- pNewAlias = NULL;
- }
- else if (!strcasecmp(v->name, "callerid")) {
- strncpy(gCallerID, v->value, sizeof(gCallerID)-1);
- }
- else if (!strcasecmp(v->name, "incominglimit")) {
- gIncomingLimit = atoi(v->value);
- }
- else if (!strcasecmp(v->name, "outgoinglimit")) {
- gOutgoingLimit = atoi(v->value);
- }
- else if (!strcasecmp(v->name, "gatekeeper")) {
- if (!strcasecmp(v->value, "DISABLE")) {
- gRasGkMode = RasNoGatekeeper;
- }
- else if (!strcasecmp(v->value, "DISCOVER")) {
- gRasGkMode = RasDiscoverGatekeeper;
- }
- else {
- gRasGkMode = RasUseSpecificGatekeeper;
- strncpy(gGatekeeper, v->value, sizeof(gGatekeeper)-1);
- }
- }
- else if (!strcasecmp(v->name, "logfile")) {
- strncpy(gLogFile, v->value, sizeof(gLogFile)-1);
- }
- else if (!strcasecmp(v->name, "context")) {
- strncpy(gContext, v->value, sizeof(gContext)-1);
- ast_verbose(VERBOSE_PREFIX_3 " == Setting default context to %s\n",
- gContext);
- }
- else if (!strcasecmp(v->name, "rtptimeout")) {
- gRTPTimeout = atoi(v->value);
- if(gRTPTimeout <= 0)
- gRTPTimeout = 60;
- }
- else if (!strcasecmp(v->name, "tos")) {
- if (sscanf(v->value, "%i", &format) == 1)
- gTOS = format & 0xff;
- else if (!strcasecmp(v->value, "lowdelay"))
- gTOS = IPTOS_LOWDELAY;
- else if (!strcasecmp(v->value, "throughput"))
- gTOS = IPTOS_THROUGHPUT;
- else if (!strcasecmp(v->value, "reliability"))
- gTOS = IPTOS_RELIABILITY;
- else if (!strcasecmp(v->value, "mincost"))
- gTOS = IPTOS_MINCOST;
- else if (!strcasecmp(v->value, "none"))
- gTOS = 0;
- else
- ast_log(LOG_WARNING, "Invalid tos value at line %d, should be "
- "'lowdelay', 'throughput', 'reliability', "
- "'mincost', or 'none'\n", v->lineno);
- }
- else if(!strcasecmp(v->name, "amaflags")) {
- gAMAFLAGS = ast_cdr_amaflags2int(v->value);
- }
- else if(!strcasecmp(v->name, "accountcode")) {
- strncpy(gAccountcode, v->value, sizeof(gAccountcode)-1);
- }
- else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0);
- }
- else if (!strcasecmp(v->name, "allow")) {
- const char* tcodecs = v->value;
- if(!strcasecmp(v->value, "all")) {
- tcodecs = "ulaw,alaw,g729,g723,gsm";
- }
- ast_parse_allow_disallow(&gPrefs, &gCapability, tcodecs, 1);
- }
- else if (!strcasecmp(v->name, "dtmfmode")) {
- if (!strcasecmp(v->value, "inband"))
- gDTMFMode=H323_DTMF_INBAND;
- else if (!strcasecmp(v->value, "rfc2833"))
- gDTMFMode = H323_DTMF_RFC2833;
- else if (!strcasecmp(v->value, "q931keypad"))
- gDTMFMode = H323_DTMF_Q931;
- else if (!strcasecmp(v->value, "h245alphanumeric"))
- gDTMFMode = H323_DTMF_H245ALPHANUMERIC;
- else if (!strcasecmp(v->value, "h245signal"))
- gDTMFMode = H323_DTMF_H245SIGNAL;
- else {
- ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n",
- v->value);
- gDTMFMode = H323_DTMF_RFC2833;
- }
- }
- v = v->next;
- }
+ int format;
+ struct ooAliases *pNewAlias = NULL;
+ struct ast_config *cfg;
+ struct ast_variable *v;
+ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+ struct ooh323_user *user = NULL;
+ struct ooh323_peer *peer = NULL;
+ char *cat;
+ const char *utype;
+
+ if (gH323Debug)
+ ast_verbose("--- reload_config\n");
+
+ cfg = ast_config_load((char*)config, config_flags);
+
+ /* We *must* have a config file otherwise stop immediately */
+ if (!cfg) {
+ ast_log(LOG_NOTICE, "Unable to load config %s, OOH323 disabled\n", config);
+ return 1;
+ } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+ return RESULT_SUCCESS;
+
+ if (reload) {
+ delete_users();
+ delete_peers();
+ }
+
+ /* Inintialize everything to default */
+ strcpy(gLogFile, DEFAULT_LOGFILE);
+ gPort = 1720;
+ gIP[0] = '\0';
+ strcpy(gCallerID, DEFAULT_H323ID);
+ gCapability = AST_FORMAT_ULAW;
+ memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
+ gDTMFMode = H323_DTMF_RFC2833;
+ gRasGkMode = RasNoGatekeeper;
+ gGatekeeper[0] = '\0';
+ gRTPTimeout = 60;
+ strcpy(gAccountcode, DEFAULT_H323ACCNT);
+ gFastStart = 1;
+ gTunneling = 1;
+ gTOS = 0;
+ strcpy(gContext, DEFAULT_CONTEXT);
+ gAliasList = NULL;
+ gMediaWaitForConnect = 0;
+ ooconfig.mTCPPortStart = 12030;
+ ooconfig.mTCPPortEnd = 12230;
+
+ v = ast_variable_browse(cfg, "general");
+ while (v) {
- cat = ast_category_browse(cfg, NULL);
- while(cat)
- {
- if(strcasecmp(cat, "general"))
- {
- int friend_type = 0;
- utype = ast_variable_retrieve(cfg, cat, "type");
- if(utype)
- {
- friend_type = strcasecmp(utype, "friend");
- if(!strcmp(utype, "user") || 0 == friend_type)
- {
- user = build_user(cat, ast_variable_browse(cfg, cat));
- if (user)
- {
- ast_mutex_lock(&userl.lock);
- user->next = userl.users;
- userl.users = user;
- ast_mutex_unlock(&userl.lock);
- }
- else {
- ast_log(LOG_WARNING, "Failed to build user %s\n", cat);
- }
- }
- if(!strcasecmp(utype, "peer") || 0 == friend_type)
- {
- peer = build_peer(cat, ast_variable_browse(cfg, cat), friend_type);
- if(peer)
- {
- ast_mutex_lock(&peerl.lock);
- peer->next = peerl.peers;
- peerl.peers = peer;
- ast_mutex_unlock(&peerl.lock);
- }
- else {
- ast_log(LOG_WARNING, "Failed to build peer %s\n", cat);
- }
- }
- }
- }
- cat = ast_category_browse(cfg, cat);
- }
- ast_config_destroy(cfg);
-
-
- /* Determine ip address if neccessary */
- if(!strlen(gIP))
- {
- ooGetLocalIPAddress(gIP);
- if(!strcmp(gIP, "127.0.0.1"))
- {
- ast_log(LOG_NOTICE, "Failed to determine local ip address. Please "
- "specify it in ooh323.conf. OOH323 Disabled\n");
- return 1;
- }
- }
+ if (!strcasecmp(v->name, "port")) {
+ gPort = (int)strtol(v->value, NULL, 10);
+ } else if (!strcasecmp(v->name, "bindaddr")) {
+ ast_copy_string(gIP, v->value, sizeof(gIP));
+ } else if (!strcasecmp(v->name, "h225portrange")) {
+ char* endlimit = 0;
+ char temp[256];
+ ast_copy_string(temp, v->value, sizeof(temp));
+ endlimit = strchr(temp, ',');
+ if (endlimit) {
+ *endlimit = '\0';
+ endlimit++;
+ ooconfig.mTCPPortStart = atoi(temp);
+ ooconfig.mTCPPortEnd = atoi(endlimit);
+
+ if (ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart,
+ ooconfig.mTCPPortEnd) == OO_FAILED) {
+ ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
+ }
+ } else {
+ ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
+ }
+ } else if (!strcasecmp(v->name, "gateway")) {
+ gIsGateway = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "faststart")) {
+ gFastStart = ast_true(v->value);
+ if (gFastStart)
+ ooH323EpEnableFastStart();
+ else
+ ooH323EpDisableFastStart();
+ } else if (!strcasecmp(v->name, "mediawaitforconnect")) {
+ gMediaWaitForConnect = ast_true(v->value);
+ if (gMediaWaitForConnect)
+ ooH323EpEnableMediaWaitForConnect();
+ else
+ ooH323EpDisableMediaWaitForConnect();
+ } else if (!strcasecmp(v->name, "h245tunneling")) {
+ gTunneling = ast_true(v->value);
+ if (gTunneling)
+ ooH323EpEnableH245Tunneling();
+ else
+ ooH323EpDisableH245Tunneling();
+ } else if (!strcasecmp(v->name, "h323id")) {
+ pNewAlias = malloc(sizeof(*pNewAlias));
+ if (!pNewAlias) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
+ return 1;
+ }
+ pNewAlias->type = T_H225AliasAddress_h323_ID;
+ pNewAlias->value = strdup(v->value);
+ pNewAlias->next = gAliasList;
+ gAliasList = pNewAlias;
+ pNewAlias = NULL;
+ } else if (!strcasecmp(v->name, "e164")) {
+ pNewAlias = malloc(sizeof(*pNewAlias));
+ if (!pNewAlias) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
+ return 1;
+ }
+ pNewAlias->type = T_H225AliasAddress_dialedDigits;
+ pNewAlias->value = strdup(v->value);
+ pNewAlias->next = gAliasList;
+ gAliasList = pNewAlias;
+ pNewAlias = NULL;
+ } else if (!strcasecmp(v->name, "email")) {
+ pNewAlias = malloc(sizeof(*pNewAlias));
+ if (!pNewAlias) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
+ return 1;
+ }
+ pNewAlias->type = T_H225AliasAddress_email_ID;
+ pNewAlias->value = strdup(v->value);
+ pNewAlias->next = gAliasList;
+ gAliasList = pNewAlias;
+ pNewAlias = NULL;
+ } else if (!strcasecmp(v->name, "callerid")) {
+ ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
+ } else if (!strcasecmp(v->name, "incominglimit")) {
+ gIncomingLimit = atoi(v->value);
+ } else if (!strcasecmp(v->name, "outgoinglimit")) {
+ gOutgoingLimit = atoi(v->value);
+ } else if (!strcasecmp(v->name, "gatekeeper")) {
+ if (!strcasecmp(v->value, "DISABLE")) {
+ gRasGkMode = RasNoGatekeeper;
+ } else if (!strcasecmp(v->value, "DISCOVER")) {
+ gRasGkMode = RasDiscoverGatekeeper;
+ } else {
+ gRasGkMode = RasUseSpecificGatekeeper;
+ ast_copy_string(gGatekeeper, v->value, sizeof(gGatekeeper));
+ }
+ } else if (!strcasecmp(v->name, "logfile")) {
+ ast_copy_string(gLogFile, v->value, sizeof(gLogFile));
+ } else if (!strcasecmp(v->name, "context")) {
+ ast_copy_string(gContext, v->value, sizeof(gContext));
+ ast_verb(3, " == Setting default context to %s\n", gContext);
+ } else if (!strcasecmp(v->name, "rtptimeout")) {
+ gRTPTimeout = atoi(v->value);
+ if (gRTPTimeout <= 0)
+ gRTPTimeout = 60;
+ } else if (!strcasecmp(v->name, "tos")) {
+ if (sscanf(v->value, "%i", &format) == 1)
+ gTOS = format & 0xff;
+ else if (!strcasecmp(v->value, "lowdelay"))
+ gTOS = IPTOS_LOWDELAY;
+ else if (!strcasecmp(v->value, "throughput"))
+ gTOS = IPTOS_THROUGHPUT;
+ else if (!strcasecmp(v->value, "reliability"))
+ gTOS = IPTOS_RELIABILITY;
+ else if (!strcasecmp(v->value, "mincost"))
+ gTOS = IPTOS_MINCOST;
+ else if (!strcasecmp(v->value, "none"))
+ gTOS = 0;
+ else
+ ast_log(LOG_WARNING, "Invalid tos value at line %d, should be "
+ "'lowdelay', 'throughput', 'reliability', "
+ "'mincost', or 'none'\n", v->lineno);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+ gAMAFLAGS = ast_cdr_amaflags2int(v->value);
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)-1);
+ } else if (!strcasecmp(v->name, "disallow")) {
+ ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0);
+ } else if (!strcasecmp(v->name, "allow")) {
+ const char* tcodecs = v->value;
+ if (!strcasecmp(v->value, "all")) {
+ tcodecs = "ulaw,alaw,g729,g723,gsm";
+ }
+ ast_parse_allow_disallow(&gPrefs, &gCapability, tcodecs, 1);
+ } else if (!strcasecmp(v->name, "dtmfmode")) {
+ if (!strcasecmp(v->value, "inband"))
+ gDTMFMode = H323_DTMF_INBAND;
+ else if (!strcasecmp(v->value, "rfc2833"))
+ gDTMFMode = H323_DTMF_RFC2833;
+ else if (!strcasecmp(v->value, "q931keypad"))
+ gDTMFMode = H323_DTMF_Q931;
+ else if (!strcasecmp(v->value, "h245alphanumeric"))
+ gDTMFMode = H323_DTMF_H245ALPHANUMERIC;
+ else if (!strcasecmp(v->value, "h245signal"))
+ gDTMFMode = H323_DTMF_H245SIGNAL;
+ else {
+ ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
+ gDTMFMode = H323_DTMF_RFC2833;
+ }
+ }
+ v = v->next;
+ }
+
+ for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
+ if (strcasecmp(cat, "general")) {
+ int friend_type = 0;
+ utype = ast_variable_retrieve(cfg, cat, "type");
+ if (utype) {
+ friend_type = strcasecmp(utype, "friend");
+ if (!strcmp(utype, "user") || 0 == friend_type) {
+ user = build_user(cat, ast_variable_browse(cfg, cat));
+ if (user) {
+ ast_mutex_lock(&userl.lock);
+ user->next = userl.users;
+ userl.users = user;
+ ast_mutex_unlock(&userl.lock);
+ } else {
+ ast_log(LOG_WARNING, "Failed to build user %s\n", cat);
+ }
+ }
+ if (!strcasecmp(utype, "peer") || 0 == friend_type) {
+ peer = build_peer(cat, ast_variable_browse(cfg, cat), friend_type);
+ if (peer) {
+ ast_mutex_lock(&peerl.lock);
+ peer->next = peerl.peers;
+ peerl.peers = peer;
+ ast_mutex_unlock(&peerl.lock);
+ } else {
+ ast_log(LOG_WARNING, "Failed to build peer %s\n", cat);
+ }
+ }
+ }
+ }
+ }
+ ast_config_destroy(cfg);
+
+
+ /* Determine ip address if neccessary */
+ if (ast_strlen_zero(gIP)) {
+ ooGetLocalIPAddress(gIP);
+ if (!strcmp(gIP, "127.0.0.1")) {
+ ast_log(LOG_NOTICE, "Failed to determine local ip address. Please "
+ "specify it in ooh323.conf. OOH323 Disabled\n");
+ return 1;
+ }
+ }
- if(gH323Debug)
- ast_verbose("+++ reload_config\n");
+ if (gH323Debug)
+ ast_verbose("+++ reload_config\n");
- return 0;
+ return 0;
}
static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2179,7 +1985,7 @@
e->command = "ooh323 show peer";
e->usage =
"Usage: ooh323 show peer <name>\n"
- " List details of specific OOH323 peer.\n";
+ " List details of specific OOH323 peer.\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2238,7 +2044,7 @@
{
char ip_port[30];
char formats[512];
- struct ooh323_peer *prev = NULL, *peer=NULL;
+ struct ooh323_peer *prev = NULL, *peer = NULL;
#define FORMAT "%-15.15s %-15.15s %-23.23s %-s\n"
@@ -2247,7 +2053,7 @@
e->command = "ooh323 show peers";
e->usage =
"Usage: ooh323 show peers\n"
- " Lists all known OOH323 peers.\n";
+ " Lists all known OOH323 peers.\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2266,7 +2072,7 @@
ast_cli(a->fd, FORMAT, peer->name,
peer->accountcode,
ip_port,
- ast_getformatname_multiple(formats, 512, peer->capability));
+ ast_getformatname_multiple(formats, sizeof(formats), peer->capability));
prev = peer;
peer = peer->next;
ast_mutex_unlock(&prev->lock);
@@ -2283,7 +2089,7 @@
{
int x, codec;
- for(x = 0; x < 32 ; x++) {
+ for (x = 0; x < 32; x++) {
codec = ast_codec_pref_index(pref, x);
if (!codec)
break;
@@ -2291,7 +2097,7 @@
ast_cli(fd, ":%d", pref->framing[x]);
if (x < 31 && ast_codec_pref_index(pref, x + 1))
ast_cli(fd, ",");
- }
+ }
if (!x)
ast_cli(fd, "none");
}
@@ -2305,7 +2111,7 @@
e->command = "ooh323 show user";
e->usage =
"Usage: ooh323 show user <name>\n"
- " List details of specific OOH323 user.\n";
+ " List details of specific OOH323 user.\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2339,7 +2145,7 @@
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)
+ else if (user->dtmfmode & H323_DTMF_H245SIGNAL)
ast_cli(a->fd, "%s\n", "h245signal");
else
ast_cli(a->fd, "%s\n", "unknown");
@@ -2360,8 +2166,8 @@
static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char formats[512];
- struct ooh323_user *prev = NULL, *user=NULL;
+ char formats[512];
+ struct ooh323_user *prev = NULL, *user = NULL;
#define FORMAT1 "%-15.15s %-15.15s %-15.15s %-s\n"
@@ -2370,7 +2176,7 @@
e->command = "ooh323 show users";
e->usage =
"Usage: ooh323 show users \n"
- " Lists all known OOH323 users.\n";
+ " Lists all known OOH323 users.\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2396,7 +2202,7 @@
#undef FORMAT1
- return CLI_SUCCESS;
+ return CLI_SUCCESS;
}
static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2406,7 +2212,7 @@
e->command = "ooh323 set debug [off]";
e->usage =
"Usage: ooh323 set debug [off]\n"
- " Enables/Disables debugging of OOH323 channel driver\n";
+ " Enables/Disables debugging of OOH323 channel driver\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2426,21 +2232,21 @@
#if 0
static int ooh323_show_channels(int fd, int argc, char *argv[])
{
- return RESULT_SUCCESS;
+ return RESULT_SUCCESS;
}
#endif
static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char value[512];
- ooAliases *pAlias = NULL, *pAliasNext=NULL;;
+ ooAliases *pAlias = NULL, *pAliasNext = NULL;;
switch (cmd) {
case CLI_INIT:
e->command = "ooh323 show config";
e->usage =
"Usage: ooh323 show config\n"
- " Shows global configuration of H.323 channel driver\n";
+ " Shows global configuration of H.323 channel driver\n";
return NULL;
case CLI_GENERATE:
return NULL;
@@ -2457,7 +2263,7 @@
ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect ? "yes" : "no");
-#if (0)
+#if 0
{
extern OOH323EndPoint gH323ep;
@@ -2486,9 +2292,9 @@
ast_cli(a->fd, "%s\n", "rfc2833");
else if (gDTMFMode & H323_DTMF_Q931)
ast_cli(a->fd, "%s\n", "q931keypad");
- else if(gDTMFMode & H323_DTMF_H245ALPHANUMERIC)
+ else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC)
ast_cli(a->fd, "%s\n", "h245alphanumeric");
- else if(gDTMFMode & H323_DTMF_H245SIGNAL)
+ else if (gDTMFMode & H323_DTMF_H245SIGNAL)
ast_cli(a->fd, "%s\n", "h245signal");
else
ast_cli(a->fd, "%s\n", "unknown");
@@ -2498,7 +2304,7 @@
pAlias = gAliasList;
if (pAlias)
ast_cli(a->fd, "%-20s\n", "Aliases: ");
- while(pAlias) {
+ while (pAlias) {
pAliasNext = pAlias->next;
if (pAliasNext) {
ast_cli(a->fd, "\t%-30s\t%-30s\n", pAlias->value, pAliasNext->value);
@@ -2513,31 +2319,31 @@
}
static struct ast_cli_entry cli_ooh323[] = {
- AST_CLI_DEFINE(handle_cli_ooh323_set_debug, "Enable/Disable OOH323 debugging"),
+ AST_CLI_DEFINE(handle_cli_ooh323_set_debug, "Enable/Disable OOH323 debugging"),
AST_CLI_DEFINE(handle_cli_ooh323_show_config, "Show details on global configuration of H.323 channel driver"),
- AST_CLI_DEFINE(handle_cli_ooh323_show_peer, "Show details on specific OOH323 peer"),
+ AST_CLI_DEFINE(handle_cli_ooh323_show_peer, "Show details on specific OOH323 peer"),
AST_CLI_DEFINE(handle_cli_ooh323_show_peers, "Show defined OOH323 peers"),
- AST_CLI_DEFINE(handle_cli_ooh323_show_user, "Show details on specific OOH323 user"),
+ AST_CLI_DEFINE(handle_cli_ooh323_show_user, "Show details on specific OOH323 user"),
AST_CLI_DEFINE(handle_cli_ooh323_show_users, "Show defined OOH323 users"),
};
static int load_module(void)
{
- int res;
- struct ooAliases * pNewAlias=NULL;
- struct ooh323_peer *peer=NULL;
- OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
-
- OOH323CALLBACKS h323Callbacks ={
- .onNewCallCreated = onNewCallCreated,
- .onAlerting = onAlerting,
- .onIncomingCall = NULL,
- .onOutgoingCall = NULL,
- .onCallEstablished = onCallEstablished,
- .onCallCleared = onCallCleared,
- .openLogicalChannels=NULL,
- .onReceivedDTMF = &ooh323_onReceivedDigit
- };
+ int res;
+ struct ooAliases * pNewAlias = NULL;
+ struct ooh323_peer *peer = NULL;
+ OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
+
+ OOH323CALLBACKS h323Callbacks = {
+ .onNewCallCreated = onNewCallCreated,
+ .onAlerting = onAlerting,
+ .onIncomingCall = NULL,
+ .onOutgoingCall = NULL,
+ .onCallEstablished = onCallEstablished,
+ .onCallCleared = onCallCleared,
+ .openLogicalChannels = NULL,
+ .onReceivedDTMF = &ooh323_onReceivedDigit
+ };
ast_log(LOG_NOTICE,
"---------------------------------------------------------------------------------\n"
@@ -2547,590 +2353,571 @@
"---\n"
"---------------------------------------------------------------------------------\n");
- h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
+ h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
- userl.users = NULL;
- ast_mutex_init(&userl.lock);
- peerl.peers = NULL;
- ast_mutex_init(&peerl.lock);
+ userl.users = NULL;
+ ast_mutex_init(&userl.lock);
+ peerl.peers = NULL;
+ ast_mutex_init(&peerl.lock);
-#if 0
- ast_register_atexit(&ast_ooh323c_exit);
+#if 0
+ ast_register_atexit(&ast_ooh323c_exit);
#endif
- sched = sched_context_create();
- if (!sched) {
- ast_log(LOG_WARNING, "Unable to create schedule context\n");
- }
- io = io_context_create();
- if (!io) {
- ast_log(LOG_WARNING, "Unable to create I/O context\n");
- }
-
-
- res = reload_config(0);
- if (!res) {
- /* Make sure we can register our OOH323 channel type */
- if (ast_channel_register(&ooh323_tech)) {
- ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
- return 0;
- }
- ast_rtp_proto_register(&ooh323_rtp);
- ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
-
- /* fire up the H.323 Endpoint */
- if(OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile))
- {
- ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
- "OOH323 Disabled\n");
- return 1;
- }
-
- if(gIsGateway)
- ooH323EpSetAsGateway();
-
- ooH323EpDisableAutoAnswer();
- ooH323EpSetH225MsgCallbacks(h225Callbacks);
- ooH323EpSetTraceLevel(OOTRCLVLDBGC);
- ooH323EpSetLocalAddress(gIP, gPort);
- ooH323EpSetCallerID(gCallerID);
+ if (!(sched = sched_context_create())) {
+ ast_log(LOG_WARNING, "Unable to create schedule context\n");
+ }
+ if (!(io = io_context_create())) {
+ ast_log(LOG_WARNING, "Unable to create I/O context\n");
+ }
+
+
+ if (!(res = reload_config(0))) {
+ /* Make sure we can register our OOH323 channel type */
+ if (ast_channel_register(&ooh323_tech)) {
+ ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+ return 0;
+ }
+ ast_rtp_proto_register(&ooh323_rtp);
+ ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
+
+ /* fire up the H.323 Endpoint */
+ if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
+ ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-OOH323 Disabled\n");
+ return 1;
+ }
+
+ if (gIsGateway)
+ ooH323EpSetAsGateway();
+
+ ooH323EpDisableAutoAnswer();
+ ooH323EpSetH225MsgCallbacks(h225Callbacks);
+ ooH323EpSetTraceLevel(OOTRCLVLDBGC);
+ ooH323EpSetLocalAddress(gIP, gPort);
+ ooH323EpSetCallerID(gCallerID);
- /* Set aliases if any */
- pNewAlias = gAliasList;
- while(pNewAlias)
- {
- switch(pNewAlias->type)
- {
- case T_H225AliasAddress_h323_ID:
- ooH323EpAddAliasH323ID(pNewAlias->value);
- break;
- case T_H225AliasAddress_dialedDigits:
- ooH323EpAddAliasDialedDigits(pNewAlias->value);
- break;
- case T_H225AliasAddress_email_ID:
- ooH323EpAddAliasEmailID(pNewAlias->value);
- break;
- default:
- ;
- }
- pNewAlias = pNewAlias->next;
- }
-
- ast_mutex_lock(&peerl.lock);
- peer = peerl.peers;
- while(peer)
- {
- if(peer->h323id) ooH323EpAddAliasH323ID(peer->h323id);
- if(peer->email) ooH323EpAddAliasEmailID(peer->email);
- if(peer->e164) ooH323EpAddAliasDialedDigits(peer->e164);
- if(peer->url) ooH323EpAddAliasURLID(peer->url);
- peer = peer->next;
- }
- ast_mutex_unlock(&peerl.lock);
-
-
- if(gMediaWaitForConnect)
- ooH323EpEnableMediaWaitForConnect();
- else
- ooH323EpDisableMediaWaitForConnect();
-
- /* Fast start and tunneling options */
- if(gFastStart)
- ooH323EpEnableFastStart();
- else
- ooH323EpDisableFastStart();
-
- if(!gTunneling)
- ooH323EpDisableH245Tunneling();
-
- /* Gatekeeper */
- if(gRasGkMode == RasUseSpecificGatekeeper)
- ooGkClientInit(gRasGkMode, gGatekeeper, 0);
- else if(gRasGkMode == RasDiscoverGatekeeper)
- ooGkClientInit(gRasGkMode, 0, 0);
-
- /* Register callbacks */
- ooH323EpSetH323Callbacks(h323Callbacks);
-
- /* Add endpoint capabilities */
- if(ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode)<0) {
- ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
- return 1;
- }
+ /* Set aliases if any */
+ for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
+ switch (pNewAlias->type) {
+ case T_H225AliasAddress_h323_ID:
+ ooH323EpAddAliasH323ID(pNewAlias->value);
+ break;
+ case T_H225AliasAddress_dialedDigits:
+ ooH323EpAddAliasDialedDigits(pNewAlias->value);
+ break;
+ case T_H225AliasAddress_email_ID:
+ ooH323EpAddAliasEmailID(pNewAlias->value);
+ break;
+ }
+ }
+
+ ast_mutex_lock(&peerl.lock);
+ peer = peerl.peers;
+ while (peer) {
+ if (peer->h323id)
+ ooH323EpAddAliasH323ID(peer->h323id);
+ if (peer->email)
+ ooH323EpAddAliasEmailID(peer->email);
+ if (peer->e164)
+ ooH323EpAddAliasDialedDigits(peer->e164);
+ if (peer->url)
+ ooH323EpAddAliasURLID(peer->url);
+ peer = peer->next;
+ }
+ ast_mutex_unlock(&peerl.lock);
+
+
+ if (gMediaWaitForConnect)
+ ooH323EpEnableMediaWaitForConnect();
+ else
+ ooH323EpDisableMediaWaitForConnect();
+
+ /* Fast start and tunneling options */
+ if (gFastStart)
+ ooH323EpEnableFastStart();
+ else
+ ooH323EpDisableFastStart();
+
+ if (!gTunneling)
+ ooH323EpDisableH245Tunneling();
+
+ /* Gatekeeper */
+ if (gRasGkMode == RasUseSpecificGatekeeper)
+ ooGkClientInit(gRasGkMode, gGatekeeper, 0);
+ else if (gRasGkMode == RasDiscoverGatekeeper)
+ ooGkClientInit(gRasGkMode, 0, 0);
+
+ /* Register callbacks */
+ ooH323EpSetH323Callbacks(h323Callbacks);
+
+ /* Add endpoint capabilities */
+ if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode) < 0) {
+ ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
+ return 1;
+ }
- /* Create H.323 listener */
- if(ooCreateH323Listener()!= OO_OK)
- {
- ast_log(LOG_ERROR, "OOH323 Listener Creation failure. "
- "OOH323 DISABLED\n");
-
- ooH323EpDestroy();
- return 1;
- }
-
- if(ooh323c_start_stack_thread() <0)
- {
- ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
- "OOH323 DISABLED\n");
- ooH323EpDestroy();
- return 1;
- }
- /* And start the monitor for the first time */
- restart_monitor();
- }
+ /* Create H.323 listener */
+ if (ooCreateH323Listener() != OO_OK) {
+ ast_log(LOG_ERROR, "OOH323 Listener Creation failure. OOH323 DISABLED\n");
+
+ ooH323EpDestroy();
+ return 1;
+ }
- return 0;
+ if (ooh323c_start_stack_thread() < 0) {
+ ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. OOH323 DISABLED\n");
+ ooH323EpDestroy();
+ return 1;
+ }
+ /* And start the monitor for the first time */
+ restart_monitor();
+ }
+
+ return 0;
}
static void *do_monitor(void *data)
{
- int res;
- int reloading;
- struct ooh323_pvt *h323 = NULL;
- time_t t;
-
- for(;;) {
- struct ooh323_pvt *h323_next;
- /* Check for a reload request */
- ast_mutex_lock(&h323_reload_lock);
- reloading = h323_reloading;
- h323_reloading = 0;
- ast_mutex_unlock(&h323_reload_lock);
- if (reloading) {
- if (option_verbose > 0) {
- ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
- }
- ooh323_do_reload();
- }
- /* Check for interfaces needing to be killed */
- ast_mutex_lock(&iflock);
- time(&t);
- h323 = iflist;
- while(h323) {
- h323_next = h323->next;
-
- /*TODO: Need to add rtptimeout keepalive support */
- if(ast_test_flag(h323, H323_NEEDDESTROY)) {
- ooh323_destroy (h323);
- }
- h323 = h323_next;
- }
- ast_mutex_unlock(&iflock);
- pthread_testcancel();
- /* Wait for sched or io */
- res = ast_sched_wait(sched);
- if ((res < 0) || (res > 1000)) {
- res = 1000;
- }
- res = ast_io_wait(io, res);
- pthread_testcancel();
- ast_mutex_lock(&monlock);
- if (res >= 0) {
- ast_sched_runq(sched);
- }
- ast_mutex_unlock(&monlock);
- }
- /* Never reached */
- return NULL;
+ int res;
+ int reloading;
+ struct ooh323_pvt *h323 = NULL;
+ time_t t;
+
+ for (;;) {
+ struct ooh323_pvt *h323_next;
+ /* Check for a reload request */
+ ast_mutex_lock(&h323_reload_lock);
+ reloading = h323_reloading;
+ h323_reloading = 0;
+ ast_mutex_unlock(&h323_reload_lock);
+ if (reloading) {
+ ast_verb(1, "Reloading H.323\n");
+ ooh323_do_reload();
+ }
+ /* Check for interfaces needing to be killed */
+ ast_mutex_lock(&iflock);
+ time(&t);
+ h323 = iflist;
+ while (h323) {
+ h323_next = h323->next;
+
+ /* TODO: Need to add rtptimeout keepalive support */
+ if (ast_test_flag(h323, H323_NEEDDESTROY)) {
+ ooh323_destroy (h323);
+ }
+ h323 = h323_next;
+ }
+ ast_mutex_unlock(&iflock);
+ pthread_testcancel();
+ /* Wait for sched or io */
+ res = ast_sched_wait(sched);
+ if ((res < 0) || (res > 1000)) {
+ res = 1000;
+ }
+ res = ast_io_wait(io, res);
+ pthread_testcancel();
+ ast_mutex_lock(&monlock);
+ if (res >= 0) {
+ ast_sched_runq(sched);
+ }
+ ast_mutex_unlock(&monlock);
+ }
+ /* Never reached */
+ return NULL;
}
int restart_monitor(void)
{
- pthread_attr_t attr;
+ pthread_attr_t attr;
- /* If we're supposed to be stopped -- stay stopped */
- if (monitor_thread == AST_PTHREADT_STOP)
- return 0;
- if (ast_mutex_lock(&monlock)) {
- ast_log(LOG_WARNING, "Unable to lock monitor\n");
- return -1;
- }
- if (monitor_thread == pthread_self()) {
- ast_mutex_unlock(&monlock);
- ast_log(LOG_WARNING, "Cannot kill myself\n");
- return -1;
- }
- if (monitor_thread != AST_PTHREADT_NULL) {
- /* Wake up the thread */
- pthread_kill(monitor_thread, SIGURG);
- }
- else {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- /* Start a new monitor */
- if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
- ast_mutex_unlock(&monlock);
- ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
- return -1;
- }
- }
- ast_mutex_unlock(&monlock);
- return 0;
+ /* If we're supposed to be stopped -- stay stopped */
+ if (monitor_thread == AST_PTHREADT_STOP)
+ return 0;
+ if (ast_mutex_lock(&monlock)) {
+ ast_log(LOG_WARNING, "Unable to lock monitor\n");
+ return -1;
+ }
+ if (monitor_thread == pthread_self()) {
+ ast_mutex_unlock(&monlock);
+ ast_log(LOG_WARNING, "Cannot kill myself\n");
+ return -1;
+ }
+ if (monitor_thread != AST_PTHREADT_NULL) {
+ /* Wake up the thread */
+ pthread_kill(monitor_thread, SIGURG);
+ } else {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ /* Start a new monitor */
+ if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
+ ast_mutex_unlock(&monlock);
+ ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
+ return -1;
+ }
+ }
+ ast_mutex_unlock(&monlock);
+ return 0;
}
int ooh323_destroy(struct ooh323_pvt *p)
{
- /* NOTE: Assumes iflock already acquired */
- struct ooh323_pvt *prev=NULL,*cur = NULL;
+ /* NOTE: Assumes iflock already acquired */
+ struct ooh323_pvt *prev = NULL, *cur = NULL;
+
+
+ if (gH323Debug) {
+ ast_verbose("--- ooh323_destroy \n");
+
+ if (p)
+ ast_verbose(" Destroying %s\n", p->username);
+ }
+
+ cur = iflist;
+ while (cur) {
+ if (cur == p) { break; }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ if (cur) {
+ ast_mutex_lock(&cur->lock);
+ if (prev)
+ prev->next = cur->next;
+ else
+ iflist = cur->next;
+
+ if (cur->callToken) {
+ free(cur->callToken);
+ cur->callToken = 0;
+ }
+
+ if (cur->username) {
+ free(cur->username);
+ cur->username = 0;
+ }
+
+ if (cur->host) {
+ free(cur->host);
+ cur->host = 0;
+ }
+
+ if (cur->callerid_name) {
+ free(cur->callerid_name);
+ cur->callerid_name = 0;
+ }
+
+ if (cur->callerid_num) {
+ free(cur->callerid_num);
+ cur->callerid_num = 0;
+ }
- if(gH323Debug)
- {
- ast_verbose("--- ooh323_destroy \n");
-
- if(p)
- ast_verbose(" Destroying %s\n", p->username);
- }
-
- cur = iflist;
- while(cur)
- {
- if(cur == p) { break; }
- prev = cur;
- cur = cur->next;
- }
-
- if(cur)
- {
- ast_mutex_lock(&cur->lock);
- if(prev)
- prev->next = cur->next;
- else
- iflist = cur->next;
-
- if(cur->callToken) {
- free(cur->callToken);
- cur->callToken = 0;
- }
-
- if(cur->username) {
- free(cur->username);
- cur->username = 0;
- }
-
- if(cur->host) {
- free(cur->host);
- cur->host = 0;
- }
-
- if(cur->callerid_name) {
- free(cur->callerid_name);
- cur->callerid_name = 0;
- }
-
- if(cur->callerid_num) {
- free(cur->callerid_num);
- cur->callerid_num = 0;
- }
-
-
- if (cur->rtp) {
- ast_rtp_destroy(cur->rtp);
- cur->rtp = 0;
- }
+ if (cur->rtp) {
+ ast_rtp_destroy(cur->rtp);
+ cur->rtp = 0;
+ }
- /* Unlink us from the owner if we have one */
- if (cur->owner) {
- ast_channel_lock(cur->owner);
- ast_debug(1, "Detaching from %s\n", cur->owner->name);
- cur->owner->tech_pvt = NULL;
- ast_channel_unlock(cur->owner);
- cur->owner = NULL;
- }
+ /* Unlink us from the owner if we have one */
+ if (cur->owner) {
+ ast_channel_lock(cur->owner);
+ ast_debug(1, "Detaching from %s\n", cur->owner->name);
+ cur->owner->tech_pvt = NULL;
+ ast_channel_unlock(cur->owner);
+ cur->owner = NULL;
+ }
- if (cur->vad) {
- ast_dsp_free(cur->vad);
- cur->vad = NULL;
- }
- ast_mutex_unlock(&cur->lock);
- ast_mutex_destroy(&cur->lock);
+ if (cur->vad) {
+ ast_dsp_free(cur->vad);
+ cur->vad = NULL;
+ }
+ ast_mutex_unlock(&cur->lock);
+ ast_mutex_destroy(&cur->lock);
- free(cur);
- }
+ free(cur);
+ }
- if(gH323Debug)
- ast_verbose("+++ ooh323_destroy\n");
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_destroy\n");
- return 0;
+ return 0;
}
int delete_peers()
{
- struct ooh323_peer *cur=NULL, *prev=NULL;
- ast_mutex_lock(&peerl.lock);
- cur = peerl.peers;
- while(cur)
- {
- prev = cur;
- cur = cur->next;
-
- ast_mutex_destroy(&prev->lock);
- if(prev->h323id) free(prev->h323id);
- if(prev->email) free(prev->email);
- if(prev->url) free(prev->url);
- if(prev->e164) free(prev->e164);
- free(prev);
-
- if(cur == peerl.peers) { break; }
- }
- peerl.peers = NULL;
- ast_mutex_unlock(&peerl.lock);
- return 0;
+ struct ooh323_peer *cur = NULL, *prev = NULL;
+ ast_mutex_lock(&peerl.lock);
+ cur = peerl.peers;
+ while (cur) {
+ prev = cur;
+ cur = cur->next;
+
+ ast_mutex_destroy(&prev->lock);
+ if (prev->h323id)
+ free(prev->h323id);
+ if (prev->email)
+ free(prev->email);
+ if (prev->url)
+ free(prev->url);
+ if (prev->e164)
+ free(prev->e164);
+ free(prev);
+
+ if (cur == peerl.peers) {
+ break;
+ }
+ }
+ peerl.peers = NULL;
+ ast_mutex_unlock(&peerl.lock);
+ return 0;
}
int delete_users()
{
- struct ooh323_user *cur=NULL, *prev=NULL;
- ast_mutex_lock(&userl.lock);
- cur = userl.users;
- while(cur)
- {
- prev = cur;
- cur = cur->next;
- ast_mutex_destroy(&prev->lock);
- free(prev);
- if(cur == userl.users) { break; }
- }
- userl.users = NULL;
- ast_mutex_unlock(&userl.lock);
- return 0;
+ struct ooh323_user *cur = NULL, *prev = NULL;
+ ast_mutex_lock(&userl.lock);
+ cur = userl.users;
+ while (cur) {
+ prev = cur;
+ cur = cur->next;
+ ast_mutex_destroy(&prev->lock);
+ free(prev);
+ if (cur == userl.users) {
+ break;
+ }
+ }
+ userl.users = NULL;
+ ast_mutex_unlock(&userl.lock);
+ return 0;
}
static int unload_module(void)
{
- struct ooh323_pvt *p;
- struct ooAliases *cur=NULL, *prev=NULL;
+ struct ooh323_pvt *p;
+ struct ooAliases *cur = NULL, *prev = NULL;
- if(gH323Debug) {
- ast_verbose("--- ooh323 unload_module \n");
- }
- /* First, take us out of the channel loop */
- ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
- ast_rtp_proto_unregister(&ooh323_rtp);
- ast_channel_unregister(&ooh323_tech);
+ if (gH323Debug) {
+ ast_verbose("--- ooh323 unload_module \n");
+ }
+ /* First, take us out of the channel loop */
+ ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
+ ast_rtp_proto_unregister(&ooh323_rtp);
+ ast_channel_unregister(&ooh323_tech);
#if 0
- ast_unregister_atexit(&ast_ooh323c_exit);
+ ast_unregister_atexit(&ast_ooh323c_exit);
#endif
- if(gH323Debug) {
- ast_verbose(" unload_module - hanging up all interfaces\n");
- }
- if (!ast_mutex_lock(&iflock)) {
- /* Hangup all interfaces if they have an owner */
- p = iflist;
- while(p) {
- if (p->owner) {
- ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
- }
- p = p->next;
- }
- iflist = NULL;
- ast_mutex_unlock(&iflock);
- }
- else {
- ast_log(LOG_WARNING, "Unable to lock the interface list\n");
- return -1;
- }
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module - stopping monitor thread\n");
- }
- if (monitor_thread != AST_PTHREADT_NULL)
- {
- if(!ast_mutex_lock(&monlock)) {
- if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
- pthread_cancel(monitor_thread);
- pthread_kill(monitor_thread, SIGURG);
- pthread_join(monitor_thread, NULL);
- }
- monitor_thread = AST_PTHREADT_STOP;
- ast_mutex_unlock(&monlock);
- }
- else {
- ast_log(LOG_WARNING, "Unable to lock the monitor\n");
- return -1;
- }
- }
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module - stopping stack thread\n");
- }
- ooh323c_stop_stack_thread();
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module - freeing up memory used by interfaces\n");
- }
- if (!ast_mutex_lock(&iflock)) {
- struct ooh323_pvt *pl;
-
- /* Destroy all the interfaces and free their memory */
- p = iflist;
- while(p) {
- pl = p;
- p = p->next;
- /* Free associated memory */
- ooh323_destroy(pl);
- }
- iflist = NULL;
- ast_mutex_unlock(&iflock);
- }
- else {
- ast_log(LOG_WARNING, "Unable to lock the interface list\n");
- return -1;
- }
+ if (gH323Debug) {
+ ast_verbose(" unload_module - hanging up all interfaces\n");
+ }
+ if (!ast_mutex_lock(&iflock)) {
+ /* Hangup all interfaces if they have an owner */
+ p = iflist;
+ while (p) {
+ if (p->owner) {
+ ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
+ }
+ p = p->next;
+ }
+ iflist = NULL;
+ ast_mutex_unlock(&iflock);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+ return -1;
+ }
+
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module - stopping monitor thread\n");
+ }
+ if (monitor_thread != AST_PTHREADT_NULL) {
+ if (!ast_mutex_lock(&monlock)) {
+ if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
+ pthread_cancel(monitor_thread);
+ pthread_kill(monitor_thread, SIGURG);
+ pthread_join(monitor_thread, NULL);
+ }
+ monitor_thread = AST_PTHREADT_STOP;
+ ast_mutex_unlock(&monlock);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+ return -1;
+ }
+ }
+
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module - stopping stack thread\n");
+ }
+ ooh323c_stop_stack_thread();
+
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module - freeing up memory used by interfaces\n");
+ }
+ if (!ast_mutex_lock(&iflock)) {
+ struct ooh323_pvt *pl;
+
+ /* Destroy all the interfaces and free their memory */
+ p = iflist;
+ while (p) {
+ pl = p;
+ p = p->next;
+ /* Free associated memory */
+ ooh323_destroy(pl);
+ }
+ iflist = NULL;
+ ast_mutex_unlock(&iflock);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+ return -1;
+ }
- if(gH323Debug) {
- ast_verbose(" unload_module - deleting users\n");
- }
- delete_users();
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module - deleting peers\n");
- }
- delete_peers();
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module - Freeing up alias list\n");
- }
- cur = gAliasList;
- while(cur)
- {
- prev = cur;
- cur = cur->next;
- free(prev->value);
- free(prev);
- }
- gAliasList = NULL;
-
-
- if(gH323Debug) {
- ast_verbose(" unload_module- destroying OOH323 endpoint \n");
- }
- ooH323EpDestroy();
-
- if(gH323Debug) {
- ast_verbose("+++ ooh323 unload_module \n");
- }
+ if (gH323Debug) {
+ ast_verbose(" unload_module - deleting users\n");
+ }
+ delete_users();
+
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module - deleting peers\n");
+ }
+ delete_peers();
- return 0;
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module - Freeing up alias list\n");
+ }
+ cur = gAliasList;
+ while (cur) {
+ prev = cur;
+ cur = cur->next;
+ free(prev->value);
+ free(prev);
+ }
+ gAliasList = NULL;
+
+
+ if (gH323Debug) {
+ ast_verbose(" unload_module- destroying OOH323 endpoint \n");
+ }
+ ooH323EpDestroy();
+
+ if (gH323Debug) {
+ ast_verbose("+++ ooh323 unload_module \n");
+ }
+
+ return 0;
}
static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
{
- struct ooh323_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+ struct ooh323_pvt *p = NULL;
+ enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
- if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
+ if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
return AST_RTP_GET_FAILED;
- *rtp = p->rtp;
+ *rtp = p->rtp;
- if (!(p->rtp)) {
- return AST_RTP_GET_FAILED;
- }
- res = AST_RTP_TRY_NATIVE;
+ if (!(p->rtp)) {
+ return AST_RTP_GET_FAILED;
+ }
+ res = AST_RTP_TRY_NATIVE;
- return res;
+ return res;
}
static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
{
- struct ooh323_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+ struct ooh323_pvt *p = NULL;
+ enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
- if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
- return AST_RTP_GET_FAILED;
+ if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
+ return AST_RTP_GET_FAILED;
- *rtp = p->vrtp;
+ *rtp = p->vrtp;
- if (!(p->rtp)) {
- return AST_RTP_GET_FAILED;
- }
- res = AST_RTP_TRY_NATIVE;
+ if (!(p->rtp)) {
+ return AST_RTP_GET_FAILED;
+ }
+ res = AST_RTP_TRY_NATIVE;
- return res;
+ return res;
}
int ooh323_update_capPrefsOrderForCall
- (ooCallData *call, struct ast_codec_pref *prefs)
+ (ooCallData *call, struct ast_codec_pref *prefs)
{
- int i=0;
- int codec = ast_codec_pref_index(prefs, i);
+ int i = 0;
+ int codec = ast_codec_pref_index(prefs, i);
- ooResetCapPrefs(call);
- while(codec)
- {
- ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(codec));
- codec = ast_codec_pref_index(prefs, ++i);
- }
+ ooResetCapPrefs(call);
+ while (codec) {
+ ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(codec));
+ codec = ast_codec_pref_index(prefs, ++i);
+ }
- return 0;
+ return 0;
}
int ooh323_convertAsteriskCapToH323Cap(int cap)
{
- char formats[512];
- switch (cap) {
- case AST_FORMAT_ULAW:
- return OO_G711ULAW64K;
- case AST_FORMAT_ALAW:
- return OO_G711ALAW64K;
- case AST_FORMAT_GSM:
- return OO_GSMFULLRATE;
- case AST_FORMAT_G729A:
- return OO_G729A;
- case AST_FORMAT_G723_1:
- return OO_G7231;
- case AST_FORMAT_H263:
- return OO_H263VIDEO;
- default:
- ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n",
- ast_getformatname_multiple(formats,512,cap));
- return -1;
- }
-}
-
-static int ooh323_set_rtp_peer
- (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp,
- struct ast_rtp *trtp, int codecs, int nat_active)
-{
- /* XXX Deal with Video */
- struct ooh323_pvt *p;
- struct sockaddr_in them;
- struct sockaddr_in us;
- int mode;
-
- if(gH323Debug)
- ast_verbose("--- ooh323_set_peer - %s\n", chan->name);
-
- if (!rtp) {
- return 0;
- }
-
- mode = ooh323_convertAsteriskCapToH323Cap(chan->writeformat);
- p = (struct ooh323_pvt *) chan->tech_pvt;
- if (!p) {
- ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
- return -1;
- }
- ast_rtp_get_peer(rtp, &them);
- ast_rtp_get_us(rtp, &us);
- return 0;
+ char formats[512];
+ switch (cap) {
+ case AST_FORMAT_ULAW:
+ return OO_G711ULAW64K;
+ case AST_FORMAT_ALAW:
+ return OO_G711ALAW64K;
+ case AST_FORMAT_GSM:
+ return OO_GSMFULLRATE;
+ case AST_FORMAT_G729A:
+ return OO_G729A;
+ case AST_FORMAT_G723_1:
+ return OO_G7231;
+ case AST_FORMAT_H263:
+ return OO_H263VIDEO;
+ default:
+ ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n",
+ ast_getformatname_multiple(formats, sizeof(formats), cap));
+ return -1;
+ }
+}
+
+static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
+ struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
+{
+ /* XXX Deal with Video */
+ struct ooh323_pvt *p;
+ struct sockaddr_in them;
+ struct sockaddr_in us;
+ int mode;
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323_set_peer - %s\n", chan->name);
+
+ if (!rtp) {
+ return 0;
+ }
+
+ mode = ooh323_convertAsteriskCapToH323Cap(chan->writeformat);
+ p = (struct ooh323_pvt *) chan->tech_pvt;
+ if (!p) {
+ ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
+ return -1;
+ }
+ ast_rtp_get_peer(rtp, &them);
+ ast_rtp_get_us(rtp, &us);
+ return 0;
}
@@ -3138,248 +2925,233 @@
int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
{
- struct sockaddr_in us;
- ooMediaInfo mediaInfo;
- int x, format=0;
-
- if(gH323Debug)
- ast_verbose("--- configure_local_rtp\n");
-
- if (p->rtp){
- ast_rtp_codec_setpref(p->rtp, &p->prefs);
- }
-
- /* figure out our local RTP port and tell the H.323 stack about it*/
- ast_rtp_get_us(p->rtp, &us);
-
- strncpy(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP)-1);
- mediaInfo.lMediaPort = ntohs(us.sin_port);
- mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
- for(x=0; 0 != (format=ast_codec_pref_index(&p->prefs, x)); x++)
- {
- strcpy(mediaInfo.dir, "transmit");
- mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
- ooAddMediaInfo(call, mediaInfo);
- strcpy(mediaInfo.dir, "receive");
- ooAddMediaInfo(call, mediaInfo);
- if(mediaInfo.cap == OO_G729A) {
- strcpy(mediaInfo.dir, "transmit");
- mediaInfo.cap = OO_G729;
- ooAddMediaInfo(call, mediaInfo);
- strcpy(mediaInfo.dir, "receive");
- ooAddMediaInfo(call, mediaInfo);
- }
- }
+ struct sockaddr_in us;
+ ooMediaInfo mediaInfo;
+ int x, format = 0;
+
+ if (gH323Debug)
+ ast_verbose("--- configure_local_rtp\n");
+
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ }
+
+ /* figure out our local RTP port and tell the H.323 stack about it*/
+ ast_rtp_get_us(p->rtp, &us);
+
+ ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP));
+ mediaInfo.lMediaPort = ntohs(us.sin_port);
+ mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
+ for (x = 0; 0 != (format = ast_codec_pref_index(&p->prefs, x)); x++) {
+ strcpy(mediaInfo.dir, "transmit");
+ mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
+ ooAddMediaInfo(call, mediaInfo);
+ strcpy(mediaInfo.dir, "receive");
+ ooAddMediaInfo(call, mediaInfo);
+ if (mediaInfo.cap == OO_G729A) {
+ strcpy(mediaInfo.dir, "transmit");
+ mediaInfo.cap = OO_G729;
+ ooAddMediaInfo(call, mediaInfo);
+ strcpy(mediaInfo.dir, "receive");
+ ooAddMediaInfo(call, mediaInfo);
+ }
+ }
- if(gH323Debug)
- ast_verbose("+++ configure_local_rtp\n");
+ if (gH323Debug)
+ ast_verbose("+++ configure_local_rtp\n");
- return 1;
+ return 1;
}
void setup_rtp_connection(ooCallData *call, const char *remoteIp,
- int remotePort)
+ int remotePort)
{
- struct ooh323_pvt *p = NULL;
- struct sockaddr_in them;
+ struct ooh323_pvt *p = NULL;
+ struct sockaddr_in them;
- if(gH323Debug)
- ast_verbose("--- setup_rtp_connection\n");
+ if (gH323Debug)
+ ast_verbose("--- setup_rtp_connection\n");
- /* Find the call or allocate a private structure if call not found */
- p = find_call(call);
+ /* Find the call or allocate a private structure if call not found */
+ p = find_call(call);
- if (!p) {
- ast_log(LOG_ERROR, "Something is wrong: rtp\n");
- return;
- }
+ if (!p) {
+ ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+ return;
+ }
- them.sin_family = AF_INET;
- them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
- them.sin_port = htons(remotePort);
- ast_rtp_set_peer(p->rtp, &them);
+ them.sin_family = AF_INET;
+ them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
+ them.sin_port = htons(remotePort);
+ ast_rtp_set_peer(p->rtp, &them);
- if(gH323Debug)
- ast_verbose("+++ setup_rtp_connection\n");
+ if (gH323Debug) {
+ ast_verbose("+++ setup_rtp_connection\n");
+ }
- return;
+ return;
}
void close_rtp_connection(ooCallData *call)
{
- struct ooh323_pvt *p = NULL;
+ struct ooh323_pvt *p = NULL;
- if(gH323Debug)
- ast_verbose("--- close_rtp_connection\n");
+ if (gH323Debug) {
+ ast_verbose("--- close_rtp_connection\n");
+ }
- p = find_call(call);
- if(!p)
- {
- ast_log(LOG_ERROR, "Couldn't find matching call to close rtp "
- "connection\n");
- return;
- }
- ast_mutex_lock(&p->lock);
- if(p->rtp){
- ast_rtp_stop(p->rtp);
- }
- ast_mutex_unlock(&p->lock);
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "Couldn't find matching call to close rtp connection\n");
+ return;
+ }
+ ast_mutex_lock(&p->lock);
+ if (p->rtp) {
+ ast_rtp_stop(p->rtp);
+ }
+ ast_mutex_unlock(&p->lock);
- if(gH323Debug)
- ast_verbose("+++ close_rtp_connection\n");
+ if (gH323Debug) {
+ ast_verbose("+++ close_rtp_connection\n");
+ }
- return;
+ return;
}
int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
{
- int updated = -1;
- ooAliases *psAlias=NULL;
-
- if(!call->ourAliases)
- return updated;
- psAlias = call->ourAliases;
- while(psAlias)
- {
- if(psAlias->type == T_H225AliasAddress_h323_ID)
- {
- strncpy(p->callee_h323id, psAlias->value, sizeof(p->callee_h323id)-1);
- updated = 1;
- }
- if(psAlias->type == T_H225AliasAddress_dialedDigits)
- {
- strncpy(p->callee_dialedDigits, psAlias->value,
- sizeof(p->callee_dialedDigits)-1);
- updated = 1;
- }
- if(psAlias->type == T_H225AliasAddress_url_ID)
- {
- strncpy(p->callee_url, psAlias->value, sizeof(p->callee_url)-1);
- updated = 1;
- }
- if(psAlias->type == T_H225AliasAddress_email_ID)
- {
- strncpy(p->callee_email, psAlias->value, sizeof(p->callee_email)-1);
- updated = 1;
- }
- psAlias = psAlias->next;
- }
- return updated;
-}
-
-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;
- static struct ast_frame null_frame = { AST_FRAME_NULL, };
- switch(ast->fdno) {
- case 0:
- f = ast_rtp_read(p->rtp); /* RTP Audio */
- break;
- case 1:
- f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
- break;
- case 2:
- f = ast_rtp_read(p->vrtp); /* RTP Video */
- break;
- case 3:
- f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
- break;
- default:
- f = &null_frame;
- }
- /* Don't send RFC2833 if we're not supposed to */
- if (f && (f->frametype == AST_FRAME_DTMF) &&
- !(p->dtmfmode & H323_DTMF_RFC2833))
- return &null_frame;
- if (p->owner)
- {
- /* We already hold the channel lock */
- if (f->frametype == AST_FRAME_VOICE)
- {
- if (f->subclass != p->owner->nativeformats)
- {
- ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
- p->owner->nativeformats = f->subclass;
- 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->vad)
- {
- 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);
- }
- }
- }
- return f;
+ int updated = -1;
+ ooAliases *psAlias = NULL;
+
+ if (!call->ourAliases)
+ return updated;
+ for (psAlias = call->ourAliases; psAlias; psAlias = psAlias->next) {
+ if (psAlias->type == T_H225AliasAddress_h323_ID) {
+ ast_copy_string(p->callee_h323id, psAlias->value, sizeof(p->callee_h323id));
+ updated = 1;
+ }
+ if (psAlias->type == T_H225AliasAddress_dialedDigits) {
+ ast_copy_string(p->callee_dialedDigits, psAlias->value, sizeof(p->callee_dialedDigits));
+ updated = 1;
+ }
+ if (psAlias->type == T_H225AliasAddress_url_ID) {
+ ast_copy_string(p->callee_url, psAlias->value, sizeof(p->callee_url));
+ updated = 1;
+ }
+ if (psAlias->type == T_H225AliasAddress_email_ID) {
+ ast_copy_string(p->callee_email, psAlias->value, sizeof(p->callee_email));
+ updated = 1;
+ }
+ }
+ return updated;
}
-
-int ooh323_convert_hangupcause_asteriskToH323(int cause)
+struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
{
- switch(cause)
- {
- case AST_CAUSE_CALL_REJECTED:
- return OO_REASON_REMOTE_REJECTED;
- case AST_CAUSE_UNALLOCATED:
- return OO_REASON_NOUSER;
- case AST_CAUSE_BUSY:
- return OO_REASON_REMOTE_BUSY;
- case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL:
- return OO_REASON_NOCOMMON_CAPABILITIES;
- case AST_CAUSE_CONGESTION:
- return OO_REASON_REMOTE_BUSY;
- case AST_CAUSE_NO_ANSWER:
- return OO_REASON_REMOTE_NOANSWER;
- case AST_CAUSE_NORMAL:
- return OO_REASON_REMOTE_CLEARED;
- case AST_CAUSE_FAILURE:
- default:
- return OO_REASON_UNKNOWN;
- }
+ /* Retrieve audio/etc from channel. Assumes p->lock is already held. */
+ struct ast_frame *f;
+ static struct ast_frame null_frame = { AST_FRAME_NULL, };
+ switch (ast->fdno) {
+ case 0:
+ f = ast_rtp_read(p->rtp); /* RTP Audio */
+ break;
+ case 1:
+ f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
+ break;
+ case 2:
+ f = ast_rtp_read(p->vrtp); /* RTP Video */
+ break;
+ case 3:
+ f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
+ break;
+ default:
+ f = &null_frame;
+ }
+ /* Don't send RFC2833 if we're not supposed to */
+ if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) {
+ return &null_frame;
+ }
+ if (p->owner) {
+ /* We already hold the channel lock */
+ if (f->frametype == AST_FRAME_VOICE) {
+ if (f->subclass != p->owner->nativeformats) {
+ ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
+ p->owner->nativeformats = f->subclass;
+ 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->vad) {
+ 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);
+ }
+ }
+ }
+ }
+ return f;
+}
- return 0;
+int ooh323_convert_hangupcause_asteriskToH323(int cause)
+{
+ switch (cause) {
+ case AST_CAUSE_CALL_REJECTED:
+ return OO_REASON_REMOTE_REJECTED;
+ case AST_CAUSE_UNALLOCATED:
+ return OO_REASON_NOUSER;
+ case AST_CAUSE_BUSY:
+ return OO_REASON_REMOTE_BUSY;
+ case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL:
+ return OO_REASON_NOCOMMON_CAPABILITIES;
+ case AST_CAUSE_CONGESTION:
+ return OO_REASON_REMOTE_BUSY;
+ case AST_CAUSE_NO_ANSWER:
+ return OO_REASON_REMOTE_NOANSWER;
+ case AST_CAUSE_NORMAL:
+ return OO_REASON_REMOTE_CLEARED;
+ case AST_CAUSE_FAILURE:
+ default:
+ return OO_REASON_UNKNOWN;
+ }
+ return 0;
}
int ooh323_convert_hangupcause_h323ToAsterisk(int cause)
{
- switch(cause) {
- case OO_REASON_REMOTE_REJECTED:
- return AST_CAUSE_CALL_REJECTED;
- case OO_REASON_NOUSER:
- return AST_CAUSE_UNALLOCATED;
- case OO_REASON_REMOTE_BUSY:
- case OO_REASON_LOCAL_BUSY:
- return AST_CAUSE_BUSY;
- case OO_REASON_NOCOMMON_CAPABILITIES: /* No codecs approved */
- return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
- case OO_REASON_REMOTE_CONGESTED:
- case OO_REASON_LOCAL_CONGESTED:
- return AST_CAUSE_CONGESTION;
- case OO_REASON_REMOTE_NOANSWER:
- return AST_CAUSE_NO_ANSWER;
- case OO_REASON_UNKNOWN:
- case OO_REASON_INVALIDMESSAGE:
- case OO_REASON_TRANSPORTFAILURE:
- return AST_CAUSE_FAILURE;
- case OO_REASON_REMOTE_CLEARED:
- return AST_CAUSE_NORMAL;
- default:
- return AST_CAUSE_NORMAL;
- }
- /* Never reached */
- return 0;
+ switch (cause) {
+ case OO_REASON_REMOTE_REJECTED:
+ return AST_CAUSE_CALL_REJECTED;
+ case OO_REASON_NOUSER:
+ return AST_CAUSE_UNALLOCATED;
+ case OO_REASON_REMOTE_BUSY:
+ case OO_REASON_LOCAL_BUSY:
+ return AST_CAUSE_BUSY;
+ case OO_REASON_NOCOMMON_CAPABILITIES: /* No codecs approved */
+ return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+ case OO_REASON_REMOTE_CONGESTED:
+ case OO_REASON_LOCAL_CONGESTED:
+ return AST_CAUSE_CONGESTION;
+ case OO_REASON_REMOTE_NOANSWER:
+ return AST_CAUSE_NO_ANSWER;
+ case OO_REASON_UNKNOWN:
+ case OO_REASON_INVALIDMESSAGE:
+ case OO_REASON_TRANSPORTFAILURE:
+ return AST_CAUSE_FAILURE;
+ case OO_REASON_REMOTE_CLEARED:
+ return AST_CAUSE_NORMAL;
+ default:
+ return AST_CAUSE_NORMAL;
+ }
+ /* Never reached */
+ return 0;
}
#if 0
void ast_ooh323c_exit()
{
- ooGkClientDestroy();
+ ooGkClientDestroy();
}
#endif
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/channels/ooh323c/src/ooCmdChannel.c
^
|
@@ -37,7 +37,7 @@
if ((ret = pipe(thePipe)) == -1) {
return OO_FAILED;
}
- pthread_mutex_init(&gCmdChanLock);
+ pthread_mutex_init(&gCmdChanLock, NULL);
gH323ep.cmdSock = dup(thePipe[0]);
close(thePipe[0]);
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/configs/cdr_mysql.conf.sample
^
|
@@ -19,6 +19,11 @@
;port=3306
;sock=/tmp/mysql.sock
;
+; If your system's locale differs from mysql database character set,
+; cdr_mysql can damage non-latin characters in CDR variables. Use this
+; option to protect your data.
+;charset=koi8r
+;
; Older versions of cdr_mysql set the calldate field to whenever the
; record was posted, rather than the start date of the call. This flag
; reverts to the old (incorrect) behavior. Note that you'll also need
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/configs/mobile.conf.sample
^
|
@@ -40,6 +40,14 @@
group=1 ; this phone is in channel group 1
;nocallsetup=yes ; set this only if your phone reports that it supports call progress notification, but does not do it. Motorola L6 for example.
+[blackberry]
+address=00:60:57:32:7E:B2
+port=2
+context=incoming-mobile
+adapter=dlink
+group=1
+;blackberry=yes ; set this if you are using a blackberry device
+
[6310i]
address=00:60:57:32:7E:B1
port=13
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/configs/res_mysql.conf.sample
^
|
@@ -6,20 +6,29 @@
; to the local host is assumed and dbsock is used instead of TCP/IP
; to connect to the server.
;
-; In addition to a [general] section, this file may also be configured
-; with separate [read] and [write] sections, which permits separation
-; of read-only queries from queries which alter the database. This
-; enables the use of master and slave replication servers for
-; scalability.
+; Multiple database contexts may be configured, with the caveat that
+; all context names should be unique and must not contain the slash ('/')
+; character. If you wish to separate reads from writes in your database
+; configuration, you specify the database (NOT HERE, in other files)
+; separated by a slash, read database first. If your database
+; specification does not contain a slash, the implication is that reads
+; and writes should be performed to the same database.
;
-; The way this meshes with extconfig.conf is kind of tricky. If the
-; externally specified database is the same as the [read] database,
-; then reads and writes will go to the separate places as specified
-; in this file. However, if the externally specified database is
-; different than in the [read] database, then both reads and writes
-; will go to the same place, as specified. That there is only read/
-; write separation for a single set of databases will be corrected
-; in a future version of Asterisk-Addons.
+; For example, in extconfig.conf, you could specify a line like:
+; sippeers => mysql,readhost.asterisk/writehost.asterisk,sipfriends
+; and then define the contexts [readhost.asterisk] and [writehost.asterisk]
+; below.
+;
+; The requirements parameter is available only in Asterisk 1.6.1 and
+; later and must be present in all contexts. It specifies the behavior
+; when a column name is required by the system. The default behavior is
+; "warn" and simply sends a warning to the logger that the column does
+; not exist (or is of the wrong type or precision). The other two
+; possibilities are "createclose", which adds the column with the right
+; type and length, and "createchar", which adds the column as a char
+; type, with the appropriate length to accept the data. Note that with
+; the MySQL driver, both "createclose" and "createchar" will, on occasion,
+; widen a table column width to meet the requirements specified.
;
[general]
;dbhost = 127.0.0.1
@@ -28,3 +37,4 @@
;dbpass = mypass
;dbport = 3306
;dbsock = /tmp/mysql.sock
+;requirements=warn ; or createclose or createchar
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/configure
^
|
@@ -699,6 +699,7 @@
BASENAME
DIRNAME
LN
+XMLSTARLET
AST_DEVMODE
BLUETOOTH_LIB
BLUETOOTH_INCLUDE
@@ -4538,6 +4539,47 @@
fi
+# Extract the first word of "xmlstarlet", so it can be a program name with args.
+set dummy xmlstarlet; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_XMLSTARLET+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $XMLSTARLET in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_XMLSTARLET="$XMLSTARLET" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_XMLSTARLET="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_XMLSTARLET" && ac_cv_path_XMLSTARLET=":"
+ ;;
+esac
+fi
+XMLSTARLET=$ac_cv_path_XMLSTARLET
+if test -n "$XMLSTARLET"; then
+ { echo "$as_me:$LINENO: result: $XMLSTARLET" >&5
+echo "${ECHO_T}$XMLSTARLET" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -7658,6 +7700,7 @@
BASENAME!$BASENAME$ac_delim
DIRNAME!$DIRNAME$ac_delim
LN!$LN$ac_delim
+XMLSTARLET!$XMLSTARLET$ac_delim
AST_DEVMODE!$AST_DEVMODE$ac_delim
BLUETOOTH_LIB!$BLUETOOTH_LIB$ac_delim
BLUETOOTH_INCLUDE!$BLUETOOTH_INCLUDE$ac_delim
@@ -7672,7 +7715,6 @@
MYSQLCLIENT_INCLUDE!$MYSQLCLIENT_INCLUDE$ac_delim
PBX_MYSQLCLIENT!$PBX_MYSQLCLIENT$ac_delim
ASTERISK_LIB!$ASTERISK_LIB$ac_delim
-ASTERISK_INCLUDE!$ASTERISK_INCLUDE$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -7714,6 +7756,7 @@
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
+ASTERISK_INCLUDE!$ASTERISK_INCLUDE$ac_delim
PBX_ASTERISK!$PBX_ASTERISK$ac_delim
CPP!$CPP$ac_delim
EGREP!$EGREP$ac_delim
@@ -7723,7 +7766,7 @@
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 7; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 8; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/configure.ac
^
|
@@ -17,7 +17,7 @@
AC_CONFIG_SRCDIR([res/res_config_mysql.c])
AC_COPYRIGHT("Asterisk-addons")
-AC_REVISION($Revision: 616 $)
+AC_REVISION($Revision: 685 $)
case "${host}" in
*freebsd*)
@@ -155,6 +155,7 @@
AC_PATH_PROG([DIRNAME], [dirname], :)
AC_PATH_PROG([SHELL], [sh], :)
AC_PATH_PROG([LN], [ln], :)
+AC_PATH_PROG([XMLSTARLET], [xmlstarlet], :)
AC_LANG(C)
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/formats/format_mp3.c
^
|
@@ -97,7 +97,7 @@
InitMP3(&p->mp, OUTSCALE);
p->dbuflen = 0;
- s->fr.data = s->buf;
+ s->fr.data.ptr = s->buf;
s->fr.frametype = AST_FRAME_VOICE;
s->fr.subclass = AST_FORMAT_SLINEAR;
/* datalen will vary for each frame */
@@ -232,7 +232,7 @@
s->fr.subclass = AST_FORMAT_SLINEAR;
s->fr.offset = AST_FRIENDLY_OFFSET;
s->fr.datalen = p->buflen;
- s->fr.data = s->buf;
+ s->fr.data.ptr = s->buf;
s->fr.mallocd = 0;
s->fr.samples = delay;
*whennext = delay;
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/makeopts.in
^
|
@@ -50,3 +50,5 @@
NCURSES_LIB=@NCURSES_LIB@
NCURSES_INCLUDE=@NCURSES_INCLUDE@
+
+XMLSTARLET=@XMLSTARLET@
|
[-]
[+]
|
Changed |
asterisk-addons-1.6.1.0.tar.bz2/res/res_config_mysql.c
^
|
@@ -52,10 +52,14 @@
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/utils.h>
+#include <asterisk/threadstorage.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <mysql/mysql.h>
#include <mysql/mysql_version.h>
#include <mysql/errmsg.h>
@@ -64,7 +68,18 @@
#define READHANDLE 0
#define WRITEHANDLE 1
-static struct mysql_conn {
+AST_THREADSTORAGE(sql_buf);
+AST_THREADSTORAGE(sql2_buf);
+AST_THREADSTORAGE(find_buf);
+AST_THREADSTORAGE(scratch_buf);
+AST_THREADSTORAGE(modify_buf);
+AST_THREADSTORAGE(modify2_buf);
+AST_THREADSTORAGE(modify3_buf);
+
+enum requirements { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR };
+
+struct mysql_conn {
+ AST_LIST_ENTRY(mysql_conn) list;
ast_mutex_t lock;
MYSQL handle;
char host[50];
@@ -75,37 +90,237 @@
int port;
int connected;
time_t connect_time;
-} dbread, dbwrite;
+ enum requirements requirements;
+ char unique_name[0];
+};
+
+struct columns {
+ char *name;
+ char *type;
+ char *dflt;
+ char null;
+ int len;
+ AST_LIST_ENTRY(columns) list;
+};
-static int parse_config(void);
+struct tables {
+ ast_mutex_t lock;
+ AST_LIST_HEAD_NOLOCK(mysql_columns, columns) columns;
+ AST_LIST_ENTRY(tables) list;
+ struct mysql_conn *database;
+ char name[0];
+};
+
+static AST_LIST_HEAD_STATIC(mysql_tables, tables);
+static AST_LIST_HEAD_STATIC(databases, mysql_conn);
+
+static int parse_config(int reload);
static int mysql_reconnect(struct mysql_conn *conn);
static char *handle_cli_realtime_mysql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *handle_cli_realtime_mysql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn);
+static int require_mysql(const char *database, const char *tablename, va_list ap);
+static int internal_require(const char *database, const char *table, ...) attribute_sentinel;
static struct ast_cli_entry cli_realtime_mysql_status[] = {
AST_CLI_DEFINE(handle_cli_realtime_mysql_status, "Shows connection information for the MySQL RealTime driver"),
+ AST_CLI_DEFINE(handle_cli_realtime_mysql_cache, "Shows cached tables within the MySQL realtime driver"),
};
-/*
- { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
- "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
-*/
+
+static struct mysql_conn *find_database(const char *database, int for_write)
+{
+ char *whichdb;
+ const char *ptr;
+ struct mysql_conn *cur;
+
+ if ((ptr = strchr(database, '/'))) {
+ /* Multiple databases encoded within string */
+ if (for_write) {
+ whichdb = ast_strdupa(ptr + 1);
+ } else {
+ whichdb = alloca(ptr - database + 1);
+ strncpy(whichdb, database, ptr - database);
+ whichdb[ptr - database] = '\0';
+ }
+ } else {
+ whichdb = ast_strdupa(database);
+ }
+
+ AST_LIST_LOCK(&databases);
+ AST_LIST_TRAVERSE(&databases, cur, list) {
+ if (!strcmp(cur->unique_name, whichdb)) {
+ ast_mutex_lock(&cur->lock);
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&databases);
+ return cur;
+}
+
+#define release_database(a) ast_mutex_unlock(&(a)->lock)
+
+static int internal_require(const char *database, const char *table, ...)
+{
+ va_list ap;
+ int res;
+ va_start(ap, table);
+ res = require_mysql(database, table, ap);
+ va_end(ap);
+ return res;
+}
+
+static void destroy_table(struct tables *table)
+{
+ struct columns *column;
+ ast_mutex_lock(&table->lock);
+ while ((column = AST_LIST_REMOVE_HEAD(&table->columns, list))) {
+ ast_free(column);
+ }
+ ast_mutex_unlock(&table->lock);
+ ast_mutex_destroy(&table->lock);
+ ast_free(table);
+}
+
+static struct tables *find_table(const char *database, const char *tablename)
+{
+ struct columns *column;
+ struct tables *table;
+ struct ast_str *sql = ast_str_thread_get(&find_buf, 30);
+ char *fname, *ftype, *flen, *fdflt, *fnull;
+ struct mysql_conn *dbh;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ if (!(dbh = find_database(database, 1))) {
+ return NULL;
+ }
+
+ AST_LIST_LOCK(&mysql_tables);
+ AST_LIST_TRAVERSE(&mysql_tables, table, list) {
+ if (!strcasecmp(table->name, tablename)) {
+ ast_mutex_lock(&table->lock);
+ AST_LIST_UNLOCK(&mysql_tables);
+ release_database(dbh);
+ return table;
+ }
+ }
+
+ /* Not found, scan the table */
+ ast_str_set(&sql, 0, "DESC %s", tablename);
+
+ if (!mysql_reconnect(dbh)) {
+ release_database(dbh);
+ AST_LIST_UNLOCK(&mysql_tables);
+ return NULL;
+ }
+
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_ERROR, "Failed to query database columns: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
+ AST_LIST_UNLOCK(&mysql_tables);
+ return NULL;
+ }
+
+ if (!(table = ast_calloc(1, sizeof(*table) + strlen(tablename) + 1))) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for new table structure\n");
+ release_database(dbh);
+ AST_LIST_UNLOCK(&mysql_tables);
+ return NULL;
+ }
+ strcpy(table->name, tablename); /* SAFE */
+ table->database = dbh;
+ ast_mutex_init(&table->lock);
+ AST_LIST_HEAD_INIT_NOLOCK(&table->columns);
+
+ if ((result = mysql_store_result(&dbh->handle))) {
+ while ((row = mysql_fetch_row(result))) {
+ fname = row[0];
+ ftype = row[1];
+ fnull = row[2];
+ fdflt = row[4];
+ ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
+
+ if (fdflt == NULL) {
+ fdflt = "";
+ }
+
+ if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + strlen(fdflt) + 3))) {
+ ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", tablename, fname);
+ destroy_table(table);
+ release_database(dbh);
+ AST_LIST_UNLOCK(&mysql_tables);
+ return NULL;
+ }
+
+ if ((flen = strchr(ftype, '('))) {
+ sscanf(flen, "(%d)", &column->len);
+ } else {
+ /* Columns like dates, times, and timestamps don't have a length */
+ column->len = -1;
+ }
+
+ column->name = (char *)column + sizeof(*column);
+ column->type = (char *)column + sizeof(*column) + strlen(fname) + 1;
+ column->dflt = (char *)column + sizeof(*column) + strlen(fname) + 1 + strlen(ftype) + 1;
+ strcpy(column->name, fname);
+ strcpy(column->type, ftype);
+ strcpy(column->dflt, fdflt);
+ column->null = (strcmp(fnull, "YES") == 0 ? 1 : 0);
+ AST_LIST_INSERT_TAIL(&table->columns, column, list);
+ }
+ mysql_free_result(result);
+ }
+
+ AST_LIST_INSERT_TAIL(&mysql_tables, table, list);
+ ast_mutex_lock(&table->lock);
+ AST_LIST_UNLOCK(&mysql_tables);
+ release_database(dbh);
+ return table;
+}
+
+static void release_table(struct tables *table)
+{
+ if (table) {
+ ast_mutex_unlock(&table->lock);
+ }
+}
+
+static struct columns *find_column(struct tables *table, const char *colname)
+{
+ struct columns *column;
+
+ AST_LIST_TRAVERSE(&table->columns, column, list) {
+ if (strcmp(column->name, colname) == 0) {
+ break;
+ }
+ }
+
+ return column;
+}
+
static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
{
+ struct mysql_conn *dbh;
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL_FIELD *fields;
int numFields, i, valsz;
- char sql[512];
- char buf[511]; /* Keep this size uneven as it is 2n+1. */
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
+ struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16);
char *stringp;
char *chunk;
char *op;
- char dbname[50] = "";
const char *newparam, *newval;
struct ast_variable *var=NULL, *prev=NULL;
+ if (!(dbh = find_database(database, 0))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: %s\n", database);
+ return NULL;
+ }
+
if (!table) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ release_database(dbh);
return NULL;
}
@@ -114,13 +329,13 @@
newval = va_arg(ap, const char *);
if (!newparam || !newval) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
+ release_database(dbh);
return NULL;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&dbread.lock);
- if (!mysql_reconnect(&dbread)) {
- ast_mutex_unlock(&dbread.lock);
+ if (!mysql_reconnect(dbh)) {
+ release_database(dbh);
return NULL;
}
@@ -132,38 +347,31 @@
else
op = "";
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
- if (strcmp(database, dbread.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
- }
- snprintf(sql, sizeof(sql), "SELECT * FROM %s%s WHERE %s%s '%s'", dbname, table, newparam, op, buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' '))
op = " =";
else
op = "";
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, buf->str);
}
va_end(ap);
- ast_debug(1, "MySQL RealTime: Retrieve SQL: %s\n", sql);
+ ast_debug(1, "MySQL RealTime: Retrieve SQL: %s\n", sql->str);
/* Execution. */
- if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
- ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
- ast_mutex_unlock(&dbread.lock);
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
return NULL;
}
- if ((result = mysql_store_result(&dbread.handle))) {
+ if ((result = mysql_store_result(&dbh->handle))) {
numFields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
@@ -186,10 +394,10 @@
}
}
} else {
- ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
+ ast_debug(1, "MySQL RealTime: Could not find any rows in table %s.\n", table);
}
- ast_mutex_unlock(&dbread.lock);
+ release_database(dbh);
mysql_free_result(result);
return var;
@@ -197,31 +405,37 @@
static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
{
+ struct mysql_conn *dbh;
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL_FIELD *fields;
int numFields, i, valsz;
- char sql[512];
- char buf[511]; /* Keep this size uneven as it is 2n+1. */
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
+ struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16);
const char *initfield = NULL;
char *stringp;
char *chunk;
char *op;
- char dbname[50] = "";
const char *newparam, *newval;
struct ast_variable *var = NULL;
struct ast_config *cfg = NULL;
struct ast_category *cat = NULL;
+ if (!(dbh = find_database(database, 0))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: '%s'\n", database);
+ return NULL;
+ }
+
if (!table) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ release_database(dbh);
return NULL;
}
- cfg = ast_config_new();
- if (!cfg) {
+ if (!(cfg = ast_config_new())) {
/* If I can't alloc memory at this point, why bother doing anything else? */
ast_log(LOG_WARNING, "Out of memory!\n");
+ release_database(dbh);
return NULL;
}
@@ -231,6 +445,7 @@
if (!newparam || !newval) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
ast_config_destroy(cfg);
+ release_database(dbh);
return NULL;
}
@@ -240,9 +455,8 @@
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&dbread.lock);
- if (!mysql_reconnect(&dbread)) {
- ast_mutex_unlock(&dbread.lock);
+ if (!mysql_reconnect(dbh)) {
+ release_database(dbh);
ast_config_destroy(cfg);
return NULL;
}
@@ -255,41 +469,34 @@
else
op = "";
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
- if (strcmp(database, dbread.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
- }
- snprintf(sql, sizeof(sql), "SELECT * FROM %s%s WHERE %s%s '%s'", dbname, table, newparam, op, buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' ')) op = " ="; else op = "";
- if ((valsz = strlen(newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, buf->str);
}
if (initfield) {
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
+ ast_str_append(&sql, 0, " ORDER BY %s", initfield);
}
va_end(ap);
- ast_debug(1, "MySQL RealTime: Retrieve SQL: %s\n", sql);
+ ast_debug(1, "MySQL RealTime: Retrieve SQL: %s\n", sql->str);
/* Execution. */
- if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
- ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
- ast_mutex_unlock(&dbread.lock);
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
ast_config_destroy(cfg);
return NULL;
}
- if ((result = mysql_store_result(&dbread.handle))) {
+ if ((result = mysql_store_result(&dbh->handle))) {
numFields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
@@ -316,26 +523,46 @@
ast_category_append(cfg, cat);
}
} else {
- ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
+ ast_debug(1, "MySQL RealTime: Could not find any rows in table %s.\n", table);
}
- ast_mutex_unlock(&dbread.lock);
+ release_database(dbh);
mysql_free_result(result);
return cfg;
}
-static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
+static int update_mysql(const char *database, const char *tablename, const char *keyfield, const char *lookup, va_list ap)
{
+ struct mysql_conn *dbh;
my_ulonglong numrows;
- char sql[512];
- char buf[511]; /* Keep this size uneven as it is 2n+1. */
- char dbname[50] = "";
int valsz;
const char *newparam, *newval;
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100), *buf = ast_str_thread_get(&scratch_buf, 100);
+ struct tables *table;
+ struct columns *column = NULL;
- if (!table) {
+ if (!(dbh = find_database(database, 1))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: '%s'.\n", database);
+ return -1;
+ }
+
+ if (!tablename) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ release_database(dbh);
+ return -1;
+ }
+
+ if (!(table = find_table(database, tablename))) {
+ ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename);
+ release_database(dbh);
+ return -1;
+ }
+
+ if (!(column = find_column(table, keyfield))) {
+ ast_log(LOG_ERROR, "MySQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", keyfield, tablename);
+ release_table(table);
+ release_database(dbh);
return -1;
}
@@ -344,54 +571,77 @@
newval = va_arg(ap, const char *);
if (!newparam || !newval) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
- return -1;
+ release_table(table);
+ release_database(dbh);
+ return -1;
+ }
+
+ /* Check that the column exists in the table */
+ if (!(column = find_column(table, newparam))) {
+ ast_log(LOG_ERROR, "MySQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", newparam, tablename);
+ release_table(table);
+ release_database(dbh);
+ return -1;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&dbwrite.lock);
- if (!mysql_reconnect(&dbwrite)) {
- ast_mutex_unlock(&dbwrite.lock);
+ if (!mysql_reconnect(dbh)) {
+ release_table(table);
+ release_database(dbh);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
- if (strcmp(database, dbwrite.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, buf->str);
+
+ /* If the column length isn't long enough, give a chance to lengthen it. */
+ if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) {
+ internal_require(database, tablename, newparam, RQ_CHAR, valsz, SENTINEL);
}
- snprintf(sql, sizeof(sql), "UPDATE %s%s SET %s = '%s'", dbname, table, newparam, buf);
- while((newparam = va_arg(ap, const char *))) {
+
+ while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, buf);
+
+ /* If the column is not within the table, then skip it */
+ if (!(column = find_column(table, newparam))) {
+ ast_log(LOG_WARNING, "Attempted to update column '%s' in table '%s', but column does not exist!\n", newparam, tablename);
+ continue;
+ }
+
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_append(&sql, 0, ", %s = '%s'", newparam, buf->str);
+
+ /* If the column length isn't long enough, give a chance to lengthen it. */
+ if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) {
+ internal_require(database, tablename, newparam, RQ_CHAR, valsz, SENTINEL);
+ }
}
va_end(ap);
- if ((valsz = strlen (lookup)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, lookup, valsz);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, buf);
- ast_debug(1, "MySQL RealTime: Update SQL: %s\n", sql);
+ ast_str_make_space(&buf, (valsz = strlen(lookup)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, lookup, valsz);
+ ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, buf->str);
+
+ ast_debug(1, "MySQL RealTime: Update SQL: %s\n", sql->str);
/* Execution. */
- if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
- ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
- ast_mutex_unlock(&dbwrite.lock);
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ release_table(table);
+ release_database(dbh);
return -1;
}
- numrows = mysql_affected_rows(&dbwrite.handle);
- ast_mutex_unlock(&dbwrite.lock);
+ numrows = mysql_affected_rows(&dbh->handle);
+ release_table(table);
+ release_database(dbh);
- ast_debug(1, "MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
+ ast_debug(1, "MySQL RealTime: Updated %llu rows on table: %s\n", numrows, tablename);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
@@ -401,20 +651,25 @@
return (int)numrows;
}
-
+
static int store_mysql(const char *database, const char *table, va_list ap)
{
+ struct mysql_conn *dbh;
my_ulonglong insertid;
- char sql[512];
- char buf[511]; /* Keep this size uneven as it is 2n+1. */
- char fields[512];
- char values[512];
- char dbname[50] = "";
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
+ struct ast_str *sql2 = ast_str_thread_get(&sql2_buf, 16);
+ struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16);
int valsz;
const char *newparam, *newval;
+ if (!(dbh = find_database(database, 1))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: '%s'.\n", database);
+ return -1;
+ }
+
if (!table) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ release_database(dbh);
return -1;
}
/* Get the first parameter and first value in our list of passed paramater/value pairs */
@@ -422,55 +677,51 @@
newval = va_arg(ap, const char *);
if (!newparam || !newval) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime storage requires at least 1 parameter and 1 value to search on.\n");
+ release_database(dbh);
return -1;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&dbwrite.lock);
- if (!mysql_reconnect(&dbwrite)) {
- ast_mutex_unlock(&dbwrite.lock);
+ if (!mysql_reconnect(dbh)) {
+ release_database(dbh);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if ((valsz = strlen(newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- if (newval) {
- mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
- } else {
- buf[0] = '\0';
- }
- snprintf(fields, sizeof(fields), "%s", newparam);
- snprintf(values, sizeof(values), "'%s'", buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+
+ ast_str_set(&sql, 0, "INSERT INTO %s (%s", table, newparam);
+ ast_str_set(&sql2, 0, ") VALUES ('%s'", buf->str);
+
+ internal_require(database, table, newparam, RQ_CHAR, valsz, SENTINEL);
+
while ((newparam = va_arg(ap, const char *))) {
- newval = va_arg(ap, const char *);
- if (newval) {
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
+ if ((newval = va_arg(ap, const char *))) {
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
} else {
- buf[0] = '\0';
+ valsz = 0;
+ ast_str_reset(buf);
+ }
+ if (internal_require(database, table, newparam, RQ_CHAR, valsz, SENTINEL) == 0) {
+ ast_str_append(&sql, 0, ", %s", newparam);
+ ast_str_append(&sql2, 0, ", '%s'", buf->str);
}
- snprintf(fields + strlen(fields), sizeof(fields), ", %s", newparam);
- snprintf(values + strlen(values), sizeof(values), ", '%s'", buf);
}
va_end(ap);
- if (strcmp(database, dbwrite.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
- }
- snprintf(sql, sizeof(sql), "INSERT into %s%s (%s) values (%s)", dbname, table, fields, values);
- ast_debug(1, "MySQL RealTime: Insert SQL: %s\n", sql);
+ ast_str_append(&sql, 0, "%s)", sql2->str);
+ ast_debug(1,"MySQL RealTime: Insert SQL: %s\n", sql->str);
/* Execution. */
- if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
- ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
- ast_mutex_unlock(&dbwrite.lock);
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
return -1;
}
- insertid = mysql_insert_id(&dbwrite.handle);
- ast_mutex_unlock(&dbwrite.lock);
+ /*!\note The return value is non-portable and may change in future versions. */
+ insertid = mysql_insert_id(&dbh->handle);
+ release_database(dbh);
ast_debug(1, "MySQL RealTime: row inserted on table: %s, id: %llu\n", table, insertid);
@@ -484,15 +735,21 @@
static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
{
+ struct mysql_conn *dbh;
my_ulonglong numrows;
- char sql[512];
- char buf[511]; /* Keep this size uneven as it is 2n+1. */
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
+ struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16);
int valsz;
- char dbname[50] = "";
const char *newparam, *newval;
+ if (!(dbh = find_database(database, 1))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: '%s'.\n", database);
+ return -1;
+ }
+
if (!table) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ release_database(dbh);
return -1;
}
@@ -501,48 +758,40 @@
newval = va_arg(ap, const char *);*/
if (ast_strlen_zero(keyfield) || ast_strlen_zero(lookup)) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime destroying requires at least 1 parameter and 1 value to search on.\n");
+ release_database(dbh);
return -1;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&dbwrite.lock);
- if (!mysql_reconnect(&dbwrite)) {
- ast_mutex_unlock(&dbwrite.lock);
+ if (!mysql_reconnect(dbh)) {
+ release_database(dbh);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
-
- if ((valsz = strlen (lookup)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, lookup, valsz);
- if (strcmp(database, dbwrite.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
- }
- snprintf(sql, sizeof(sql), "DELETE FROM %s%s WHERE %s = '%s'", dbname, table, keyfield, buf);
+ ast_str_make_space(&buf, (valsz = strlen(lookup)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, lookup, valsz);
+ ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, keyfield, buf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
- valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s = '%s'", newparam, buf);
+ ast_str_make_space(&buf, (valsz = strlen(newval)) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, buf->str, newval, valsz);
+ ast_str_append(&sql, 0, " AND %s = '%s'", newparam, buf->str);
}
va_end(ap);
- ast_debug(1, "MySQL RealTime: Delete SQL: %s\n", sql);
+ ast_debug(1, "MySQL RealTime: Delete SQL: %s\n", sql->str);
/* Execution. */
- if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
- ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
- ast_mutex_unlock(&dbwrite.lock);
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
return -1;
}
- numrows = mysql_affected_rows(&dbwrite.handle);
- ast_mutex_unlock(&dbwrite.lock);
+ numrows = mysql_affected_rows(&dbh->handle);
+ release_database(dbh);
ast_debug(1, "MySQL RealTime: Deleted %llu rows on table: %s\n", numrows, table);
@@ -557,57 +806,57 @@
static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *unused, const char *who_asked)
{
+ struct mysql_conn *dbh;
MYSQL_RES *result;
MYSQL_ROW row;
my_ulonglong num_rows;
struct ast_variable *new_v;
struct ast_category *cur_cat;
- char sql[250] = "";
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 200);
char last[80] = "";
- char dbname[50] = "";
int last_cat_metric = 0;
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
- last[0] = '\0';
if (!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
return NULL;
}
- ast_mutex_lock(&dbread.lock);
- if (!mysql_reconnect(&dbread)) {
- ast_mutex_unlock(&dbread.lock);
+ if (!(dbh = find_database(database, 0))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Invalid database specified: '%s'\n", database);
return NULL;
}
- if (strcmp(database, dbread.name)) {
- snprintf(dbname, sizeof(dbname), "%s.", database);
- }
- snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s%s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", dbname, table, file);
+ ast_str_set(&sql, 0, "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=1 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
- ast_debug(1, "MySQL RealTime: Static SQL: %s\n", sql);
+ ast_debug(1, "MySQL RealTime: Static SQL: %s\n", sql->str);
- if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ if (!mysql_reconnect(dbh)) {
+ return NULL;
+ }
+
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "MySQL RealTime: Query: %s\n", sql);
- ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
- ast_mutex_unlock(&dbread.lock);
+ ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbh->handle));
+ release_database(dbh);
return NULL;
}
- if ((result = mysql_store_result(&dbread.handle))) {
+ if ((result = mysql_store_result(&dbh->handle))) {
num_rows = mysql_num_rows(result);
ast_debug(1, "MySQL RealTime: Found %llu rows.\n", num_rows);
/* There might exist a better way to access the column names other than counting,
- but I believe that would require another loop that we don't need. */
+ * but I believe that would require another loop that we don't need. */
while ((row = mysql_fetch_row(result))) {
if (!strcmp(row[1], "#include")) {
if (!ast_config_internal_load(row[2], cfg, config_flags, "", who_asked)) {
mysql_free_result(result);
- ast_mutex_unlock(&dbread.lock);
+ release_database(dbh);
ast_config_destroy(cfg);
return NULL;
}
@@ -615,8 +864,7 @@
}
if (strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
- cur_cat = ast_category_new(row[0], "", -1);
- if (!cur_cat) {
+ if (!(cur_cat = ast_category_new(row[0], "", -1))) {
ast_log(LOG_WARNING, "Out of memory!\n");
break;
}
@@ -633,11 +881,366 @@
}
mysql_free_result(result);
- ast_mutex_unlock(&dbread.lock);
+ release_database(dbh);
return cfg;
}
+static int unload_mysql(const char *database, const char *tablename)
+{
+ struct tables *cur;
+ AST_LIST_LOCK(&mysql_tables);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&mysql_tables, cur, list) {
+ if (strcmp(cur->name, tablename) == 0) {
+ AST_LIST_REMOVE_CURRENT(list);
+ destroy_table(cur);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&mysql_tables);
+ return cur ? 0 : -1;
+}
+
+static int modify_mysql(const char *database, const char *tablename, struct columns *column, require_type type, int len)
+{
+ /*!\note Cannot use ANY of the same scratch space as is used in other functions, as this one is interspersed. */
+ struct ast_str *sql = ast_str_thread_get(&modify_buf, 100), *escbuf = ast_str_thread_get(&modify2_buf, 100);
+ struct ast_str *typestr = ast_str_thread_get(&modify3_buf, 30);
+ int waschar = strncasecmp(column->type, "char", 4) == 0 ? 1 : 0;
+ int wasvarchar = strncasecmp(column->type, "varchar", 7) == 0 ? 1 : 0;
+ int res = 0;
+ struct mysql_conn *dbh;
+
+ if (!(dbh = find_database(database, 1))) {
+ return -1;
+ }
+
+ do {
+ if (type == RQ_CHAR || waschar || wasvarchar) {
+ if (wasvarchar) {
+ ast_str_set(&typestr, 0, "VARCHAR(%d)", len);
+ } else {
+ ast_str_set(&typestr, 0, "CHAR(%d)", len);
+ }
+ } else if (type == RQ_UINTEGER1) {
+ ast_str_set(&typestr, 0, "tinyint(3) unsigned");
+ } else if (type == RQ_INTEGER1) {
+ ast_str_set(&typestr, 0, "tinyint(4)");
+ } else if (type == RQ_UINTEGER2) {
+ ast_str_set(&typestr, 0, "smallint(5) unsigned");
+ } else if (type == RQ_INTEGER2) {
+ ast_str_set(&typestr, 0, "smallint(6)");
+ } else if (type == RQ_UINTEGER3) {
+ ast_str_set(&typestr, 0, "mediumint(8) unsigned");
+ } else if (type == RQ_INTEGER3) {
+ ast_str_set(&typestr, 0, "mediumint(8)");
+ } else if (type == RQ_UINTEGER4) {
+ ast_str_set(&typestr, 0, "int(10) unsigned");
+ } else if (type == RQ_INTEGER4) {
+ ast_str_set(&typestr, 0, "int(11)");
+ } else if (type == RQ_UINTEGER8) {
+ ast_str_set(&typestr, 0, "bigint(19) unsigned");
+ } else if (type == RQ_INTEGER8) {
+ ast_str_set(&typestr, 0, "bigint(20)");
+ } else if (type == RQ_DATETIME) {
+ ast_str_set(&typestr, 0, "datetime");
+ } else if (type == RQ_DATE) {
+ ast_str_set(&typestr, 0, "date");
+ } else if (type == RQ_FLOAT) {
+ ast_str_set(&typestr, 0, "FLOAT(%d,2)", len);
+ } else {
+ ast_log(LOG_ERROR, "Unknown type (should NEVER happen)\n");
+ res = -1;
+ break;
+ }
+ ast_str_set(&sql, 0, "ALTER TABLE %s MODIFY %s %s", tablename, column->name, typestr->str);
+ if (!column->null) {
+ ast_str_append(&sql, 0, " NOT NULL");
+ }
+ if (!ast_strlen_zero(column->dflt)) {
+ ast_str_make_space(&escbuf, strlen(column->dflt) * 2 + 1);
+ mysql_real_escape_string(&dbh->handle, escbuf->str, column->dflt, strlen(column->dflt));
+ ast_str_append(&sql, 0, " DEFAULT '%s'", escbuf->str);
+ }
+
+ if (!mysql_reconnect(dbh)) {
+ ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str);
+ res = -1;
+ break;
+ }
+
+ /* Execution. */
+ if (mysql_real_query(&dbh->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
+ ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
+ res = -1;
+ }
+ } while (0);
+
+ release_database(dbh);
+ return res;
+}
+
+#define PICK_WHICH_ALTER_ACTION(stringtype) \
+ if (table->database->requirements == RQ_WARN) { \
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \
+ "the required data length: %d (detected stringtype)\n", \
+ tablename, database, column->name, size); \
+ res = -1; \
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { \
+ table_altered = 1; \
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { \
+ table_altered = 1; \
+ } else { \
+ res = -1; \
+ }
+
+static int require_mysql(const char *database, const char *tablename, va_list ap)
+{
+ struct columns *column;
+ struct tables *table = find_table(database, tablename);
+ char *elm;
+ int type, size, res = 0, table_altered = 0;
+
+ if (!table) {
+ ast_log(LOG_WARNING, "Table %s not found in database. This table should exist if you're using realtime.\n", tablename);
+ return -1;
+ }
+
+ while ((elm = va_arg(ap, char *))) {
+ type = va_arg(ap, require_type);
+ size = va_arg(ap, int);
+ AST_LIST_TRAVERSE(&table->columns, column, list) {
+ if (strcmp(column->name, elm) == 0) {
+ /* Char can hold anything, as long as it is large enough */
+ if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) {
+ if ((size > column->len) && column->len != -1) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column '%s' should be at least %d long, but is only %d long.\n", database, tablename, column->name, size, column->len);
+ res = -1;
+ } else if (modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ }
+ } else if (strcasestr(column->type, "unsigned")) {
+ if (!ast_rq_is_int(type)) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
+ database, tablename, column->name, column->type,
+ type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" :
+ type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "a rather stiff drink");
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if (strncasecmp(column->type, "tinyint", 1) == 0) {
+ if (type != RQ_UINTEGER1) {
+ PICK_WHICH_ALTER_ACTION(unsigned tinyint)
+ }
+ } else if (strncasecmp(column->type, "smallint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
+ PICK_WHICH_ALTER_ACTION(unsigned smallint)
+ }
+ } else if (strncasecmp(column->type, "mediumint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3) {
+ PICK_WHICH_ALTER_ACTION(unsigned mediumint)
+ }
+ } else if (strncasecmp(column->type, "int", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+ type != RQ_UINTEGER4) {
+ PICK_WHICH_ALTER_ACTION(unsigned int)
+ }
+ } else if (strncasecmp(column->type, "bigint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+ type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
+ type != RQ_UINTEGER8) {
+ PICK_WHICH_ALTER_ACTION(unsigned bigint)
+ }
+ }
+ } else if (strcasestr(column->type, "int")) {
+ if (!ast_rq_is_int(type)) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
+ database, tablename, column->name, column->type,
+ type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" :
+ type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" :
+ "to get a life, rather than writing silly error messages");
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if (strncasecmp(column->type, "tinyint", 1) == 0) {
+ if (type != RQ_INTEGER1) {
+ PICK_WHICH_ALTER_ACTION(tinyint)
+ }
+ } else if (strncasecmp(column->type, "smallint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
+ PICK_WHICH_ALTER_ACTION(smallint)
+ }
+ } else if (strncasecmp(column->type, "mediumint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_INTEGER3) {
+ PICK_WHICH_ALTER_ACTION(mediumint)
+ }
+ } else if (strncasecmp(column->type, "int", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+ type != RQ_INTEGER4) {
+ PICK_WHICH_ALTER_ACTION(int)
+ }
+ } else if (strncasecmp(column->type, "bigint", 1) == 0) {
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+ type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
+ type != RQ_INTEGER8) {
+ PICK_WHICH_ALTER_ACTION(bigint)
+ }
+ }
+ } else if (strncmp(column->type, "float", 5) == 0 && !ast_rq_is_int(type) && type != RQ_FLOAT) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if ((strncmp(column->type, "datetime", 8) == 0 || strncmp(column->type, "timestamp", 9)) && type != RQ_DATETIME) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else if ((strncmp(column->type, "date", 4) == 0) && type != RQ_DATE) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ res = -1;
+ }
+ } else { /* Other, possibly unsupported types? */
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name);
+ res = -1;
+ } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+ table_altered = 1;
+ } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+ table_altered = 1;
+ } else {
+ }
+ }
+ break;
+ }
+ }
+
+ if (!column) {
+ if (table->database->requirements == RQ_WARN) {
+ ast_log(LOG_WARNING, "Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size);
+ } else {
+ struct ast_str *sql = ast_str_thread_get(&modify_buf, 100), *fieldtype = ast_str_thread_get(&modify3_buf, 16);
+
+ if (table->database->requirements == RQ_CREATECHAR || type == RQ_CHAR) {
+ ast_str_set(&fieldtype, 0, "CHAR(%d)", size);
+ } else if (type == RQ_UINTEGER1 || type == RQ_UINTEGER2 || type == RQ_UINTEGER3 || type == RQ_UINTEGER4 || type == RQ_UINTEGER8) {
+ if (type == RQ_UINTEGER1) {
+ ast_str_set(&fieldtype, 0, "TINYINT(3) UNSIGNED");
+ } else if (type == RQ_UINTEGER2) {
+ ast_str_set(&fieldtype, 0, "SMALLINT(5) UNSIGNED");
+ } else if (type == RQ_UINTEGER3) {
+ ast_str_set(&fieldtype, 0, "MEDIUMINT(8) UNSIGNED");
+ } else if (type == RQ_UINTEGER4) {
+ ast_str_set(&fieldtype, 0, "INT(10) UNSIGNED");
+ } else if (type == RQ_UINTEGER8) {
+ ast_str_set(&fieldtype, 0, "BIGINT(20) UNSIGNED");
+ } else {
+ ast_log(LOG_WARNING, "Somebody should check this code for a rather large bug... it's about to squash Tokyo.\n");
+ continue;
+ }
+ } else if (ast_rq_is_int(type)) {
+ if (type == RQ_INTEGER1) {
+ ast_str_set(&fieldtype, 0, "TINYINT(3)");
+ } else if (type == RQ_INTEGER2) {
+ ast_str_set(&fieldtype, 0, "SMALLINT(5)");
+ } else if (type == RQ_INTEGER3) {
+ ast_str_set(&fieldtype, 0, "MEDIUMINT(8)");
+ } else if (type == RQ_INTEGER4) {
+ ast_str_set(&fieldtype, 0, "INT(10)");
+ } else if (type == RQ_INTEGER8) {
+ ast_str_set(&fieldtype, 0, "BIGINT(20)");
+ } else {
+ ast_log(LOG_WARNING, "Somebody should check this code for a rather large bug... it's about to eat Cincinnati.\n");
+ continue;
+ }
+ } else if (type == RQ_FLOAT) {
+ ast_str_set(&fieldtype, 0, "FLOAT");
+ } else if (type == RQ_DATE) {
+ ast_str_set(&fieldtype, 0, "DATE");
+ } else if (type == RQ_DATETIME) {
+ ast_str_set(&fieldtype, 0, "DATETIME");
+ } else {
+ continue;
+ }
+ ast_str_set(&sql, 0, "ALTER TABLE %s ADD COLUMN %s %s", tablename, elm, fieldtype->str);
+
+ ast_mutex_lock(&table->database->lock);
+ if (!mysql_reconnect(table->database)) {
+ ast_mutex_unlock(&table->database->lock);
+ ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str);
+ continue;
+ }
+
+ /* Execution. */
+ if (mysql_real_query(&table->database->handle, sql->str, sql->used)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_debug(1, "MySQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&table->database->handle));
+ } else {
+ table_altered = 1;
+ }
+ }
+ }
+ }
+ release_table(table);
+
+ /* If we altered the table, we must refresh the cache */
+ if (table_altered) {
+ unload_mysql(database, tablename);
+ release_table(find_table(database, tablename));
+ }
+ return res;
+}
+
static struct ast_config_engine mysql_engine = {
.name = "mysql",
.load_func = config_mysql,
@@ -645,37 +1248,27 @@
.realtime_multi_func = realtime_multi_mysql,
.store_func = store_mysql,
.destroy_func = destroy_mysql,
- .update_func = update_mysql
+ .update_func = update_mysql,
+ .require_func = require_mysql,
+ .unload_func = unload_mysql,
};
static int load_module(void)
{
- int writeokay = 0;
- parse_config();
-
- ast_mutex_init(&dbread.lock);
- ast_mutex_init(&dbwrite.lock);
-
- if (!mysql_reconnect(&dbwrite))
- ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish write connection: %s\n", mysql_error(&dbwrite.handle));
- else
- writeokay = 1;
-
- if (!mysql_reconnect(&dbread)) {
- if (!writeokay)
- ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish read connection, either: %s\n", mysql_error(&dbread.handle));
- }
+ parse_config(0);
ast_config_engine_register(&mysql_engine);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime driver loaded.\n");
ast_cli_register_multiple(cli_realtime_mysql_status, sizeof(cli_realtime_mysql_status) / sizeof(struct ast_cli_entry));
-
return 0;
}
static int unload_module(void)
{
+ struct mysql_conn *cur;
+ struct tables *table;
+
ast_cli_unregister_multiple(cli_realtime_mysql_status, sizeof(cli_realtime_mysql_status) / sizeof(struct ast_cli_entry));
ast_config_engine_deregister(&mysql_engine);
if (option_verbose > 1)
@@ -684,101 +1277,70 @@
ast_module_user_hangup_all();
usleep(1);
- ast_mutex_destroy(&dbread.lock);
- ast_mutex_destroy(&dbwrite.lock);
+ AST_LIST_LOCK(&databases);
+ while ((cur = AST_LIST_REMOVE_HEAD(&databases, list))) {
+ mysql_close(&cur->handle);
+ ast_mutex_destroy(&cur->lock);
+ ast_free(cur);
+ }
- mysql_close(&dbwrite.handle);
- mysql_close(&dbread.handle);
+ /* Destroy cached table info */
+ AST_LIST_LOCK(&mysql_tables);
+ while ((table = AST_LIST_REMOVE_HEAD(&mysql_tables, list))) {
+ destroy_table(table);
+ }
+ AST_LIST_UNLOCK(&mysql_tables);
return 0;
}
static int reload(void)
{
- int writeokay = 0;
+ parse_config(1);
- ast_mutex_lock(&dbwrite.lock);
- ast_mutex_lock(&dbread.lock);
- mysql_close(&dbwrite.handle);
- mysql_close(&dbread.handle);
- parse_config();
-
- if (!mysql_reconnect(&dbwrite))
- ast_log(LOG_WARNING, "MySQL RealTime: Cannot connect write handle: %s\n", mysql_error(&dbwrite.handle));
- else
- writeokay = 1;
-
- if (!mysql_reconnect(&dbread)) {
- if (!writeokay)
- ast_log(LOG_WARNING, "MySQL RealTime: Cannot Connect read handle, either: %s\n", mysql_error(&dbread.handle));
+ if (option_verbose > 1) {
+ ast_verb(2, "MySQL RealTime reloaded.\n");
}
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
-
- /* Done reloading. Release lock so others can now use driver. */
- ast_mutex_unlock(&dbread.lock);
- ast_mutex_unlock(&dbwrite.lock);
-
- return 0;
-}
-
-static int set_defaults(struct mysql_conn *conn)
-{
- ast_copy_string(conn->user, "asterisk", sizeof(conn->user));
- ast_copy_string(conn->pass, "asterisk", sizeof(conn->pass));
- ast_copy_string(conn->host, "", sizeof(conn->host));
- ast_copy_string(conn->name, "asterisk", sizeof(conn->name));
- conn->port = 3306;
- ast_copy_string(conn->sock, "/tmp/mysql.sock", sizeof(conn->sock));
-
- if (!ast_strlen_zero(conn->host)) {
- ast_debug(1, "MySQL RealTime host: %s\n", conn->host);
- ast_debug(1, "MySQL RealTime port: %i\n", conn->port);
- } else
- ast_debug(1, "MySQL RealTime socket: %s\n", conn->sock);
- ast_debug(1, "MySQL RealTime database name: %s\n", conn->name);
- ast_debug(1, "MySQL RealTime user: %s\n", conn->user);
- ast_debug(1, "MySQL RealTime password: %s\n", conn->pass);
return 0;
}
-static int parse_config(void)
+static int parse_config(int reload)
{
struct ast_config *config = NULL;
- struct ast_flags config_flags = { 0 };
- const char *catg = "write";
- int haswriteconfig = 0;
+ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+ const char *catg;
+ struct mysql_conn *cur;
if (!(config = ast_config_load(RES_CONFIG_MYSQL_CONF, config_flags))) {
- set_defaults(&dbwrite);
- set_defaults(&dbread);
+ return 0;
+ } else if (config == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
}
- if (!ast_category_exist(config, catg))
- catg = "general";
- if (!ast_category_exist(config, catg)) {
- ast_log(LOG_WARNING, "No configuration set for writing to the MySQL database. Using defaults.\n");
- set_defaults(&dbwrite);
- } else
- haswriteconfig = load_mysql_config(config, catg, &dbwrite);
-
- if (!ast_category_exist(config, "read")) {
- if (haswriteconfig) {
- /* Copy from write config */
- ast_copy_string(dbread.host, dbwrite.host, sizeof(dbread.host));
- ast_copy_string(dbread.sock, dbwrite.sock, sizeof(dbread.sock));
- ast_copy_string(dbread.name, dbwrite.name, sizeof(dbread.name));
- ast_copy_string(dbread.user, dbwrite.user, sizeof(dbread.user));
- ast_copy_string(dbread.pass, dbwrite.pass, sizeof(dbread.pass));
- dbread.port = dbwrite.port;
- } else {
- ast_log(LOG_WARNING, "It's kind of silly to be loading res_config_mysql.so if there's no configuration settings. Let's use the defaults!\n");
- set_defaults(&dbread);
+ AST_LIST_LOCK(&databases);
+ for (catg = ast_category_browse(config, NULL); catg; catg = ast_category_browse(config, catg)) {
+ /* Does this category already exist? */
+ AST_LIST_TRAVERSE(&databases, cur, list) {
+ if (!strcmp(cur->unique_name, catg)) {
+ break;
+ }
}
- } else
- load_mysql_config(config, "read", &dbread);
+
+ if (!cur) {
+ if (!(cur = ast_calloc(1, sizeof(*cur) + strlen(catg) + 1))) {
+ ast_log(LOG_WARNING, "Could not allocate space for MySQL database '%s'\n", catg);
+ continue;
+ }
+
+ strcpy(cur->unique_name, catg); /* SAFE */
+ ast_mutex_init(&cur->lock);
+ AST_LIST_INSERT_TAIL(&databases, cur, list);
+ }
+
+ load_mysql_config(config, catg, cur);
+ }
+ AST_LIST_UNLOCK(&databases);
ast_config_destroy(config);
@@ -811,7 +1373,7 @@
ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
s = "asterisk";
}
- ast_copy_string(conn->name, s, sizeof(conn->name) - 1);
+ ast_copy_string(conn->name, s, sizeof(conn->name));
if (!(s = ast_variable_retrieve(config, category, "dbport"))) {
ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
@@ -819,14 +1381,39 @@
} else
conn->port = atoi(s);
- if (!(s = ast_variable_retrieve(config, "general", "dbsock"))) {
+ if (!(s = ast_variable_retrieve(config, category, "dbsock"))) {
if (ast_strlen_zero(conn->host)) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
- ast_copy_string(conn->sock, "/tmp/mysql.sock", sizeof(conn->sock));
+ char *paths[3] = { "/tmp/mysql.sock", "/var/lib/mysql/mysql.sock", "/var/run/mysqld/mysqld.sock" };
+ struct stat st;
+ int i;
+ for (i = 0; i < 3; i++) {
+ if (!stat(paths[i], &st)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '%s' as default.\n", paths[i]);
+ ast_copy_string(conn->sock, paths[i], sizeof(conn->sock));
+ }
+ }
+ if (i == 3) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database socket found (and unable to detect a suitable path).\n");
+ return 0;
+ }
}
} else
ast_copy_string(conn->sock, s, sizeof(conn->sock));
+ if (!(s = ast_variable_retrieve(config, category, "requirements"))) {
+ ast_log(LOG_WARNING, "MySQL realtime: no requirements setting found, using 'warn' as default.\n");
+ conn->requirements = RQ_WARN;
+ } else if (!strcasecmp(s, "createclose")) {
+ conn->requirements = RQ_CREATECLOSE;
+ } else if (!strcasecmp(s, "createchar")) {
+ conn->requirements = RQ_CREATECHAR;
+ } else if (!strcasecmp(s, "warn")) {
+ conn->requirements = RQ_WARN;
+ } else {
+ ast_log(LOG_WARNING, "MySQL realtime: unrecognized requirements setting '%s', using 'warn'\n", s);
+ conn->requirements = RQ_WARN;
+ }
+
if (!ast_strlen_zero(conn->host)) {
ast_debug(1, "MySQL RealTime host: %s\n", conn->host);
ast_debug(1, "MySQL RealTime port: %i\n", conn->port);
@@ -873,7 +1460,7 @@
} else {
/* MySQL likes to return an error, even if it reconnects successfully.
* So the postman pings twice. */
- if (mysql_ping(&conn->handle) != 0 && mysql_ping(&conn->handle) != 0) {
+ if (mysql_ping(&conn->handle) != 0 && (usleep(1) + 2 > 0) && mysql_ping(&conn->handle) != 0) {
conn->connected = 0;
ast_log(LOG_ERROR, "MySQL RealTime: Ping failed (%d). Trying an explicit reconnect.\n", mysql_errno(&conn->handle));
ast_debug(1, "MySQL RealTime: Server Error (%d): %s\n", mysql_errno(&conn->handle), mysql_error(&conn->handle));
@@ -893,52 +1480,166 @@
}
}
+static char *handle_cli_realtime_mysql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct tables *cur;
+ int l, which;
+ char *ret = NULL;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "realtime mysql cache";
+ e->usage =
+ "Usage: realtime mysql cache [<database> <table>]\n"
+ " Shows table cache for the MySQL RealTime driver\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->argc < 4 || a->argc > 5) {
+ return NULL;
+ }
+ l = strlen(a->word);
+ which = 0;
+ if (a->argc == 5) {
+ AST_LIST_LOCK(&mysql_tables);
+ AST_LIST_TRAVERSE(&mysql_tables, cur, list) {
+ if (!strcasecmp(a->argv[3], cur->database->unique_name) && !strncasecmp(a->word, cur->name, l) && ++which > a->n) {
+ ret = ast_strdup(cur->name);
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&mysql_tables);
+ } else {
+ struct mysql_conn *cur;
+ AST_LIST_LOCK(&databases);
+ AST_LIST_TRAVERSE(&databases, cur, list) {
+ if (!strncasecmp(a->word, cur->unique_name, l) && ++which > a->n) {
+ ret = ast_strdup(cur->unique_name);
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&databases);
+ }
+ return ret;
+ }
+
+ if (a->argc == 3) {
+ /* List of tables */
+ AST_LIST_LOCK(&mysql_tables);
+ AST_LIST_TRAVERSE(&mysql_tables, cur, list) {
+ ast_cli(a->fd, "%20.20s %s\n", cur->database->unique_name, cur->name);
+ }
+ AST_LIST_UNLOCK(&mysql_tables);
+ } else if (a->argc == 4) {
+ int found = 0;
+ /* List of tables */
+ AST_LIST_LOCK(&mysql_tables);
+ AST_LIST_TRAVERSE(&mysql_tables, cur, list) {
+ if (!strcasecmp(cur->database->unique_name, a->argv[3])) {
+ ast_cli(a->fd, "%s\n", cur->name);
+ found = 1;
+ }
+ }
+ AST_LIST_UNLOCK(&mysql_tables);
+ if (!found) {
+ ast_cli(a->fd, "No tables cached within %s database\n", a->argv[3]);
+ }
+ } else if (a->argc == 5) {
+ /* List of columns */
+ if ((cur = find_table(a->argv[3], a->argv[4]))) {
+ struct columns *col;
+ ast_cli(a->fd, "Columns for Table Cache '%s':\n", a->argv[3]);
+ ast_cli(a->fd, "%-20.20s %-20.20s %-3.3s\n", "Name", "Type", "Len");
+ AST_LIST_TRAVERSE(&cur->columns, col, list) {
+ ast_cli(a->fd, "%-20.20s %-20.20s %3d\n", col->name, col->type, col->len);
+ }
+ ast_mutex_unlock(&cur->lock);
+ } else {
+ ast_cli(a->fd, "No such table '%s'\n", a->argv[3]);
+ }
+ }
+ return CLI_SUCCESS;
+}
+
static char *handle_cli_realtime_mysql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char status[256], status2[100] = "";
- int ctime = 0;
+ char status[256], status2[100] = "", type[20];
+ char *ret = NULL;
+ int ctime = 0, found = 0;
+ struct mysql_conn *cur;
+ int l, which;
switch (cmd) {
case CLI_INIT:
e->command = "realtime mysql status";
e->usage =
- "Usage: realtime mysql status\n"
+ "Usage: realtime mysql status [<database>]\n"
" Shows connection information for the MySQL RealTime driver\n";
return NULL;
case CLI_GENERATE:
- return NULL;
+ if (a->argc == 4) {
+ AST_LIST_LOCK(&databases);
+ AST_LIST_TRAVERSE(&databases, cur, list) {
+ if (!strncasecmp(a->word, cur->unique_name, l) && ++which > a->n) {
+ ret = ast_strdup(cur->unique_name);
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&databases);
+ }
+ return ret;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
- ctime = time(NULL) - dbread.connect_time;
+ AST_LIST_LOCK(&databases);
+ AST_LIST_TRAVERSE(&databases, cur, list) {
+ if (a->argc == 3 || (a->argc == 4 && !strcasecmp(a->argv[3], cur->unique_name))) {
+ found = 1;
+
+ if (mysql_reconnect(cur)) {
+ snprintf(type, sizeof(type), "connected to");
+ ctime = time(NULL) - cur->connect_time;
+ } else {
+ snprintf(type, sizeof(type), "configured for");
+ ctime = -1;
+ }
- if (mysql_reconnect(&dbread)) {
- if (!ast_strlen_zero(dbread.host))
- snprintf(status, sizeof(status), "Connected to %s@%s, port %d", dbread.name, dbread.host, dbread.port);
- else
- snprintf(status, sizeof(status), "Connected to %s on socket file %s", dbread.name, dbread.sock);
+ if (!ast_strlen_zero(cur->host)) {
+ snprintf(status, sizeof(status), "%s %s %s@%s, port %d", cur->unique_name, type, cur->name, cur->host, cur->port);
+ } else {
+ snprintf(status, sizeof(status), "%s %s %s on socket file %s", cur->unique_name, type, cur->name, cur->sock);
+ }
- if (!ast_strlen_zero(dbread.user))
- snprintf(status2, sizeof(status2), " with username %s", dbread.user);
+ if (!ast_strlen_zero(cur->user)) {
+ snprintf(status2, sizeof(status2), " with username %s", cur->user);
+ } else {
+ status2[0] = '\0';
+ }
- if (ctime > 31536000)
- ast_cli(a->fd, "%s%s for %.1f years.\n", status, status2, (double)ctime / 31536000.0);
- else if (ctime > 86400 * 30)
- ast_cli(a->fd, "%s%s for %d days.\n", status, status2, ctime / 86400);
- else if (ctime > 86400)
- ast_cli(a->fd, "%s%s for %d days, %d hours.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600);
- else if (ctime > 3600)
- ast_cli(a->fd, "%s%s for %d hours, %d minutes.\n", status, status2, ctime / 3600, (ctime % 3600) / 60);
- else if (ctime > 60)
- ast_cli(a->fd, "%s%s for %d minutes.\n", status, status2, ctime / 60);
- else
- ast_cli(a->fd, "%s%s for %d seconds.\n", status, status2, ctime);
+ if (ctime > 31536000) {
+ ast_cli(a->fd, "%s%s for %.1f years.\n", status, status2, (double)ctime / 31536000.0);
+ } else if (ctime > 86400 * 30) {
+ ast_cli(a->fd, "%s%s for %d days.\n", status, status2, ctime / 86400);
+ } else if (ctime > 86400) {
+ ast_cli(a->fd, "%s%s for %d days, %d hours.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600);
+ } else if (ctime > 3600) {
+ ast_cli(a->fd, "%s%s for %d hours, %d minutes.\n", status, status2, ctime / 3600, (ctime % 3600) / 60);
+ } else if (ctime > 60) {
+ ast_cli(a->fd, "%s%s for %d minutes.\n", status, status2, ctime / 60);
+ } else if (ctime > -1) {
+ ast_cli(a->fd, "%s%s for %d seconds.\n", status, status2, ctime);
+ } else {
+ ast_cli(a->fd, "%s%s.\n", status, status2);
+ }
+ }
+ }
+ AST_LIST_UNLOCK(&databases);
- return CLI_SUCCESS;
- } else
- return CLI_FAILURE;
+ if (!found) {
+ ast_cli(a->fd, "No connections configured.\n");
+ }
+ return CLI_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "MySQL RealTime Configuration Driver",
|