]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sending termination in-service/out-of-service service change for termination whenever...
authorroot <root@nsg-media-test.sangoma.local>
Mon, 30 Jul 2012 16:32:46 +0000 (12:32 -0400)
committerroot <root@nsg-media-test.sangoma.local>
Mon, 30 Jul 2012 16:32:46 +0000 (12:32 -0400)
libs/freetdm/mod_freetdm/tdm.c
src/mod/endpoints/mod_media_gateway/media_gateway.c
src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c
src/mod/endpoints/mod_media_gateway/media_gateway_stack.h
src/mod/endpoints/mod_media_gateway/media_gateway_utils.c
src/mod/endpoints/mod_media_gateway/media_gateway_xml.c
src/mod/endpoints/mod_media_gateway/mod_media_gateway.c
src/mod/endpoints/mod_media_gateway/mod_media_gateway.h

index 790f7c17d34fd8a03d7a94e8c95c2e321c5facb0..0cc02a85c748c4a560a2043fe84065fe1b15cdca 100644 (file)
@@ -84,7 +84,7 @@ switch_io_routines_t ctdm_io_routines = {
        .receive_message = channel_receive_message
 };
 
-static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_name)
+static void ctdm_report_alarms(ftdm_channel_t *channel)
 {
        switch_event_t *event = NULL;
        ftdm_alarm_flag_t alarmflag = 0;
@@ -109,8 +109,6 @@ static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_n
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
        }
 
-       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "mg-profile-name", mg_profile_name);
-
        if (alarmflag & FTDM_ALARM_RED) {
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
        }
@@ -149,7 +147,6 @@ static void ctdm_event_handler(switch_event_t *event)
                                const char *chan_number = NULL;
                                uint32_t chan_id = 0;
                                const char *cond = switch_event_get_header(event, "condition");
-                               const char *mg_profile_name = switch_event_get_header(event, "mg-profile-name");
                                
                                if (zstr(cond)) {
                                        return;
@@ -187,7 +184,7 @@ static void ctdm_event_handler(switch_event_t *event)
                                                return;
                                        }
 
-                                       ctdm_report_alarms(channel, mg_profile_name);
+                                       ctdm_report_alarms(channel);
                                }
                        }
                        break;
index 7e13fbaebe01c7952ccced4ba27703aafe5566b8..8beeedc3caf79d41c1ac6cb61d2d5bad97b83e9f 100644 (file)
@@ -22,6 +22,8 @@ megaco_profile_t *megaco_profile_locate(const char *name)
        return profile;
 }
 
+
+
 mg_peer_profile_t *megaco_peer_profile_locate(const char *name)
 {
        mg_peer_profile_t *profile = switch_core_hash_find_rdlock(megaco_globals.peer_profile_hash, name, megaco_globals.peer_profile_rwlock);
@@ -171,7 +173,6 @@ switch_status_t megaco_prepare_tdm_termination(mg_termination_t *term)
     return SWITCH_STATUS_SUCCESS;
 }
 
-/*  @Kapil Call this function once H.248 link is up  */
 switch_status_t megaco_check_tdm_termination(mg_termination_t *term)
 {
        switch_event_t *event = NULL;
@@ -186,7 +187,6 @@ switch_status_t megaco_check_tdm_termination(mg_termination_t *term)
        switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s",  term->u.tdm.span_name);
        switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", term->u.tdm.channel);
        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "mg-tdm-check");
-       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "mg-profile-name", term->profile->name);
 
        switch_event_fire(&event);
        return SWITCH_STATUS_SUCCESS;
@@ -241,7 +241,34 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
     return term;
 }
 
-mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, char *span_name, char *chan_number)
+mg_termination_t *megaco_term_locate_by_span_chan_id(const char *span_name, const char *chan_number)
+{
+       void                    *val = NULL;
+       switch_hash_index_t     *hi = NULL;
+       mg_termination_t        *term = NULL;
+       megaco_profile_t        *profile = NULL;
+       const void              *var;
+
+       switch_assert(span_name);
+       switch_assert(chan_number);
+
+       /* span + chan will be unique across all the mg_profiles  *
+        * loop through all profiles and then all terminations to *
+        * get the mg termination associated with input span+chan */
+
+       switch_thread_rwlock_rdlock(megaco_globals.profile_rwlock);
+       for (hi = switch_hash_first(NULL, megaco_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+               switch_hash_this(hi, &var, NULL, &val);
+               profile = (megaco_profile_t *) val;
+
+               if(NULL != (term = megaco_find_termination_by_span_chan(profile, span_name, chan_number))) break;
+       }
+       switch_thread_rwlock_unlock(megaco_globals.profile_rwlock);
+
+       return term;
+}
+
+mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, const char *span_name, const char *chan_number)
 {
        void                *val = NULL;
        switch_hash_index_t *hi = NULL;
@@ -262,7 +289,8 @@ mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile
 
                if ((!strcasecmp(span_name, term->u.tdm.span_name))&& (atoi(chan_number) == term->u.tdm.channel)) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, 
-                                       "Got term[%s] associated with span[%s], channel[%s]\n",term->name, span_name, chan_number);
+                                       "Got term[%s] associated with span[%s], channel[%s] in MG profile[%s]\n",
+                                        term->name, span_name, chan_number, profile->name);
                        found = 0x01;
                        break;
                }
