]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: ISDN Changes to better match SIP-to-TDM states
authorDavid Yat Sin <dyatsin@sangoma.com>
Thu, 25 Nov 2010 01:04:43 +0000 (20:04 -0500)
committerDavid Yat Sin <dyatsin@sangoma.com>
Thu, 25 Nov 2010 01:04:43 +0000 (20:04 -0500)
12 files changed:
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.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_cfg.c
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_support.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_types.h
libs/freetdm/src/testanalog.c

index 8d961123cb60c166ea2bd95ac21057249efa9441..27dc8d8c9286139d6eb8374f825cf104977c10c7 100755 (executable)
@@ -425,8 +425,11 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+       assert(tech_pvt->ftdmchan != NULL);
 
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+       
+       ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -852,7 +855,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
        switch (msg->message_id) {
        case SWITCH_MESSAGE_INDICATE_RINGING:
                {
-                       ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS);
+                       ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
                }
                break;
        case SWITCH_MESSAGE_INDICATE_PROGRESS:
@@ -935,7 +938,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
                        !switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
                        !switch_channel_test_flag(channel, CF_RING_READY)
                        ) {
-                               ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RING);
+                               ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
                                switch_channel_mark_ring_ready(channel);
                }
                break;
@@ -2133,7 +2136,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
                                        spanid, chanid, (uuid) ? uuid : "N/A");
                        }
                }
-               break;
+               break;  
        case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
                {       
                        ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
@@ -2141,6 +2144,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
                                        spanid, chanid, ftdm_signaling_status2str(sigstatus));
                }
                break;
+       case FTDM_SIGEVENT_PROCEED:
+       case FTDM_SIGEVENT_MSG:
+               /* FS does not have handlers for these messages, so ignore them for now */
+               break;
        default:
                {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
index 64233a97acf7f49a36dc1e3053f92674277770d9..ede3ff8fc8cd08445af35c8e10ae6ca605b58a6b 100644 (file)
@@ -2033,7 +2033,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
                goto done;
        }
 
-
        if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
                ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
        }
@@ -2202,14 +2201,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
        switch (indication) {
        /* FIXME: ring and busy cannot be used with all signaling stacks 
         * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */
-       case FTDM_CHANNEL_INDICATE_RING:
-               ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1);
+       case FTDM_CHANNEL_INDICATE_RINGING:
+               ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1);
                break;
-
        case FTDM_CHANNEL_INDICATE_BUSY:
                ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
                break;
-
+       case FTDM_CHANNEL_INDICATE_PROCEED:
+               if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) {
+                       if (ftdmchan->state == FTDM_CHANNEL_STATE_RING) {
+                               ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1);
+                       }
+               }
+               break;
        case FTDM_CHANNEL_INDICATE_PROGRESS:
                if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
                        ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@@ -2217,7 +2221,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
                        ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
                }
                break;
-
        case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA:
                if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
                        ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@@ -2236,7 +2239,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
                        ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
                }
                break;
-
        default:
                ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication);
                status = FTDM_FAIL;
index fc9bea6ef04d7cac4273947273e8f0ea65ed2fff..99d256655a4c5883df6491be8f61ded41ae62a36 100644 (file)
@@ -438,7 +438,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                {
                                        if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
                                                ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL);
-                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
                                        }
                                }
                                break;
@@ -492,8 +492,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                                }
                                                
                                                if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && 
-                                                       (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE 
-                                                        || ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
+                                                       (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE 
+                                                        || ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) {
                                                        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
                                                } else {
                                                        ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@@ -535,7 +535,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                        }
                                }
                        case FTDM_CHANNEL_STATE_UP:
-                       case FTDM_CHANNEL_STATE_IDLE:
+                       case FTDM_CHANNEL_STATE_RING:
                                {
                                        ftdm_sleep(interval);
                                        continue;
@@ -599,7 +599,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                        ftdm_channel_use(ftdmchan);
                                }
                                break;
-                       case FTDM_CHANNEL_STATE_IDLE:
+                       case FTDM_CHANNEL_STATE_RING:
                                {
                                        ftdm_channel_use(ftdmchan);
                                        sig.event_id = FTDM_SIGEVENT_START;
@@ -669,7 +669,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                        continue;
                                }
                                break;
