<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][17306] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=17306">17306</a></dd>
<dt>Author</dt> <dd>ncorbic</dd>
<dt>Date</dt> <dd>2010-04-15 10:39:55 -0500 (Thu, 15 Apr 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Multiple updates and bug fixes to ftdm/openzap. Major stress test</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsfreetdmsrcftdm_ioc">freeswitch/trunk/libs/freetdm/src/ftdm_io.c</a></li>
<li><a href="#freeswitchtrunklibsfreetdmsrcftdm_threadmutexc">freeswitch/trunk/libs/freetdm/src/ftdm_threadmutex.c</a></li>
<li><a href="#freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostftmod_sangoma_boostc">freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c</a></li>
<li><a href="#freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostsangoma_boost_clientc">freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c</a></li>
<li><a href="#freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostsigboosth">freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h</a></li>
<li><a href="#freeswitchtrunklibsopenzapsrcozmodozmod_sangoma_boostozmod_sangoma_boostc">freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c</a></li>
<li><a href="#freeswitchtrunklibsopenzapsrcozmodozmod_sangoma_boostsigboosth">freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/sigboost.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunklibsfreetdmsrcftdm_ioc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/freetdm/src/ftdm_io.c (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/freetdm/src/ftdm_io.c        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/freetdm/src/ftdm_io.c        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -1087,15 +1087,19 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (lock) {
+                ftdm_mutex_lock(ftdmchan-&gt;mutex);
+        }
+
</ins><span class="cx">         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
</span><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;Ignored state change request from %s to %s, the previous state change has not been processed yet\n&quot;,
</span><span class="cx">                                 ftdm_channel_state2str(ftdmchan-&gt;state), ftdm_channel_state2str(state));
</span><ins>+                if (lock) {
+                        ftdm_mutex_unlock(ftdmchan-&gt;mutex);
+                }
</ins><span class="cx">                 return FTDM_FAIL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (lock) {
-                ftdm_mutex_lock(ftdmchan-&gt;mutex);
-        }
</del><span class="cx"> 
</span><span class="cx">         if (ftdmchan-&gt;span-&gt;state_map) {
</span><span class="cx">                 ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan-&gt;span-&gt;state_map);
</span><span class="lines">@@ -1353,7 +1357,8 @@
</span><span class="cx">                 ftdm_span_channel_use_count(span, &amp;count);
</span><span class="cx"> 
</span><span class="cx">                 if (count &gt;= span-&gt;chan_count) {
</span><del>-                        ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy.\n&quot;);
</del><ins>+                        ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy: active=%i max=%i.\n&quot;,
+                                count, span-&gt;chan_count);
</ins><span class="cx">                         *ftdmchan = NULL;
</span><span class="cx">                         return FTDM_FAIL;
</span><span class="cx">                 }
</span></span></pre></div>
<a id="freeswitchtrunklibsfreetdmsrcftdm_threadmutexc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/freetdm/src/ftdm_threadmutex.c (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/freetdm/src/ftdm_threadmutex.c        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/freetdm/src/ftdm_threadmutex.c        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -414,7 +414,7 @@
</span><span class="cx">         for (i = 0; i &lt; size; i++) {
</span><span class="cx">                 ints[i] = interrupts[i]-&gt;event;
</span><span class="cx">                 if (interrupts[i]-&gt;device != FTDM_INVALID_SOCKET) {
</span><del>-                        ints[i+numdevices] = interrupts[i]-&gt;device;
</del><ins>+                        ints[size+numdevices] = interrupts[i]-&gt;device;
</ins><span class="cx">                         numdevices++;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -446,9 +446,9 @@
</span><span class="cx">                 ints[i].revents = 0;
</span><span class="cx">                 ints[i].fd = interrupts[i]-&gt;readfd;
</span><span class="cx">                 if (interrupts[i]-&gt;device != FTDM_INVALID_SOCKET) {
</span><del>-                        ints[i+numdevices].events = POLLIN;
-                        ints[i+numdevices].revents = 0;
-                        ints[i+numdevices].fd = interrupts[i]-&gt;device;
</del><ins>+                        ints[size+numdevices].events = POLLIN;
+                        ints[size+numdevices].revents = 0;
+                        ints[size+numdevices].fd = interrupts[i]-&gt;device;
</ins><span class="cx">                         numdevices++;
</span><span class="cx">                 }
</span><span class="cx">         }
</span></span></pre></div>
<a id="freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostftmod_sangoma_boostc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -89,7 +89,6 @@
</span><span class="cx"> typedef enum {
</span><span class="cx">         BST_FREE,
</span><span class="cx">         BST_WAITING,
</span><del>-        BST_ACK,
</del><span class="cx">         BST_READY,
</span><span class="cx">         BST_FAIL
</span><span class="cx"> } sangoma_boost_request_status_t;
</span><span class="lines">@@ -106,6 +105,13 @@
</span><span class="cx">         int flags;
</span><span class="cx"> } sangoma_boost_request_t;
</span><span class="cx"> 
</span><ins>+typedef struct {
+        int call_setup_id;
+        int last_event_id;
+} sangoma_boost_call_t;
+
+#define CALL_DATA(ftdmchan) ((sangoma_boost_call_t*)((ftdmchan)-&gt;call_data))
+
</ins><span class="cx"> //#define MAX_REQ_ID FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN * FTDM_MAX_CHANNELS_PHYSICAL_SPAN
</span><span class="cx"> #define MAX_REQ_ID 6000
</span><span class="cx"> 
</span><span class="lines">@@ -132,7 +138,7 @@
</span><span class="cx"> 
</span><span class="cx">         ftdm_mutex_lock(request_mutex);
</span><span class="cx">         if ((id = SETUP_GRID[span][chan])) {
</span><del>-                assert(id &lt;= MAX_REQ_ID);
</del><ins>+                ftdm_assert(id &lt;= MAX_REQ_ID, &quot;Invalid id&quot;);
</ins><span class="cx">                 req_map[id] = 0;
</span><span class="cx">                 SETUP_GRID[span][chan] = 0;
</span><span class="cx">         }
</span><span class="lines">@@ -148,7 +154,7 @@
</span><span class="cx">  */
</span><span class="cx"> static void __release_request_id(sangoma_boost_request_id_t r, const char *func, int line)
</span><span class="cx"> {
</span><del>-        assert(r &lt;= MAX_REQ_ID);
</del><ins>+        ftdm_assert(r &lt;= MAX_REQ_ID, &quot;Invalid id&quot;);
</ins><span class="cx">         ftdm_mutex_lock(request_mutex);
</span><span class="cx">         req_map[r] = 0;
</span><span class="cx">         ftdm_mutex_unlock(request_mutex);
</span><span class="lines">@@ -176,7 +182,7 @@
</span><span class="cx">                 r = ++last_req;
</span><span class="cx"> 
</span><span class="cx">                 if (r &gt;= MAX_REQ_ID) {
</span><del>-                        r = i = last_req = 1;
</del><ins>+                        r = last_req = 1;
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if (req_map[r]) {
</span><span class="lines">@@ -201,6 +207,25 @@
</span><span class="cx"> }
</span><span class="cx"> #define next_request_id() __next_request_id(__FUNCTION__, __LINE__)
</span><span class="cx"> 
</span><ins>+
+static void print_request_ids(void)
+{
+        sangoma_boost_request_id_t i = 0;
+        
+        ftdm_mutex_lock(request_mutex);
+
+        for (i=1; i&lt;= MAX_REQ_ID; i++){
+                if (req_map[i]) {
+                        ftdm_log(FTDM_LOG_CRIT, &quot;Used Request ID=%i\n&quot;,i);
+                }
+        }
+
+        ftdm_mutex_unlock(request_mutex);
+
+        return;
+}
+
+
</ins><span class="cx"> /**
</span><span class="cx">  * \brief Finds the channel that triggered an event
</span><span class="cx">  * \param span Span where to search the channel
</span><span class="lines">@@ -212,9 +237,26 @@
</span><span class="cx"> {
</span><span class="cx">         uint32_t i;
</span><span class="cx">         ftdm_channel_t *ftdmchan = NULL;
</span><del>-        ftdm_sangoma_boost_data_t *sangoma_boost_data = span-&gt;signal_data;
</del><ins>+        ftdm_sangoma_boost_data_t *sangoma_boost_data;
</ins><span class="cx">         uint32_t targetspan = event-&gt;span+1;
</span><span class="cx">         uint32_t targetchan = event-&gt;chan+1;
</span><ins>+
+        /* NC: Sanity check in case the call setup id does not relate
+                to span.  This can happen if RESTART is received on a
+                   full load. Where stray ACK messages can arrive after
+                   a RESTART has taken place.
+     */
+        if (!span) {
+                ftdm_log(FTDM_LOG_CRIT, &quot;No Span for Event=%s s%dc%d cid=%d\n&quot;,
+                                                BOOST_DECODE_EVENT_ID(event-&gt;event_id),
+                                                event-&gt;span,
+                                                event-&gt;chan,
+                                                event-&gt;call_setup_id);
+                return NULL;
+        }
+
+        sangoma_boost_data = span-&gt;signal_data;
+
</ins><span class="cx">         if (sangoma_boost_data-&gt;sigmod) {
</span><span class="cx">                 /* span is not strictly needed here since we're supposed to get only events for our span */
</span><span class="cx">                 targetspan = event-&gt;span;
</span><span class="lines">@@ -278,12 +320,20 @@
</span><span class="cx">          * and PRI stack will retransmit a second SETUP after the first timeout, so
</span><span class="cx">          * we should allow for at least 8 seconds.
</span><span class="cx">          */
</span><ins>+
</ins><span class="cx">         int boost_request_timeout = 10000;
</span><span class="cx">         sangoma_boost_request_status_t st;
</span><span class="cx">         char dnis[128] = &quot;&quot;;
</span><span class="cx">         char *gr = NULL;
</span><span class="cx">         uint32_t count = 0;
</span><span class="cx">         int tg=0;
</span><ins>+
+        /* NC: On large number of calls 10 seconds is not enough.
+                Resetting to 30 seconds. Especially on ss7 when
+                links are reset during large call volume */
+        if (!sangoma_boost_data-&gt;sigmod) {
+                boost_request_timeout = 30000;
+        }
</ins><span class="cx">         
</span><span class="cx">         if (sangoma_boost_data-&gt;sigmod) {
</span><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;This function should not be called when sigmod was configured in boost\n&quot;);
</span><span class="lines">@@ -292,21 +342,35 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED)) {
</span><del>-                ftdm_log(FTDM_LOG_CRIT, &quot;SPAN is not online.\n&quot;);
</del><ins>+                ftdm_log(FTDM_LOG_CRIT, &quot;SPAN is Suspended.\n&quot;);
</ins><span class="cx">                 *ftdmchan = NULL;
</span><span class="cx">                 return FTDM_FAIL;
</span><span class="cx">         }
</span><del>-        
-        ftdm_set_string(dnis, caller_data-&gt;dnis.digits);
</del><span class="cx"> 
</span><ins>+        if (check_congestion(tg)) {
+                ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy. Trunk Group=%i (CONGESTION)\n&quot;,tg+1);
+                *ftdmchan = NULL;
+                return FTDM_FAIL;
+        }
+
+        if (count &gt;= span-&gt;chan_count) {
+                ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy.\n&quot;);
+                *ftdmchan = NULL;
+                return FTDM_FAIL;
+        }
+
</ins><span class="cx">         r = next_request_id();
</span><span class="cx">         if (r == 0) {
</span><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;All tanks ids are busy.\n&quot;);
</span><span class="cx">                 *ftdmchan = NULL;
</span><span class="cx">                 return FTDM_FAIL;
</span><span class="cx">         }
</span><del>-        sangomabc_call_init(&amp;event, caller_data-&gt;cid_num.digits, dnis, r);
</del><span class="cx"> 
</span><ins>+        /* After this point we must release request id before we leave the function
+           in case of an error. */
+
+        ftdm_set_string(dnis, caller_data-&gt;dnis.digits);
+
</ins><span class="cx">         if ((gr = strchr(dnis, '@'))) {
</span><span class="cx">                 *gr++ = '\0';
</span><span class="cx">         }
</span><span class="lines">@@ -317,22 +381,14 @@
</span><span class="cx">                         tg--;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        
+        sangomabc_call_init(&amp;event, caller_data-&gt;cid_num.digits, dnis, r);
+
</ins><span class="cx">         event.trunk_group = tg;
</span><span class="cx"> 
</span><del>-        if (check_congestion(tg)) {
-                ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy. Trunk Group=%i (BOOST REQUESTED BACK OFF)\n&quot;,tg+1);
-                *ftdmchan = NULL;
-                return FTDM_FAIL;
-        }
</del><span class="cx"> 
</span><span class="cx">         ftdm_span_channel_use_count(span, &amp;count);
</span><span class="cx"> 
</span><del>-        if (count &gt;= span-&gt;chan_count) {
-                ftdm_log(FTDM_LOG_CRIT, &quot;All circuits are busy.\n&quot;);
-                *ftdmchan = NULL;
-                return FTDM_FAIL;
-        }        
-
</del><span class="cx">         if (gr &amp;&amp; *(gr+1)) {
</span><span class="cx">                 switch(*gr) {
</span><span class="cx">                                 case 'g':
</span><span class="lines">@@ -375,7 +431,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (sangomabc_connection_write(&amp;sangoma_boost_data-&gt;mcon, &amp;event) &lt;= 0) {
</span><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;Failed to tx boost event [%s]\n&quot;, strerror(errno));
</span><del>-                status = FTDM_FAIL;
</del><ins>+                status = OUTBOUND_REQUESTS[r].status = FTDM_FAIL;
</ins><span class="cx">                 if (!sangoma_boost_data-&gt;sigmod) {
</span><span class="cx">                         *ftdmchan = NULL;
</span><span class="cx">                 }
</span><span class="lines">@@ -389,7 +445,7 @@
</span><span class="cx">                         if (!sangoma_boost_data-&gt;sigmod) {
</span><span class="cx">                                 *ftdmchan = NULL;
</span><span class="cx">                         }
</span><del>-                        ftdm_log(FTDM_LOG_CRIT, &quot;s%dc%d: Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n&quot;, (*ftdmchan)-&gt;physical_span_id, (*ftdmchan)-&gt;physical_chan_id, r);
</del><ins>+                        ftdm_log(FTDM_LOG_CRIT, &quot;Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n&quot;, r);
</ins><span class="cx">                         goto done;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -496,6 +552,7 @@
</span><span class="cx"> 
</span><span class="cx">         ftdm_log(FTDM_LOG_DEBUG, &quot;Dialing number %s over boost channel with request id %d\n&quot;, event.called_number_digits, r);
</span><span class="cx">         if (sangomabc_connection_write(&amp;sangoma_boost_data-&gt;mcon, &amp;event) &lt;= 0) {
</span><ins>+                release_request_id(r);
</ins><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;Failed to tx boost event [%s]\n&quot;, strerror(errno));
</span><span class="cx">                 return FTDM_FAIL;
</span><span class="cx">         }
</span><span class="lines">@@ -552,7 +609,12 @@
</span><span class="cx">         uint32_t event_span = event-&gt;span+1;
</span><span class="cx">         uint32_t event_chan = event-&gt;chan+1;
</span><span class="cx"> 
</span><ins>+        
</ins><span class="cx">         if (nack_map[event-&gt;call_setup_id]) {
</span><ins>+                /* In this scenario outgoing call was alrady stopped
+                    via NACK and now we are expecting an NACK_ACK.
+               If we receive an ACK its a race condition thus
+                   ignor it */
</ins><span class="cx">                 return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -614,15 +676,43 @@
</span><span class="cx">                         OUTBOUND_REQUESTS[event-&gt;call_setup_id].status = BST_READY;
</span><span class="cx">                         return;
</span><span class="cx">                 }
</span><del>-        } 
</del><ins>+        } else {
</ins><span class="cx"> 
</span><ins>+                ftdm_assert(!mcon-&gt;sigmod, &quot;CALL STOP ACK: Invalid Sigmod Path&quot;);

+                if ((ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event-&gt;call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
+                                int r;
+                                /* NC: If we get CALL START ACK and channel is in active state
+                                                then we are completely out of sync with the other end.
+                                                Treat CALL START ACK as CALL STOP and hangup the current call.
+                                */
+
+                                if (ftdmchan-&gt;state == FTDM_CHANNEL_STATE_UP ||
+                                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
+                                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_PROGRESS) {
+                                                ftdm_log(FTDM_LOG_CRIT, &quot;FTDM_CHAN STATE UP/PROG/PROG_MEDIA -&gt; Changed to HANGUP %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
+                                                ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP, 0, r);
+
+                                } else if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
+                                                /* Do nothing because outgoing STOP will generaate a stop ack */
+
+                                } else {
+                                                ftdm_log(FTDM_LOG_CRIT, &quot;FTDM_CHAN STATE INVALID %s on IN CALL ACK %d:%d\n&quot;, ftdm_channel_state2str(ftdmchan-&gt;state),event-&gt;span+1,event-&gt;chan+1);
+
+                                }
+                                ftdmchan=NULL;
+                }
+        }
+
+
</ins><span class="cx">         if (!ftdmchan) {
</span><span class="cx">                 ftdm_log(FTDM_LOG_CRIT, &quot;START ACK CANT FIND A CHAN %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
</span><span class="cx">         } else {
</span><span class="cx">                 /* only reason to be here is failed to open channel when we we're in sigmod  */
</span><span class="cx">                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
</span><ins>+                ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
</ins><span class="cx">         }
</span><del>-        ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
</del><ins>+        
</ins><span class="cx">         sangomabc_exec_command(mcon,
</span><span class="cx">                                            event-&gt;span,
</span><span class="cx">                                            event-&gt;chan,
</span><span class="lines">@@ -643,7 +733,7 @@
</span><span class="cx"> {
</span><span class="cx">         ftdm_channel_t *ftdmchan;
</span><span class="cx">         int r = 0;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if ((ftdmchan = find_ftdmchan(span, event, 1))) {
</span><span class="cx">                 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan-&gt;span-&gt;signal_data;
</span><span class="cx">                 ftdm_mutex_lock(ftdmchan-&gt;mutex);
</span><span class="lines">@@ -684,6 +774,7 @@
</span><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> /**
</span><span class="cx">  * \brief Handler for call start nack event
</span><span class="cx">  * \param span Span where event was fired
</span><span class="lines">@@ -725,7 +816,7 @@
</span><span class="cx">         if (event-&gt;call_setup_id) {
</span><span class="cx">                 if (sangoma_boost_data-&gt;sigmod) {
</span><span class="cx">                         ftdmchan = OUTBOUND_REQUESTS[event-&gt;call_setup_id].ftdmchan;
</span><del>-                        ftdmchan-&gt;call_data = (void*)(intptr_t)event-&gt;event_id;
</del><ins>+                        CALL_DATA(ftdmchan)-&gt;last_event_id = event-&gt;event_id;
</ins><span class="cx">                         ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
</span><span class="cx">                 } else {
</span><span class="cx">                         sangomabc_exec_command(mcon,
</span><span class="lines">@@ -747,7 +838,7 @@
</span><span class="cx">                         /* if there is no call setup id this should not be an outbound channel for sure */
</span><span class="cx">                         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), &quot;Yay, outbound flag should not be set here!\n&quot;);
</span><span class="cx"> 
</span><del>-                        ftdmchan-&gt;call_data = (void*)(intptr_t)event-&gt;event_id;
</del><ins>+                        CALL_DATA(ftdmchan)-&gt;last_event_id = event-&gt;event_id;
</ins><span class="cx">                         ftdm_mutex_lock(ftdmchan-&gt;mutex);
</span><span class="cx">                         ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
</span><span class="cx">                         if (r == FTDM_STATE_CHANGE_SUCCESS) {
</span><span class="lines">@@ -800,7 +891,16 @@
</span><span class="cx"> 
</span><span class="cx">                 ftdm_mutex_lock(ftdmchan-&gt;mutex);
</span><span class="cx">                 
</span><del>-                if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
</del><ins>+                if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
+                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_DOWN ||
+                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_TERMINATING) {
+
+                        /* NC: Checking for state DOWN because ss7box can
+                                send CALL_STOP twice in a row.  If we do not check for
+                                STATE_DOWN we will set the state back to termnating
+                                and block the channel forever
+                        */
+
</ins><span class="cx">                         /* racing condition where both sides initiated a hangup 
</span><span class="cx">                          * Do not change current state as channel is already clearing
</span><span class="cx">                          * itself through local initiated hangup */
</span><span class="lines">@@ -855,8 +955,18 @@
</span><span class="cx">         
</span><span class="cx">         if ((ftdmchan = find_ftdmchan(span, event, 1))) {
</span><span class="cx">                 ftdm_mutex_lock(ftdmchan-&gt;mutex);
</span><del>-                if (ftdmchan-&gt;state == FTDM_CHANNEL_STATE_HOLD) {
</del><ins>+
+                if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
+                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_DOWN ||
+                        ftdmchan-&gt;state == FTDM_CHANNEL_STATE_TERMINATING) {
+
+                        /* NC: Do nothing here because we are in process
+                                of stopping the call. So ignore the ANSWER. */
+                        ftdm_log(FTDM_LOG_CRIT, &quot;ANSWER BUT CALL IS HANGUP %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
+
+                } else if (ftdmchan-&gt;state == FTDM_CHANNEL_STATE_HOLD) {
</ins><span class="cx">                         ftdmchan-&gt;init_state = FTDM_CHANNEL_STATE_UP;
</span><ins>+
</ins><span class="cx">                 } else {
</span><span class="cx">                         int r = 0;
</span><span class="cx">                         ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, 0, r);
</span><span class="lines">@@ -888,6 +998,12 @@
</span><span class="cx">         if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
</span><span class="cx">                 if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
</span><span class="cx">                         int r;
</span><ins>+
+                         /* NC: If we get CALL START and channel is in active state
+                                then we are completely out of sync with the other end.
+                                    Treat CALL START as CALL STOP and hangup the current call.
+                          */
+
</ins><span class="cx">                         if (ftdmchan-&gt;state == FTDM_CHANNEL_STATE_UP) {
</span><span class="cx">                                 ftdm_log(FTDM_LOG_CRIT, &quot;ZCHAN STATE UP -&gt; Changed to TERMINATING %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
</span><span class="cx">                                 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
</span><span class="lines">@@ -1186,8 +1302,12 @@
</span><span class="cx">                 handle_call_done(span, mcon, event);
</span><span class="cx">                 break;
</span><span class="cx">     case SIGBOOST_EVENT_CALL_START_NACK_ACK:
</span><del>-                handle_call_done(span, mcon, event);
-                nack_map[event-&gt;call_setup_id] = 0;
</del><ins>+                /* On NACK ack span chan are always invalid
+                   All there is to do is to clear the id */
+                if (event-&gt;call_setup_id) {
+                        nack_map[event-&gt;call_setup_id] = 0;
+                        release_request_id(event-&gt;call_setup_id);
+                }
</ins><span class="cx">                 break;
</span><span class="cx">     case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
</span><span class="cx">                 handle_call_loop_start(span, mcon, event);
</span><span class="lines">@@ -1253,7 +1373,7 @@
</span><span class="cx">                         if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG)) {
</span><span class="cx">                                 ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
</span><span class="cx"> 
</span><del>-                                if (ftdmchan-&gt;call_data &amp;&amp; ((uint32_t)(intptr_t)ftdmchan-&gt;call_data == SIGBOOST_EVENT_CALL_START_NACK)) {
</del><ins>+                                if (ftdmchan-&gt;call_data &amp;&amp; CALL_DATA(ftdmchan)-&gt;last_event_id == SIGBOOST_EVENT_CALL_START_NACK) {
</ins><span class="cx">                                         sangomabc_exec_command(mcon,
</span><span class="cx">                                                                         BOOST_SPAN(ftdmchan),
</span><span class="cx">                                                                         BOOST_CHAN(ftdmchan),
</span><span class="lines">@@ -1273,7 +1393,8 @@
</span><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx">                         ftdmchan-&gt;sflags = 0;
</span><del>-                        ftdmchan-&gt;call_data = NULL;
</del><ins>+                        memset(ftdmchan-&gt;call_data,0,sizeof(sangoma_boost_call_t));
+
</ins><span class="cx">                         if (sangoma_boost_data-&gt;sigmod &amp;&amp; call_stopped_ack_sent) {
</span><span class="cx">                                 /* we dont want to call ftdm_channel_done just yet until call released is received */
</span><span class="cx">                                 ftdm_log(FTDM_LOG_DEBUG, &quot;Waiting for call release confirmation before declaring chan %d:%d as available \n&quot;, 
</span><span class="lines">@@ -1464,13 +1585,17 @@
</span><span class="cx">                 uint32_t j;
</span><span class="cx">                 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
</span><span class="cx">                 if (susp) {
</span><del>-                        for (j = 0; j &lt;= span-&gt;chan_count; j++) {
-                                ftdm_mutex_lock(span-&gt;channels[j]-&gt;mutex);
-                                ftdm_clear_flag((span-&gt;channels[j]), FTDM_CHANNEL_STATE_CHANGE);
-                                ftdm_channel_set_state(span-&gt;channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
-                                state_advance(span-&gt;channels[j]);
-                                ftdm_channel_complete_state(span-&gt;channels[j]);
-                                ftdm_mutex_unlock(span-&gt;channels[j]-&gt;mutex);
</del><ins>+                        for(j = 1; j &lt;= span-&gt;chan_count; j++) {
+                                if (ftdm_test_flag((span-&gt;channels[j]), FTDM_CHANNEL_STATE_CHANGE) || susp) {
+                                        ftdm_mutex_lock(span-&gt;channels[j]-&gt;mutex);
+                                        ftdm_clear_flag((span-&gt;channels[j]), FTDM_CHANNEL_STATE_CHANGE);
+                                        if (susp &amp;&amp; span-&gt;channels[j]-&gt;state != FTDM_CHANNEL_STATE_DOWN) {
+                                                ftdm_channel_set_state(span-&gt;channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
+                                        }
+                                        state_advance(span-&gt;channels[j]);
+                                        ftdm_channel_complete_state(span-&gt;channels[j]);
+                                        ftdm_mutex_unlock(span-&gt;channels[j]-&gt;mutex);
+                                }
</ins><span class="cx">                         }
</span><span class="cx">                 } else {
</span><span class="cx">                         while ((ftdmchan = ftdm_queue_dequeue(span-&gt;pendingchans))) {
</span><span class="lines">@@ -1649,8 +1774,8 @@
</span><span class="cx">                         sangoma_boost_data-&gt;iteration = 0;
</span><span class="cx">                 }
</span><span class="cx"> #endif
</span><del>-                res = ftdm_interrupt_multiple_wait(ints, numints, -1);
-                if (FTDM_SUCCESS != res) {
</del><ins>+                res = ftdm_interrupt_multiple_wait(ints, numints, 100);
+                if (FTDM_SUCCESS != res &amp;&amp; FTDM_TIMEOUT != res) {
</ins><span class="cx">                         ftdm_log(FTDM_LOG_CRIT, &quot;Unexpected return value from interrupt waiting: %d\n&quot;, res);
</span><span class="cx">                         return -1;
</span><span class="cx">                 }
</span><span class="lines">@@ -1737,7 +1862,6 @@
</span><span class="cx"> 
</span><span class="cx">                 if (ftdm_boost_wait_event(span) &lt; 0) {
</span><span class="cx">                         ftdm_log(FTDM_LOG_ERROR, &quot;ftdm_boost_wait_event failed\n&quot;);
</span><del>-                        goto error;
</del><span class="cx">                 }
</span><span class="cx">                 
</span><span class="cx">                 while ((event = ftdm_boost_read_event(span))) {
</span><span class="lines">@@ -1750,7 +1874,6 @@
</span><span class="cx"> 
</span><span class="cx">         goto end;
</span><span class="cx"> 
</span><del>-error:
</del><span class="cx">         ftdm_log(FTDM_LOG_CRIT, &quot;Boost event processing Error!\n&quot;);
</span><span class="cx"> 
</span><span class="cx"> end:
</span><span class="lines">@@ -1765,7 +1888,38 @@
</span><span class="cx">         return NULL;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if 0
+static int sigmod_ss7box_isup_exec_cmd(ftdm_stream_handle_t *stream, char *cmd)
+{
+        FILE *fp;
+        int status=0;
+        char path[1024];
+        
+        fp = popen(cmd, &quot;r&quot;);
+        if (fp == NULL) {
+                stream-&gt;write_function(stream, &quot;%s: -ERR failed to execute cmd: %s\n&quot;,
+                                __FILE__,cmd);
+                return -1;
+        }
+        
+        while (fgets(path, sizeof(path)-1, fp) != NULL) {
+                path[sizeof(path)-1]='\0';
+                stream-&gt;write_function(stream,&quot;%s&quot;, path);
+        }
+        
+        
+        status = pclose(fp);
+        if (status == -1) {
+                /* Error reported by pclose() */
+        } else {
+                /* Use macros described under wait() to inspect `status' in order
+                to determine success/failure of command executed by popen() */
+        }
</ins><span class="cx"> 
</span><ins>+        return status;
+}
+#endif
+
</ins><span class="cx"> #define FTDM_BOOST_SYNTAX &quot;list sigmods | &lt;sigmod_name&gt; &lt;command&gt;&quot;
</span><span class="cx"> /**
</span><span class="cx">  * \brief API function to kill or debug a sangoma_boost span
</span><span class="lines">@@ -1787,11 +1941,63 @@
</span><span class="cx">                 if (!strcasecmp(argv[0], &quot;list&quot;)) {
</span><span class="cx">                         if (!strcasecmp(argv[1], &quot;sigmods&quot;)) {
</span><span class="cx">                                 if (ftdm_sangoma_boost_list_sigmods(stream) != FTDM_SUCCESS) {
</span><del>-                                        stream-&gt;write_function(stream, &quot;%s: -ERR failed to execute cmd\n&quot;, __FILE__);
</del><ins>+                                        stream-&gt;write_function(stream, &quot;-ERR failed to list sigmods\n&quot;);
</ins><span class="cx">                                         goto done;
</span><span class="cx">                                 }
</span><span class="cx">                                 goto done;
</span><span class="cx">                         }
</span><ins>+
+                        if (!strcasecmp(argv[1], &quot;ids&quot;)) {
+                                print_request_ids();
+                                goto done;
+                        }
+                        
+#ifndef __WINDOWS__
+#if 0
+/* NC: This code crashes the kernel due to fork on heavy fs load */
+                } else if (!strcasecmp(argv[0], &quot;ss7box_isupd_ckt&quot;)) {
+                
+                        if (!strcasecmp(argv[1], &quot;used&quot;)) {
+                                stream-&gt;write_function(stream, &quot;ss7box_isupd: in use\n&quot;, FTDM_BOOST_SYNTAX);
+                                sigmod_ss7box_isup_exec_cmd(stream, (char*) &quot;ckt_report.sh inuse&quot;);
+                        } else if (!strcasecmp(argv[1], &quot;reset&quot;)) {
+                                stream-&gt;write_function(stream, &quot;ss7box_isupd: in reset\n&quot;, FTDM_BOOST_SYNTAX);
+                                sigmod_ss7box_isup_exec_cmd(stream, (char*) &quot;ckt_report.sh reset&quot;);
+                        } else if (!strcasecmp(argv[1], &quot;ready&quot;)) {
+                                stream-&gt;write_function(stream, &quot;ss7box_isupd: ready \n&quot;, FTDM_BOOST_SYNTAX);
+                                sigmod_ss7box_isup_exec_cmd(stream, (char*) &quot;ckt_report.sh free&quot;);
+                        } else {
+                                stream-&gt;write_function(stream, &quot;ss7box_isupd: list\n&quot;, FTDM_BOOST_SYNTAX);
+                                sigmod_ss7box_isup_exec_cmd(stream, (char*) &quot;ckt_report.sh&quot;);
+                        }
+
+                        goto done;
+#endif
+#endif
+                } else if (!strcasecmp(argv[0], &quot;restart&quot;)) {
+                        sangomabc_connection_t *pcon;
+                        ftdm_sangoma_boost_data_t *sangoma_boost_data;
+                        ftdm_span_t *span;
+                        int err = ftdm_span_find_by_name(argv[1], &amp;span);
+                        if (FTDM_SUCCESS != err) {
+                                stream-&gt;write_function(stream, &quot;-ERR failed to find span by name %s\n&quot;,argv[1]);
+                                goto done;
+                        }
+        
+                        sangoma_boost_data = span-&gt;signal_data;
+                        pcon = &amp;sangoma_boost_data-&gt;pcon;
+
+                        /* No need to set any span flags because
+                            our RESTART will generate a RESTART from the sig daemon */
+                        sangomabc_exec_commandp(pcon,
+                                                   0,
+                                                   0,
+                                                   -1,
+                                                   SIGBOOST_EVENT_SYSTEM_RESTART,
+                                                   0);                        
+
+                        goto done;
+
</ins><span class="cx">                 } else {
</span><span class="cx">                         boost_sigmod_interface_t *sigmod_iface = NULL;
</span><span class="cx">                         sigmod_iface = hashtable_search(g_boost_modules_hash, argv[0]);
</span><span class="lines">@@ -1829,7 +2035,7 @@
</span><span class="cx">  */
</span><span class="cx"> static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_boost_io_init)
</span><span class="cx"> {
</span><del>-        assert(fio != NULL);
</del><ins>+        ftdm_assert(fio != NULL, &quot;fio is NULL&quot;);
</ins><span class="cx">         memset(&amp;ftdm_sangoma_boost_interface, 0, sizeof(ftdm_sangoma_boost_interface));
</span><span class="cx"> 
</span><span class="cx">         ftdm_sangoma_boost_interface.name = &quot;boost&quot;;
</span><span class="lines">@@ -2212,6 +2418,7 @@
</span><span class="cx">         ftdm_dso_lib_t lib = NULL;
</span><span class="cx">         char path[255] = &quot;&quot;;
</span><span class="cx">         char *err = NULL;
</span><ins>+        int j = 0;
</ins><span class="cx">         unsigned paramindex = 0;
</span><span class="cx">         ftdm_status_t rc = FTDM_SUCCESS;
</span><span class="cx"> 
</span><span class="lines">@@ -2306,6 +2513,14 @@
</span><span class="cx">                 ftdm_set_string(sangoma_boost_data-&gt;mcon.cfg.remote_ip, remote_ip);
</span><span class="cx">                 sangoma_boost_data-&gt;mcon.cfg.remote_port = remote_port;
</span><span class="cx">         }
</span><ins>+
+        for (j = 1; j &lt;= span-&gt;chan_count; j++) {
+                span-&gt;channels[j]-&gt;call_data = ftdm_calloc(1,sizeof(sangoma_boost_call_t));
+                if (!span-&gt;channels[j]-&gt;call_data) {
+                        FAIL_CONFIG_RETURN(FTDM_FAIL);
+                }
+        }
+
</ins><span class="cx">         span-&gt;signal_cb = sig_cb;
</span><span class="cx">         span-&gt;start = ftdm_sangoma_boost_start;
</span><span class="cx">         span-&gt;stop = ftdm_sangoma_boost_stop;
</span></span></pre></div>
<a id="freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostsangoma_boost_clientc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx">         if (event-&gt;event_id == SIGBOOST_EVENT_HEARTBEAT)
</span><span class="cx">                 return;
</span><span class="cx"> 
</span><del>-        ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, &quot;%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n&quot;,
</del><ins>+        ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, &quot;%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n&quot;,
</ins><span class="cx">                     dir ? &quot;TX&quot;:&quot;RX&quot;,
</span><span class="cx">                         priority ? &quot;P&quot;:&quot;N&quot;,
</span><span class="cx">                         sangomabc_event_id_name(event-&gt;event_id),
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx"> {
</span><span class="cx">         if (event-&gt;event_id == SIGBOOST_EVENT_HEARTBEAT)
</span><span class="cx">                 return;
</span><del>-        ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, &quot;%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n&quot;,
</del><ins>+        ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, &quot;%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n&quot;,
</ins><span class="cx">                            dir ? &quot;TX&quot;:&quot;RX&quot;, 
</span><span class="cx">                            priority ? &quot;P&quot;:&quot;N&quot;,
</span><span class="cx">                            sangomabc_event_id_name(event-&gt;event_id), 
</span></span></pre></div>
<a id="freeswitchtrunklibsfreetdmsrcftmodftmod_sangoma_boostsigboosth"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sigboost.h        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -51,6 +51,24 @@
</span><span class="cx">         SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE                = 0x8c, /*140*/
</span><span class="cx">         SIGBOOST_EVENT_DIGIT_IN                                        = 0x8d, /*141*/
</span><span class="cx"> };
</span><ins>+
+#define BOOST_DECODE_EVENT_ID(id) \
+        (id==SIGBOOST_EVENT_CALL_START)?&quot;SIGBOOST_EVENT_CALL_START&quot;: \
+        (id==SIGBOOST_EVENT_CALL_START_ACK)?&quot;SIGBOOST_EVENT_CALL_START_ACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_START_NACK)?&quot;SIGBOOST_EVENT_CALL_START_NACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_ANSWERED)?&quot;SIGBOOST_EVENT_CALL_ANSWERED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_STOPPED)?&quot;SIGBOOST_EVENT_CALL_STOPPED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?&quot;SIGBOOST_EVENT_CALL_STOPPED_ACK&quot;: \
+        (id==SIGBOOST_EVENT_SYSTEM_RESTART)?&quot;SIGBOOST_EVENT_SYSTEM_RESTART&quot;: \
+        (id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?&quot;SIGBOOST_EVENT_SYSTEM_RESTART_ACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_RELEASED)?&quot;SIGBOOST_EVENT_CALL_RELEASED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_PROGRESS)?&quot;SIGBOOST_EVENT_CALL_PROGRESS&quot;: \
+        (id==SIGBOOST_EVENT_HEARTBEAT)?&quot;SIGBOOST_EVENT_HEARTBEAT&quot;: \
+        (id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?&quot;SIGBOOST_EVENT_INSERT_CHECK_LOOP&quot;: \
+        (id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?&quot;SIGBOOST_EVENT_REMOVE_CHECK_LOOP&quot;: \
+        (id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?&quot;SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE&quot;: \
+        (id==SIGBOOST_EVENT_DIGIT_IN)?&quot;SIGBOOST_EVENT_DIGIT_IN&quot;: &quot;Unknown&quot;
+
</ins><span class="cx"> enum        e_sigboost_release_cause_values
</span><span class="cx"> {
</span><span class="cx">         SIGBOOST_RELEASE_CAUSE_UNDEFINED                = 0,
</span></span></pre></div>
<a id="freeswitchtrunklibsopenzapsrcozmodozmod_sangoma_boostozmod_sangoma_boostc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -32,11 +32,14 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;openzap.h&quot;
</span><del>-#include &quot;sangoma_boost_client.h&quot;
</del><ins>+#include &quot;sangoma_boost_client.h&quot; 
</ins><span class="cx"> #include &quot;zap_sangoma_boost.h&quot;
</span><span class="cx"> #ifdef HAVE_SYS_SELECT_H
</span><span class="cx"> #include &lt;sys/select.h&gt;
</span><span class="cx"> #endif
</span><ins>+#ifndef __WINDOWS__
+#include &lt;poll.h&gt;
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #define MAX_TRUNK_GROUPS 64
</span><span class="cx"> static time_t congestion_timeouts[MAX_TRUNK_GROUPS];
</span><span class="lines">@@ -484,7 +487,31 @@
</span><span class="cx">                         OUTBOUND_REQUESTS[event-&gt;call_setup_id].status = BST_READY;
</span><span class="cx">                         return;
</span><span class="cx">                 }
</span><del>-        } 
</del><ins>+        } else {
+                if ((zchan = find_zchan(OUTBOUND_REQUESTS[event-&gt;call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
+                        int r;
+                        
+                        /* NC: If we get CALL START ACK and channel is in active state
+                               then we are completely out of sync with the other end.
+                               Treat CALL START ACK as CALL STOP and hangup the current call.
+                        */
+                        
+                        if (zchan-&gt;state == ZAP_CHANNEL_STATE_UP || 
+                                zchan-&gt;state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA ||
+                            zchan-&gt;state == ZAP_CHANNEL_STATE_PROGRESS) {
+                                zap_log(ZAP_LOG_CRIT, &quot;ZCHAN STATE UP/PROG/PROG_MEDIA -&gt; Changed to HANGUP %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
+                                zap_set_state_r(zchan, ZAP_CHANNEL_STATE_HANGUP, 0, r);
+
+                        } else if (zap_test_sflag(zchan, SFLAG_HANGUP)) { 
+                                /* Do nothing because outgoing STOP will generaate a stop ack */
+
+                        } else {
+                                zap_log(ZAP_LOG_CRIT, &quot;ZCHAN STATE INVALID %s on IN CALL ACK %d:%d\n&quot;, zap_channel_state2str(zchan-&gt;state),event-&gt;span+1,event-&gt;chan+1);
+
+                        }
+                        zchan=NULL;
+                }
+        }
</ins><span class="cx">         
</span><span class="cx">         //printf(&quot;WTF BAD ACK CSid=%d span=%d chan=%d\n&quot;, event-&gt;call_setup_id, event-&gt;span+1,event-&gt;chan+1);
</span><span class="cx">         if ((zchan = find_zchan(OUTBOUND_REQUESTS[event-&gt;call_setup_id].span, event, 1))) {
</span><span class="lines">@@ -640,7 +667,14 @@
</span><span class="cx"> 
</span><span class="cx">                 zap_mutex_lock(zchan-&gt;mutex);
</span><span class="cx"> 
</span><del>-                if (zap_test_sflag(zchan, SFLAG_HANGUP)) {
</del><ins>+                if (zap_test_sflag(zchan, SFLAG_HANGUP) || zchan-&gt;state == ZAP_CHANNEL_STATE_DOWN) {
+        
+                        /* NC: Checking for state DOWN because ss7box can
+                                   send CALL_STOP twice in a row.  If we do not check for
+                                   STATE_DOWN we will set the state back to termnating
+                                   and block the channel forever
+                        */
+        
</ins><span class="cx">                         /* racing condition where both sides initiated a hangup 
</span><span class="cx">                          * Do not change current state as channel is already clearing
</span><span class="cx">                          * itself through local initiated hangup */
</span><span class="lines">@@ -697,7 +731,14 @@
</span><span class="cx">         
</span><span class="cx">         if ((zchan = find_zchan(span, event, 1))) {
</span><span class="cx">                 zap_mutex_lock(zchan-&gt;mutex);
</span><del>-                if (zchan-&gt;state == ZAP_CHANNEL_STATE_HOLD) {
</del><ins>+                if (zap_test_sflag(zchan, SFLAG_HANGUP) || 
+                    zchan-&gt;state == ZAP_CHANNEL_STATE_DOWN || 
+                        zchan-&gt;state == ZAP_CHANNEL_STATE_TERMINATING) {
+                        /* NC: Do nothing here because we are in process
+                               of stopping the call. So ignore the ANSWER. */
+                        zap_log(ZAP_LOG_CRIT, &quot;ANSWER BUT CALL IS HANGUP %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
+
+                } else if (zchan-&gt;state == ZAP_CHANNEL_STATE_HOLD) {
</ins><span class="cx">                         zchan-&gt;init_state = ZAP_CHANNEL_STATE_UP;
</span><span class="cx">                 } else {
</span><span class="cx">                         int r = 0;
</span><span class="lines">@@ -731,6 +772,12 @@
</span><span class="cx">         if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
</span><span class="cx">                 if ((zchan = find_zchan(span, (sangomabc_short_event_t*)event, 1))) {
</span><span class="cx">                         int r;
</span><ins>+                        
+                        /* NC: If we get CALL START and channel is in active state
+                               then we are completely out of sync with the other end.
+                               Treat CALL START as CALL STOP and hangup the current call.
+                        */
+                        
</ins><span class="cx">                         if (zchan-&gt;state == ZAP_CHANNEL_STATE_UP) {
</span><span class="cx">                                 zap_log(ZAP_LOG_CRIT, &quot;ZCHAN STATE UP -&gt; Changed to TERMINATING %d:%d\n&quot;, event-&gt;span+1,event-&gt;chan+1);
</span><span class="cx">                                 zap_set_state_r(zchan, ZAP_CHANNEL_STATE_TERMINATING, 0, r);
</span><span class="lines">@@ -1380,6 +1427,65 @@
</span><span class="cx">         return NULL;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+#ifndef __WINDOWS__
+static int waitfor_2sockets(int fda, int fdb, char *a, char *b, int timeout)
+{
+    struct pollfd pfds[2];
+    int res = 0;
+    int errflags = (POLLERR | POLLHUP | POLLNVAL);
+
+    if (fda &lt; 0 || fdb &lt; 0) {
+                return -1;
+    }
+
+
+waitfor_2sockets_tryagain:
+
+    *a=0;
+    *b=0;
+
+
+    memset(pfds, 0, sizeof(pfds));
+
+    pfds[0].fd = fda;
+    pfds[1].fd = fdb;
+    pfds[0].events = POLLIN | errflags;
+    pfds[1].events = POLLIN | errflags;
+
+    res = poll(pfds, 2, timeout); 
+
+    if (res &gt; 0) {
+                res = 1;
+                if ((pfds[0].revents &amp; errflags) || (pfds[1].revents &amp; errflags)) {
+                        res = -1;
+                } else { 
+                        if ((pfds[0].revents &amp; POLLIN)) {
+                                *a=1;
+                                res++;
+                        }
+                        if ((pfds[1].revents &amp; POLLIN)) {
+                                *b=1;                
+                                res++;
+                        }
+                }
+
+                if (res == 1) {
+                        /* No event found what to do */
+                        res=-1;
+                }
+    } else if (res &lt; 0) {
+        
+                if (errno == EINTR || errno == EAGAIN) {
+                        goto waitfor_2sockets_tryagain;
+                }
+
+    }
+        
+    return res;
+}
+#endif
+
</ins><span class="cx"> /**
</span><span class="cx">  * \brief Main thread function for sangoma boost span (monitor)
</span><span class="cx">  * \param me Current thread
</span><span class="lines">@@ -1391,7 +1497,13 @@
</span><span class="cx">     zap_sangoma_boost_data_t *sangoma_boost_data = span-&gt;signal_data;
</span><span class="cx">         sangomabc_connection_t *mcon, *pcon;
</span><span class="cx">         uint32_t ms = 10; //, too_long = 20000;
</span><del>-                
</del><ins>+        int max, activity, i;
+        sangomabc_event_t *event;
+        struct timeval tv;
+        fd_set rfds, efds;
+#ifndef __WINDOWS__
+        char a=0,b=0;
+#endif
</ins><span class="cx"> 
</span><span class="cx">         sangoma_boost_data-&gt;pcon = sangoma_boost_data-&gt;mcon;
</span><span class="cx"> 
</span><span class="lines">@@ -1427,11 +1539,14 @@
</span><span class="cx">         zap_set_flag(mcon, MSU_FLAG_DOWN);
</span><span class="cx"> 
</span><span class="cx">         while (zap_test_flag(sangoma_boost_data, ZAP_SANGOMA_BOOST_RUNNING)) {
</span><del>-                fd_set rfds, efds;
-                struct timeval tv = { 0, ms * 1000 };
-                int max, activity, i = 0;
-                sangomabc_event_t *event = NULL;
</del><span class="cx">                 
</span><ins>+                tv.tv_sec = 0;
+                tv.tv_usec = ms* 1000;
+                max=0;
+                activity=0;
+                i=0;
+                event = NULL;
+                
</ins><span class="cx">                 if (!zap_running()) {
</span><span class="cx">                         sangomabc_exec_commandp(pcon,
</span><span class="cx">                                                            0,
</span><span class="lines">@@ -1451,7 +1566,8 @@
</span><span class="cx">                 FD_SET(pcon-&gt;socket, &amp;efds);
</span><span class="cx"> 
</span><span class="cx">                 max = ((pcon-&gt;socket &gt; mcon-&gt;socket) ? pcon-&gt;socket : mcon-&gt;socket) + 1;
</span><del>-                
</del><ins>+
+#ifdef __WINDOWS__
</ins><span class="cx">                 if ((activity = select(max, &amp;rfds, NULL, &amp;efds, &amp;tv)) &lt; 0) {
</span><span class="cx">                         goto error;
</span><span class="cx">                 }
</span><span class="lines">@@ -1477,8 +1593,34 @@
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                 }
</span><ins>+#else
</ins><span class="cx">                 
</span><ins>+                a=0;
+                b=0;
+                i=0;
+                tv.tv_sec=0;
+                activity = waitfor_2sockets(pcon-&gt;socket,mcon-&gt;socket,&amp;a,&amp;b,ms);
+                if (activity) {
+                        if (a) {
+                                while ((event = sangomabc_connection_readp(pcon, i))) {
+                                        parse_sangoma_event(span, pcon, (sangomabc_short_event_t*)event);
+                                        i++;
+                                }
+                        }
+                        i=0;
</ins><span class="cx"> 
</span><ins>+                        if (b) {
+                                if ((event = sangomabc_connection_read(mcon, i))) {
+                                        parse_sangoma_event(span, mcon, (sangomabc_short_event_t*)event);
+                                        i++;
+                                }
+                        }
+                } else if (activity &lt; 0) {
+                        goto error;
+                }
+
+#endif                
+
</ins><span class="cx">                 pcon-&gt;hb_elapsed += ms;
</span><span class="cx"> 
</span><span class="cx">                 if (zap_test_flag(span, ZAP_SPAN_SUSPENDED) || zap_test_flag(mcon, MSU_FLAG_DOWN)) {
</span></span></pre></div>
<a id="freeswitchtrunklibsopenzapsrcozmodozmod_sangoma_boostsigboosth"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/sigboost.h (17305 => 17306)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/sigboost.h        2010-04-15 13:24:04 UTC (rev 17305)
+++ freeswitch/trunk/libs/openzap/src/ozmod/ozmod_sangoma_boost/sigboost.h        2010-04-15 15:39:55 UTC (rev 17306)
</span><span class="lines">@@ -57,6 +57,24 @@
</span><span class="cx">         SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE                = 0x8c, /*140*/
</span><span class="cx">         SIGBOOST_EVENT_DIGIT_IN                                        = 0x8d, /*141*/
</span><span class="cx"> };
</span><ins>+
+#define BOOST_DECODE_EVENT_ID(id) \
+        (id==SIGBOOST_EVENT_CALL_START)?&quot;SIGBOOST_EVENT_CALL_START&quot;: \
+        (id==SIGBOOST_EVENT_CALL_START_ACK)?&quot;SIGBOOST_EVENT_CALL_START_ACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_START_NACK)?&quot;SIGBOOST_EVENT_CALL_START_NACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_ANSWERED)?&quot;SIGBOOST_EVENT_CALL_ANSWERED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_STOPPED)?&quot;SIGBOOST_EVENT_CALL_STOPPED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?&quot;SIGBOOST_EVENT_CALL_STOPPED_ACK&quot;: \
+        (id==SIGBOOST_EVENT_SYSTEM_RESTART)?&quot;SIGBOOST_EVENT_SYSTEM_RESTART&quot;: \
+        (id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?&quot;SIGBOOST_EVENT_SYSTEM_RESTART_ACK&quot;: \
+        (id==SIGBOOST_EVENT_CALL_RELEASED)?&quot;SIGBOOST_EVENT_CALL_RELEASED&quot;: \
+        (id==SIGBOOST_EVENT_CALL_PROGRESS)?&quot;SIGBOOST_EVENT_CALL_PROGRESS&quot;: \
+        (id==SIGBOOST_EVENT_HEARTBEAT)?&quot;SIGBOOST_EVENT_HEARTBEAT&quot;: \
+        (id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?&quot;SIGBOOST_EVENT_INSERT_CHECK_LOOP&quot;: \
+        (id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?&quot;SIGBOOST_EVENT_REMOVE_CHECK_LOOP&quot;: \
+        (id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?&quot;SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE&quot;: \
+        (id==SIGBOOST_EVENT_DIGIT_IN)?&quot;SIGBOOST_EVENT_DIGIT_IN&quot;: &quot;Unknown&quot;
+
</ins><span class="cx"> enum        e_sigboost_release_cause_values
</span><span class="cx"> {
</span><span class="cx">         SIGBOOST_RELEASE_CAUSE_UNDEFINED                = 0,
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>