@@ -271,7 +299,8 @@ mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile
        if(!found){
                term = NULL;
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, 
-                               " Not able to find termination associated with span[%s], channel[%s]\n", span_name, chan_number); 
+                               " MG profile[%s] does not have termination associated with span[%s], channel[%s]\n", 
+                                profile->name, span_name, chan_number); 
        }
 
        return term;
index ca2209b08758a1451286bcfc27c8bfcea50356af..f392612cbbea7e47ad75126fd50ae76973958f2b 100644 (file)
@@ -2288,18 +2288,15 @@ U32 get_txn_id(){
        return outgoing_txn_id;
 }
 /*****************************************************************************************************************************/
-switch_status_t mg_send_term_service_change(char* mg_profile_name,char *span_name, char *chan_number, mg_term_states_e term_state)
+switch_status_t mg_send_term_service_change(char *span_name, char *chan_number, mg_term_states_e term_state)
 {
        mg_termination_t* term = NULL;
        switch_status_t  ret = SWITCH_STATUS_SUCCESS;
-       megaco_profile_t *profile = NULL;
 
        switch_assert(span_name);
        switch_assert(chan_number);
 
-       profile = megaco_profile_locate(mg_profile_name);
-
-       term =  megaco_find_termination_by_span_chan(profile, span_name, chan_number);
+       term =  megaco_term_locate_by_span_chan_id(span_name, chan_number);
 
        if(!term || !term->profile){
                return SWITCH_STATUS_FALSE;
@@ -2309,11 +2306,17 @@ switch_status_t mg_send_term_service_change(char* mg_profile_name,char *span_nam
        {
                case MG_TERM_SERVICE_STATE_IN_SERVICE:
                        {
+                               /* set INS flag...clear oos flag */
+                               switch_clear_flag(term, MG_OUT_OF_SERVICE);
+                               switch_set_flag(term, MG_IN_SERVICE);
                                ret = mg_send_ins_service_change(term->profile, term->name, 0x00 );
                                break;
                        }
                case MG_TERM_SERVICE_STATE_OUT_OF_SERVICE:
                        {
+                               /* set OOS flag...clear ins flag */
+                               switch_clear_flag(term, MG_IN_SERVICE);
+                               switch_set_flag(term, MG_OUT_OF_SERVICE);
                                ret = mg_send_oos_service_change(term->profile, term->name, 0x00 );
                                break;
                        }
index 3e2ec81bdbc61ec3160d3b12d3c47eadb3ae1fcb..994b1a573afd8490126b792230782c099a4144ce 100644 (file)
@@ -164,8 +164,7 @@ void mg_util_set_err_string ( MgStr  *errTxt, char* str);
 
 switch_status_t mg_build_sdp(MgMgcoMediaDesc* out, MgMgcoMediaDesc* inc, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp     *memCp);
 switch_status_t mg_add_local_descriptor(MgMgcoMediaDesc* media, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp  *memCp);
-switch_status_t mg_send_term_service_change(char* mg_profile_name, char *span_name, char *chan_number, mg_term_states_e term_state); 
-mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile , char *span_name, char *chan_number);
+switch_status_t mg_send_term_service_change(char *span_name, char *chan_number, mg_term_states_e term_state); 
 
 
 switch_status_t sng_mgco_cfg(megaco_profile_t* profile);
@@ -190,7 +189,8 @@ void mg_util_set_txn_string(MgStr  *errTxt, U32 *txnId);
 switch_status_t mg_build_mgco_err_request(MgMgcoInd  **errcmd,U32  trans_id, MgMgcoContextId   *ctxt_id, U32  err, MgStr  *errTxt);
 switch_status_t mg_send_audit_rsp(SuId suId, MgMgcoCommand *req);
 switch_status_t handle_mg_audit_cmd(SuId suId, MgMgcoCommand *auditReq);
-switch_status_t mg_stack_termination_is_in_service(char* term_str, int len);
+switch_status_t mg_stack_termination_is_in_service(megaco_profile_t* mg_profile, char* term_str, int len);
+void mg_create_tdm_term(megaco_profile_t *profile, const char *tech, const char *channel_prefix, const char *prefix, int j);
 void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand       *cmd);
 switch_status_t mgco_init_ins_service_change(SuId suId);
 
index f7e9dde5446e4102b05dc02c6b67a2c9c708de9c..c565da7e6bf788f2ee10a0894f9f06280b39f7a9 100644 (file)
@@ -80,10 +80,16 @@ switch_status_t mg_stack_free_mem(void* msg)
 
 /*****************************************************************************************************************************/
 
-/* TODO - Matt - to see if term is in service or not */
-switch_status_t mg_stack_termination_is_in_service(char* term_str,int len)
+/* To see if term is in service or not */
+switch_status_t mg_stack_termination_is_in_service(megaco_profile_t* mg_profile, char* term_str,int len)
 {
-        return SWITCH_STATUS_SUCCESS;
+       mg_termination_t* term = NULL;
+       term = megaco_find_termination(mg_profile, term_str);
+       if(switch_test_flag(term, MG_IN_SERVICE)){
+               return SWITCH_STATUS_SUCCESS;
+       } else {
+               return SWITCH_STATUS_FALSE;
+       }
 }
 
 /*****************************************************************************************************************************/
index 6c87afa780c4c9c8c00ec928c86f12c7bd0e35ce..9890f152c311d356258cd9592592813dd2be1afb 100644 (file)
@@ -65,62 +65,74 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
 
 
                profile->idx = ++mg_sap_id;
-        
-        
-        if ((mg_phys_terms = switch_xml_child(mg_interface, "physical_terminations"))) {
-            for (mg_term = switch_xml_child(mg_phys_terms, "map"); mg_term; mg_term = mg_term->next) {
-                switch_memory_pool_t *pool;
-                mg_termination_t *term;
-                // <map  termination-id-prefix="Term1/" termination-id-base="1" tech="freetdm" channel-prefix="wp2" channel-map"1-15,17-31"/>
-                const char *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
-                //const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base");
-                const char *tech =  switch_xml_attr(mg_term, "tech");
-                const char *channel_prefix = switch_xml_attr(mg_term, "channel-prefix");
-                const char *channel_map = switch_xml_attr(mg_term, "channel-map");
-                
-                
-                if (!zstr(channel_map)) {
-                    /* Split channel-map */
-                    char *channel_map_dup = strdup(channel_map);
-                    char *chanmap[24];
-                    int chanmap_count, i;
-                    chanmap_count = switch_split(channel_map_dup, ',', chanmap);
-                    for (i = 0; i < chanmap_count; i++) {
-                        char *p = strchr(chanmap[i], '-');
-                        if (p) {
-                            int startchan, endchan, j;
-                            *p++ = '\0';
-                            startchan = atoi(chanmap[i]);
-                            endchan = atoi(p);
-                            
-                            for (j = startchan; j < endchan; j++) {
-                                switch_core_new_memory_pool(&pool);
-                                term = switch_core_alloc(profile->pool, sizeof *term);
-                                term->pool = pool;
-                                term->type = MG_TERM_TDM;
-                                term->profile = profile;
-                                term->mg_ctxt = NULL;
-                                                               term->tech = switch_core_strdup(pool, tech);
-                                                               term->active_events = NULL;
-                                term->name = switch_core_sprintf(pool, "%s%d", prefix, j);
-                                term->u.tdm.channel = j;
-                                term->u.tdm.span_name = switch_core_strdup(pool, channel_prefix);
-                                
-                                switch_core_hash_insert_wrlock(profile->terminations, term->name, term, profile->terminations_rwlock);
-                                term->next = profile->physical_terminations;
-                                profile->physical_terminations = term;
-                                
-                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mapped termination [%s] to freetdm span: %s chan: %d\n", term->name, term->u.tdm.span_name, term->u.tdm.channel);
-
-                                                               megaco_prepare_tdm_termination(term);
-                            }
-                        }
-                    }
-                    
-                    free(channel_map_dup);
-                }
-            }
-        }
+
+
+               if ((mg_phys_terms = switch_xml_child(mg_interface, "physical_terminations"))) {
+                       for (mg_term = switch_xml_child(mg_phys_terms, "map"); mg_term; mg_term = mg_term->next) {
+                               // <map  termination-id-prefix="Term1/" termination-id-base="1" tech="freetdm" channel-prefix="wp2" channel-map"1-15,17-31"/>
+                               const char *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
+                               //const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base");
+                               const char *tech =  switch_xml_attr(mg_term, "tech");
+                               const char *channel_prefix = switch_xml_attr(mg_term, "channel-prefix");
+                               const char *channel_map = switch_xml_attr(mg_term, "channel-map");
+                               char *p = NULL;
+
+                               if (!zstr(channel_map)) {
+                                       /* Split channel-map */
+                                       char *channel_map_dup = strdup(channel_map);
+                                       char *chanmap[24] = {0};
+                                       int chanmap_count = 0;
+                                       int i = 0;
+                                       int startchan, endchan, j;
+
+                                       /* we can have following combinations *
+                                        * i)   only one channel i.e. channel-map="1"
+                                        * ii)  only one chanel range i.e channel-map="1-15"
+                                        * iii) full channel range i.e. channel-map="1-15,17-31"
+                                        */
+
+
+                                       chanmap_count = switch_split(channel_map_dup, ',', chanmap);
+
+                                       if(1 == chanmap_count) {
+                                               p = strchr(channel_map_dup, '-');
+                                               if(NULL != p){
+                                                       /* case (ii) */ 
+                                                       i = switch_split(channel_map_dup, '-', chanmap);
+                                                       if(i && chanmap[0] && chanmap[1]) {
+                                                               startchan = atoi(chanmap[0]);
+                                                               endchan   = atoi(chanmap[1]);
+                                                               for (j = startchan; j < endchan; j++) {
+                                                                       mg_create_tdm_term(profile, tech, channel_prefix, prefix, j);
+                                                               }
+                                                       }
+                                               }else{
+                                                       /* case (i) */ 
+                                                       p = channel_map_dup;    
+                                                       startchan = endchan = atoi(p);
+                                                       mg_create_tdm_term(profile, tech, channel_prefix, prefix, startchan);
+                                               }
+                                       }else
+                                       {
+                                               /* case (iii) */
+                                               for (i = 0; i < chanmap_count; i++) {
+                                                       p = strchr(chanmap[i], '-');
+                                                       if (p) {
+                                                               *p++ = '\0';
+                                                               startchan = atoi(chanmap[i]);
+                                                               endchan = atoi(p);
+
+                                                               for (j = startchan; j < endchan; j++) {
+                                                                       mg_create_tdm_term(profile, tech, channel_prefix, prefix, j);
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       free(channel_map_dup);
+                               }
+                       }
+               }
 
 
                /* we should break from here , profile name should be unique */
@@ -129,7 +141,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
 
        if (!mg_interface) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error profile %s not found\n", profile->name);
-                       return SWITCH_STATUS_FALSE;
+               return SWITCH_STATUS_FALSE;
        }
 
        /* go through the peer configuration and get the mg profile associated peers only */
@@ -169,7 +181,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
                        }
                }
        }
-    
+
        /* configure the MEGACO stack */
        status = sng_mgco_cfg(profile);
 
@@ -184,6 +196,34 @@ done:
        return status;
 }
 
+/****************************************************************************************************************************/
+void mg_create_tdm_term(megaco_profile_t *profile, const char *tech, const char *channel_prefix, const char *prefix, int chan_num)
+{
+       mg_termination_t *term;
+       switch_memory_pool_t *pool;
+
+       switch_core_new_memory_pool(&pool);
+       term = switch_core_alloc(profile->pool, sizeof *term);
+       term->pool = pool;
+       term->type = MG_TERM_TDM;
+       term->profile = profile;
+       term->mg_ctxt = NULL;
+       term->tech = switch_core_strdup(pool, tech);
+       term->active_events = NULL;
+       term->name = switch_core_sprintf(pool, "%s%d", prefix, chan_num);
+       term->u.tdm.channel = chan_num;
+       term->u.tdm.span_name = switch_core_strdup(pool, channel_prefix);
+
+       switch_core_hash_insert_wrlock(profile->terminations, term->name, term, profile->terminations_rwlock);
+       term->next = profile->physical_terminations;
+       profile->physical_terminations = term;
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, 
+                       "Mapped termination [%s] to freetdm span: %s chan: %d\n", 
+                       term->name, term->u.tdm.span_name, term->u.tdm.channel);
+       megaco_prepare_tdm_termination(term);
+
+}
 /****************************************************************************************************************************/
 switch_status_t mg_config_cleanup(megaco_profile_t* profile)
 {
index 97158fdcea249b4fb2ff372711f8cf344123811e..22c07275a83f04a2cfdde03ec90204f064965c3c 100644 (file)
@@ -64,38 +64,23 @@ static void mg_event_handler(switch_event_t *event)
                                const char *span_name = NULL;
                                const char *chan_number = NULL;
                                const char *cond = NULL;
-                               const char *mg_profile_name = NULL;
-
 
                                cond = switch_event_get_header(event, "condition");
                                if (zstr(cond)) {
-                                       printf("Condition NULL, returning \n");
-                                       return;
-                               }
-
-                               mg_profile_name = switch_event_get_header(event, "mg-profile-name");
-                               if (zstr(mg_profile_name)) {
-                                       printf("mg_profile_name NULL, returning \n");
                                        return;
                                }
 
-                               span_name = switch_event_get_header(event, "span-name");
+                               span_name   = switch_event_get_header(event, "span-name");
                                chan_number = switch_event_get_header(event, "chan-number");
                                
                                if (!strcmp(cond, "ftdm-alarm-trap")) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
-                                        "ftdm-alarm-trap for span_name[%s] chan_number[%s] associated with  MG profile[%s]\n",
-                                       span_name,chan_number, mg_profile_name);
-                                       /* @KAPIL: TDM is in alarm, notify MGC */
-                                       mg_send_term_service_change(
-                                               (char*)mg_profile_name, (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_OUT_OF_SERVICE);
+                                        "ftdm-alarm-trap for span_name[%s] chan_number[%s]\n", span_name,chan_number);
+                                       mg_send_term_service_change((char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_OUT_OF_SERVICE);
                                } else if (!strcmp(cond, "ftdm-alarm-clear")) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
