]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: Support for channel restarts
authorDavid Yat Sin <dyatsin@sangoma.com>
Tue, 14 Dec 2010 16:23:47 +0000 (11:23 -0500)
committerDavid Yat Sin <dyatsin@sangoma.com>
Tue, 14 Dec 2010 16:23:47 +0000 (11:23 -0500)
15 files changed:
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftdm_m3ua.c
libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c
libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h
libs/freetdm/src/include/private/ftdm_types.h

index 38197bb2f0f090c3b77598658a10c28fa91ff087..26b84636caafa8082f64093e56750a2f5cb8c293 100755 (executable)
@@ -3922,6 +3922,28 @@ SWITCH_STANDARD_API(ft_function)
                        }
                }
                stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
+       } else if (!strcasecmp(argv[0], "restart")) {
+               uint32_t chan_id = 0;
+               ftdm_channel_t *chan;
+               ftdm_span_t *span = NULL;
+               if (argc < 3) {
+                       stream->write_function(stream, "-ERR Usage: ftdm restart <span_id> <chan_id>\n");
+                       goto end;
+               }
+               ftdm_span_find_by_name(argv[1], &span);
+               if (!span) {
+                       stream->write_function(stream, "-ERR invalid span\n");
+                       goto end;
+               }
+               
+               chan_id = atoi(argv[2]);
+               chan = ftdm_span_get_channel(span, chan_id);
+               if (!chan) {
+                       stream->write_function(stream, "-ERR Could not find chan\n");
+                       goto end;
+               }
+               stream->write_function(stream, "Resetting channel %s:%s\n", argv[2], argv[3]);
+               ftdm_channel_reset(chan);
        } else {
 
                char *rply = ftdm_api_execute(cmd);
index e13d0196b8b10075fa6077edcde11ce2f743e0f5..deeb578c81a030966f0c458f8c480f6a7d4ed0aa 100644 (file)
@@ -65,6 +65,8 @@ ftdm_time_t time_current_throttle_log = 0;
 static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
 static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data);
 static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data);
+static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
+static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan);
 
 static int time_is_init = 0;
 
@@ -1874,45 +1876,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
        return status;
 }
 
-static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan)
-{
-       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
-       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
-       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
-       ftdm_channel_done(ftdmchan);
-       ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_HOLD);
-
-       memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
-       ftdmchan->token_count = 0;
-
-       ftdm_channel_flush_dtmf(ftdmchan);
-
-       if (ftdmchan->gen_dtmf_buffer) {
-               ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
-       }
-
-       if (ftdmchan->digit_buffer) {
-               ftdm_buffer_zero(ftdmchan->digit_buffer);
-       }
-
-       if (!ftdmchan->dtmf_on) {
-               ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
-       }
-
-       if (!ftdmchan->dtmf_off) {
-               ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
-       }
-
-       memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
-
-       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
-               ftdmchan->effective_codec = ftdmchan->native_codec;
-               ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
-               ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
-       }
-
-       return FTDM_SUCCESS;
-}
 
 FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan)
 {
@@ -2462,6 +2425,21 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const ch
        return status;
 }
 
+FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
+{
+       ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
+#ifdef __WINDOWS__
+       UNREFERENCED_PARAMETER(file);
+       UNREFERENCED_PARAMETER(func);
+       UNREFERENCED_PARAMETER(line);
+#endif
+
+       ftdm_channel_lock(ftdmchan);
+       ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RESET, 0);
+       ftdm_channel_unlock(ftdmchan);
+       return FTDM_SUCCESS;
+}
+
 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
 {
        ftdm_status_t status = FTDM_FAIL;
@@ -2545,12 +2523,13 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
        }
 }
 
