]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
merged 1023:1039 http://svn.openzap.org/svn/openzap/trunk
authorMoises Silva <moy@sangoma.com>
Thu, 25 Feb 2010 23:36:18 +0000 (23:36 +0000)
committerMoises Silva <moy@sangoma.com>
Thu, 25 Feb 2010 23:36:18 +0000 (23:36 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/branches/sangoma_boost@1040 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
libs/freetdm/src/include/ftdm_types.h

index 496131a2139e3a7a4feba89028aca7c4efb5b9ff..8a19d3d7259cbb4e2c5469fca742155c5fc574a2 100644 (file)
@@ -675,7 +675,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
                tech_pvt->read_frame.samples /= 2;
        }
 
-       if (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) {
+       while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) {
                switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
                char *p;
                for (p = dtmf; p && *p; p++) {
@@ -737,10 +737,11 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 
 
        wflags = FTDM_WRITE;    
-       status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, tech_pvt->ftdmchan->effective_interval * 4);
+       status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, tech_pvt->ftdmchan->effective_interval * 10);
        
        if (!(wflags & FTDM_WRITE)) {
-               goto fail;
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n");
+               return SWITCH_STATUS_SUCCESS;
        }
 
        len = frame->datalen;
index d81737886b9f097f5e51684db8c924f0d1f6775e..2ea9ad7d77188046a024dca7a128388c9c25a36d 100644 (file)
@@ -1322,9 +1322,7 @@ static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan)
        memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
        ftdmchan->token_count = 0;
 
-       if (ftdmchan->dtmf_buffer) {
-               ftdm_buffer_zero(ftdmchan->dtmf_buffer);
-       }
+       ftdm_channel_flush_dtmf(ftdmchan);
 
        if (ftdmchan->gen_dtmf_buffer) {
                ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
index 758942452e9f38dd9903a6abed9cc4e4b87fcda3..85fe09f7bc1f09c56448d973a00ba362fd880631 100644 (file)
@@ -239,7 +239,6 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons
 {
        ftdm_sigmsg_t sigev;
        ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
-       ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
 
        ftdm_log(FTDM_LOG_NOTICE, "Call offered on chan %d, ANI = %s, DNIS = %s, Category = %s\n", openr2_chan_get_number(r2chan), 
                        ani, dnis, openr2_proto_get_category_string(category));
@@ -910,7 +909,6 @@ static void *ftdm_r2_channel_run(ftdm_thread_t *me, void *obj)
        ftdm_sigmsg_t sigev;
        ftdm_channel_t *ftdmchan = (ftdm_channel_t *)obj;
        openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
-       ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
 
        ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INTHREAD);
 
index 88e19454de8a0131a7dfdbaee5ba81afd026f509..53e1beb9b41dda7bb17865665cd1b081e78922fa 100644 (file)
@@ -111,7 +111,6 @@ static uint16_t SETUP_GRID[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN+1][FTDM_MAX_
 static sangoma_boost_request_t OUTBOUND_REQUESTS[MAX_REQ_ID+1] = {{ 0 }};
 
 static ftdm_mutex_t *request_mutex = NULL;
-static ftdm_mutex_t *signal_mutex = NULL;
 
 static uint8_t req_map[MAX_REQ_ID+1] = { 0 };
 static uint8_t nack_map[MAX_REQ_ID+1] = { 0 };
@@ -219,7 +218,6 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t
                targetchan = event->chan;
        }
 
-       ftdm_mutex_lock(signal_mutex);
        for(i = 1; i <= span->chan_count; i++) {
                if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) {
                        ftdmchan = span->channels[i];
@@ -237,7 +235,6 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t
                        }
                }
        }
-       ftdm_mutex_unlock(signal_mutex);
 
        return ftdmchan;
 }
@@ -273,7 +270,12 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
        ftdm_status_t status = FTDM_FAIL;
        sangoma_boost_request_id_t r;
        sangomabc_event_t event = {0};
-       int boost_request_timeout = 5000;
+       /* sanity has to be more than 8 seconds.
+        * In PRI specs, timeout is 4 seconds for remote switch to respond to a SETUP,
+        * and PRI stack will retransmit a second SETUP after the first timeout, so
+        * we should allow for at least 8 seconds.
+        */
+       int boost_request_timeout = 10000;
        sangoma_boost_request_status_t st;
        char dnis[128] = "";
        char *gr = NULL;
@@ -864,18 +866,8 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
        ftdm_channel_t *ftdmchan;
 
        if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
