diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index 790f7c17d3..0cc02a85c7 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -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; diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index 7e13fbaebe..8beeedc3ca 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -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; diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c b/src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c index ca2209b087..f392612cbb 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c @@ -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; } diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h b/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h index 3e2ec81bdb..994b1a573a 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h @@ -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); diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c index f7e9dde544..c565da7e6b 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c @@ -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; + } } /*****************************************************************************************************************************/ diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c index 6c87afa780..9890f152c3 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c @@ -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; - // - 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) { + // + 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) { diff --git a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c index 97158fdcea..22c07275a8 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c @@ -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; diff --git a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h index 86acb28861..06cbffca11 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -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);