-                                        "ftdm-alarm-clear for span_name[%s] chan_number[%s] associated with  MG profile[%s] \n",
-                                        span_name,chan_number, mg_profile_name);
-                                       /* TDM alarm cleared, notify MGC */
-                                       mg_send_term_service_change(
-                                               (char*)mg_profile_name, (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_IN_SERVICE);
+                                        "ftdm-alarm-clear for span_name[%s] chan_number[%s] \n", span_name,chan_number);
+                                       mg_send_term_service_change( (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_IN_SERVICE);
                                }
                        }
                break;
@@ -561,8 +546,9 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
        }
 
        /*If term type is other then check if that term is configured with us..for term type CHOOSE/ALL , no need to check */
-       if (MGT_TERMID_OTHER == termId->type.val){
-               if(SWITCH_STATUS_FALSE == mg_stack_termination_is_in_service((char*)termId->name.lcl.val, termId->name.lcl.len)){
+       if ((CH_CMD_TYPE_IND == cmd->cmdType.val) &&
+                       (MGT_TERMID_OTHER == termId->type.val)){
+               if(SWITCH_STATUS_FALSE == mg_stack_termination_is_in_service(mg_profile, (char*)termId->name.lcl.val, termId->name.lcl.len)){
                        mg_util_set_term_string(&errTxt, termId);
                        err_code = MGT_MGCO_RSP_CODE_UNKNOWN_TERM_ID;
                        goto error;
index 86acb28861e5d2e1a2a4648dc8a9150ab5f3d6c7..06cbffca1102530bd2b7fb83c40ce9db08ccba14 100644 (file)
@@ -89,8 +89,10 @@ typedef struct mg_context_s mg_context_t;
 typedef struct mg_termination_s mg_termination_t;
 
 enum {
-    MGT_ALLOCATED = (1 << 0),
-    MGT_ACTIVE = (1 << 1),
+    MGT_ALLOCATED      = (1 << 0),
+    MGT_ACTIVE         = (1 << 1),
+    MG_IN_SERVICE      = (1 << 2),
+    MG_OUT_OF_SERVICE  = (1 << 3),
     
 } mg_termination_flags;
 
@@ -222,8 +224,10 @@ static inline megaco_codec_t megaco_codec_parse(const char *codec) {
 
 
 megaco_profile_t *megaco_profile_locate(const char *name);
+mg_termination_t *megaco_term_locate_by_span_chan_id(const char *span_name, const char *chan_number);
 mg_peer_profile_t *megaco_peer_profile_locate(const char *name);
 void megaco_profile_release(megaco_profile_t *profile);
+mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, const char *span_name, const char *chan_number);
 
 switch_status_t megaco_profile_start(const char *profilename);
 switch_status_t megaco_profile_destroy(megaco_profile_t **profile);