-static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
-FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
+static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
 {
        ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n");
-
        ftdm_mutex_lock(ftdmchan->mutex);
+       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
+       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
+       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_INUSE);
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_WINK);
@@ -2591,17 +2570,47 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
                sigmsg.event_id = FTDM_SIGEVENT_RELEASED;
                ftdm_span_send_signal(ftdmchan->span, &sigmsg);
                ftdm_call_clear_call_id(&ftdmchan->caller_data);
-       }       
+       }
 
        if (ftdmchan->txdrops || ftdmchan->rxdrops) {
-               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n", 
+               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n",
                                ftdmchan->txdrops, ftdmchan->rxdrops);
        }
 
        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
        memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
-       ftdm_mutex_unlock(ftdmchan->mutex);
 
+       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD);
+
+       memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
+       ftdmchan->token_count = 0;
+
+       ftdm_channel_flush_dtmf(ftdmchan);
+
+       if (ftdmchan->gen_dtmf_buffer) {
+               ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
+       }
+
+       if (ftdmchan->digit_buffer) {
+               ftdm_buffer_zero(ftdmchan->digit_buffer);
+       }
+
+       if (!ftdmchan->dtmf_on) {
+               ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
+       }
+
+       if (!ftdmchan->dtmf_off) {
+               ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
+       }
+
+       memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
+
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
+               ftdmchan->effective_codec = ftdmchan->native_codec;
+               ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
+               ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
+       }
+       ftdm_mutex_unlock(ftdmchan->mutex);
        return FTDM_SUCCESS;
 }
 
@@ -2632,7 +2641,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan)
                        status = check->fio->close(check);
                        if (status == FTDM_SUCCESS) {
                                ftdm_clear_flag(check, FTDM_CHANNEL_INUSE);
-                               ftdm_channel_reset(check);
+                               ftdm_channel_done(check);
                                *ftdmchan = NULL;
                        }
                } else {
index 1a6fe362e74d3b5a4e8542dc9a3993e22428ed29..5a468d1378bf4aebdb6b8d357e1d7c711478bda2 100644 (file)
@@ -156,7 +156,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                                release_request_id((m3ua_request_id_t)ftdmchan->extra_id);
                                ftdmchan->extra_id = 0;
                        }
-                       ftdm_channel_done(ftdmchan);                    
+                       ftdm_channel_close(ftdmchan);                   
                }
                break;
        case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
index 6a8a4eb3794e6e63ecfbd29ed6f02ebcb7f0c512..c6a0e5ff0e1a3404aca8a71c69ffab862f7ffda1 100644 (file)
@@ -1325,7 +1325,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                                }
                                Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
                        }
-                       ftdm_channel_done(ftdmchan);
+                       ftdm_channel_close(ftdmchan);
                }
                break;
        case FTDM_CHANNEL_STATE_PROGRESS:
index 220a96515b9cf8d6fa852ddc8564bc7e2ddd73aa..b3b4f2a9dcc41cc125fdf2788ac1115a29599b40 100644 (file)
@@ -281,10 +281,10 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
        switch (ftdmchan->state) {
        case FTDM_CHANNEL_STATE_DOWN:
                {
-                       ftdm_channel_done(ftdmchan);                    
+                       ftdm_channel_close(ftdmchan);                   
                        ftdmchan->call_data = NULL;
 
-                       ftdm_channel_done(peerchan);
+                       ftdm_channel_close(peerchan);
                        peerchan->call_data = NULL;
                }
                break;
index 50a01cc0ec4ef8bff0c387ee551beef5da99a2d8..a196725d4edcd2b9a830e052be2eb5f1460e3ace 100644 (file)
@@ -839,7 +839,7 @@ static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon
        if ((ftdmchan = find_ftdmchan(span, event, 1))) {
                ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), 
                                BOOST_EVENT_CHAN(mcon->sigmod, event));
-               ftdm_channel_done(ftdmchan);
+               ftdm_channel_close(ftdmchan);
        } else {
                ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n", 
                                BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
@@ -1106,7 +1106,7 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
        ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, 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);
+               ftdm_channel_close(ftdmchan);
                return;
        }
        ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