-                       case FTDM_CHANNEL_STATE_RING:
+                       case FTDM_CHANNEL_STATE_RINGING:
                                {
                                        ftdm_buffer_zero(dt_buffer);
                                        teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@@ -732,7 +732,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
 
                if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
                        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
                        last_digit = 0;
                        collecting = 0;
                }
@@ -890,7 +890,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
                                if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) {
                                        ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
                                } else {
-                                       ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_IDLE);
+                                       ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING);
                                }
                                event->channel->ring_count = 1;
                                ftdm_mutex_unlock(event->channel->mutex);
index 77ad917bf15089d0f7259166955752253c5ace3d..6f5f83859045117d56bac8cdcd27277f19c5bb56 100644 (file)
@@ -115,7 +115,19 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_INBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_RING, FTDM_END},
-               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
+               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
+       },
+       {
+               ZSD_INBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
+               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END}
+       },
+       {
+               ZSD_INBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
+               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
        },
        {
                ZSD_INBOUND,
@@ -189,9 +201,17 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_OUTBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
-               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
-                FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+                FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
+                FTDM_CHANNEL_STATE_DOWN, FTDM_END}
        },
+       {
+               ZSD_OUTBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
+               {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+                FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
+               },
        {
                ZSD_OUTBOUND,
                ZSM_UNACCEPTABLE,
@@ -604,13 +624,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                break;
        case FTDM_CHANNEL_STATE_GET_CALLERID:
                {
-                       sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
-                       sngisdn_snd_proceed(ftdmchan);
+                       if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
+                               sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
+                               sngisdn_snd_proceed(ftdmchan);
+                       }
                        /* Wait in this state until we get FACILITY msg */                      
                }
                break;
        case FTDM_CHANNEL_STATE_RING: /* incoming call request */
-               {
+               {                       
                        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits);
 
                        /* we have enough information to inform FTDM of the call*/
@@ -635,6 +657,25 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                        }
                }
                break;
+       case FTDM_CHANNEL_STATE_PROCEED:
+               {
+                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                               /*OUTBOUND...so we were told by the line of this so noifiy the user*/
+                               sigev.event_id = FTDM_SIGEVENT_PROCEED;
+                               ftdm_span_send_signal(ftdmchan->span, &sigev);
+                       } else {
+                               if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
+                                       sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
+                                       sngisdn_snd_proceed(ftdmchan);
+                               }
+                       }
+               }
+               break;
+       case FTDM_CHANNEL_STATE_RINGING:
+               {
+                       sngisdn_snd_alert(ftdmchan, SNGISDN_PROGIND_NETE_ISDN);
+               }
+               break;
        case FTDM_CHANNEL_STATE_PROGRESS:
                {
                        /*check if the channel is inbound or outbound*/
@@ -642,9 +683,12 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                                /*OUTBOUND...so we were told by the line of this so noifiy the user*/
                                sigev.event_id = FTDM_SIGEVENT_PROGRESS;
                                ftdm_span_send_signal(ftdmchan->span, &sigev);
-                       } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
-                               sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
-                               sngisdn_snd_proceed(ftdmchan);
+                       } else {
+                               /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
+                               if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
+                                       /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
+                                       sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_NETE_ISDN);
+                               }
                        }
                }
                break;
@@ -654,7 +698,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                                sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
                                ftdm_span_send_signal(ftdmchan->span, &sigev);
                        } else {
-                               sngisdn_snd_progress(ftdmchan);
+                               /* Send a progress message, indicating: In-band information/pattern available */
+                               sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_IB_AVAIL);
                        }
                }
                break; 
@@ -992,6 +1037,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
        span->state_map = &sangoma_isdn_state_map;
        ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
        ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
