aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b>2011-01-20 20:24:53 +0000
committerlmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b>2011-01-20 20:24:53 +0000
commit2c484c278869c6feb3ca4b33572c58af20e01033 (patch)
treeac0654bd7b0cf7f7d465befd27828a6aa3fcb5e1
parenta00c54c4c5d9894c7dcd8c6f9427203520beedee (diff)
Update .version, ChangeLog, and merge changes.
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.6.2.17-rc2@303141 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--.version2
-rw-r--r--ChangeLog133
-rw-r--r--asterisk-1.6.2.17-rc1-summary.html320
-rw-r--r--asterisk-1.6.2.17-rc1-summary.txt386
-rw-r--r--main/features.c796
5 files changed, 676 insertions, 961 deletions
diff --git a/.version b/.version
index d46d7f0f2..042d3acea 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-1.6.2.17-rc1
+1.6.2.17-rc2
diff --git a/ChangeLog b/ChangeLog
index bb46cf814..f18635e02 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,136 @@
+2011-01-20 Leif Madsen <lmadsen@digium.com>
+
+ * Asterisk 1.6.2.17-rc2 Released.
+
+ ------------------------------------------------------------------------
+ r302172 | rmudgett | 2011-01-18 12:04:37 -0600 (Tue, 18 Jan 2011) | 88
+ lines
+
+ Issues with DTMF triggered attended transfers.
+
+ Issue 0017999
+ 1) A calls B. B answers.
+ 2) B using DTMF dial *2 (code in features.conf for attended transfer).
+ 3) A hears MOH. B dial number C
+ 4) C ringing. A hears MOH.
+ 5) B hangup. A still hears MOH. C ringing.
+ 6) A hangup. C still ringing until "atxfernoanswertimeout" expires.
+ For v1.4 C will ring forever until C answers the dead line. (Issue
+ 0017096)
+
+ Problem: When A and B hangup, C is still ringing.
+
+ Issue 0018395
+ SIP call limit of B is 1
+ 1. A call B, B answered
+ 2. B *2(atxfer) call C
+ 3. B hangup, C ringing
+ 4. Timeout waiting for C to answer
+ 5. Recall to B fails because B has reached its call limit.
+
+ Because B reached its call limit, it cannot do anything until the
+ transfer
+ it started completes.
+
+ Issue 0017273
+ Same scenario as issue 18395 but party B is an FXS port. Party B
+ cannot
+ do anything until the transfer it started completes. If B goes back
+ off
+ hook before C answers, B hears ringback instead of the expected
+ dialtone.
+
+ **********
+ Note for the issue 0017273 and 0018395 fix:
+
+ DTMF attended transfer works within the channel bridge. Unfortunately,
+ when either party A or B in the channel bridge hangs up, that channel
+ is
+ not completely hung up until the transfer completes. This is a real
+ problem depending upon the channel technology involved.
+
+ For chan_dahdi, the channel is crippled until the hangup is complete.
+ Either the channel is not useable (analog) or the protocol disconnect
+ messages are held up (PRI/BRI/SS7) and the media is not released.
+
+ For chan_sip, a call limit of one is going to block that endpoint from
+ any
+ further calls until the hangup is complete.
+
+ For party A this is a minor problem. The party A channel will only be
+ in
+ this condition while party B is dialing and when party B and C are
+ conferring. The conversation between party B and C is expected to be a
+ short one. Party B is either asking a question of party C or
+ announcing
+ party A. Also party A does not have much incentive to hangup at this
+ point.
+
+ For party B this can be a major problem during a blonde transfer. (A
+ blonde transfer is our term for an attended transfer that is converted
+ into a blind transfer. :)) Party B could be the operator. When party B
+ hangs up, he assumes that he is out of the original call entirely. The
+ party B channel will be in this condition while party C is ringing,
+ while
+ attempting to recall party B, and while waiting between call attempts.
+
+ WARNING:
+ The ATXFER_NULL_TECH conditional is a hack to fix the problem. It will
+ replace the party B channel technology with a NULL channel driver to
+ complete hanging up the party B channel technology. The consequences
+ of
+ this code is that the 'h' extension will not be able to access any
+ channel
+ technology specific information like SIP statistics for the call.
+
+ ATXFER_NULL_TECH is not defined by default.
+ **********
+
+ (closes issue 0017999)
+ Reported by: iskatel
+ Tested by: rmudgett
+ JIRA SWP-2246
+
+ (closes issue 0017096)
+ Reported by: gelo
+ Tested by: rmudgett
+ JIRA SWP-1192
+
+ (closes issue 0018395)
+ Reported by: shihchuan
+ Tested by: rmudgett
+
+ (closes issue 0017273)
+ Reported by: grecco
+ Tested by: rmudgett
+
+ Review: https://reviewboard.asterisk.org/r/1047/ [^]
+
+ ------------------------------------------------------------------------
+
+ ------------------------------------------------------------------------
+ r303106 | sruffell | 2011-01-20 13:56:35 -0600 (Thu, 20 Jan 2011) | 15
+ lines
+
+ main/features: Use POLLPRI when waiting for events on parked channels.
+
+ This change resolves a regression in the 1.6.2 when converting from
+ select to poll. The DAHDI timers use POLLPRI to indicate that the
+ timer
+ fired, but features was not waiting for that flag. The result was no
+ audio for MOH when a call was parked and res_timing_dahdi was in use.
+
+ This patch is slightly modified from the one on the mantis issue. It
+ does
+ not set an exception on the channel if the POLLPRI flag is set.
+
+ (closes issue 0018262)
+ Reported by: francesco_r
+ Patches:
+ patch_park_moh-trunk-2.txt uploaded by cjacobsen (license 1029)
+ Tested by: francesco_r, rfrantik, one47
+ ------------------------------------------------------------------------
+
2011-01-14 Leif Madsen <lmadsen@digium.com>
* Asterisk 1.6.2.17-rc1 Released.
diff --git a/asterisk-1.6.2.17-rc1-summary.html b/asterisk-1.6.2.17-rc1-summary.html
deleted file mode 100644
index a4b62b444..000000000
--- a/asterisk-1.6.2.17-rc1-summary.html
+++ /dev/null
@@ -1,320 +0,0 @@
-<!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-1.6.2.17-rc1</title></head>
-<body>
-<h1 align="center"><a name="top">Release Summary</a></h1>
-<h3 align="center">asterisk-1.6.2.17-rc1</h3>
-<h3 align="center">Date: 2011-01-14</h3>
-<h3 align="center">&lt;asteriskteam@digium.com&gt;</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 only bug fixes. The changes included were made only to address problems that have been identified in this release series. Users should be able to safely upgrade to this version if this release series is already in use. Users considering upgrading from a previous release series are strongly encouraged to review the UPGRADE.txt document as well as the CHANGES document for information about upgrading to this release series.</p>
-<p>The data in this summary reflects changes that have been made since the previous release, asterisk-1.6.2.16.</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>
-10 tilghman<br/>
-5 jpeeler<br/>
-4 pabelanger<br/>
-3 lathama<br/>
-3 mnicholson<br/>
-2 moy<br/>
-2 rmudgett<br/>
-2 twilson<br/>
-1 cjacobsen<br/>
-1 dimas<br/>
-1 jcovert<br/>
-1 ks3<br/>
-1 kshumard<br/>
-1 lmadsen<br/>
-1 pprindeville<br/>
-1 russell<br/>
-1 seanbright<br/>
-1 tzafrir<br/>
-</td>
-<td>
-2 elguero<br/>
-2 jthurman<br/>
-2 lathama<br/>
-2 pabelanger<br/>
-2 trev<br/>
-2 zerohalo<br/>
-1 bunny<br/>
-1 dimas<br/>
-1 joscas<br/>
-1 ks3<br/>
-1 mdu113<br/>
-1 mmurdock<br/>
-1 moy<br/>
-1 nivek<br/>
-1 pprindeville<br/>
-1 seanbright<br/>
-1 twilson<br/>
-</td>
-<td>
-2 pabelanger<br/>
-1 bcnit<br/>
-1 bunny<br/>
-1 cabal95<br/>
-1 cjacobsen<br/>
-1 dimas<br/>
-1 jcovert<br/>
-1 jlaguilar<br/>
-1 joscas<br/>
-1 ks3<br/>
-1 kshumard<br/>
-1 lathama<br/>
-1 mariner7<br/>
-1 mdu113<br/>
-1 mmurdock<br/>
-1 nivek<br/>
-1 pprindeville<br/>
-1 rgj<br/>
-1 thsgmbh<br/>
-1 zerohalo<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: Applications/app_meetme</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18182">#18182</a>: [patch] useropts not initialized<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301089">301089</a><br/>
-Reporter: dimas<br/>
-Testers: dimas<br/>
-Coders: dimas<br/>
-<br/>
-<h3>Category: Applications/app_verbose</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18586">#18586</a>: [patch] Indicate log level argument for Log() is not optional<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301176">301176</a><br/>
-Reporter: kshumard<br/>
-Coders: kshumard<br/>
-<br/>
-<h3>Category: Applications/app_voicemail</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18358">#18358</a>: [patch] Cannot forward voicemail with file storage backend<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301046">301046</a><br/>
-Reporter: cabal95<br/>
-Coders: jpeeler<br/>
-<br/>
-<h3>Category: CDR/cdr_pgsql</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18460">#18460</a>: [patch] CDR(billsec) is not inserted properly for unanswered calls<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299130">299130</a><br/>
-Reporter: joscas<br/>
-Testers: joscas<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Channels/chan_dahdi</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18438">#18438</a>: Ealry media is lost on accepted calls (with open r2 support, Elastix 2 flavor)<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299530">299530</a><br/>
-Reporter: mariner7<br/>
-Testers: moy<br/>
-Coders: moy<br/>
-<br/>
-<h3>Category: Channels/chan_sip/DatabaseSupport</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18251">#18251</a>: [patch] Realtime field 'fullcontact' populated with invalid data<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298481">298481</a><br/>
-Reporter: bcnit<br/>
-Testers: trev, jthurman, elguero, zerohalo<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Channels/chan_sip/Subscriptions</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18075">#18075</a>: [patch] Asterisk fails to recognize SUBSCRIBE retransmissions and tries to re-authenticate them, which breaks presence on polyco<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300298">300298</a><br/>
-Reporter: mdu113<br/>
-Testers: twilson, mdu113<br/>
-Coders: twilson<br/>
-<br/>
-<a href="https://issues.asterisk.org/view.php?id=18597">#18597</a>: [regression] Snom BLF subscription does not work<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301682">301682</a><br/>
-Reporter: thsgmbh<br/>
-Coders: twilson<br/>
-<br/>
-<h3>Category: Core/BuildSystem</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18493">#18493</a>: [patch] Sqlite3 requires -lpthread to build in configure.ac<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298817">298817</a><br/>
-Reporter: pprindeville<br/>
-Testers: pprindeville<br/>
-Coders: pprindeville<br/>
-<br/>
-<a href="https://issues.asterisk.org/view.php?id=18589">#18589</a>: [patch] [regression] asterisk 1.8 tarball sound files ignored, Makefile re-downloads them.<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301220">301220</a><br/>
-Reporter: pabelanger<br/>
-Testers: pabelanger<br/>
-Coders: pabelanger<br/>
-<br/>
-<h3>Category: Documentation</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18531">#18531</a>: [patch] Note more settings in users.conf.sample to guide the user<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300431">300431</a><br/>
-Reporter: lathama<br/>
-Testers: lathama<br/>
-Coders: lathama<br/>
-<br/>
-<h3>Category: Features/Parking</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=15758">#15758</a>: Park application expects timeout to be in Milliseconds<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299087">299087</a><br/>
-Reporter: mmurdock<br/>
-Testers: mmurdock, seanbright<br/>
-Coders: lmadsen<br/>
-<br/>
-<h3>Category: Functions/func_dialgroup</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18091">#18091</a>: [patch] dialgroup fills database with duplicates<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298477">298477</a><br/>
-Reporter: bunny<br/>
-Testers: bunny<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Functions/func_odbc</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18243">#18243</a>: [patch] Random segfault when querying MySQL via func_odbc<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300622">300622</a><br/>
-Reporter: ks3<br/>
-Testers: ks3<br/>
-Coders: ks3<br/>
-<br/>
-<h3>Category: General</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18130">#18130</a>: [regression] DTMF on agent channel causes high CPU<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301503">301503</a><br/>
-Reporter: rgj<br/>
-Coders: jpeeler<br/>
-<br/>
-<a href="https://issues.asterisk.org/view.php?id=18547">#18547</a>: [patch] main/xmldoc.c error message is backwards -- fix that, and remove the sources of the error while we're at it<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300520">300520</a><br/>
-Reporter: jcovert<br/>
-Coders: jcovert<br/>
-<br/>
-<h3>Category: PBX/pbx_ael</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18480">#18480</a>: [patch] Contexts with a 'switch' statement in a 's' extension adds MSet to the beginning of the Context<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299448">299448</a><br/>
-Reporter: nivek<br/>
-Testers: nivek<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: PBX/pbx_realtime</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=16228">#16228</a>: eswitch does not substiotute variables when using Local Channel<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299625">299625</a><br/>
-Reporter: jlaguilar<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Resources/res_config_odbc</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18279">#18279</a>: [patch] res_odbc using ^ separator in M(macro) option as argument separator in Dial app gives control characters<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298481">298481</a><br/>
-Reporter: zerohalo<br/>
-Testers: trev, jthurman, elguero, zerohalo<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Resources/res_fax</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18481">#18481</a>: [patch] *** glibc detected *** /usr/sbin/asterisk: free(): invalid pointer on shutdown<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298393">298393</a><br/>
-Reporter: pabelanger<br/>
-Testers: pabelanger<br/>
-Coders: tilghman<br/>
-<br/>
-<h3>Category: Resources/res_phoneprov</h3><br/>
-<a href="https://issues.asterisk.org/view.php?id=18607">#18607</a>: [patch] Static entry for Polycom 331 split firmware<br/>
-Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301730">301730</a><br/>
-Reporter: cjacobsen<br/>
-Testers: lathama<br/>
-Coders: cjacobsen<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/branches/1.6.2?view=revision&revision=298194">298194</a></td><td>rmudgett</td><td>Outgoing PRI/BRI calls cannot do DTMF triggered transfers.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298346">298346</a></td><td>seanbright</td><td>Fix reference and container leaks when running 'astobj2 test.'</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298597">298597</a></td><td>jpeeler</td><td>Fix improper hangup when doing an attended transfer to queue.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298684">298684</a></td><td>jpeeler</td><td>After recording only silence for a voicemail prepending, restore backup files.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298957">298957</a></td><td>tilghman</td><td>Let Asterisk find better backtrace information with libbfd.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=298962">298962</a></td><td>tilghman</td><td>Remove backtrace used for testing merge process</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299003">299003</a></td><td>tzafrir</td><td>Typos: recieved => received</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299136">299136</a></td><td>tilghman</td><td>Documentation fix</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299242">299242</a></td><td>mnicholson</td><td>Respond as soon as possible with a 202 Accepted to refer requests.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299533">299533</a></td><td>moy</td><td>do not use progress which is for PRI and SS7, add mfcr2_progress member</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=299864">299864</a></td><td>pabelanger</td><td>Documentation typo</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300165">300165</a></td><td>rmudgett</td><td>Use correct variable for atxfercallbackretries config option.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300429">300429</a></td><td>russell</td><td>Update the autosupport script from Digium support.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300574">300574</a></td><td>pabelanger</td><td>Change deprecated message to LOG_WARNING</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=300951">300951</a></td><td>jpeeler</td><td>Ensure good bye prompt in voicemail is played at the correct time.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301307">301307</a></td><td>mnicholson</td><td>Prevent buffer overflows in ast_uri_encode()</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301310">301310</a></td><td>pabelanger</td><td>Fix a logic issue when passing context ARG</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301594">301594</a></td><td>mnicholson</td><td>Removed a usleep(1) that shouldn't be necessary in session_do, and removed the</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301842">301842</a></td><td>lathama</td><td>Add relationships to function documentation.</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.6.2?view=revision&revision=301848">301848</a></td><td>lathama</td><td>Add relationships to function documentation.</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>
-apps/app_chanspy.c | 2
-apps/app_meetme.c | 4
-apps/app_queue.c | 1
-apps/app_verbose.c | 2
-apps/app_voicemail.c | 37
-autoconf/ast_ext_lib.m4 | 2
-build_tools/cflags-devmode.xml | 5
-build_tools/menuselect-deps.in | 2
-cdr/cdr_pgsql.c | 6
-cdr/cdr_sqlite.c | 9
-channels/chan_agent.c | 2
-channels/chan_dahdi.c | 23
-channels/chan_iax2.c | 4
-channels/chan_local.c | 12
-channels/chan_sip.c | 93 -
-configs/extensions.conf.sample | 14
-configs/phoneprov.conf.sample | 2
-configs/users.conf.sample | 29
-configure.ac | 34
-contrib/scripts/autosupport | 619 +++++--
-contrib/scripts/autosupport.8 | 63
-funcs/func_aes.c | 10
-funcs/func_base64.c | 10
-funcs/func_dialgroup.c | 5
-include/asterisk/autoconfig.h.in | 6
-include/asterisk/logger.h | 10
-include/asterisk/utils.h | 9
-main/Makefile | 4
-main/astobj2.c | 4
-main/channel.c | 2
-main/features.c | 22
-main/logger.c | 156 +
-main/manager.c | 14
-main/utils.c | 49
-main/xmldoc.c | 2
-makeopts.in | 3
-pbx/ael/ael-test/ref.ael-test19 | 2
-pbx/ael/ael-test/ref.ael-test3 | 14
-pbx/ael/ael-test/ref.ael-vtest13 | 3367 +++++++++++++++++++--------------------
-pbx/ael/ael-test/ref.ael-vtest17 | 16
-pbx/ael/ael-test/ref.ael-vtest25 | 2
-res/ael/pval.c | 8
-res/res_config_odbc.c | 5
-res/res_odbc.c | 17
-sample.call | 2
-utils/ael_main.c | 11
-utils/check_expr.c | 12
-utils/conf2ael.c | 12
-utils/hashtest.c | 13
-utils/hashtest2.c | 12
-utils/refcounter.c | 13
-51 files changed, 2725 insertions(+), 2052 deletions(-)
-</pre><br/>
-<hr/>
-</body>
-</html>
diff --git a/asterisk-1.6.2.17-rc1-summary.txt b/asterisk-1.6.2.17-rc1-summary.txt
deleted file mode 100644
index 34e959ba5..000000000
--- a/asterisk-1.6.2.17-rc1-summary.txt
+++ /dev/null
@@ -1,386 +0,0 @@
- Release Summary
-
- asterisk-1.6.2.17-rc1
-
- Date: 2011-01-14
-
- <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 only bug fixes. The changes included were made only
- to address problems that have been identified in this release series.
- Users should be able to safely upgrade to this version if this release
- series is already in use. Users considering upgrading from a previous
- release series are strongly encouraged to review the UPGRADE.txt document
- as well as the CHANGES document for information about upgrading to this
- release series.
-
- The data in this summary reflects changes that have been made since the
- previous release, asterisk-1.6.2.16.
-
- ----------------------------------------------------------------------
-
- 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
- 10 tilghman 2 elguero 2 pabelanger
- 5 jpeeler 2 jthurman 1 bcnit
- 4 pabelanger 2 lathama 1 bunny
- 3 lathama 2 pabelanger 1 cabal95
- 3 mnicholson 2 trev 1 cjacobsen
- 2 moy 2 zerohalo 1 dimas
- 2 rmudgett 1 bunny 1 jcovert
- 2 twilson 1 dimas 1 jlaguilar
- 1 cjacobsen 1 joscas 1 joscas
- 1 dimas 1 ks3 1 ks3
- 1 jcovert 1 mdu113 1 kshumard
- 1 ks3 1 mmurdock 1 lathama
- 1 kshumard 1 moy 1 mariner7
- 1 lmadsen 1 nivek 1 mdu113
- 1 pprindeville 1 pprindeville 1 mmurdock
- 1 russell 1 seanbright 1 nivek
- 1 seanbright 1 twilson 1 pprindeville
- 1 tzafrir 1 rgj
- 1 thsgmbh
- 1 zerohalo
-
- ----------------------------------------------------------------------
-
- 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: Applications/app_meetme
-
- #18182: [patch] useropts not initialized
- Revision: 301089
- Reporter: dimas
- Testers: dimas
- Coders: dimas
-
- Category: Applications/app_verbose
-
- #18586: [patch] Indicate log level argument for Log() is not optional
- Revision: 301176
- Reporter: kshumard
- Coders: kshumard
-
- Category: Applications/app_voicemail
-
- #18358: [patch] Cannot forward voicemail with file storage backend
- Revision: 301046
- Reporter: cabal95
- Coders: jpeeler
-
- Category: CDR/cdr_pgsql
-
- #18460: [patch] CDR(billsec) is not inserted properly for unanswered calls
- Revision: 299130
- Reporter: joscas
- Testers: joscas
- Coders: tilghman
-
- Category: Channels/chan_dahdi
-
- #18438: Ealry media is lost on accepted calls (with open r2 support,
- Elastix 2 flavor)
- Revision: 299530
- Reporter: mariner7
- Testers: moy
- Coders: moy
-
- Category: Channels/chan_sip/DatabaseSupport
-
- #18251: [patch] Realtime field 'fullcontact' populated with invalid data
- Revision: 298481
- Reporter: bcnit
- Testers: trev, jthurman, elguero, zerohalo
- Coders: tilghman
-
- Category: Channels/chan_sip/Subscriptions
-
- #18075: [patch] Asterisk fails to recognize SUBSCRIBE retransmissions and
- tries to re-authenticate them, which breaks presence on polyco
- Revision: 300298
- Reporter: mdu113
- Testers: twilson, mdu113
- Coders: twilson
-
- #18597: [regression] Snom BLF subscription does not work
- Revision: 301682
- Reporter: thsgmbh
- Coders: twilson
-
- Category: Core/BuildSystem
-
- #18493: [patch] Sqlite3 requires -lpthread to build in configure.ac
- Revision: 298817
- Reporter: pprindeville
- Testers: pprindeville
- Coders: pprindeville
-
- #18589: [patch] [regression] asterisk 1.8 tarball sound files ignored,
- Makefile re-downloads them.
- Revision: 301220
- Reporter: pabelanger
- Testers: pabelanger
- Coders: pabelanger
-
- Category: Documentation
-
- #18531: [patch] Note more settings in users.conf.sample to guide the user
- Revision: 300431
- Reporter: lathama
- Testers: lathama
- Coders: lathama
-
- Category: Features/Parking
-
- #15758: Park application expects timeout to be in Milliseconds
- Revision: 299087
- Reporter: mmurdock
- Testers: mmurdock, seanbright
- Coders: lmadsen
-
- Category: Functions/func_dialgroup
-
- #18091: [patch] dialgroup fills database with duplicates
- Revision: 298477
- Reporter: bunny
- Testers: bunny
- Coders: tilghman
-
- Category: Functions/func_odbc
-
- #18243: [patch] Random segfault when querying MySQL via func_odbc
- Revision: 300622
- Reporter: ks3
- Testers: ks3
- Coders: ks3
-
- Category: General
-
- #18130: [regression] DTMF on agent channel causes high CPU
- Revision: 301503
- Reporter: rgj
- Coders: jpeeler
-
- #18547: [patch] main/xmldoc.c error message is backwards -- fix that, and
- remove the sources of the error while we're at it
- Revision: 300520
- Reporter: jcovert
- Coders: jcovert
-
- Category: PBX/pbx_ael
-
- #18480: [patch] Contexts with a 'switch' statement in a 's' extension adds
- MSet to the beginning of the Context
- Revision: 299448
- Reporter: nivek
- Testers: nivek
- Coders: tilghman
-
- Category: PBX/pbx_realtime
-
- #16228: eswitch does not substiotute variables when using Local Channel
- Revision: 299625
- Reporter: jlaguilar
- Coders: tilghman
-
- Category: Resources/res_config_odbc
-
- #18279: [patch] res_odbc using ^ separator in M(macro) option as argument
- separator in Dial app gives control characters
- Revision: 298481
- Reporter: zerohalo
- Testers: trev, jthurman, elguero, zerohalo
- Coders: tilghman
-
- Category: Resources/res_fax
-
- #18481: [patch] *** glibc detected *** /usr/sbin/asterisk: free(): invalid
- pointer on shutdown
- Revision: 298393
- Reporter: pabelanger
- Testers: pabelanger
- Coders: tilghman
-
- Category: Resources/res_phoneprov
-
- #18607: [patch] Static entry for Polycom 331 split firmware
- Revision: 301730
- Reporter: cjacobsen
- Testers: lathama
- Coders: cjacobsen
-
- ----------------------------------------------------------------------
-
- 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 |
- |----------+------------+-----------------------------------+------------|
- | 298194 | rmudgett | Outgoing PRI/BRI calls cannot do | |
- | | | DTMF triggered transfers. | |
- |----------+------------+-----------------------------------+------------|
- | 298346 | seanbright | Fix reference and container leaks | |
- | | | when running 'astobj2 test.' | |
- |----------+------------+-----------------------------------+------------|
- | 298597 | jpeeler | Fix improper hangup when doing an | |
- | | | attended transfer to queue. | |
- |----------+------------+-----------------------------------+------------|
- | | | After recording only silence for | |
- | 298684 | jpeeler | a voicemail prepending, restore | |
- | | | backup files. | |
- |----------+------------+-----------------------------------+------------|
- | | | Let Asterisk find better | |
- | 298957 | tilghman | backtrace information with | |
- | | | libbfd. | |
- |----------+------------+-----------------------------------+------------|
- | 298962 | tilghman | Remove backtrace used for testing | |
- | | | merge process | |
- |----------+------------+-----------------------------------+------------|
- | 299003 | tzafrir | Typos: recieved => received | |
- |----------+------------+-----------------------------------+------------|
- | 299136 | tilghman | Documentation fix | |
- |----------+------------+-----------------------------------+------------|
- | 299242 | mnicholson | Respond as soon as possible with | |
- | | | a 202 Accepted to refer requests. | |
- |----------+------------+-----------------------------------+------------|
- | | | do not use progress which is for | |
- | 299533 | moy | PRI and SS7, add mfcr2_progress | |
- | | | member | |
- |----------+------------+-----------------------------------+------------|
- | 299864 | pabelanger | Documentation typo | |
- |----------+------------+-----------------------------------+------------|
- | | | Use correct variable for | |
- | 300165 | rmudgett | atxfercallbackretries config | |
- | | | option. | |
- |----------+------------+-----------------------------------+------------|
- | 300429 | russell | Update the autosupport script | |
- | | | from Digium support. | |
- |----------+------------+-----------------------------------+------------|
- | 300574 | pabelanger | Change deprecated message to | |
- | | | LOG_WARNING | |
- |----------+------------+-----------------------------------+------------|
- | | | Ensure good bye prompt in | |
- | 300951 | jpeeler | voicemail is played at the | |
- | | | correct time. | |
- |----------+------------+-----------------------------------+------------|
- | 301307 | mnicholson | Prevent buffer overflows in | |
- | | | ast_uri_encode() | |
- |----------+------------+-----------------------------------+------------|
- | 301310 | pabelanger | Fix a logic issue when passing | |
- | | | context ARG | |
- |----------+------------+-----------------------------------+------------|
- | | | Removed a usleep(1) that | |
- | 301594 | mnicholson | shouldn't be necessary in | |
- | | | session_do, and removed the | |
- |----------+------------+-----------------------------------+------------|
- | 301842 | lathama | Add relationships to function | |
- | | | documentation. | |
- |----------+------------+-----------------------------------+------------|
- | 301848 | lathama | Add relationships to function | |
- | | | documentation. | |
- +------------------------------------------------------------------------+
-
- ----------------------------------------------------------------------
-
- 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.
-
- apps/app_chanspy.c | 2
- apps/app_meetme.c | 4
- apps/app_queue.c | 1
- apps/app_verbose.c | 2
- apps/app_voicemail.c | 37
- autoconf/ast_ext_lib.m4 | 2
- build_tools/cflags-devmode.xml | 5
- build_tools/menuselect-deps.in | 2
- cdr/cdr_pgsql.c | 6
- cdr/cdr_sqlite.c | 9
- channels/chan_agent.c | 2
- channels/chan_dahdi.c | 23
- channels/chan_iax2.c | 4
- channels/chan_local.c | 12
- channels/chan_sip.c | 93 -
- configs/extensions.conf.sample | 14
- configs/phoneprov.conf.sample | 2
- configs/users.conf.sample | 29
- configure.ac | 34
- contrib/scripts/autosupport | 619 +++++--
- contrib/scripts/autosupport.8 | 63
- funcs/func_aes.c | 10
- funcs/func_base64.c | 10
- funcs/func_dialgroup.c | 5
- include/asterisk/autoconfig.h.in | 6
- include/asterisk/logger.h | 10
- include/asterisk/utils.h | 9
- main/Makefile | 4
- main/astobj2.c | 4
- main/channel.c | 2
- main/features.c | 22
- main/logger.c | 156 +
- main/manager.c | 14
- main/utils.c | 49
- main/xmldoc.c | 2
- makeopts.in | 3
- pbx/ael/ael-test/ref.ael-test19 | 2
- pbx/ael/ael-test/ref.ael-test3 | 14
- pbx/ael/ael-test/ref.ael-vtest13 | 3367 +++++++++++++++++++--------------------
- pbx/ael/ael-test/ref.ael-vtest17 | 16
- pbx/ael/ael-test/ref.ael-vtest25 | 2
- res/ael/pval.c | 8
- res/res_config_odbc.c | 5
- res/res_odbc.c | 17
- sample.call | 2
- utils/ael_main.c | 11
- utils/check_expr.c | 12
- utils/conf2ael.c | 12
- utils/hashtest.c | 13
- utils/hashtest2.c | 12
- utils/refcounter.c | 13
- 51 files changed, 2725 insertions(+), 2052 deletions(-)
-
- ----------------------------------------------------------------------
diff --git a/main/features.c b/main/features.c
index fc9ef5593..74adde7e9 100644
--- a/main/features.c
+++ b/main/features.c
@@ -57,6 +57,56 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/global_datastores.h"
#include "asterisk/astobj2.h"
+/*
+ * Party A - transferee
+ * Party B - transferer
+ * Party C - target of transfer
+ *
+ * DTMF attended transfer works within the channel bridge.
+ * Unfortunately, when either party A or B in the channel bridge
+ * hangs up, that channel is not completely hung up until the
+ * transfer completes. This is a real problem depending upon
+ * the channel technology involved.
+ *
+ * For chan_dahdi, the channel is crippled until the hangup is
+ * complete. Either the channel is not useable (analog) or the
+ * protocol disconnect messages are held up (PRI/BRI/SS7) and
+ * the media is not released.
+ *
+ * For chan_sip, a call limit of one is going to block that
+ * endpoint from any further calls until the hangup is complete.
+ *
+ * For party A this is a minor problem. The party A channel
+ * will only be in this condition while party B is dialing and
+ * when party B and C are conferring. The conversation between
+ * party B and C is expected to be a short one. Party B is
+ * either asking a question of party C or announcing party A.
+ * Also party A does not have much incentive to hangup at this
+ * point.
+ *
+ * For party B this can be a major problem during a blonde
+ * transfer. (A blonde transfer is our term for an attended
+ * transfer that is converted into a blind transfer. :)) Party
+ * B could be the operator. When party B hangs up, he assumes
+ * that he is out of the original call entirely. The party B
+ * channel will be in this condition while party C is ringing,
+ * while attempting to recall party B, and while waiting between
+ * call attempts.
+ *
+ * WARNING:
+ * The ATXFER_NULL_TECH conditional is a hack to fix the
+ * problem. It will replace the party B channel technology with
+ * a NULL channel driver. The consequences of this code is that
+ * the 'h' extension will not be able to access any channel
+ * technology specific information like SIP statistics for the
+ * call.
+ *
+ * Uncomment the ATXFER_NULL_TECH define below to replace the
+ * party B channel technology in the channel bridge to complete
+ * hanging up the channel technology.
+ */
+//#define ATXFER_NULL_TECH 1
+
/*** DOCUMENTATION
<application name="Bridge" language="en_US">
<synopsis>
@@ -278,6 +328,119 @@ struct ast_dial_features {
int is_caller;
};
+#if defined(ATXFER_NULL_TECH)
+static struct ast_frame *null_read(struct ast_channel *chan)
+{
+ /* Hangup channel. */
+ return NULL;
+}
+
+static struct ast_frame *null_exception(struct ast_channel *chan)
+{
+ /* Hangup channel. */
+ return NULL;
+}
+
+static int null_write(struct ast_channel *chan, struct ast_frame *frame)
+{
+ /* Hangup channel. */
+ return -1;
+}
+
+static int null_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+{
+ /* No problem fixing up the channel. */
+ return 0;
+}
+
+static int null_hangup(struct ast_channel *chan)
+{
+ chan->tech_pvt = NULL;
+ return 0;
+}
+
+static const struct ast_channel_tech null_tech = {
+ .type = "NULL",
+ .description = "NULL channel driver for atxfer",
+ .capabilities = -1,
+ .read = null_read,
+ .exception = null_exception,
+ .write = null_write,
+ .fixup = null_fixup,
+ .hangup = null_hangup,
+};
+#endif /* defined(ATXFER_NULL_TECH) */
+
+#if defined(ATXFER_NULL_TECH)
+/*!
+ * \internal
+ * \brief Set the channel technology to the NULL technology.
+ *
+ * \param chan Channel to change technology.
+ *
+ * \return Nothing
+ */
+static void set_null_chan_tech(struct ast_channel *chan)
+{
+ int idx;
+
+ ast_channel_lock(chan);
+
+ /* Hangup the channel's physical side */
+ if (chan->tech->hangup) {
+ chan->tech->hangup(chan);
+ }
+ if (chan->tech_pvt) {
+ ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
+ chan->name);
+ ast_free(chan->tech_pvt);
+ chan->tech_pvt = NULL;
+ }
+
+ /* Install the NULL technology and wake up anyone waiting on it. */
+ chan->tech = &null_tech;
+ for (idx = 0; idx < AST_MAX_FDS; ++idx) {
+ switch (idx) {
+ case AST_ALERT_FD:
+ case AST_TIMING_FD:
+ case AST_GENERATOR_FD:
+ /* Don't clear these fd's. */
+ break;
+ default:
+ ast_channel_set_fd(chan, idx, -1);
+ break;
+ }
+ }
+ ast_queue_frame(chan, &ast_null_frame);
+
+ ast_channel_unlock(chan);
+}
+#endif /* defined(ATXFER_NULL_TECH) */
+
+#if defined(ATXFER_NULL_TECH)
+/*!
+ * \internal
+ * \brief Set the channel name to something unique.
+ *
+ * \param chan Channel to change name.
+ *
+ * \return Nothing
+ */
+static void set_new_chan_name(struct ast_channel *chan)
+{
+ char *orig_name;
+ static int seq_num;
+
+ ast_channel_lock(chan);
+
+ orig_name = ast_strdupa(chan->name);
+ ast_string_field_build(chan, name, "%s<XFER_%x>", orig_name,
+ ast_atomic_fetchadd_int(&seq_num, +1));
+
+ ast_channel_unlock(chan);
+}
+#endif /* defined(ATXFER_NULL_TECH) */
+
static void *dial_features_duplicate(void *data)
{
struct ast_dial_features *df = data, *df_copy;
@@ -400,7 +563,10 @@ static void check_goto_on_transfer(struct ast_channel *chan)
}
}
-static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language);
+static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
+ const char *caller_name, struct ast_channel *transferee, const char *type,
+ int format, void *data, int timeout, int *outstate, const char *cid_num,
+ const char *cid_name, const char *language);
/*!
* \brief bridge the call
@@ -1392,9 +1558,9 @@ static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
* \param config
* \param code
* \param sense feature options
- *
+ *
* \param data
- * Get extension to transfer to, if you cannot generate channel (or find extension)
+ * Get extension to transfer to, if you cannot generate channel (or find extension)
* return to host channel. After called channel answered wait for hangup of transferer,
* bridge call between transfer peer (taking them off hold) to attended transfer channel.
*
@@ -1402,8 +1568,8 @@ static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
*/
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
- struct ast_channel *transferer;
- struct ast_channel *transferee;
+ struct ast_channel *transferer;/* Party B */
+ struct ast_channel *transferee;/* Party A */
const char *transferer_real_context;
char xferto[256] = "";
int res;
@@ -1412,60 +1578,60 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
struct ast_channel *xferchan;
struct ast_bridge_thread_obj *tobj;
struct ast_bridge_config bconfig;
- struct ast_frame *f;
int l;
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
+ char *transferer_tech;
+ char *transferer_name;
+ char *transferer_name_orig;
+ char *dash;
ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
set_peers(&transferer, &transferee, peer, chan, sense);
transferer_real_context = real_ctx(transferer, transferee);
- /* Start autoservice on chan while we talk to the originator */
+
+ /* Start autoservice on transferee while we talk to the transferer */
ast_autoservice_start(transferee);
- ast_autoservice_ignore(transferee, AST_FRAME_DTMF_END);
ast_indicate(transferee, AST_CONTROL_HOLD);
-
+
/* Transfer */
res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
if (res < 0) {
finishup(transferee);
- return res;
+ return -1;
}
if (res > 0) /* If they've typed a digit already, handle it */
xferto[0] = (char) res;
/* this is specific of atxfer */
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
- if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
+ if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
finishup(transferee);
- return res;
+ return -1;
}
+ l = strlen(xferto);
if (res == 0) {
- ast_log(LOG_WARNING, "Did not read data.\n");
+ if (l) {
+ ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
+ xferto, transferer_real_context);
+ } else {
+ /* Does anyone care about this case? */
+ ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
+ }
+ ast_stream_and_wait(transferer, "pbx-invalid", "");
finishup(transferee);
- if (ast_stream_and_wait(transferer, "beeperr", ""))
- return -1;
return AST_FEATURE_RETURN_SUCCESS;
}
- /* valid extension, res == 1 */
- if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
- ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
+ /* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
+ * the different variables for handling this properly with a builtin_atxfer */
+ if (!strcmp(xferto, ast_parking_ext())) {
finishup(transferee);
- if (ast_stream_and_wait(transferer, "beeperr", ""))
- return -1;
- return AST_FEATURE_RETURN_SUCCESS;
+ return builtin_parkcall(chan, peer, config, code, sense, data);
}
- /* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
- * the different variables for handling this properly with a builtin_atxfer */
- if (!strcmp(xferto, ast_parking_ext())) {
- finishup(transferee);
- return builtin_parkcall(chan, peer, config, code, sense, data);
- }
-
- l = strlen(xferto);
- snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
+ /* Append context to dialed transfer number. */
+ snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
/* If we are performing an attended transfer and we have two channels involved then
copy sound file information to play upon attended transfer completion */
@@ -1481,29 +1647,66 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
}
}
- newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
- xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+ /* Extract redial transferer information from the channel name. */
+ transferer_name_orig = ast_strdupa(transferer->name);
+ transferer_name = ast_strdupa(transferer_name_orig);
+ transferer_tech = strsep(&transferer_name, "/");
+ dash = strrchr(transferer_name, '-');
+ if (dash) {
+ /* Trim off channel name sequence/serial number. */
+ *dash = '\0';
+ }
+
+ /* Stop autoservice so we can monitor all parties involved in the transfer. */
+ if (ast_autoservice_stop(transferee) < 0) {
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
+ return -1;
+ }
+
+ /* Dial party C */
+ newchan = feature_request_and_dial(transferer, transferer_name_orig, transferee,
+ "Local", ast_best_codec(transferer->nativeformats), xferto, atxfernoanswertimeout,
+ &outstate, transferer->cid.cid_num, transferer->cid.cid_name,
+ transferer->language);
+ ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
if (!ast_check_hangup(transferer)) {
int hangup_dont = 0;
- /* Transferer is up - old behaviour */
+ /* Transferer (party B) is up */
+ ast_debug(1, "Actually doing an attended transfer.\n");
+
+ /* Start autoservice on transferee while the transferer deals with party C. */
+ ast_autoservice_start(transferee);
+
ast_indicate(transferer, -1);
if (!newchan) {
- finishup(transferee);
/* any reason besides user requested cancel and busy triggers the failed sound */
- if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
- ast_stream_and_wait(transferer, xferfailsound, ""))
- return -1;
- if (ast_stream_and_wait(transferer, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ switch (outstate) {
+ case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
+ case AST_CONTROL_BUSY:
+ case AST_CONTROL_CONGESTION:
+ if (ast_stream_and_wait(transferer, xfersound, "")) {
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ }
+ break;
+ default:
+ if (ast_stream_and_wait(transferer, xferfailsound, "")) {
+ ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
+ }
+ break;
+ }
+ finishup(transferee);
return AST_FEATURE_RETURN_SUCCESS;
}
if (check_compat(transferer, newchan)) {
+ if (ast_stream_and_wait(transferer, xferfailsound, "")) {
+ ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
+ }
/* we do mean transferee here, NOT transferer */
finishup(transferee);
- return -1;
+ return AST_FEATURE_RETURN_SUCCESS;
}
memset(&bconfig,0,sizeof(struct ast_bridge_config));
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
@@ -1515,205 +1718,194 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
hangup_dont = 1;
}
- res = ast_bridge_call(transferer, newchan, &bconfig);
+ /* Let party B and party C talk as long as they want. */
+ ast_bridge_call(transferer, newchan, &bconfig);
if (hangup_dont) {
ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
}
if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
ast_hangup(newchan);
- if (ast_stream_and_wait(transferer, xfersound, ""))
+ if (ast_stream_and_wait(transferer, xfersound, "")) {
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ }
finishup(transferee);
- transferer->_softhangup = 0;
return AST_FEATURE_RETURN_SUCCESS;
}
+
+ /* Transferer (party B) is confirmed hung up at this point. */
if (check_compat(transferee, newchan)) {
finishup(transferee);
return -1;
}
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
if ((ast_autoservice_stop(transferee) < 0)
- || (ast_waitfordigit(transferee, 100) < 0)
- || (ast_waitfordigit(newchan, 100) < 0)
- || ast_check_hangup(transferee)
- || ast_check_hangup(newchan)) {
+ || (ast_waitfordigit(transferee, 100) < 0)
+ || (ast_waitfordigit(newchan, 100) < 0)
+ || ast_check_hangup(transferee)
+ || ast_check_hangup(newchan)) {
ast_hangup(newchan);
return -1;
}
- xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
- if (!xferchan) {
- ast_hangup(newchan);
- return -1;
- }
- /* Make formats okay */
- xferchan->visible_indication = transferer->visible_indication;
- xferchan->readformat = transferee->readformat;
- xferchan->writeformat = transferee->writeformat;
- ast_channel_masquerade(xferchan, transferee);
- ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
- xferchan->_state = AST_STATE_UP;
- ast_clear_flag(xferchan, AST_FLAGS_ALL);
- xferchan->_softhangup = 0;
- if ((f = ast_read(xferchan)))
- ast_frfree(f);
- newchan->_state = AST_STATE_UP;
- ast_clear_flag(newchan, AST_FLAGS_ALL);
- newchan->_softhangup = 0;
- if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
- ast_hangup(xferchan);
- ast_hangup(newchan);
- return -1;
- }
-
- ast_channel_lock(newchan);
- if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
- dialfeatures = features_datastore->data;
- }
- ast_channel_unlock(newchan);
-
- if (dialfeatures) {
- /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
- I don't currently understand, the abilities of newchan seem to be stored on the caller side */
- ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
- dialfeatures = NULL;
- }
-
- ast_channel_lock(xferchan);
- if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
- dialfeatures = features_datastore->data;
- }
- ast_channel_unlock(xferchan);
-
- if (dialfeatures) {
- ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
- }
-
- tobj->chan = newchan;
- tobj->peer = xferchan;
- tobj->bconfig = *config;
-
- if (tobj->bconfig.end_bridge_callback_data_fixup) {
- tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
- }
-
- if (ast_stream_and_wait(newchan, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- bridge_call_thread_launch(tobj);
- return -1; /* XXX meaning the channel is bridged ? */
} else if (!ast_check_hangup(transferee)) {
- /* act as blind transfer */
- if (ast_autoservice_stop(transferee) < 0) {
- ast_hangup(newchan);
- return -1;
- }
+ /* Transferer (party B) has hung up at this point. Doing blonde transfer. */
+ ast_debug(1, "Actually doing a blonde transfer.\n");
- if (!newchan) {
+ if (!newchan && !atxferdropcall) {
+ /* Party C is not available, try to call party B back. */
unsigned int tries = 0;
- char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
-
- transferer_tech = strsep(&transferer_name, "/");
- transferer_name = strsep(&transferer_name, "-");
if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
- ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
- if (ast_stream_and_wait(transferee, "beeperr", ""))
- return -1;
- return AST_FEATURE_RETURN_SUCCESS;
+ ast_log(LOG_WARNING,
+ "Transferer channel name: '%s' cannot be used for callback.\n",
+ transferer_name_orig);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
+ return -1;
}
- ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
- newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
- transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
- while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
- /* Trying to transfer again */
- ast_autoservice_start(transferee);
- ast_autoservice_ignore(transferee, AST_FRAME_DTMF_END);
- ast_indicate(transferee, AST_CONTROL_HOLD);
-
- newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
- xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
- if (ast_autoservice_stop(transferee) < 0) {
- if (newchan)
- ast_hangup(newchan);
- return -1;
+ tries = 0;
+ for (;;) {
+ /* Try to get party B back. */
+ ast_debug(1, "We're trying to callback %s/%s\n",
+ transferer_tech, transferer_name);
+ newchan = feature_request_and_dial(transferer, transferer_name_orig,
+ transferee, transferer_tech,
+ ast_best_codec(transferee->nativeformats), transferer_name,
+ atxfernoanswertimeout, &outstate, transferee->cid.cid_num,
+ transferee->cid.cid_name, transferer->language);
+ ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
+ !!newchan, outstate);
+ if (newchan || ast_check_hangup(transferee)) {
+ break;
}
- if (!newchan) {
+
+ ++tries;
+ if (atxfercallbackretries <= tries) {
+ /* No more callback tries remaining. */
+ break;
+ }
+
+ if (atxferloopdelay) {
/* Transfer failed, sleeping */
- ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
+ ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
+ atxferloopdelay);
ast_safe_sleep(transferee, atxferloopdelay);
- ast_debug(1, "Trying to callback...\n");
- newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
- transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+ if (ast_check_hangup(transferee)) {
+ return -1;
+ }
}
- tries++;
- }
- }
- if (!newchan)
- return -1;
- /* newchan is up, we should prepare transferee and bridge them */
- if (check_compat(transferee, newchan)) {
- finishup(transferee);
- return -1;
+ /* Retry dialing party C. */
+ ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
+ newchan = feature_request_and_dial(transferer, transferer_name_orig,
+ transferee, "Local", ast_best_codec(transferee->nativeformats),
+ xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num,
+ transferer->cid.cid_name, transferer->language);
+ ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
+ !!newchan, outstate);
+ if (newchan || ast_check_hangup(transferee)) {
+ break;
+ }
+ }
}
ast_indicate(transferee, AST_CONTROL_UNHOLD);
-
- if ((ast_waitfordigit(transferee, 100) < 0)
- || (ast_waitfordigit(newchan, 100) < 0)
- || ast_check_hangup(transferee)
- || ast_check_hangup(newchan)) {
- ast_hangup(newchan);
+ if (!newchan) {
+ /* No party C or could not callback party B. */
return -1;
}
- xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
- if (!xferchan) {
+ /* newchan is up, we should prepare transferee and bridge them */
+ if (ast_check_hangup(newchan)) {
ast_hangup(newchan);
return -1;
}
- /* Make formats okay */
- xferchan->visible_indication = transferer->visible_indication;
- xferchan->readformat = transferee->readformat;
- xferchan->writeformat = transferee->writeformat;
- ast_channel_masquerade(xferchan, transferee);
- ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
- xferchan->_state = AST_STATE_UP;
- ast_clear_flag(xferchan, AST_FLAGS_ALL);
- xferchan->_softhangup = 0;
- if ((f = ast_read(xferchan)))
- ast_frfree(f);
- newchan->_state = AST_STATE_UP;
- ast_clear_flag(newchan, AST_FLAGS_ALL);
- newchan->_softhangup = 0;
- if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
- ast_hangup(xferchan);
- ast_hangup(newchan);
+ if (check_compat(transferee, newchan)) {
return -1;
}
- tobj->chan = newchan;
- tobj->peer = xferchan;
- tobj->bconfig = *config;
-
- if (tobj->bconfig.end_bridge_callback_data_fixup) {
- tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
- }
-
- if (ast_stream_and_wait(newchan, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- bridge_call_thread_launch(tobj);
- return -1; /* XXX meaning the channel is bridged ? */
} else {
- /* Transferee hung up */
- finishup(transferee);
- /* At this point both the transferer transferee have hungup,
- * so if newchan is up, hang it up as it has no one to talk to */
+ /*
+ * Both the transferer and transferee have hungup. If newchan
+ * is up, hang it up as it has no one to talk to.
+ */
+ ast_debug(1, "Everyone is hungup.\n");
if (newchan) {
ast_hangup(newchan);
}
return -1;
}
+
+ /* Initiate the channel transfer of party A to party C (or recalled party B). */
+
+ xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
+ if (!xferchan) {
+ ast_hangup(newchan);
+ return -1;
+ }
+
+ /* Give party A a momentary ringback tone during transfer. */
+ xferchan->visible_indication = AST_CONTROL_RINGING;
+
+ /* Make formats okay */
+ xferchan->readformat = transferee->readformat;
+ xferchan->writeformat = transferee->writeformat;
+
+ ast_channel_masquerade(xferchan, transferee);
+ ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
+ xferchan->_state = AST_STATE_UP;
+ ast_clear_flag(xferchan, AST_FLAGS_ALL);
+
+ /* Do the masquerade manually to make sure that is is completed. */
+ ast_channel_lock(xferchan);
+ if (xferchan->masq) {
+ ast_do_masquerade(xferchan);
+ }
+ ast_channel_unlock(xferchan);
+
+ newchan->_state = AST_STATE_UP;
+ ast_clear_flag(newchan, AST_FLAGS_ALL);
+ tobj = ast_calloc(1, sizeof(*tobj));
+ if (!tobj) {
+ ast_hangup(xferchan);
+ ast_hangup(newchan);
+ return -1;
+ }
+
+ ast_channel_lock(newchan);
+ if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
+ dialfeatures = features_datastore->data;
+ }
+ ast_channel_unlock(newchan);
+
+ if (dialfeatures) {
+ /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
+ I don't currently understand, the abilities of newchan seem to be stored on the caller side */
+ ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
+ dialfeatures = NULL;
+ }
+
+ ast_channel_lock(xferchan);
+ if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
+ dialfeatures = features_datastore->data;
+ }
+ ast_channel_unlock(xferchan);
+
+ if (dialfeatures) {
+ ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
+ }
+
+ tobj->chan = newchan;
+ tobj->peer = xferchan;
+ tobj->bconfig = *config;
+
+ if (tobj->bconfig.end_bridge_callback_data_fixup) {
+ tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
+ }
+
+ if (ast_stream_and_wait(newchan, xfersound, ""))
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ bridge_call_thread_launch(tobj);
+ return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
}
/* add atxfer and automon as undefined so you can only use em if you configure them */
@@ -2191,54 +2383,100 @@ static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer,
}
}
-/*!
- * \brief Get feature and dial
- * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
+/*!
+ * \internal
+ * \brief Get feature and dial.
*
- * Request channel, set channel variables, initiate call,check if they want to disconnect
- * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
- * check for answer break loop, set cdr return channel.
+ * \param caller Channel to represent as the calling channel for the dialed channel.
+ * \param caller_name Original caller channel name.
+ * \param transferee Channel that the dialed channel will be transferred to.
+ * \param type Channel technology type to dial.
+ * \param format Codec formats for dialed channel.
+ * \param data Dialed channel extra parameters for ast_request() and ast_call().
+ * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
+ * \param outstate Status of dialed channel if unsuccessful.
+ * \param cid_num CallerID number to give dialed channel.
+ * \param cid_name CallerID name to give dialed channel.
+ * \param language Language of the caller.
*
- * \todo XXX Check - this is very similar to the code in channel.c
- * \return always a channel
-*/
-static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language)
+ * \note
+ * outstate can be:
+ * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
+ * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD. If
+ * AST_CONTROL_UNHOLD then the caller channel cancelled the
+ * transfer or the dialed channel did not answer before the
+ * timeout.
+ *
+ * \details
+ * Request channel, set channel variables, initiate call,
+ * check if they want to disconnect, go into loop, check if timeout has elapsed,
+ * check if person to be transfered hung up, check for answer break loop,
+ * set cdr return channel.
+ *
+ * \retval Channel Connected channel for transfer.
+ * \retval NULL on failure to get third party connected.
+ *
+ * \note This is similar to __ast_request_and_dial() in channel.c
+ */
+static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
+ const char *caller_name, struct ast_channel *transferee, const char *type,
+ int format, void *data, int timeout, int *outstate, const char *cid_num,
+ const char *cid_name, const char *language)
{
int state = 0;
int cause = 0;
int to;
+ int caller_hungup;
+ int transferee_hungup;
struct ast_channel *chan;
- struct ast_channel *monitor_chans[2];
+ struct ast_channel *monitor_chans[3];
struct ast_channel *active_channel;
- int res = 0, ready = 0;
+ int ready = 0;
struct timeval started;
int x, len = 0;
char *disconnect_code = NULL, *dialed_code = NULL;
+ struct ast_frame *f;
+ AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
+
+ caller_hungup = ast_check_hangup(caller);
if (!(chan = ast_request(type, format, data, &cause))) {
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
- switch(cause) {
+ switch (cause) {
case AST_CAUSE_BUSY:
state = AST_CONTROL_BUSY;
break;
case AST_CAUSE_CONGESTION:
state = AST_CONTROL_CONGESTION;
break;
+ default:
+ state = 0;
+ break;
}
goto done;
}
ast_set_callerid(chan, cid_num, cid_name, cid_num);
ast_string_field_set(chan, language, language);
- ast_channel_inherit_variables(caller, chan);
- pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
-
+ ast_channel_inherit_variables(caller, chan);
+ pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
+
if (ast_call(chan, data, timeout)) {
ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
+ switch (chan->hangupcause) {
+ case AST_CAUSE_BUSY:
+ state = AST_CONTROL_BUSY;
+ break;
+ case AST_CAUSE_CONGESTION:
+ state = AST_CONTROL_CONGESTION;
+ break;
+ default:
+ state = 0;
+ break;
+ }
goto done;
}
-
- ast_indicate(caller, AST_CONTROL_RINGING);
+
/* support dialing of the featuremap disconnect code while performing an attended tranfer */
ast_rwlock_rdlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) {
@@ -2255,57 +2493,111 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
x = 0;
started = ast_tvnow();
to = timeout;
+ AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
ast_poll_channel_add(caller, chan);
- while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
- struct ast_frame *f = NULL;
-
- monitor_chans[0] = caller;
- monitor_chans[1] = chan;
- active_channel = ast_waitfor_n(monitor_chans, 2, &to);
+ transferee_hungup = 0;
+ while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
+ int num_chans = 0;
+
+ monitor_chans[num_chans++] = transferee;
+ monitor_chans[num_chans++] = chan;
+ if (!caller_hungup) {
+ if (ast_check_hangup(caller)) {
+ caller_hungup = 1;
+
+#if defined(ATXFER_NULL_TECH)
+ /* Change caller's name to ensure that it will remain unique. */
+ set_new_chan_name(caller);
+
+ /*
+ * Get rid of caller's physical technology so it is free for
+ * other calls.
+ */
+ set_null_chan_tech(caller);
+#endif /* defined(ATXFER_NULL_TECH) */
+ } else {
+ /* caller is not hungup so monitor it. */
+ monitor_chans[num_chans++] = caller;
+ }
+ }
/* see if the timeout has been violated */
- if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
+ if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
state = AST_CONTROL_UNHOLD;
- ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
+ ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
break; /*doh! timeout*/
}
+ active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
if (!active_channel)
continue;
- if (chan && (chan == active_channel)){
+ f = NULL;
+ if (transferee == active_channel) {
+ struct ast_frame *dup_f;
+
+ f = ast_read(transferee);
+ if (f == NULL) { /*doh! where'd he go?*/
+ transferee_hungup = 1;
+ state = 0;
+ break;
+ }
+ if (ast_is_deferrable_frame(f)) {
+ dup_f = ast_frisolate(f);
+ if (dup_f) {
+ if (dup_f == f) {
+ f = NULL;
+ }
+ AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
+ }
+ }
+ } else if (chan == active_channel) {
if (!ast_strlen_zero(chan->call_forward)) {
- if (!(chan = ast_call_forward(caller, chan, NULL, format, NULL, outstate))) {
- return NULL;
+ state = 0;
+ chan = ast_call_forward(caller, chan, NULL, format, NULL, &state);
+ if (!chan) {
+ break;
}
continue;
}
f = ast_read(chan);
if (f == NULL) { /*doh! where'd he go?*/
- state = AST_CONTROL_HANGUP;
- res = 0;
+ switch (chan->hangupcause) {
+ case AST_CAUSE_BUSY:
+ state = AST_CONTROL_BUSY;
+ break;
+ case AST_CAUSE_CONGESTION:
+ state = AST_CONTROL_CONGESTION;
+ break;
+ default:
+ state = 0;
+ break;
+ }
break;
}
-
- if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
+
+ if (f->frametype == AST_FRAME_CONTROL) {
if (f->subclass == AST_CONTROL_RINGING) {
- state = f->subclass;
ast_verb(3, "%s is ringing\n", chan->name);
ast_indicate(caller, AST_CONTROL_RINGING);
- } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
+ } else if (f->subclass == AST_CONTROL_BUSY) {
state = f->subclass;
ast_verb(3, "%s is busy\n", chan->name);
ast_indicate(caller, AST_CONTROL_BUSY);
ast_frfree(f);
- f = NULL;
+ break;
+ } else if (f->subclass == AST_CONTROL_CONGESTION) {
+ state = f->subclass;
+ ast_verb(3, "%s is congested\n", chan->name);
+ ast_indicate(caller, AST_CONTROL_CONGESTION);
+ ast_frfree(f);
break;
} else if (f->subclass == AST_CONTROL_ANSWER) {
/* This is what we are hoping for */
state = f->subclass;
ast_frfree(f);
- f = NULL;
ready=1;
break;
} else if (f->subclass != -1 && f->subclass != AST_CONTROL_PROGRESS) {
@@ -2315,22 +2607,9 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
ast_write(caller, f);
}
-
- } else if (caller && (active_channel == caller)) {
+ } else if (caller == active_channel) {
f = ast_read(caller);
- if (f == NULL) { /*doh! where'd he go?*/
- if (!igncallerstate) {
- if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
- /* make this a blind transfer */
- ready = 1;
- break;
- }
- state = AST_CONTROL_HANGUP;
- res = 0;
- break;
- }
- } else {
-
+ if (f) {
if (f->frametype == AST_FRAME_DTMF) {
dialed_code[x++] = f->subclass;
dialed_code[x] = '\0';
@@ -2344,7 +2623,6 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
/* Caller Canceled the call */
state = AST_CONTROL_UNHOLD;
ast_frfree(f);
- f = NULL;
break;
}
} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
@@ -2357,21 +2635,31 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
} /* end while */
ast_poll_channel_del(caller, chan);
-
+
+ /*
+ * We need to free all the deferred frames, but we only need to
+ * queue the deferred frames if no hangup was received.
+ */
+ ast_channel_lock(transferee);
+ transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
+ while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
+ if (!transferee_hungup) {
+ ast_queue_frame_head(transferee, f);
+ }
+ ast_frfree(f);
+ }
+ ast_channel_unlock(transferee);
+
done:
ast_indicate(caller, -1);
if (chan && ready) {
- if (chan->_state == AST_STATE_UP)
+ if (chan->_state == AST_STATE_UP)
state = AST_CONTROL_ANSWER;
- res = 0;
} else if (chan) {
- res = -1;
ast_hangup(chan);
chan = NULL;
- } else {
- res = -1;
}
-
+
if (outstate)
*outstate = state;
@@ -3190,7 +3478,7 @@ int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds,
continue;
}
- if (!(pfds[y].revents & (POLLIN | POLLERR))) {
+ if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
/* Next x */
continue;
}
@@ -3247,7 +3535,7 @@ std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
}
*new_pfds = tmp;
(*new_pfds)[*new_nfds].fd = chan->fds[x];
- (*new_pfds)[*new_nfds].events = POLLIN | POLLERR;
+ (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
(*new_pfds)[*new_nfds].revents = 0;
(*new_nfds)++;
}