@@ -1426,11 +1426,11 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
                        ftdmchan->sflags = 0;
                        memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t));
                        if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
-                               /* we dont want to call ftdm_channel_done just yet until call released is received */
+                               /* we dont want to call ftdm_channel_close just yet until call released is received */
                                ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n", 
                                                ftdmchan->span_id, ftdmchan->chan_id);
                        } else {
-                               ftdm_channel_done(ftdmchan);
+                               ftdm_channel_close(ftdmchan);
                        }
                }
                break;
index e20d3ae7e0b17edbe275224e72feed414c61ef74..49e16ea12c6bbd397ffa93a4095e431b75b2e4bc 100644 (file)
@@ -65,7 +65,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_INBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_ANY_STATE, FTDM_END},
-               {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
+               {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
+       },
+       {
+               ZSD_INBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_RESET, FTDM_END},
+               {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
        },
        {
                ZSD_INBOUND,
@@ -170,7 +176,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_OUTBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_ANY_STATE, FTDM_END},
-               {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+               {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+       },
+       {
+               ZSD_OUTBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_RESET, FTDM_END},
+               {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
        },
        {
                ZSD_OUTBOUND,
@@ -780,7 +792,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                                        sngisdn_snd_release(ftdmchan, 0);
 
                                        if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
-                                               sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+                                               sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
                                        }
                                } else {
                                        sngisdn_snd_disconnect(ftdmchan);
@@ -838,6 +850,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                        /* IMPLEMENT ME */
                }
                break;
+       case FTDM_CHANNEL_STATE_RESET:
+               {
+                       sngisdn_snd_restart(ftdmchan);
+               }
+               break;
        default:
                {
                        ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
@@ -862,10 +879,6 @@ static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
        ftdm_status_t status = FTDM_FAIL;
 
        switch (sigmsg->event_id) {
-               case FTDM_SIGEVENT_RESTART:
-                       /* TODO: Send a channel restart here */
-                       /* Implement me */
-                       break;
                case FTDM_SIGEVENT_FACILITY:
                        sngisdn_snd_fac_req(ftdmchan);
                        break;
@@ -1072,7 +1085,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
        if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
                span->trunk_type == FTDM_TRUNK_BRI) {
                
-               sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
+               sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
        }
 
        /* Initialize scheduling context */
@@ -1167,6 +1180,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
                goto done;
        }
 
+       /* TODO: Move functions to table + function pointers */
        if (!strcasecmp(argv[0], "trace")) {
                char *trace_opt;
                
@@ -1210,7 +1224,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
                }
                sngisdn_print_phy_stats(stream, span);
        }
-
+       
        if (!strcasecmp(argv[0], "show_spans")) {
                ftdm_span_t *span = NULL;
                if (argc == 2) {
index f15eff9200bb043a5a464c60bd16d377cc70974a..4662d4e9bbb4eabfd6bad45cbae354eb4a538b71 100644 (file)
@@ -352,8 +352,11 @@ void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
 ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
 ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
 
+ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
+ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail);
+void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
+void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
 
-ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
 ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
 
 
@@ -374,6 +377,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
 void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
 
@@ -453,6 +457,9 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
 ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
 ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
 ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
+ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
+ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
+ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
 ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
 ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
 
@@ -482,7 +489,6 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
 
 
 void handle_sng_log(uint8_t level, char *fmt,...);
-void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
 void sngisdn_delayed_setup(void* p_sngisdn_info);
 void sngisdn_delayed_release(void* p_sngisdn_info);
 void sngisdn_delayed_connect(void* p_sngisdn_info);
index fb65d20cab39466b11b778ccf145ce0ef74b1d48..003227016de3260e5f997b3687b1662fb3cc60da 100644 (file)
@@ -33,7 +33,8 @@
  */
 
 #include "ftmod_sangoma_isdn.h"
-ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
+static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
+static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
 
 /* Remote side transmit a SETUP */
 void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -232,6 +233,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                                ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
                        }
                        break;
+               case FTDM_CHANNEL_STATE_RESET:
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+                       break;
                default:
                        ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
                        break;
@@ -285,6 +289,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
                        case FTDM_CHANNEL_STATE_HANGUP:
                                /* Race condition, we just hung up the call - ignore this message */
                                break;
+                       case FTDM_CHANNEL_STATE_RESET:
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+                               break;                          
                        default:
                                ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 
@@ -301,6 +308,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
                        case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
                                /* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
                                break;
+                       case FTDM_CHANNEL_STATE_RESET:
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+                               break;
                        default:
                                ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
                                
@@ -375,6 +385,9 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
                                        /* We are already in progress media, we can't go to any higher state except up */
                                        /* Do nothing */
                                        break;
+                               case FTDM_CHANNEL_STATE_RESET:
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+                                       break;
                                default:
                                        ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 
@@ -414,6 +427,9 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
                                        case FTDM_CHANNEL_STATE_UP:
                                                ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
                                                break;
+                                       case FTDM_CHANNEL_STATE_RESET:
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+                                               break;
                                        default:
                                                ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
                                                break;
@@ -531,7 +547,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
                case FTDM_CHANNEL_STATE_DIALING:
                        /* Remote side rejected our SETUP message on outbound call */
                        if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
-                               sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+                               sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
                        }
                        /* fall-through */
                case FTDM_CHANNEL_STATE_PROCEED:
@@ -581,6 +597,9 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
                                /* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
                        }
                        break;
+               case FTDM_CHANNEL_STATE_RESET:
+                       /* User initiated reset, so they do not know about this call */
+                       break;
                default:
                        ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
                                                        ftdm_channel_state2str(ftdmchan->state));
@@ -1050,18 +1069,91 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
        return;
 }
 
+static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
+{
+       switch (ftdmchan->state) {
+               case FTDM_CHANNEL_STATE_RESET:
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                       break;
+               case FTDM_CHANNEL_STATE_DOWN:
+                       /* Do nothing */
+                       break;
+               default:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
+                                                 ftdm_channel_state2str(ftdmchan->state));
+       }
+
+       return;
+}
+
+
 void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
 {
        int16_t suId = sngisdn_event->suId;
        int16_t dChan = sngisdn_event->dChan;
        uint8_t ces = sngisdn_event->ces;
        uint8_t evntType = sngisdn_event->evntType;
+       uint8_t chan_no = 0;
+       Rst *rstEvnt = &sngisdn_event->event.rstEvnt;
+       
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
+       if (!signal_data) {
+               ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
+               return;
+       }
+       
+       if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
+               ftdm_log(FTDM_LOG_CRIT, "Receved RESTART, but Restart Indicator IE not present\n");
+               return;
+       }
+               
+       switch(rstEvnt->rstInd.rstClass.val) {
+               case IN_CL_INDCHAN: /* Indicated b-channel */
+                       if (rstEvnt->chanId.eh.pres) {
+                               if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
+                                       if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
+                                               chan_no = rstEvnt->chanId.infoChanSel.val;
+                                       }
+                               } else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
+                                       if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
+                                               chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
+                                       }
+                               }
+                       }
+                       if (!chan_no) {
+                               ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
+                               return;
+                       }
+                       break;
+               case IN_CL_SNGINT: /* Single interface */
+               case IN_CL_ALLINT: /* All interfaces */
+                       /* In case restart class indicates all interfaces, we will duplicate
+                       this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
+                       so treat it as a single interface anyway */
+                       break;
+               default:
+                       ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
+                       return;
+       }
 
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       if (chan_no) { /* For a single channel */
+               if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
+                       ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
+               } else {
+                       ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
+                       sngisdn_process_restart_confirm(ftdmchan);
+               }
+       } else { /* for all channels */
+               ftdm_iterator_t *chaniter = NULL;
+               ftdm_iterator_t *curr = NULL;
+
+               chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
+               for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+                       sngisdn_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
+               }
+               ftdm_iterator_free(chaniter);
+       }
 
-       /* Function does not require any info from ssHlEvnt struct for now */
-       /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
-       
        ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
        ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
        return;
@@ -1090,7 +1182,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
        return;
 }
 
-ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
+static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
        
index 297c59c3b7457b623925265329e8e366f836dab2..bb04f887abf591fb8fe246ca72bf6858010cc75c 100644 (file)
@@ -51,72 +51,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
        ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
 
        memset(&conEvnt, 0, sizeof(conEvnt));
-
-       conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
-       conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
-       conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
-
-       conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
-       conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
-       conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
-       conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
-       conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
-       conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
-
-       conEvnt.chanId.eh.pres = PRSNT_NODEF;
-       conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
-       conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
-       conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
-       conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
-       conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
-       conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-       conEvnt.chanId.intIdent.pres = NOTPRSNT;
-
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
-               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-               /* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
-               Check with Trillium if this ever causes calls to fail in the field */
-
-               /* BRI only params */
-               conEvnt.chanId.intType.pres = PRSNT_NODEF;
-               conEvnt.chanId.intType.val = IN_IT_BASIC;
-               conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
-       } else {
-               /* PRI only params */
-               conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
-               conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
-               
-               if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
-                       conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
-                       
-                       /* We are bridging a call from T1 */
-                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
-                       
-               } else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
-                       
-                       /* We are bridging a call from E1 */
-                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
-               }
-               
-               conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
-               conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
-
-               conEvnt.chanId.intType.pres = PRSNT_NODEF;
-               conEvnt.chanId.intType.val = IN_IT_OTHER;
-               conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
-               conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
-               conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
-               conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
-               conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
-               conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
-               conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
-               conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
-               conEvnt.chanId.chanNmbSlotMap.len = 1;
-               conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
-       }
-
        if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
                conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
        }
@@ -126,6 +60,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
        }
        ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
 
+       set_chan_id_ie(ftdmchan, &conEvnt.chanId);
+       set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]);
        set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
        set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
        set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
@@ -161,38 +97,7 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
        
        memset(&cnStEvnt, 0, sizeof(cnStEvnt)); 
 
-       cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
-       cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
-       cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
 
-       
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
-               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
-               /* BRI only params */
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_BASIC;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
-       } else {
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_OTHER;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
-               cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
-               cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
-               cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
-               cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanNmbSlotMap.len = 1;
-               cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
-       }
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
@@ -221,38 +126,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
        
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
        
-       cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
-       cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
-       cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-       
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
-               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
-               /* BRI only params */
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_BASIC;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
-       } else {
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_OTHER;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
-               cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
-               cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
-               cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
-               cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanNmbSlotMap.len = 1;
-               cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
-       }
-
+       set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
@@ -277,41 +151,11 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_i
        }
        
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-       
-       cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
-       cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
-       cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-       
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
-               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
-               /* BRI only params */
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_BASIC;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
-       } else {
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_OTHER;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
-               cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
-               cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
-               cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
-               cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanNmbSlotMap.len = 1;
-               cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
-       }
 
+       set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+       
        ftdm_call_clear_data(&ftdmchan->caller_data);
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -397,39 +241,8 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
        }
        
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-
-       cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
-       cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
-       cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
-       cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
        
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
-               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
-               /* BRI only params */
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_BASIC;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
-       } else {
-               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.intType.val = IN_IT_OTHER;
-               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
-               cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
-               cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
-               cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
-               cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
-               cnStEvnt.chanId.chanNmbSlotMap.len = 1;
-               cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
-       }
-
+       set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
        ftdm_call_clear_data(&ftdmchan->caller_data);
@@ -563,6 +376,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
        }
        return;
 }