+       ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
 
        if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
                span->trunk_type == FTDM_TRUNK_BRI) {
index 81a98cf0d399d8a5c2d394d1b2ad511d2fbbc1da..25ffef85e5ed5c62d4ed4217d6c548474b3331d5 100644 (file)
@@ -75,7 +75,8 @@ typedef enum {
        FLAG_DELAYED_REL        = (1 << 7),
        FLAG_SENT_PROCEED       = (1 << 8),
        FLAG_SEND_DISC                  = (1 << 9),
-       FLAG_ACTIVATING                 = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */
+       /* Used for BRI only, flag is set after we request line CONNECTED */
+       FLAG_ACTIVATING                 = (1 << 10), 
 } sngisdn_flag_t;
 
 
@@ -135,6 +136,21 @@ typedef enum {
        SNGISDN_EVENT_RST_IND,
 } ftdm_sngisdn_event_id_t;
 
+typedef enum {
+       /* Call is not end-to-end ISDN */
+       SNGISDN_PROGIND_NETE_ISDN = 1,
+       /* Destination address is non-ISDN */
+       SNGISDN_PROGIND_DEST_NISDN,
+       /* Origination address is non-ISDN */
+       SNGISDN_PROGIND_ORIG_NISDN,
+       /* Call has returned to the ISDN */
+       SNGISDN_PROGIND_RET_ISDN,
+       /* Interworking as occured and has resulted in a telecommunication service change */
+       SNGISDN_PROGIND_SERV_CHANGE,
+       /* In-band information or an appropriate pattern is now available */
+       SNGISDN_PROGIND_IB_AVAIL, 
+} ftdm_sngisdn_progind_t;
+
 /* Only timers that can be cancelled are listed here */
 #define SNGISDN_NUM_TIMERS 1
 /* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */
@@ -181,6 +197,7 @@ typedef struct sngisdn_span_data {
        uint8_t                 trace_flags;            /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
        uint8_t                 overlap_dial;
        uint8_t                 setup_arb;
+       uint8_t                 facility_ie_decode;
        uint8_t                 facility;
        int8_t                  facility_timeout;
        uint8_t                 num_local_numbers;
@@ -288,13 +305,14 @@ void stack_pst_init(Pst *pst);
 void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_alert(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
+void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
 void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
 void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
 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_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
@@ -362,6 +380,8 @@ ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgP
 ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
 ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
 ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display);
+ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len);
+
 ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
 ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
 ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
index 3b264ae02fffe70be7f949e9ecdca6b37d948bb1..657aa5e2069c68ccd13bcbad08bfba4da992b618 100644 (file)
@@ -190,6 +190,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
        signal_data->min_digits = 8;
        signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
        signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
+       signal_data->facility_ie_decode = SNGISDN_OPT_TRUE;
        signal_data->timer_t3 = 8;
 
        signal_data->link_id = span->span_id;
@@ -289,6 +290,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                        if (signal_data->facility_timeout < 0) {
                                signal_data->facility_timeout = 0;
                        }
+               } else if (!strcasecmp(var, "facility-ie-decode")) {
+                       if (!strcasecmp(val, "yes")) {
+                               signal_data->facility_ie_decode = SNGISDN_OPT_TRUE;
+                       } else if (!strcasecmp(val, "no")) {
+                               signal_data->facility_ie_decode = SNGISDN_OPT_FALSE;
+                       } else {
+                               ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
+                       }
                } else {
                        ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
                }
index 3fe0422a4e7c0910b31a28c28631f2193ce4971c..209284a8b6272a7d09d837f5bd680ef11d42e3ef 100644 (file)
@@ -144,31 +144,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                                                snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
                                        }
                                }
-                               
-                               if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
-                                       /* Verify whether the Caller Name will come in a subsequent FACILITY message */
-                                       uint16_t ret_val;
-                                       char retrieved_str[255];
-                                       
-                                       ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
-                                       /*
-                                               return values for "sng_isdn_retrieve_facility_information_following":
-                                               If there will be no information following, or fails to decode IE, returns -1
-                                               If there will be no information following, but current FACILITY IE contains a caller name, returns 0
-                                               If there will be information following, returns 1
-                                       */
-
-                                       if (ret_val == 1) {
-                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
-                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
-                                               /* Launch timer in case we never get a FACILITY msg */
-                                               if (signal_data->facility_timeout) {
-                                                       ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, 
-                                                                       sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
+
+                               if (conEvnt->facilityStr.eh.pres) {
+                                       if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+                                               cpy_facility_ie_from_stack(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len);
+                                       } else if (signal_data->facility == SNGISDN_OPT_TRUE) {
+                                               /* Verify whether the Caller Name will come in a subsequent FACILITY message */
+                                               uint16_t ret_val;
+                                               char retrieved_str[255];
+                                               
+                                               ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
+                                               /*
+                                                       return values for "sng_isdn_retrieve_facility_information_following":
+                                                       If there will be no information following, or fails to decode IE, returns -1
+                                                       If there will be no information following, but current FACILITY IE contains a caller name, returns 0
+                                                       If there will be information following, returns 1
+                                               */
+
+                                               if (ret_val == 1) {
+                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
+                                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
+                                                       /* Launch timer in case we never get a FACILITY msg */
+                                                       if (signal_data->facility_timeout) {
+                                                               ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, 
+                                                                               sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
+                                                       }
+                                                       break;
+                                               } else if (ret_val == 0) {
+                                                       strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
                                                }
-                                               break;
-                                       } else if (ret_val == 0) {
-                                               strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
                                        }
                                }
                        }
@@ -269,6 +273,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
 
        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
                switch(ftdmchan->state) {
+                       case FTDM_CHANNEL_STATE_PROCEED:
                        case FTDM_CHANNEL_STATE_PROGRESS:
                        case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                        case FTDM_CHANNEL_STATE_DIALING:
@@ -367,8 +372,10 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
                case MI_CALLPROC:
                
                        switch(ftdmchan->state) {
-                               case FTDM_CHANNEL_STATE_DIALING:                                        
-                                       if (evntType == MI_PROGRESS ||
+                               case FTDM_CHANNEL_STATE_DIALING:
+                                       if (evntType == MI_CALLPROC) {
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
+                                       } else if (evntType == MI_PROGRESS ||
                                                (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
                                                ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
                                        } else {
@@ -417,6 +424,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
                                        }
                                        break;
                                        case FTDM_CHANNEL_STATE_RING:
+                                       case FTDM_CHANNEL_STATE_PROCEED:
                                        case FTDM_CHANNEL_STATE_PROGRESS:
                                        case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                                        case FTDM_CHANNEL_STATE_UP:
@@ -446,6 +454,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
        uint32_t spInstId = sngisdn_event->spInstId;
        sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
        ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
        
        DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt;
 
@@ -454,12 +463,20 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 
        ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
-       switch (ftdmchan->state) {
+       switch (ftdmchan->state) {              
                case FTDM_CHANNEL_STATE_RING:
                case FTDM_CHANNEL_STATE_DIALING:
+               case FTDM_CHANNEL_STATE_PROCEED:
                case FTDM_CHANNEL_STATE_PROGRESS:
                case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-               case FTDM_CHANNEL_STATE_UP:
+               case FTDM_CHANNEL_STATE_UP:                     
+                       if (discEvnt->facilityStr.eh.pres) {
+                               if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+                                       cpy_facility_ie_from_stack(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len);
+                               } else {
+                                       /* Call libsng_isdn facility decode function and copy variables here */
+                               }
+                       }
                        if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
                                ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
                        } else {
@@ -503,6 +520,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
        uint32_t spInstId = sngisdn_event->spInstId;
        sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;        
        ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
        
        RelEvnt *relEvnt = &sngisdn_event->event.relEvnt;
 
@@ -538,6 +556,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
                                sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
                        }
                        /* fall-through */
+               case FTDM_CHANNEL_STATE_PROCEED:
                case FTDM_CHANNEL_STATE_PROGRESS:
                case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                case FTDM_CHANNEL_STATE_UP:
@@ -547,6 +566,15 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
                        not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
                        if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
                                                                        ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
+
+                               if (relEvnt->facilityStr.eh.pres) {
+                                       if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+                                               cpy_facility_ie_from_stack(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len);
+                                       } else {
+                                               /* Call libsng_isdn facility decode function and copy variables here */
+                                       }
+                               }
+                               
                                if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
                                        ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
                                        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
@@ -725,15 +753,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
        switch (ftdmchan->state) {
                case FTDM_CHANNEL_STATE_GET_CALLERID:
                        /* Update the caller ID Name */
+
                        if (facEvnt->facElmt.facStr.pres) {
                                char retrieved_str[255];
-                               
+
                                /* return values for "sng_isdn_retrieve_facility_information_following":
                                If there will be no information following, or fails to decode IE, returns -1
                                If there will be no information following, but current FACILITY IE contains a caller name, returns 0
                                If there will be information following, returns 1
                                */
-                               
+
                                if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
                                        strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
                                } else {
@@ -751,6 +780,25 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
                        /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */
                        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n");
                        break;
+               case FTDM_CHANNEL_STATE_UP:
+                       {
+                               ftdm_sigmsg_t sigev;
+                               if (facEvnt->facElmt.facStr.pres) {
+                                       if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+                                               cpy_facility_ie_from_stack(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
+                                       } else {
+                                               /* Call libsng_isdn facility decode function and copy variables here */
+                                       }
+                               }
+                               memset(&sigev, 0, sizeof(sigev));
+                               sigev.chan_id = ftdmchan->chan_id;
+                               sigev.span_id = ftdmchan->span_id;
+                               sigev.channel = ftdmchan;
+                               
+                               sigev.event_id = FTDM_SIGEVENT_MSG;
+                               ftdm_span_send_signal(ftdmchan->span, &sigev);
+                       }
+                       break;
                default:
                        /* We do not support other FACILITY types for now, so do nothing */
                        break;
@@ -865,6 +913,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
                                                        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
                                                        ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
                                                        break;
+                                               case FTDM_CHANNEL_STATE_PROCEED:
                                                case FTDM_CHANNEL_STATE_PROGRESS:
                                                case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                                                        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
@@ -882,6 +931,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
                                        break;
                        case 3:
                                switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_PROCEED:
                                        case FTDM_CHANNEL_STATE_PROGRESS:
                                                /* T310 timer has expired */
                                                ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
index 2853335efc2af7e9eddaa073a0c10834f64d2ca1..385d1eba9d05f8ef42fa2a9bfe222b7ec0d87881 100644 (file)
@@ -34,6 +34,9 @@
 
 #include "ftmod_sangoma_isdn.h"
 
+static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind);
+static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
+
 void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
 {
        ConEvnt conEvnt;
@@ -138,6 +141,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
        cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data);
        cpy_calling_name_from_user(&conEvnt, ftdmchan);
 
+       sngisdn_set_facilityStr(ftdmchan, &conEvnt.facilityStr);
+
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (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);
 
        if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -323,14 +328,14 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
        return;
 }
 
-void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
 {
        CnStEvnt cnStEvnt;
        
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
      if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
                sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -351,7 +356,8 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
        cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
        cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
        cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
-       cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL;
+
+       sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind);
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (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);
        if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -360,14 +366,14 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
        return;
 }
 
-void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
 {
        CnStEvnt cnStEvnt;
        
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
      if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
                sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -382,7 +388,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
        cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
        cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
        cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
-       cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
+       sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind);
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (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);
 
@@ -456,6 +462,27 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
        return;
 }
 
+void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
+{
+       FacEvnt facEvnt;
+       
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+       if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               return;
+       }
+               
+       memset(&facEvnt, 0, sizeof(facEvnt));
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (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);
+
+       if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused FACILITY request\n");
+       }
+       return;
+}
 
 void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
 {
@@ -510,7 +537,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
      if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
 
                sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
@@ -531,6 +558,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
        discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
        discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
 
+       sngisdn_set_facilityStr(ftdmchan, &discEvnt.facilityStr);
+
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
        if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
@@ -575,6 +604,8 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
                spInstId = sngisdn_info->spInstId;
        }
 
+       sngisdn_set_facilityStr(ftdmchan, &relEvnt.facilityStr);
+       
        ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
 
        if (glare) {
@@ -589,6 +620,46 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
        return;
 }
 
+static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind)
+{
+       switch(prog_ind) {
+               case SNGISDN_PROGIND_NETE_ISDN:
+                       progInd->progDesc.val = IN_PD_NOTETEISDN;
+                       break;
+               case SNGISDN_PROGIND_DEST_NISDN:
+                       progInd->progDesc.val = IN_PD_DSTNOTISDN;
+                       break;
+               case SNGISDN_PROGIND_ORIG_NISDN:
+                       progInd->progDesc.val = IN_PD_ORGNOTISDN;
+                       break;
+               case SNGISDN_PROGIND_RET_ISDN:
+                       progInd->progDesc.val = IN_PD_CALLRET;
+                       break;
+               case SNGISDN_PROGIND_SERV_CHANGE:
+                       /* Trillium defines do not match ITU-T Q931 Progress descriptions,
+                       indicate a delayed response for now */
+                       progInd->progDesc.val = IN_PD_DELRESP;
+                       break;
+               case SNGISDN_PROGIND_IB_AVAIL:
+                       progInd->progDesc.val = IN_PD_IBAVAIL;
+                       break;
+       }
+       return;
+}
+
+static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
+{
+       const char *facility_str = NULL;        
+       
+       facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val");
+       if (facility_str) {
+               facilityStr->eh.pres = PRSNT_NODEF;
+               facilityStr->facilityStr.len = strlen(facility_str);
+               memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len);
+       }
+       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 056bf66ef2258abf4ac2c8fffe278a888e3f0f76..379c481c0e02ac6ec37fe5d47493d0bb137ad6d6 100644 (file)
@@ -229,6 +229,24 @@ ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *dis
        return FTDM_SUCCESS;
 }
 
+ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len)
+{
+       if (data_len > sizeof(caller_data->raw_data)-2) {
+               ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
+               return FTDM_FAIL;
+       }
+       
+       memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
+       /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
+       caller_data->raw_data[0] = 0x1C;
+       caller_data->raw_data[1] = data_len;
+       
+       memcpy(&caller_data->raw_data[2], data, data_len);
+       caller_data->raw_data_len = data_len+2;
+       
+       return FTDM_SUCCESS;
+}
+
 ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm)
 {
        uint8_t len = strlen(ftdm->cid_num.digits);
index 508c6996d58da219d2f1af37f0105f32a98342c0..87da5d1dd0da88894efe6b622d23f0f2bbdc38c8 100644 (file)
@@ -289,7 +289,8 @@ typedef enum {
        FTDM_SIGEVENT_STOP, /*!< Hangup */
        FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */
        FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
-       FTDM_SIGEVENT_FLASH, /*< Flash event  (typically on-hook/off-hook for analog devices) */
+       FTDM_SIGEVENT_FLASH, /*!< Flash event  (typically on-hook/off-hook for analog devices) */
+       FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
        FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
        FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */
        FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */
@@ -299,9 +300,10 @@ typedef enum {
        FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
        FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
        FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
+       FTDM_SIGEVENT_MSG, /* !< We received an in-call msg */
        FTDM_SIGEVENT_INVALID
 } ftdm_signal_event_t;
-#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROGRESS", \
+#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \
                "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
                "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID"
 
@@ -581,7 +583,7 @@ typedef enum {
  * This is used during incoming calls when you want to request the signaling stack
  * to notify about indications occurring locally */
 typedef enum {
-       FTDM_CHANNEL_INDICATE_RING,
+       FTDM_CHANNEL_INDICATE_RINGING,
        FTDM_CHANNEL_INDICATE_PROCEED,
        FTDM_CHANNEL_INDICATE_PROGRESS,
        FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA,
index d9cefc3c6fafa5e11e6607e64e116933c3c79e2f..f265cb1a3dea83f6bbc6ca52431fbf5d038506f8 100644 (file)
@@ -181,6 +181,8 @@ typedef enum {
         * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal
         * for later delivery */
        FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
+       /* If this flag is set, channel will be moved to proceed state when calls goes to routing */
+       FTDM_SPAN_USE_PROCEED_STATE = (1 << 11),
 } ftdm_span_flag_t;
 
 /*! \brief Channel supported features */
@@ -204,6 +206,7 @@ typedef enum {
        FTDM_CHANNEL_STATE_DIALTONE,
        FTDM_CHANNEL_STATE_COLLECT,
        FTDM_CHANNEL_STATE_RING,
+       FTDM_CHANNEL_STATE_RINGING,
        FTDM_CHANNEL_STATE_BUSY,
        FTDM_CHANNEL_STATE_ATTN,
        FTDM_CHANNEL_STATE_GENRING,
@@ -211,6 +214,7 @@ typedef enum {
        FTDM_CHANNEL_STATE_GET_CALLERID,
        FTDM_CHANNEL_STATE_CALLWAITING,
        FTDM_CHANNEL_STATE_RESTART,
+       FTDM_CHANNEL_STATE_PROCEED,
        FTDM_CHANNEL_STATE_PROGRESS,
        FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
        FTDM_CHANNEL_STATE_UP,
@@ -223,8 +227,8 @@ typedef enum {
        FTDM_CHANNEL_STATE_INVALID
 } ftdm_channel_state_t;
 #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
-               "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
-               "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
+               "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
+               "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
                "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
 FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
 
index 84d09f73c908468cd02f2d12d0b4147540e03da2..326bb5aec5ead459ad9c4b7059176db774dfab96 100644 (file)
@@ -50,7 +50,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_signal)
 
        switch(sigmsg->event_id) {
        case FTDM_SIGEVENT_START:
-               ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RING);
+               ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING);
                ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n");
                ftdm_thread_create_detached(test_call, sigmsg->channel);
                break;