-               if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
-                       ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1);
-                       goto error;
-               }
-               /* this handles race conditions where state handlers are still pending to be executed for finished calls
-                  but an incoming call arrives first, we must complete the channel states and then try again to get the 
-                  ftdm channel */
-               advance_chan_states(ftdmchan);
-               if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
-                       ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d EVEN AFTER STATE ADVANCE\n", event->span+1,event->chan+1);
-                       goto error;
-               }
+               ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1);
+               goto error;
        }
 
        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
@@ -931,6 +923,48 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
                
 }
 
+static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
+{
+       ftdm_status_t res = FTDM_FAIL;
+       ftdm_channel_t *ftdmchan;
+
+       if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
+               ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CHAN NOT AVAILABLE %d:%d\n", event->span+1,event->chan+1);
+               return;
+       }
+
+       if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CANT OPEN CHAN %d:%d\n", event->span+1,event->chan+1);
+               return;
+       }
+
+       ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, 0, res);
+       if (res != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
+               ftdm_channel_done(ftdmchan);
+               return;
+       }
+       ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL);
+}
+
+static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
+{
+       ftdm_channel_t *ftdmchan;
+       ftdm_status_t res = FTDM_FAIL;
+       if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
+               ftdm_log(FTDM_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", event->span+1,event->chan+1);
+               return;
+       }
+       if (ftdmchan->state != FTDM_CHANNEL_STATE_IN_LOOP) {
+               ftdm_log(FTDM_LOG_ERROR, "Got stop loop request in a channel that is not in loop, ignoring ...\n");
+               return;
+       }
+       ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
+       /* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */
+       ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG);
+       ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, 0, res);
+}
+
 /**
  * \brief Handler for heartbeat event
  * \param mcon sangoma boost connection
@@ -1015,6 +1049,53 @@ static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *spa
        return;
 }
 
+
+/**
+ * \brief Checks if span has state changes pending and processes 
+ * \param span Span where event was fired
+ * \param event Event to handle
+ * \return The locked FTDM channel associated to the event if any, NULL otherwise
+ */
+static ftdm_channel_t* event_process_states(ftdm_span_t *span, sangomabc_short_event_t *event) 
+{
+    ftdm_channel_t *ftdmchan = NULL;
+    
+    switch (event->event_id) {
+        case SIGBOOST_EVENT_CALL_START_NACK:
+        case SIGBOOST_EVENT_CALL_START_NACK_ACK:
+            if (event->call_setup_id) {
+                return NULL;
+            } 
+            //if event->span and event->chan is valid, fall-through
+        case SIGBOOST_EVENT_CALL_START:
+        case SIGBOOST_EVENT_CALL_START_ACK:
+        case SIGBOOST_EVENT_CALL_STOPPED:
+        case SIGBOOST_EVENT_CALL_PROGRESS:
+        case SIGBOOST_EVENT_CALL_ANSWERED:
+        case SIGBOOST_EVENT_CALL_STOPPED_ACK:
+        case SIGBOOST_EVENT_DIGIT_IN:
+        case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
+        case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
+            if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
+                ftdm_log(FTDM_LOG_DEBUG, "PROCESS STATES  CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1);
+                return NULL;
+            }
+            break;
+        case SIGBOOST_EVENT_HEARTBEAT:
+        case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
+        case SIGBOOST_EVENT_SYSTEM_RESTART:
+        case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE:
+            return NULL;
+        default:
+            ftdm_log(FTDM_LOG_CRIT, "Unhandled event id:%d\n", event->event_id);
+            return NULL;
+    }
+
+    ftdm_mutex_lock(ftdmchan->mutex);
+    advance_chan_states(ftdmchan);
+    return ftdmchan;
+}
+
 /**
  * \brief Handler for sangoma boost event
  * \param span Span where event was fired
@@ -1023,14 +1104,19 @@ static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *spa
  */
 static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
 {
-       ftdm_mutex_lock(signal_mutex);
+    ftdm_channel_t* ftdmchan = NULL;
        
        if (!ftdm_running()) {
                ftdm_log(FTDM_LOG_WARNING, "System is shutting down.\n");
-               goto end;
+               return -1;
        }
 
     ftdm_assert_return(event->call_setup_id <= MAX_REQ_ID, -1, "Unexpected call setup id\n");
+
+       /* process all pending state changes for that channel before
+        * processing the new boost event */
+       ftdmchan = event_process_states(span, event);
+
     switch(event->event_id) {
     case SIGBOOST_EVENT_CALL_START:
                handle_call_start(span, mcon, (sangomabc_event_t*)event);
@@ -1064,10 +1150,10 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon,
                nack_map[event->call_setup_id] = 0;
                break;
     case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
-               //handle_call_loop_start(event);
+               handle_call_loop_start(span, mcon, event);
                break;
     case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
-               //handle_call_stop(event);
+               handle_call_loop_stop(span, mcon, event);
                break;
     case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
                handle_restart_ack(mcon, span, event);
@@ -1086,11 +1172,13 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon,
                break;
     }
 
- end:
-
-       ftdm_mutex_unlock(signal_mutex);
+    if(ftdmchan != NULL) {
+        advance_chan_states(ftdmchan);
+        ftdm_mutex_unlock(ftdmchan->mutex);
+    }
 
        return 0;
+
 }
 
 /**
@@ -1290,6 +1378,11 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                        status = ftdm_span_send_signal(ftdmchan->span, &sig);
                }
                break;
+       case FTDM_CHANNEL_STATE_IN_LOOP:
+               {
+                       /* nothing to do, we sent the FTDM_COMMAND_ENABLE_LOOP command in handle_call_loop_start() right away */
+               }
+               break;
        default:
                break;
        }