+
 void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
 {
        RelEvnt relEvnt;
@@ -618,6 +432,24 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
        return;
 }
 
+void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
+{
+       Rst rstEvnt;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+       memset(&rstEvnt, 0, sizeof(rstEvnt));
+
+       set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
+       set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
+
+       if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
+       }
+       return;
+}
+
 
 /* We received an incoming frame on the d-channel, send data to the stack */
 void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
index af180d1f7c1a054436523440a21d9abf133da202..4b04fb065e51127197a31d120e6075a3948f98ca 100644 (file)
@@ -630,8 +630,9 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
 
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
+
        ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
-       
+
        /* Enqueue the event to each span within the dChan */
        for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
                signal_data = g_sngisdn_data.dchans[dChan].spans[i];
@@ -725,14 +726,25 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
                        ftdmspan = signal_data->ftdm_span;
                        
                        if (status->t.usta.alarm.event == LCM_EVENT_UP) {
+                               uint32_t chan_no = status->t.usta.evntParm[2];
                                ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
                                                 status->t.usta.suId,
                                                                DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
                                                                DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
                                                                DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-                               
-                               sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
-                               sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
+
+                               if (chan_no) {
+                                       ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
+                                       if (ftdmchan) {
+                                               sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
+                                               sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
+                                       } else {
+                                               ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
+                                       }
+                               } else {
+                                       sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
+                                       sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
+                               }
                        } else {
                                ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
                                                                status->t.usta.suId,
@@ -741,7 +753,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
                                                                DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
                                
                                sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
-                               sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
+                               sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
                        }
                }
                break;
index 76d11d6d345eaebcc42cc06cee0887d592cfa240..28768a1f09d66d9eaece7301b36327d1f4b56e16 100644 (file)
@@ -136,19 +136,25 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn
        return FTDM_SUCCESS;
 }
 
-ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
+ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail)
 {
-       if (span->trunk_type == FTDM_TRUNK_BRI ||
-               span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+       if (FTDM_SPAN_IS_BRI(chan->span)) {
+               ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
+               chan->availability_rate = avail;
+       }
+       return FTDM_SUCCESS;
+}
 
+ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
+{
+       if (FTDM_SPAN_IS_BRI(span)) {
                ftdm_iterator_t *chaniter = NULL;
                ftdm_iterator_t *curr = NULL;
 
-
                chaniter = ftdm_span_get_chan_iterator(span, NULL);
                for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
                        ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
-                       ((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
+                       sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail);
                }
                ftdm_iterator_free(chaniter);
        }
@@ -676,7 +682,6 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
        return FTDM_SUCCESS;
 }
 
-
 ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
 {
        ftdm_status_t status;
@@ -789,6 +794,93 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
        return FTDM_SUCCESS;
 }
 
+ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
+{
+       if (!ftdmchan) {
+               return FTDM_SUCCESS;
+       }
+       chanId->eh.pres = PRSNT_NODEF;
+       chanId->prefExc.pres = PRSNT_NODEF;
+       chanId->prefExc.val = IN_PE_EXCLSVE;
+       chanId->dChanInd.pres = PRSNT_NODEF;
+       chanId->dChanInd.val = IN_DSI_NOTDCHAN;
+       chanId->intIdentPres.pres = PRSNT_NODEF;
+       chanId->intIdentPres.val = IN_IIP_IMPLICIT;
+
+       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
+                  ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+
+               /* BRI only params */
+               chanId->intType.pres = PRSNT_NODEF;
+               chanId->intType.val = IN_IT_BASIC;
+               chanId->infoChanSel.pres = PRSNT_NODEF;
+               chanId->infoChanSel.val = ftdmchan->physical_chan_id;
+       } else {
+               chanId->intType.pres = PRSNT_NODEF;
+               chanId->intType.val = IN_IT_OTHER;
+               chanId->infoChanSel.pres = PRSNT_NODEF;
+               chanId->infoChanSel.val = IN_ICS_B1CHAN;
+               chanId->chanMapType.pres = PRSNT_NODEF;
+               chanId->chanMapType.val = IN_CMT_BCHAN;
+               chanId->nmbMap.pres = PRSNT_NODEF;
+               chanId->nmbMap.val = IN_NM_CHNNMB;
+               chanId->codeStand1.pres = PRSNT_NODEF;
+               chanId->codeStand1.val = IN_CSTD_CCITT;
+               chanId->chanNmbSlotMap.pres = PRSNT_NODEF;
+               chanId->chanNmbSlotMap.len = 1;
+               chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
+       }
+       return FTDM_SUCCESS;
+}
+
+ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
+{
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+       
+       bearCap->eh.pres = PRSNT_NODEF;
+       bearCap->infoTranCap.pres = PRSNT_NODEF;
+       bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
+
+       bearCap->codeStand0.pres = PRSNT_NODEF;
+       bearCap->codeStand0.val = IN_CSTD_CCITT;
+       bearCap->infoTranRate0.pres = PRSNT_NODEF;
+       bearCap->infoTranRate0.val = IN_ITR_64KBIT;
+       bearCap->tranMode.pres = PRSNT_NODEF;
+       bearCap->tranMode.val = IN_TM_CIRCUIT;
+
+       if (!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
+               /* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
+               Check with Trillium if this ever causes calls to fail in the field */
+
+               /* PRI only params */
+               bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
+               bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
+
+               if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
+                       bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
+
+                       /* We are bridging a call from T1 */
+                       bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
+
+               } else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
+
+                       /* We are bridging a call from E1 */
+                       bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
+               }
+
+               bearCap->lyr1Ident.pres = PRSNT_NODEF;
+               bearCap->lyr1Ident.val = IN_L1_IDENT;
+       }
+       return FTDM_SUCCESS;
+}
+
+ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
+{
+       rstInd->eh.pres = PRSNT_NODEF;
+       rstInd->rstClass.pres = PRSNT_NODEF;
+       rstInd->rstClass.val = IN_CL_INDCHAN;
+       return FTDM_SUCCESS;
+}
 
 void sngisdn_t3_timeout(void* p_sngisdn_info)
 {
index cc32d66bdd507463a842a14d0b049d280c24bd85..a3cddadb819f6386eb24fa965dfa4d89349052ca 100644 (file)
@@ -702,6 +702,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char
 /*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */
 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t);
 
+/*! \brief Reset the channel */
+#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
+
+/*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro) 
+ *  \note if there was a call on this channel, call will be cleared without any notifications to the user
+ */
+FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
+
 /*! \brief Put a call on hold (if supported by the signaling stack) */
 #define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
 
@@ -741,6 +749,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signa
 /*! \brief Get span signaling status (ie: whether protocol layer is up or down) */
 FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *status);
 
+
 /*! 
  * \brief Set user private data in the channel
  *
index deabafd537c8ea5ee2a72475843103fc816ffd36..9222da3a4294a1fff4edef83f94f69cffca5bf99 100644 (file)
@@ -599,7 +599,6 @@ FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan);
 FT_DECLARE(int) ftdm_load_module(const char *name);
 FT_DECLARE(int) ftdm_load_module_assume(const char *name);
 FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
-FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan);
 
 FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void);
 FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
index 313044abc4538f983cddcd010e22307021dc1441..f03c060e5a970f65b99c72fd261c28ea258ddd07 100644 (file)
@@ -228,12 +228,13 @@ typedef enum {
        FTDM_CHANNEL_STATE_HANGUP,
        FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
        FTDM_CHANNEL_STATE_IN_LOOP,
+       FTDM_CHANNEL_STATE_RESET,
        FTDM_CHANNEL_STATE_INVALID
 } ftdm_channel_state_t;
 #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
                "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
                "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
-               "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
+               "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID"
 FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
 
 typedef enum {