@@ -1297,13 +1390,11 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
 
 static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan)
 {
-       ftdm_mutex_lock(ftdmchan->mutex);
        while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
                ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
                state_advance(ftdmchan);
                ftdm_channel_complete_state(ftdmchan);
        }
-       ftdm_mutex_unlock(ftdmchan->mutex);
 }
 
 /**
@@ -1668,7 +1759,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_boost_init)
                return FTDM_FAIL;
        }
        ftdm_mutex_create(&request_mutex);
-       ftdm_mutex_create(&signal_mutex);
        ftdm_mutex_create(&g_boost_modules_mutex);
        memset(&g_trunkgroups[0], 0, sizeof(g_trunkgroups));
        return FTDM_SUCCESS;
@@ -1693,7 +1783,6 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_boost_destroy)
 
        hashtable_destroy(g_boost_modules_hash);
        ftdm_mutex_destroy(&request_mutex);
-       ftdm_mutex_destroy(&signal_mutex);
        ftdm_mutex_destroy(&g_boost_modules_mutex);
        return FTDM_SUCCESS;
 }
@@ -1811,6 +1900,18 @@ static ftdm_state_map_t boost_state_map = {
                        {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
                        {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
                },
+               {
+                       ZSD_INBOUND,
+                       ZSM_UNACCEPTABLE,
+                       {FTDM_CHANNEL_STATE_DOWN},
+                       {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
+               },
+               {
+                       ZSD_INBOUND,
+                       ZSM_UNACCEPTABLE,
+                       {FTDM_CHANNEL_STATE_IN_LOOP},
+                       {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+               },
                {
                        ZSD_INBOUND,
                        ZSM_UNACCEPTABLE,
index 9e66d8ec53f70de8084ebffd38bc57a5e55204cd..c7723e94a9ce8419084637b2af536aa3123702de 100644 (file)
@@ -497,6 +497,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
        wanpipe_tdm_api_t tdm_api;
 
        memset(&tdm_api,0,sizeof(tdm_api));
+       sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api);
+#ifdef LIBSANGOMA_VERSION
+       sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api);
+#endif
 
        if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
                ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
@@ -605,6 +609,14 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
                        //code me
                }
                break;
+       case FTDM_COMMAND_ENABLE_LOOP:
+               {
+                       // code me
+               }
+       case FTDM_COMMAND_DISABLE_LOOP:
+               {
+                       // code me
+               }
        case FTDM_COMMAND_SET_INTERVAL: 
                {
                        err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT);
@@ -1051,7 +1063,9 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
 
                                        if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
                                                ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
-                                               ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf);
+                                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
+                                                       ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf);
+                                               }
                                        } 
                                }
                                break;
index d1b3a4f71152002f56f7b570f42cd6bb8fddc569..776ec073678876c3c4b0d913c9d4e67fb8ea31fc 100644 (file)
@@ -315,6 +315,8 @@ typedef enum {
        FTDM_COMMAND_SET_PRE_BUFFER_SIZE,
        FTDM_COMMAND_SET_LINK_STATUS,
        FTDM_COMMAND_GET_LINK_STATUS,
+       FTDM_COMMAND_ENABLE_LOOP,
+       FTDM_COMMAND_DISABLE_LOOP,
        FTDM_COMMAND_COUNT
 } ftdm_command_t;
 
@@ -374,6 +376,7 @@ typedef enum {
        FTDM_CHANNEL_STATE_CANCEL,
        FTDM_CHANNEL_STATE_HANGUP,
        FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
+       FTDM_CHANNEL_STATE_IN_LOOP,
        FTDM_CHANNEL_STATE_INVALID
 } ftdm_channel_state_t;
 #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \