From 0a000613e203e3ef1053e1ab563be16622802873 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Wed, 25 Jul 2012 15:13:04 -0400 Subject: [PATCH 01/12] fix warnings --- src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c | 2 +- src/mod/endpoints/mod_media_gateway/media_gateway_xml.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 6a6ef5c4d9..4307a8e91b 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 @@ -143,7 +143,7 @@ switch_status_t mg_is_ito_pkg_req(megaco_profile_t* mg_profile, MgMgcoCommand *c (reqEvtPar->u.other.val.u.eq.type.val == MGT_VALTYPE_UINT32)) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO," Received Inactivity timer value [%d]\n", - reqEvtPar->u.other.val.u.eq.u.decInt.val); + (int)reqEvtPar->u.other.val.u.eq.u.decInt.val); mg_profile->inact_tmr = reqEvtPar->u.other.val.u.eq.u.decInt.val/MG_INACTIVITY_TMR_RESOLUTION; 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 b52d4da0f1..0d6390a173 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c @@ -123,7 +123,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload) 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_prefix = switch_xml_attr(mg_term, "channel-prefix"); const char *channel_map = switch_xml_attr(mg_term, "channel-map"); const char *szspan_id = switch_xml_attr(mg_term, "span-id"); const int span_id = !zstr(szspan_id) ? atoi(szspan_id) : 0; From 258900818a5fd7f3eb9fed91bf8ebd2659d5471a Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 26 Jul 2012 16:43:18 -0400 Subject: [PATCH 02/12] freetdm: Added thread to service events when there is no signalling module on a span --- libs/freetdm/src/ftdm_io.c | 48 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index b8b9cff527..758827c9ed 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5618,16 +5618,61 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const return status; } +static void *ftdm_span_service_events(ftdm_thread_t *me, void *obj) +{ + int i; + unsigned waitms; + ftdm_event_t *event; + ftdm_status_t status = FTDM_SUCCESS; + ftdm_span_t *span = (ftdm_span_t*) obj; + short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); + + memset(poll_events, 0, sizeof(short) * span->chan_count); + + for(i = 1; i <= span->chan_count; i++) { + poll_events[i] |= FTDM_EVENTS; + } + + while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { + waitms = 1000; + status = ftdm_span_poll_event(span, waitms, poll_events); + switch (status) { + case FTDM_FAIL: + ftdm_log(FTDM_LOG_CRIT, "%s:Failed to poll span for events\n", span->name); + break; + case FTDM_TIMEOUT: + break; + case FTDM_SUCCESS: + /* Check if there are any channels that have events available */ + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS); + break; + default: + ftdm_log(FTDM_LOG_CRIT, "%s:Unhandled IO event\n", span->name); + } + } + return NULL; +} + FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span) { ftdm_status_t status = FTDM_FAIL; - ftdm_mutex_lock(span->mutex); if (ftdm_test_flag(span, FTDM_SPAN_STARTED)) { status = FTDM_EINVAL; goto done; } + if (span->signal_type == FTDM_SIGTYPE_NONE) { + /* If there is no signalling component, start a thread to poll events */ + status = ftdm_thread_create_detached(ftdm_span_service_events, span); + if (status != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT,"Failed to start span event monitor thread!\n"); + goto done; + } + + status = ftdm_report_initial_channels_alarms(span); + goto done; + } if (!span->start) { status = FTDM_ENOSYS; @@ -5643,7 +5688,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span) if (status == FTDM_SUCCESS) { ftdm_set_flag_locked(span, FTDM_SPAN_STARTED); } - done: ftdm_mutex_unlock(span->mutex); return status; From 3519ebc981eff76d7ab506f407558e93992e59b1 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 27 Jul 2012 10:59:37 -0400 Subject: [PATCH 03/12] add megaco_prepare_termination --- .../mod_media_gateway/media_gateway.c | 42 +++++++++++++++++++ .../mod_media_gateway/mod_media_gateway.h | 1 + 2 files changed, 43 insertions(+) diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index e47055236a..ee5abe7d2f 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -155,6 +155,48 @@ done: return SWITCH_STATUS_SUCCESS; } + +/* + * Originate a channel so the target technology gets to run initialization code + */ +switch_status_t megaco_prepare_termination(mg_termination_t *term) +{ + switch_event_t *var_event = NULL; + switch_core_session_t *session = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char dialstring[100]; + switch_call_cause_t cause; + switch_channel_t *channel; + switch_event_create(&var_event, SWITCH_EVENT_CLONE); + + if (term->type == MG_TERM_RTP) { + } else if (term->type == MG_TERM_TDM) { + switch_snprintf(dialstring, sizeof dialstring, "tdm/%s", term->name); + + switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ftdm_start_only", "true"); + switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, kSPAN_NAME, term->u.tdm.span_name); + switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, kCHAN_ID, "%d", term->u.tdm.channel); + } + + /* Set common variables on the channel */ + switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true"); + if (switch_ivr_originate(NULL, &session, &cause, dialstring, 0, NULL, NULL, NULL, NULL, var_event, 0, NULL) != SWITCH_STATUS_SUCCESS) { + status = SWITCH_STATUS_FALSE; + goto done; + } + channel = switch_core_session_get_channel(session); + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + +done: + if (session) { + switch_core_session_rwunlock(session); + } + switch_event_destroy(&var_event); + + return SWITCH_STATUS_SUCCESS; +} + + mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix) { mg_termination_type_t termtype; 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 af53052fbb..4ffeaaa4e0 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -235,6 +235,7 @@ void megaco_release_context(mg_context_t *ctx); switch_status_t megaco_context_sub_termination(mg_context_t *ctx, mg_termination_t *term); switch_status_t megaco_context_sub_all_termination(mg_context_t *ctx); switch_status_t megaco_activate_termination(mg_termination_t *term); +switch_status_t megaco_prepare_termination(mg_termination_t *term); mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix); mg_termination_t *megaco_find_termination(megaco_profile_t *profile, const char *name); From a668b9ddf65c8f58f6d4cc734e6aa7095d4bb05f Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 27 Jul 2012 11:06:23 -0400 Subject: [PATCH 04/12] automatically fail new tdm channel if ftdm_start_only is true --- libs/freetdm/mod_freetdm/tdm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index efdf4dce3e..b2d37d47ed 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -112,7 +112,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ftdm_codec_t codec; uint32_t interval; ftdm_status_t fstatus; - + const char *ftdm_start_only = switch_event_get_header(var_event, "ftdm_start_only"); ctdm_private_t *tech_pvt = NULL; if (zstr(szchanid) || zstr(span_name)) { @@ -129,6 +129,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi goto fail; } + if ((fstatus = ftdm_span_start(span)) != FTDM_SUCCESS && fstatus != FTDM_EINVAL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start span %s.\n", span_name); + goto fail; + } + + if (!zstr(ftdm_start_only) && switch_true(ftdm_start_only)) { + goto fail; + } + if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); @@ -137,11 +146,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi channel = switch_core_session_get_channel(*new_session); - if ((fstatus = ftdm_span_start(span)) != FTDM_SUCCESS && fstatus != FTDM_EINVAL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start span %s.\n", span_name); - goto fail; - } - if (ftdm_channel_open(span_id, chan_id, &chan) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); goto fail; From 3350403d04e8dfcdb9e2548f4c9b0e4890f6a178 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 11:22:29 -0400 Subject: [PATCH 05/12] commit from testbox --- libs/freetdm/mod_freetdm/tdm.c | 6 + .../media_gateway_cmd_handler.c | 26 +- .../mod_media_gateway/media_gateway_stack.h | 6 + .../mod_media_gateway/media_gateway_utils.c | 500 ++++++++++++++++++ .../mod_media_gateway/media_gateway_xml.c | 6 +- .../mod_media_gateway/mod_media_gateway.h | 1 + 6 files changed, 535 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index c66fdbebd1..efdf4dce3e 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -111,6 +111,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi const char *dname; ftdm_codec_t codec; uint32_t interval; + ftdm_status_t fstatus; ctdm_private_t *tech_pvt = NULL; @@ -136,6 +137,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi channel = switch_core_session_get_channel(*new_session); + if ((fstatus = ftdm_span_start(span)) != FTDM_SUCCESS && fstatus != FTDM_EINVAL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start span %s.\n", span_name); + goto fail; + } + if (ftdm_channel_open(span_id, chan_id, &chan) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); goto fail; 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 185f3fb5a9..ca0d286ba2 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 @@ -500,7 +500,7 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i mg_context_t* mg_ctxt; int mediaId; MgMgcoLocalDesc *local = NULL; - CmSdpInfoSet *psdp = NULL; + /*CmSdpInfoSet *psdp = NULL;*/ /* TODO - Kapil dummy line , will need to add with proper code */ @@ -707,6 +707,11 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i /* only for RTP */ if(is_rtp){ + mg_build_sdp(&desc->u.media, inc_med_desc, mg_profile, term, &rsp.u.mgCmdRsp[0]->memCp); + } +#if 0 + if(is_rtp){ + mg_build_sdp(desc, inc_med_desc, mg_profile, term, &rsp.u.mgCmdRsp[0]->memCp); /* build local descriptors */ /*MgMgcoStreamDesc *stream;*/ char* ipAddress[4];// = "192.168.1.1"; @@ -762,11 +767,14 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i psdp = &(local->sdp); - if (mgUtlGrowList((void ***)&psdp->info, sizeof(CmSdpInfo), - &psdp->numComp, &rsp.u.mgCmdRsp[0]->memCp) != ROK) - { - switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); - return SWITCH_STATUS_FALSE; + if((NOTPRSNT == local->sdp.numComp.pres) || (0 == local->sdp.numComp.val)){ + + if (mgUtlGrowList((void ***)&psdp->info, sizeof(CmSdpInfo), + &psdp->numComp, &rsp.u.mgCmdRsp[0]->memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } } psdp->info[psdp->numComp.val-1]->pres.pres = PRSNT_NODEF; @@ -875,7 +883,7 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts[0]->type), CM_SDP_SPEC); - MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts[0]->val), 4); + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts[0]->val), 8); /* Fill attribute if reqd */ { @@ -893,6 +901,7 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i free(dup); } +#endif /* We will always send one command at a time..*/ @@ -1055,10 +1064,11 @@ switch_status_t handle_mg_modify_cmd(megaco_profile_t* mg_profile, MgMgcoCommand ret = mg_prc_descriptors(mg_profile, inc_cmd, term); /* SDP updated to termination */ - megaco_activate_termination(term); } + /* TODO - copy inc descriptor...not sure if we need to do this.. */ + /********************************************************************/ /* Matt - to provide the response SDP structure which needs to fill in Modify command response */ 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 e5c16df9c0..f84bfbd5e4 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h @@ -155,6 +155,9 @@ int mg_enable_logging(void); int mg_disable_logging(void); 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 sng_mgco_cfg(megaco_profile_t* profile); switch_status_t sng_mgco_init(sng_mg_event_interface_t* event); @@ -193,6 +196,9 @@ switch_status_t mg_fill_svc_change(MgMgcoSvcChgPar *srvPar, uint8_t method, c void mg_fill_null_context(MgMgcoContextId* ctxt); switch_status_t mg_send_service_change(SuId suId, const char* term_name, uint8_t method, MgServiceChangeReason_e reason,uint8_t wild); switch_status_t mg_create_mgco_command(MgMgcoCommand *cmd, uint8_t apiType, uint8_t cmdType); +switch_status_t mg_add_lcl_media(CmSdpMediaDescSet* med, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp); +switch_status_t mg_add_supported_media_codec(CmSdpMediaDesc* media, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp); +switch_status_t mg_rem_unsupported_codecs (megaco_profile_t* mg_profile, mg_termination_t* term, CmSdpMedFmtRtpList *fmtList, CmSdpAttrSet *attrSet, CmMemListCp *memCp); switch_status_t mg_send_oos_service_change(megaco_profile_t* mg_profile, const char* term_name, int wild); switch_status_t mg_send_ins_service_change(megaco_profile_t* mg_profile, const char* term_name, int wild); 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 e5d08c1d84..39a69f3921 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c @@ -1441,3 +1441,503 @@ void mg_print_time() switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO,"Current Time = %s", ctime(&now)); } /*****************************************************************************************************************************/ +switch_status_t mg_add_local_descriptor(MgMgcoMediaDesc* media, megaco_profile_t* mg_profile, mg_termination_t* term,CmMemListCp *memCp) +{ + char* ipAddress[4]; + MgMgcoLocalDesc *local; + CmSdpInfoSet *psdp = NULL; + char * dup = NULL; + switch_status_t ret = SWITCH_STATUS_SUCCESS; + CmSdpMediaDescSet* med = NULL; + + switch_assert(media); + switch_assert(mg_profile); + switch_assert(term); + + dup = strdup((char*)term->u.rtp.local_addr); + switch_split(dup,'.',ipAddress); + + /* allocating mem for local descriptor */ + if (mgUtlGrowList((void ***)&media->parms, sizeof(MgMgcoMediaPar), &media->num, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + media->parms[media->num.val-1]->type.pres = PRSNT_NODEF; + media->parms[media->num.val-1]->type.val = MGT_MEDIAPAR_LOCAL; + + local = &media->parms[media->num.val-1]->u.local; + + local->pres.pres = PRSNT_NODEF; + + psdp = &(local->sdp); + + if (mgUtlGrowList((void ***)&psdp->info, sizeof(CmSdpInfo), &psdp->numComp, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + psdp->info[psdp->numComp.val-1]->pres.pres = PRSNT_NODEF; + + /* fill version */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->ver),1); + + /* fill orig */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.pres), 1); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.type), CM_SDP_SPEC); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.orig.pres), 1); + + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.usrName, 1, "-", + memCp); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessId, 1, "0", + memCp); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessVer, 1, "0", + memCp); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.netType.type), + CM_SDP_NET_TYPE_IN); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.addrType), + CM_SDP_ADDR_TYPE_IPV4); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.addrType), + CM_SDP_IPV4_IP_UNI); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.addrType), + CM_SDP_IPV4_IP_UNI); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[0]), + atoi(ipAddress[0])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[1]), + atoi(ipAddress[1])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[2]), + atoi(ipAddress[2])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[3]), + atoi(ipAddress[3])); + + /* fill session name */ + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->sessName, 8, "SANGOMA", memCp); + + + /* Fill the SDP Connection Info */ + /* "c=" line - ipaddress */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.netType.type),CM_SDP_NET_TYPE_IN); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.addrType), CM_SDP_ADDR_TYPE_IPV4); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.u.ip4.addrType), CM_SDP_IPV4_IP_UNI); + + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[0]), atoi(ipAddress[0])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[1]), atoi(ipAddress[1])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[2]), atoi(ipAddress[2])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[3]), atoi(ipAddress[3])); + + + /* t= line */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->sdpTime.pres),1); +#if 0 + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->sdpTime.sdpOpTimeSet.numComp),0); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->sdpTime.zoneAdjSet.numComp),0); +#endif + + med = &psdp->info[psdp->numComp.val-1]->mediaDescSet; + ret = mg_add_lcl_media(med, mg_profile, term, memCp); + + return ret; +} +/*****************************************************************************************************************************/ +switch_status_t mg_add_supported_media_codec(CmSdpMediaDesc* media, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp) +{ + const switch_codec_implementation_t *codecs[16]; + char *codec_prefs[16] = { 0 }; + char *szcodec_prefs; + int codec_count; + int i; + int fmt= 0x00; + + switch_assert(media); + switch_assert(mg_profile); + switch_assert(term); + switch_assert(memCp); + + szcodec_prefs = strdup(mg_profile->codec_prefs); + codec_count = switch_split(szcodec_prefs, ',', codec_prefs); + + /* Get the list of codecs, by preference */ + switch_loadable_module_get_codecs_sorted(codecs, switch_arraylen(codecs), codec_prefs, switch_arraylen(codec_prefs)); + for (i = 0; codecs[i] && i < codec_count; i++) { + int pt = codecs[i]->ianacode; + const char *name = codecs[i]->iananame; + + printf("Preference %d is %s/%d\n", i, name, pt); + + + if (mgUtlGrowList((void ***)&media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts, sizeof(CmSdpU8OrNil), + &media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.num, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + fmt = media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.num.val-1; + + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts[fmt]->type), CM_SDP_SPEC); + + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->u.rtp.fmts[fmt]->val), pt); + + /* add associated attributes */ + { + if (mgUtlGrowList((void ***)&media->attrSet.attr, sizeof(CmSdpAttr), &media->attrSet.numComp, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->type),CM_SDP_ATTR_RTPMAP); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.pres), 1); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.pay.type), CM_SDP_SPEC); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.pay.val), pt); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.enc.val), CM_SDP_ENC_UNKNOWN); + MG_SET_TKNSTROSXL((media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.enc.name), strlen(name), name, memCp); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.rtpmap.clk), codecs[i]->samples_per_second); + /* encoding parameter not required to fill */ + } + + } + free(szcodec_prefs); + return SWITCH_STATUS_SUCCESS; +} +/*****************************************************************************************************************************/ +switch_status_t mg_add_lcl_media(CmSdpMediaDescSet* med, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp) +{ + CmSdpMediaDesc* media; + + switch_assert(med); + switch_assert(mg_profile); + switch_assert(term); + switch_assert(memCp); + + if (mgUtlGrowList((void ***)&med->mediaDesc, sizeof(CmSdpMediaDesc), + &med->numComp, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + media = med->mediaDesc[med->numComp.val-1]; + + MG_INIT_TOKEN_VALUE(&(media->pres),1); + + /* Fill CmSdpMediaField */ + MG_INIT_TOKEN_VALUE(&(media->field.pres),1); + MG_INIT_TOKEN_VALUE(&(media->field.mediaType),CM_SDP_MEDIA_AUDIO); + + MG_INIT_TOKEN_VALUE(&(media->field.id.type),CM_SDP_VCID_PORT); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.type),CM_SDP_PORT_INT); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.pres),1); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.port.type), CM_SDP_SPEC); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.port.val), term->u.rtp.local_port); + + if (mgUtlGrowList((void ***)&media->field.par.pflst, sizeof(CmSdpMedProtoFmts), + &media->field.par.numProtFmts, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + /* CmSdpMedProtoFmts */ + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->prot.type), CM_SDP_MEDIA_PROTO_RTP); + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->prot.u.subtype.type), CM_SDP_PROTO_RTP_AVP); + MG_INIT_TOKEN_VALUE(&(media->field.par.pflst[media->field.par.numProtFmts.val-1]->protType), CM_SDP_MEDIA_PROTO_RTP); + + + /***************************************************************************************************************************************************************/ + /* Fill ptime attribute */ + { + if (mgUtlGrowList((void ***)&media->attrSet.attr, sizeof(CmSdpAttr), &media->attrSet.numComp, memCp) != ROK) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); + return SWITCH_STATUS_FALSE; + } + + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->type),CM_SDP_ATTR_PTIME); + MG_INIT_TOKEN_VALUE(&(media->attrSet.attr[media->attrSet.numComp.val-1]->u.ptime), term->u.rtp.ptime); + } + /***************************************************************************************************************************************************************/ + /* fill codec info */ + mg_add_supported_media_codec(media, mg_profile, term, memCp); + + return SWITCH_STATUS_SUCCESS; +} +/***************************************************************************************************************************************************************/ + +switch_status_t mg_rem_unsupported_codecs (megaco_profile_t* mg_profile, mg_termination_t* term, CmSdpMedFmtRtpList *fmtList, CmSdpAttrSet *attrSet, CmMemListCp *memCp) +{ + int i = 0x00; + int id = 0x00; + int j = 0x00; + int a = 0x00; + CmSdpU8OrNil *fmt = NULL; + int foundCodec = 0x00; + const switch_codec_implementation_t *codecs[16]; + char *codec_prefs[16] = { 0 }; + char *szcodec_prefs; + int codec_count; + CmSdpAttr *attr = NULL; + CmSdpAttrRtpMap *rtp = NULL; + + /* Check if code list is present */ + if (!fmtList || (NOTPRSNT == fmtList->num.pres)) + { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "codec List Not present\n"); + return SWITCH_STATUS_FALSE; + } + + szcodec_prefs = strdup(mg_profile->codec_prefs); + codec_count = switch_split(szcodec_prefs, ',', codec_prefs); + + /* Get the list of codecs, by preference */ + switch_loadable_module_get_codecs_sorted(codecs, switch_arraylen(codecs), codec_prefs, switch_arraylen(codec_prefs)); + + + /* codec type is specified one */ + + /* loop through coddec list and remove un-supported codec */ + for(i = 0; i < fmtList->num.val; i++) + { + fmt = fmtList->fmts[i]; + + if((NOTPRSNT == fmt->type.pres) || (NOTPRSNT == fmt->val.pres)) continue; + + if(CM_SDP_SPEC != fmt->type.val) continue; /* TODO - need to see for other cases like CM_SDP_NIL/CM_SDP_CHOICE etc not sure as of now */ + + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "codec[%d] number \n", fmt->val.val); + + /* see if received codec is present in our codec supported list */ + for (id = 0; codecs[id] && id < codec_count; id++) { + int pt = codecs[id]->ianacode; + //const char *name = codecs[id]->iananame; + if(pt == fmt->val.val){ + foundCodec = 0x01; + break; + } + } + + /* IF codec not found in list, remove it */ + if(!foundCodec) { + + for(j = i; j < fmtList->num.val - 1; j++) + { + fmtList->fmts[j] = fmtList->fmts[j +1]; + } + mgUtlShrinkList((Void ***)&fmtList->fmts, sizeof(CmSdpU8OrNil), &fmtList->num, memCp); + i-- ; + + /* remove associated a= , if present */ + if((NOTPRSNT != attrSet->numComp.pres) && (0 != attrSet->numComp.val)){ + for(a = 0; a < attrSet->numComp.val; a++) { + attr = attrSet->attr[a]; + + if(CM_SDP_ATTR_RTPMAP != attr->type.val) continue; /* as of now only checking RTPMAP */ + + rtp = &attr->u.rtpmap; + + if((NOTPRSNT != rtp->pres.pres) && (fmt->val.val == rtp->pay.val.val)) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "a line found against codec[%d]..Removing a line \n", fmt->val.val); + + /* mgUtlShrinkList API will delete last node from list, hence suffling list nodes */ + for(j = a; j < attrSet->numComp.val - 1; j++) + { + attrSet->attr[j] = attrSet->attr[j +1]; + } + mgUtlShrinkList((Void ***)&attrSet->attr, sizeof(CmSdpAttr), &attrSet->numComp, memCp); + } + } + } + } + } + + return SWITCH_STATUS_SUCCESS; +} + + + +/*****************************************************************************************************************************/ +switch_status_t mg_build_sdp(MgMgcoMediaDesc* out, MgMgcoMediaDesc* inc, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp) +{ + CmSdpU8OrNil *fmt = NULL; + CmSdpInfoSet *psdp = NULL; + char* ipAddress[4]; + int i = 0x00; + int j = 0x00; + int choose_codec = 0x00; + int k = 0x00; + MgMgcoLocalDesc *local = NULL; + int fresh_sdp = 0x00; + char* dup = NULL; + CmSdpMedProtoFmts *format=NULL; + + + switch_assert(out); + switch_assert(inc); + switch_assert(mg_profile); + switch_assert(term); + + dup = strdup((char*)term->u.rtp.local_addr); + switch_split(dup,'.',ipAddress); + + + if((NOTPRSNT == inc->num.pres) || (0 == inc->num.val)){ + fresh_sdp = 0x01; + } + + /* if its fresh sdp then add only local descriptor */ + if(fresh_sdp) { + mg_add_local_descriptor(out, mg_profile, term, memCp); + } else { + /* incoming has sdp, so copy that sdp and overwrite only local sdp */ + mgUtlCpyMgMgcoMediaDesc(out, inc, memCp); + + /* now see if we have local descriptor, then pick up that and modify the fields */ + + if((NOTPRSNT != out->num.pres) && (0 != out->num.val)) + { + for(i=0; inum.val; i++) { + if(MGT_MEDIAPAR_LOCAL == out->parms[i]->type.val) { + local = &out->parms[i]->u.local; + } + } + } + } + + if(!local || (NOTPRSNT == local->sdp.numComp.pres) || (0 == local->sdp.numComp.val)){ + /* local sdp is not part of media descriptor, then add local sdp*/ + mg_add_local_descriptor(out, mg_profile, term, memCp); + }else{ + /* local sdp is present.. now go over the local descriptor and modify fields */ + psdp = &(local->sdp); + + for(i=0; i< psdp->numComp.val; i++) { +/**********************************************************************************************************************************/ + /* version - let it be same, if present else use version 1 */ + if(NOTPRSNT == psdp->info[psdp->numComp.val-1]->ver.pres) { + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->ver),1); + } +/**********************************************************************************************************************************/ + /* orig (o- line) fill with our info */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.pres), 1); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.type), CM_SDP_SPEC); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.orig.pres), 1); + + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.usrName, 1, "-", + NULL); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessId, 1, "0", + NULL); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessVer, 1, "0", + NULL); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.netType.type), + CM_SDP_NET_TYPE_IN); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.addrType), + CM_SDP_ADDR_TYPE_IPV4); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.addrType), + CM_SDP_IPV4_IP_UNI); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.addrType), + CM_SDP_IPV4_IP_UNI); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[0]), + atoi(ipAddress[0])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[1]), + atoi(ipAddress[1])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[2]), + atoi(ipAddress[2])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.u.ip4.u.ip.b[3]), + atoi(ipAddress[3])); + +/**********************************************************************************************************************************/ + /* session-name , let it be like this if present, else skip it */ +/**********************************************************************************************************************************/ + /* "c=" line - ipaddress */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.netType.type),CM_SDP_NET_TYPE_IN); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.addrType), CM_SDP_ADDR_TYPE_IPV4); + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->conn.u.ip4.addrType), CM_SDP_IPV4_IP_UNI); + + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[0]), atoi(ipAddress[0])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[1]), atoi(ipAddress[1])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[2]), atoi(ipAddress[2])); + MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->conn.u.ip4.u.uniIp.b[3]), atoi(ipAddress[3])); + +/**********************************************************************************************************************************/ + /* t= line */ + MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->sdpTime.pres),1); +/**********************************************************************************************************************************/ + /* fill media descriptors */ + { + CmSdpMediaDescSet* med = &psdp->info[psdp->numComp.val-1]->mediaDescSet; + CmSdpMediaDesc* media; + + if((NOTPRSNT == med->numComp.pres) || (0 == med->numComp.val)){ + mg_add_lcl_media(med, mg_profile, term, memCp); + }else{ + for(j =0;j < med->numComp.val; j++){ + media = med->mediaDesc[j]; + /* check for choose port and fill the port */ + if(NOTPRSNT != media->field.id.type.pres){ + if(CM_SDP_VCID_CHOOSE == media->field.id.type.val){ + MG_INIT_TOKEN_VALUE(&(media->field.id.type),CM_SDP_VCID_PORT); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.type),CM_SDP_PORT_INT); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.pres),1); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.port.type), CM_SDP_SPEC); + MG_INIT_TOKEN_VALUE(&(media->field.id.u.port.u.portInt.port.val), term->u.rtp.local_port); + + } + } + + /* check for codec */ + if((NOTPRSNT == media->field.par.numProtFmts.pres) || + (0 == media->field.par.numProtFmts.val)){ + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"No codec specified in incoming local descriptor \n"); + mg_add_supported_media_codec(media, mg_profile, term, memCp ); + }else{ + /* check for media format/codec */ + for(k =0;k < media->field.par.numProtFmts.val; k++){ + format = media->field.par.pflst[k]; + if ((NOTPRSNT != format->protType.pres) && + (CM_SDP_MEDIA_PROTO_RTP == format->protType.val)) + { + if((NOTPRSNT != format->u.rtp.num.pres) + &&(0 != format->u.rtp.num.val)) + { + /* If the codec type is CHOOSE then we need to fill our list */ + for(i = 0; i < format->u.rtp.num.val; i++) + { + fmt = format->u.rtp.fmts[i]; + + if((NOTPRSNT == fmt->type.pres) || (NOTPRSNT == fmt->val.pres)) continue; + + if(CM_SDP_CHOOSE == fmt->type.val){ + choose_codec = 0x1; + } + } + if(choose_codec){ + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "CHOOSE codec is requested fill out supported codecs \n"); + + /* delete existing rtp format list..TODO find better way */ + for(i = 0; i < format->u.rtp.num.val; i++) + { + mgUtlShrinkList((Void ***)&format->u.rtp.fmts, sizeof(CmSdpU8OrNil), &format->u.rtp.num, memCp); + } + /* If the codec type is CHOOSE then we need to fill our list */ + mg_add_supported_media_codec(media, mg_profile, term, memCp); + } + else if (!choose_codec && (SWITCH_STATUS_FALSE == mg_rem_unsupported_codecs(mg_profile, term , &format->u.rtp, &media->attrSet, memCp))) + { + return SWITCH_STATUS_FALSE; + } + } + } + } + } + } + } +/**********************************************************************************************************************************/ + } + + } + + } + return SWITCH_STATUS_SUCCESS; +} + 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 e3c3b8c3de..011c36ce56 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c @@ -74,7 +74,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload) // 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 *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"); @@ -100,7 +100,8 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload) term->type = MG_TERM_TDM; term->profile = profile; term->mg_ctxt = NULL; - term->active_events = 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); @@ -260,6 +261,7 @@ static switch_xml_config_item_t *get_instructions(megaco_profile_t *profile) { SWITCH_CONFIG_ITEM("rtp-port-range", SWITCH_CONFIG_STRING, CONFIG_REQUIRED, &profile->rtp_port_range, "1-65535", &switch_config_string_strdup, "", "rtp port range"), SWITCH_CONFIG_ITEM("rtp-termination-id-prefix", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->rtp_termination_id_prefix, "", &switch_config_string_strdup, "", "rtp termination prefix"), SWITCH_CONFIG_ITEM("rtp-termination-id-len", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &profile->rtp_termination_id_len, "", &opt_termination_id_len, "", "rtp termination id"), + SWITCH_CONFIG_ITEM("codec-prefs", SWITCH_CONFIG_STRING, 0, &profile->codec_prefs, "", &switch_config_string_strdup, "", "codec preferences, coma-separated"), SWITCH_CONFIG_ITEM_END() }; 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 af53052fbb..fdecf761b9 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -113,6 +113,7 @@ struct mg_termination_s { mg_termination_t *next; /*!< List for physical terminations */ mg_context_t* mg_ctxt; uint32_t flags; + const char *tech; /* Endpoint controlling the TDM interface - only FreeTDM tested so far */ union { struct { From 6e54a5e9bca0eb8bbbf4f748519c0a33bc883619 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 12:08:15 -0400 Subject: [PATCH 06/12] local descriptor codec negotiation done --- .../media_gateway_cmd_handler.c | 8 +++++- .../mod_media_gateway/media_gateway_utils.c | 26 ++++++++++++++----- .../mod_media_gateway/mod_media_gateway.h | 3 ++- 3 files changed, 28 insertions(+), 9 deletions(-) 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 ca0d286ba2..8940d36e66 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 @@ -707,7 +707,13 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i /* only for RTP */ if(is_rtp){ - mg_build_sdp(&desc->u.media, inc_med_desc, mg_profile, term, &rsp.u.mgCmdRsp[0]->memCp); + if(SWITCH_STATUS_FALSE == mg_build_sdp(&desc->u.media, inc_med_desc, mg_profile, term, &rsp.u.mgCmdRsp[0]->memCp)) { + if(term->mg_error_code && (*term->mg_error_code == MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT)){ + mg_util_set_err_string(&errTxt, " Unsupported Codec "); + err_code = MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT; + goto error; + } + } } #if 0 if(is_rtp){ 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 39a69f3921..ae4ec24b04 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c @@ -1699,17 +1699,18 @@ switch_status_t mg_rem_unsupported_codecs (megaco_profile_t* mg_profile, mg_term /* loop through coddec list and remove un-supported codec */ for(i = 0; i < fmtList->num.val; i++) { + foundCodec = 0x00; fmt = fmtList->fmts[i]; if((NOTPRSNT == fmt->type.pres) || (NOTPRSNT == fmt->val.pres)) continue; if(CM_SDP_SPEC != fmt->type.val) continue; /* TODO - need to see for other cases like CM_SDP_NIL/CM_SDP_CHOICE etc not sure as of now */ - switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "codec[%d] number \n", fmt->val.val); /* see if received codec is present in our codec supported list */ for (id = 0; codecs[id] && id < codec_count; id++) { int pt = codecs[id]->ianacode; + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "Matching recv codec[%d] with supported codec[%d] \n", fmt->val.val, pt); //const char *name = codecs[id]->iananame; if(pt == fmt->val.val){ foundCodec = 0x01; @@ -1751,6 +1752,14 @@ switch_status_t mg_rem_unsupported_codecs (megaco_profile_t* mg_profile, mg_term } } + if(0 == fmtList->num.val) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "No Supported codec found in offer, Rejecting request \n"); + term->mg_error_code = switch_core_alloc(term->pool, sizeof(term->mg_error_code)); + *term->mg_error_code = MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT; + + return SWITCH_STATUS_FALSE; + } + return SWITCH_STATUS_SUCCESS; } @@ -1799,6 +1808,12 @@ switch_status_t mg_build_sdp(MgMgcoMediaDesc* out, MgMgcoMediaDesc* inc, megaco_ for(i=0; inum.val; i++) { if(MGT_MEDIAPAR_LOCAL == out->parms[i]->type.val) { local = &out->parms[i]->u.local; + break; + } else if(MGT_MEDIAPAR_STRPAR == out->parms[i]->type.val){ + MgMgcoStreamDesc *stream = &out->parms[i]->u.stream; + if((NOTPRSNT != stream->sl.pres.pres) && (NOTPRSNT != stream->sl.local.pres.pres)){ + local = &stream->sl.local; + } } } } @@ -1823,12 +1838,9 @@ switch_status_t mg_build_sdp(MgMgcoMediaDesc* out, MgMgcoMediaDesc* inc, megaco_ MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.type), CM_SDP_SPEC); MG_INIT_TOKEN_VALUE(&(psdp->info[psdp->numComp.val-1]->orig.orig.pres), 1); - MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.usrName, 1, "-", - NULL); - MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessId, 1, "0", - NULL); - MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessVer, 1, "0", - NULL); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.usrName, 1, "-", memCp); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessId, 1, "0", memCp); + MG_SET_TKNSTROSXL(psdp->info[psdp->numComp.val-1]->orig.orig.sessVer, 1, "0", memCp); MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.netType.type), CM_SDP_NET_TYPE_IN); MG_SET_VAL_PRES( (psdp->info[psdp->numComp.val-1]->orig.orig.sdpAddr.addrType), 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 fdecf761b9..5c50ed9cfe 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -112,8 +112,9 @@ struct mg_termination_s { MgMgcoReqEvtDesc *active_events; /* !< active megaco events */ mg_termination_t *next; /*!< List for physical terminations */ mg_context_t* mg_ctxt; + int *mg_error_code; /* MEGACO error code */ uint32_t flags; - const char *tech; /* Endpoint controlling the TDM interface - only FreeTDM tested so far */ + const char *tech; /* Endpoint controlling the TDM interface - only FreeTDM tested so far */ union { struct { From ad5297cab71287bb48e6efe004104da34d756ace Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 12:54:58 -0400 Subject: [PATCH 07/12] adding codec nogotiation code --- .../media_gateway_cmd_handler.c | 28 ++++++--- .../mod_media_gateway/media_gateway_stack.h | 4 +- .../mod_media_gateway/media_gateway_utils.c | 58 +++++++++++++++++-- 3 files changed, 75 insertions(+), 15 deletions(-) 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 8940d36e66..18129ff975 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 @@ -198,7 +198,7 @@ switch_status_t mg_is_ito_pkg_req(megaco_profile_t* mg_profile, MgMgcoCommand *c * * */ -switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *cmd, mg_termination_t* term) +switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *cmd, mg_termination_t* term, CmMemListCp *memCp) { CmSdpMedProtoFmts *format; TknU8 *fmt; @@ -301,7 +301,7 @@ switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand * } } - mgco_handle_sdp(&local->sdp, term, MG_SDP_LOCAL); + mgco_handle_incoming_sdp(&local->sdp, term, MG_SDP_LOCAL, mg_profile, memCp); break; } @@ -313,7 +313,7 @@ switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand * remote = &mediaPar->u.remote; sdp = remote->sdp.info[0]; /* for Matt - same like local descriptor */ - mgco_handle_sdp(&remote->sdp, term, MG_SDP_REMOTE); + mgco_handle_incoming_sdp(&remote->sdp, term, MG_SDP_REMOTE, mg_profile, memCp); break; } @@ -406,12 +406,12 @@ switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand * if (mgStream->sl.remote.pres.pres) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got remote stream media description:\n"); - mgco_handle_sdp(&mgStream->sl.remote.sdp, term, MG_SDP_LOCAL); + mgco_handle_incoming_sdp(&mgStream->sl.remote.sdp, term, MG_SDP_LOCAL, mg_profile, memCp); } if (mgStream->sl.local.pres.pres) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got local stream media description:\n"); - mgco_handle_sdp(&mgStream->sl.local.sdp, term, MG_SDP_REMOTE); + mgco_handle_incoming_sdp(&mgStream->sl.local.sdp, term, MG_SDP_REMOTE, mg_profile, memCp); } break; @@ -610,7 +610,14 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i /********************************************************************/ - ret = mg_prc_descriptors(mg_profile, inc_cmd, term); + ret = mg_prc_descriptors(mg_profile, inc_cmd, term, &inc_cmd->u.mgCmdInd[0]->memCp); + + /* IF there is any error , return */ + if(term->mg_error_code && (*term->mg_error_code == MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT)){ + mg_util_set_err_string(&errTxt, " Unsupported Codec "); + err_code = MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT; + goto error; + } /* TODO - locally assigned SDP must be the part of termination...which we can use to fill responses*/ @@ -1067,7 +1074,14 @@ switch_status_t handle_mg_modify_cmd(megaco_profile_t* mg_profile, MgMgcoCommand /********************************************************************/ - ret = mg_prc_descriptors(mg_profile, inc_cmd, term); + ret = mg_prc_descriptors(mg_profile, inc_cmd, term, &inc_cmd->u.mgCmdInd[0]->memCp); + + /* IF there is any error , return */ + if(term->mg_error_code && (*term->mg_error_code == MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT)){ + mg_util_set_err_string(&errTxt, " Unsupported Codec "); + err_code = MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT; + goto error; + } /* SDP updated to termination */ megaco_activate_termination(term); 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 f84bfbd5e4..20354b0ccb 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h @@ -141,7 +141,7 @@ typedef enum { (_reqId)->id.val = 0xFFFFFFFF; -switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *inc_cmd, mg_termination_t* term); +switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *inc_cmd, mg_termination_t* term, CmMemListCp *memCp); void handle_sng_log(uint8_t level, char *fmt, ...); void handle_mgco_sta_ind(Pst *pst, SuId suId, MgMgtSta* msg); void handle_mgco_txn_sta_ind(Pst *pst, SuId suId, MgMgcoInd* msg); @@ -166,7 +166,7 @@ int sng_mgco_mg_get_status(int elemId, MgMngmt* cfm, megaco_profile_t* mg_cfg, m switch_status_t mg_is_ito_pkg_req(megaco_profile_t* mg_profile, MgMgcoCommand *cmd); switch_status_t mg_send_end_of_axn(SuId suId, MgMgcoTransId* transId, MgMgcoContextId* ctxtId, TknU32* peerId); -void mgco_handle_sdp(CmSdpInfoSet *sdp,mg_termination_t* term, mgco_sdp_types_e sdp_type); +void mgco_handle_incoming_sdp(CmSdpInfoSet *sdp,mg_termination_t* term, mgco_sdp_types_e sdp_type, megaco_profile_t* mg_profile, CmMemListCp *memCp); void mg_util_set_ctxt_string ( MgStr *errTxt, MgMgcoContextId *ctxtId); switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *inc_cmd, MgMgcoContextId* new_ctxtId); switch_status_t handle_mg_subtract_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *inc_cmd); 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 ae4ec24b04..019725208f 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c @@ -421,7 +421,7 @@ void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand *cmd) } /*****************************************************************************************************************************/ -void mgco_print_sdp_attr_set(CmSdpAttrSet *s) +void mgco_handle_sdp_attr_set(CmSdpAttrSet *s, mg_termination_t* term) { int i=0x00; if (s->numComp.pres) { @@ -461,6 +461,9 @@ void mgco_print_sdp_attr_set(CmSdpAttrSet *s) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\t PTIME = %ld \n", (NOTPRSNT != a->u.ptime.pres)?a->u.ptime.val:-1); #endif + if(MG_TERM_RTP == term->type){ + term->u.rtp.ptime = a->u.ptime.val; + } break; } case CM_SDP_ATTR_RECVONLY: @@ -786,7 +789,30 @@ void mgco_print_CmSdpU8OrNil(CmSdpU8OrNil* p) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,"CmSdpU8OrNil: Value = %d \n", (NOTPRSNT != p->val.pres)?p->val.val:-1); } -void mgco_print_sdp_media_param(CmSdpMedPar *s, mg_termination_t* term, mgco_sdp_types_e sdp_type) +const char* mg_get_codec_name(megaco_profile_t* mg_profile, int iana_code) +{ + int i = 0x00; + const switch_codec_implementation_t *codecs[16]; + char *codec_prefs[16] = { 0 }; + char *szcodec_prefs; + int codec_count; + + szcodec_prefs = strdup(mg_profile->codec_prefs); + codec_count = switch_split(szcodec_prefs, ',', codec_prefs); + + /* Get the list of codecs, by preference */ + switch_loadable_module_get_codecs_sorted(codecs, switch_arraylen(codecs), codec_prefs, switch_arraylen(codec_prefs)); + /* see if received codec is present in our codec supported list */ + for (i = 0; codecs[i] && i < codec_count; i++) { + if(iana_code == codecs[i]->ianacode){ + return codecs[i]->iananame; + } + } + + return NULL; +} + +void mgco_handle_sdp_media_param(CmSdpMedPar *s, mg_termination_t* term, mgco_sdp_types_e sdp_type, megaco_profile_t* mg_profile, CmSdpAttrSet *attrSet, CmMemListCp *memCp) { int i=0x00; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "***** Media Parameter *********** \n"); @@ -837,6 +863,26 @@ void mgco_print_sdp_media_param(CmSdpMedPar *s, mg_termination_t* term, mgco_sdp } } } + + /* Ideally remote descriptor should have supported codec..but just in case calling remove un-supported codecs api */ + mg_rem_unsupported_codecs(mg_profile, term , r, attrSet, memCp); + + + /* now whatever we have , that will be suported one */ + if((NOTPRSNT != r->num.pres) && (0 != r->num.val) && (NULL != r->fmts[0])){ + const char* name = mg_get_codec_name(mg_profile, r->fmts[0]->val.val); + if(name){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, " Updating codec to[%d], name[%s] \n", + r->fmts[0]->val.val, name); + if(MG_TERM_RTP == term->type){ + term->u.rtp.codec = name; + } + }else{ + /* ERROR */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, " NO Codec Name found against iana[%d] \n", r->fmts[0]->val.val); + } + } + break; } @@ -854,7 +900,7 @@ void mgco_print_sdp_media_param(CmSdpMedPar *s, mg_termination_t* term, mgco_sdp switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "**************** \n"); } -void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e sdp_type) +void mgco_handle_incoming_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e sdp_type, megaco_profile_t* mg_profile, CmMemListCp *memCp) { int i; @@ -1021,7 +1067,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e /************************************************************************************************************************/ /* Attribute Set */ - mgco_print_sdp_attr_set(&s->attrSet); + mgco_handle_sdp_attr_set(&s->attrSet, term); /************************************************************************************************************************/ /* Media Descriptor Set */ @@ -1077,7 +1123,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e break; } } - mgco_print_sdp_media_param(&f->par, term, sdp_type); + mgco_handle_sdp_media_param(&f->par, term, sdp_type, mg_profile, &desc->attrSet, memCp); } /*info */ @@ -1097,7 +1143,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e } /* attribute set */ - mgco_print_sdp_attr_set(&desc->attrSet); + mgco_handle_sdp_attr_set(&desc->attrSet, term); if (desc->field.mediaType.val == CM_SDP_MEDIA_AUDIO && From ed5875b54b15a7bfb9312a3dfaeb548297f6f4f0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 13:01:54 -0400 Subject: [PATCH 08/12] fixing issue --- src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c | 1 + 1 file changed, 1 insertion(+) 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 18129ff975..f9ae4fe90a 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 @@ -1080,6 +1080,7 @@ switch_status_t handle_mg_modify_cmd(megaco_profile_t* mg_profile, MgMgcoCommand if(term->mg_error_code && (*term->mg_error_code == MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT)){ mg_util_set_err_string(&errTxt, " Unsupported Codec "); err_code = MGT_MGCP_RSP_CODE_INCONSISTENT_LCL_OPT; + /* TODO delete RTP termination */ goto error; } From 008bb4942be0a6e2d1b2f5db425c7cace04a6449 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 16:11:46 -0400 Subject: [PATCH 09/12] adding code for updating codec types --- libs/freetdm/mod_freetdm/tdm.c | 4 +- .../mod_media_gateway/media_gateway_utils.c | 1 + src/mod/endpoints/mod_sofia/rtp.c | 82 ++++++++++++++++--- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index b2d37d47ed..ab061a3812 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -111,7 +111,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi const char *dname; ftdm_codec_t codec; uint32_t interval; - ftdm_status_t fstatus; + /*ftdm_status_t fstatus;*/ const char *ftdm_start_only = switch_event_get_header(var_event, "ftdm_start_only"); ctdm_private_t *tech_pvt = NULL; @@ -129,10 +129,12 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi goto fail; } +#if 0 if ((fstatus = ftdm_span_start(span)) != FTDM_SUCCESS && fstatus != FTDM_EINVAL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start span %s.\n", span_name); goto fail; } +#endif if (!zstr(ftdm_start_only) && switch_true(ftdm_start_only)) { goto fail; 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 019725208f..f7e9dde544 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_utils.c @@ -876,6 +876,7 @@ void mgco_handle_sdp_media_param(CmSdpMedPar *s, mg_termination_t* term, mgco_sd r->fmts[0]->val.val, name); if(MG_TERM_RTP == term->type){ term->u.rtp.codec = name; + term->u.rtp.pt = r->fmts[0]->val.val; } }else{ /* ERROR */ diff --git a/src/mod/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c index 04feb55a8a..bf3e36ca19 100644 --- a/src/mod/endpoints/mod_sofia/rtp.c +++ b/src/mod/endpoints/mod_sofia/rtp.c @@ -421,17 +421,26 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi const char *command = switch_event_get_header(event, "command"); switch_channel_t *channel = switch_core_session_get_channel(session); crtp_private_t *tech_pvt = switch_core_session_get_private(session); - + char *codec = switch_event_get_header_nil(event, kCODEC); + char *szptime = switch_event_get_header_nil(event, kPTIME); + char *szrate = switch_event_get_header_nil(event, kRATE); + char *szpt = switch_event_get_header_nil(event, kPT); + + int ptime = !zstr(szptime) ? atoi(szptime) : 0, + rate = !zstr(szrate) ? atoi(szrate) : 8000, + pt = !zstr(szpt) ? atoi(szpt) : 0; + + if (!zstr(command) && !strcasecmp(command, "media_modify")) { /* Compare parameters */ if (compare_var(event, channel, kREMOTEADDR) || compare_var(event, channel, kREMOTEPORT)) { - char *remote_addr = switch_event_get_header(event, kREMOTEADDR); - char *szremote_port = switch_event_get_header(event, kREMOTEPORT); - switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; - const char *err; + char *remote_addr = switch_event_get_header(event, kREMOTEADDR); + char *szremote_port = switch_event_get_header(event, kREMOTEPORT); + switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; + const char *err; + - switch_channel_set_variable(channel, kREMOTEADDR, remote_addr); switch_channel_set_variable(channel, kREMOTEPORT, szremote_port); @@ -446,10 +455,47 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi if (compare_var(event, channel, kCODEC) || compare_var(event, channel, kPTIME) || compare_var(event, channel, kPT) || - compare_var(event, channel, kRATE)) { - /* Reset codec */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Switching codec not yet implemented\n"); - } + compare_var(event, channel, kRATE)) { + /* Reset codec */ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Switching codec updating \n"); + + if (switch_core_codec_init(&tech_pvt->read_codec, + codec, + NULL, + rate, + ptime, + 1, + /*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } else { + if (switch_core_codec_init(&tech_pvt->write_codec, + codec, + NULL, + rate, + ptime, + 1, + SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } + } + + if (switch_core_session_set_read_codec(session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); + goto fail; + } + + if (switch_core_session_set_write_codec(session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); + goto fail; + } + + switch_rtp_set_default_payload(tech_pvt->rtp_session, pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt); + } if (compare_var(event, channel, kRFC2833PT)) { const char *szpt = switch_channel_get_variable(channel, kRFC2833PT); @@ -464,6 +510,22 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi } return SWITCH_STATUS_SUCCESS; +fail: + if (tech_pvt) { + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + } + + if (session) { + switch_core_session_destroy(&session); + } + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) From 2dc5b322dd7cdd7a08c351805769a0a3862b9bbd Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Jul 2012 21:31:24 -0400 Subject: [PATCH 10/12] Added event system for TDM termination alarms --- libs/freetdm/mod_freetdm/mod_freetdm.c | 6 +- libs/freetdm/mod_freetdm/tdm.c | 205 ++++++++++++++++-- libs/freetdm/src/ftdm_io.c | 15 +- libs/freetdm/src/include/freetdm.h | 12 +- .../mod_media_gateway/media_gateway.c | 61 +++--- .../mod_media_gateway/media_gateway_xml.c | 2 + .../mod_media_gateway/mod_media_gateway.c | 32 ++- .../mod_media_gateway/mod_media_gateway.h | 3 +- 8 files changed, 275 insertions(+), 61 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 34fb3f469a..a746c1877f 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2097,7 +2097,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session static FIO_SIGNAL_CB_FUNCTION(on_common_signal) { uint32_t chanid, spanid; - switch_event_t *event = NULL; + switch_event_t *event = NULL; ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; chanid = ftdm_channel_get_id(sigmsg->channel); @@ -2200,9 +2200,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) break; } - if (event) { - - + if (event) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index ab061a3812..c5850e6f51 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -68,6 +68,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg); static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf); + +static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span); + switch_state_handler_table_t ctdm_state_handlers = { .on_init = channel_on_init, .on_destroy = channel_on_destroy @@ -81,6 +84,115 @@ switch_io_routines_t ctdm_io_routines = { .receive_message = channel_receive_message }; +static void ctdm_report_alarms(ftdm_channel_t *channel) +{ + switch_event_t *event = NULL; + ftdm_alarm_flag_t alarmflag = 0; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); + return; + } + + if (ftdm_channel_get_alarms(channel, &alarmflag) != FTDM_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve alarms %s:%d\n", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel)); + return; + } + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(channel)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(channel)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(channel)); + + if (alarmflag) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); + } else { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); + } + + if (alarmflag & FTDM_ALARM_RED) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); + } + if (alarmflag & FTDM_ALARM_YELLOW) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); + } + if (alarmflag & FTDM_ALARM_RAI) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); + } + if (alarmflag & FTDM_ALARM_BLUE) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); + } + if (alarmflag & FTDM_ALARM_AIS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); + } + if (alarmflag & FTDM_ALARM_GENERAL) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); + } + + switch_event_fire(&event); + return; +} + + + +static void ctdm_event_handler(switch_event_t *event) +{ + ftdm_status_t status = FTDM_FAIL; + switch(event->event_id) { + case SWITCH_EVENT_TRAP: + { + ftdm_span_t *span = NULL; + ftdm_channel_t *channel = NULL; + const char *span_name = NULL; + const char *chan_number = NULL; + uint32_t chan_id = 0; + const char *cond = switch_event_get_header(event, "condition"); + + if (zstr(cond)) { + return; + } + + span_name = switch_event_get_header(event, "span-name"); + chan_number = switch_event_get_header(event, "chan-number"); + + if (ftdm_span_find_by_name(span_name, &span) != FTDM_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name); + return; + } + + if (!strcmp(cond, "mg-tdm-prepare")) { + status = ctdm_span_prepare(span); + if (status == FTDM_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Span %s prepared successfully\n", span_name); + } else if (status != FTDM_EINVAL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to prepare span %s.\n", span_name); + } + } else if (!strcmp(cond, "mg-tdm-check")) { + if (zstr(chan_number)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channel number specified\n"); + return; + } + chan_id = atoi(chan_number); + if (!chan_id) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid channel number:%s\n", chan_number); + return; + } + + channel = ftdm_span_get_channel(span, chan_id); + if (!channel) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n"); + return; + } + + ctdm_report_alarms(channel); + } + } + break; + default: + break; + } + return; +} + void ctdm_init(switch_loadable_module_interface_t *module_interface) { switch_endpoint_interface_t *endpoint_interface; @@ -90,7 +202,82 @@ void ctdm_init(switch_loadable_module_interface_t *module_interface) endpoint_interface->io_routines = &ctdm_io_routines; endpoint_interface->state_handler = &ctdm_state_handlers; ctdm.endpoint_interface = endpoint_interface; - + + switch_event_bind("mod_freetdm", SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, ctdm_event_handler, NULL); +} + +static FIO_SIGNAL_CB_FUNCTION(on_signal_cb) +{ + uint32_t chanid, spanid; + switch_event_t *event = NULL; + ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; + + chanid = ftdm_channel_get_id(sigmsg->channel); + spanid = ftdm_channel_get_span_id(sigmsg->channel); + + switch(sigmsg->event_id) { + case FTDM_SIGEVENT_ALARM_CLEAR: + case FTDM_SIGEVENT_ALARM_TRAP: + { + if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n"); + return FTDM_FAIL; + } + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); + return FTDM_FAIL; + } + if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) { + ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); + } else { + ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); + } + } + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unhandled event %d\n", sigmsg->event_id); + break; + } + + if (event) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); + + if (alarmbits & FTDM_ALARM_RED) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); + } + if (alarmbits & FTDM_ALARM_YELLOW) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); + } + if (alarmbits & FTDM_ALARM_RAI) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); + } + if (alarmbits & FTDM_ALARM_BLUE) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); + } + if (alarmbits & FTDM_ALARM_AIS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); + } + if (alarmbits & FTDM_ALARM_GENERAL) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); + } + + switch_event_fire(&event); + } + return FTDM_SUCCESS; +} + +static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span) +{ + if (ftdm_span_register_signal_cb(span, on_signal_cb) != FTDM_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register signal CB\n"); + return FTDM_FAIL; + } + return ftdm_span_start(span); } static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, @@ -111,10 +298,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi const char *dname; ftdm_codec_t codec; uint32_t interval; - /*ftdm_status_t fstatus;*/ - const char *ftdm_start_only = switch_event_get_header(var_event, "ftdm_start_only"); ctdm_private_t *tech_pvt = NULL; - + if (zstr(szchanid) || zstr(span_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n"); goto fail; @@ -129,18 +314,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi goto fail; } -#if 0 - if ((fstatus = ftdm_span_start(span)) != FTDM_SUCCESS && fstatus != FTDM_EINVAL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start span %s.\n", span_name); - goto fail; - } -#endif - - if (!zstr(ftdm_start_only) && switch_true(ftdm_start_only)) { - goto fail; - } - - if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); goto fail; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 758827c9ed..4e110df659 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5653,6 +5653,12 @@ static void *ftdm_span_service_events(ftdm_thread_t *me, void *obj) return NULL; } +FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb) +{ + span->signal_cb = sig_cb; + return FTDM_SUCCESS; +} + FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span) { ftdm_status_t status = FTDM_FAIL; @@ -5670,7 +5676,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span) goto done; } - status = ftdm_report_initial_channels_alarms(span); + //ftdm_report_initial_channels_alarms(span); + ftdm_set_flag_locked(span, FTDM_SPAN_STARTED); goto done; } @@ -5872,8 +5879,10 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { - ftdm_status_t status = span->signal_cb(sigmsg); - return status; + if (!span->signal_cb) { + return FTDM_FAIL; + } + return span->signal_cb(sigmsg); } static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index f7de8519b7..e041e1f0e7 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1611,6 +1611,17 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span(ftdm_span_t *span, const char *typ */ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *parameters); +/*! + * \brief Register callback to listen for incoming events + * \note This function should only be used when there is no signalling module + * \param span The span to register to + * \param sig_cb The callback that the signaling stack will use to notify about events + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb); + /*! * \brief Start the span signaling (must call ftdm_configure_span_signaling first) * @@ -1626,7 +1637,6 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const */ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span); - /*! * \brief Stop the span signaling (must call ftdm_span_start first) * \note certain signalings (boost signaling) does not support granular span start/stop diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index ee5abe7d2f..9056ee1bdc 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -155,47 +155,38 @@ done: return SWITCH_STATUS_SUCCESS; } - -/* - * Originate a channel so the target technology gets to run initialization code - */ -switch_status_t megaco_prepare_termination(mg_termination_t *term) +switch_status_t megaco_prepare_tdm_termination(mg_termination_t *term) { - switch_event_t *var_event = NULL; - switch_core_session_t *session = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; - char dialstring[100]; - switch_call_cause_t cause; - switch_channel_t *channel; - switch_event_create(&var_event, SWITCH_EVENT_CLONE); - - if (term->type == MG_TERM_RTP) { - } else if (term->type == MG_TERM_TDM) { - switch_snprintf(dialstring, sizeof dialstring, "tdm/%s", term->name); + switch_event_t *event = NULL; + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to create NOTIFY event\n"); + return SWITCH_STATUS_FALSE; + } - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ftdm_start_only", "true"); - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, kSPAN_NAME, term->u.tdm.span_name); - switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, kCHAN_ID, "%d", term->u.tdm.channel); - } - - /* Set common variables on the channel */ - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true"); - if (switch_ivr_originate(NULL, &session, &cause, dialstring, 0, NULL, NULL, NULL, NULL, var_event, 0, NULL) != SWITCH_STATUS_SUCCESS) { - status = SWITCH_STATUS_FALSE; - goto done; - } - channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - -done: - if (session) { - switch_core_session_rwunlock(session); - } - switch_event_destroy(&var_event); + 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-prepare"); + switch_event_fire(&event); 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; + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to create NOTIFY event\n"); + return SWITCH_STATUS_FALSE; + } + + 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_fire(&event); + return SWITCH_STATUS_SUCCESS; +} mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix) { 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 011c36ce56..1b8173aa1e 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c @@ -111,6 +111,8 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload) 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); } } } 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 de315d7ae9..00f5e9760f 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c @@ -56,6 +56,35 @@ static switch_status_t list_profiles(const char *line, const char *cursor, switc return status; } +static void mg_event_handler(switch_event_t *event) +{ + switch(event->event_id) { + case SWITCH_EVENT_TRAP: + { + const char *span_name = NULL; + const char *chan_number = NULL; + const char *cond = NULL; + + cond = switch_event_get_header(event, "condition"); + if (zstr(cond)) { + return; + } + + span_name = switch_event_get_header(event, "span-name"); + chan_number = switch_event_get_header(event, "chan-number"); + + if (!strcmp(cond, "ftdm-alarm-trap")) { + /* @KAPIL: TDM is in alarm, notify MGC */ + } else if (!strcmp(cond, "ftdm-alarm-clear")) { + /* @KAPIL: TDM alarm cleared, notify MGC */ + } + } + break; + default: + break; + } +} + SWITCH_MODULE_LOAD_FUNCTION(mod_media_gateway_load) { switch_api_interface_t *api_interface; @@ -82,7 +111,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_media_gateway_load) switch_console_set_complete("add mg logging ::mg::list_profiles disable"); switch_console_add_complete_func("::mg::list_profiles", list_profiles); - /* Initialize MEGACO Stack */ sng_event.mg.sng_mgco_txn_ind = handle_mgco_txn_ind; sng_event.mg.sng_mgco_cmd_ind = handle_mgco_cmd_ind; @@ -96,6 +124,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_media_gateway_load) /* Log */ sng_event.sm.sng_log = handle_sng_log; + switch_event_bind("mod_media_gateway", SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, mg_event_handler, NULL); + /* initualize MEGACO stack */ return sng_mgco_init(&sng_event); } 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 504f147d76..86acb28861 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -256,7 +256,8 @@ switch_status_t mg_process_cli_cmd(const char *cmd, switch_stream_handle_t *stre switch_status_t megaco_context_add_termination(mg_context_t *ctx, mg_termination_t *term); switch_status_t megaco_context_is_term_present(mg_context_t *ctx, mg_termination_t *term); - +switch_status_t megaco_prepare_tdm_termination(mg_termination_t *term); +switch_status_t megaco_check_tdm_termination(mg_termination_t *term); #endif /* MOD_MEGACO_H */ From da26b4de4122a2a6e4b6a0ca5d6ea63871b04a05 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Jul 2012 10:17:13 -0400 Subject: [PATCH 11/12] adding termination service-change code --- libs/freetdm/mod_freetdm/tdm.c | 8 ++- .../mod_media_gateway/media_gateway.c | 69 +++++++++++++++++++ .../media_gateway_cmd_handler.c | 39 +++++++++++ .../mod_media_gateway/media_gateway_stack.h | 10 +++ .../media_gateway_stack_alarms.c | 9 ++- .../mod_media_gateway/media_gateway_xml.c | 2 +- .../mod_media_gateway/mod_media_gateway.c | 21 +++++- 7 files changed, 149 insertions(+), 9 deletions(-) diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index c5850e6f51..790f7c17d3 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) +static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_name) { switch_event_t *event = NULL; ftdm_alarm_flag_t alarmflag = 0; @@ -109,6 +109,8 @@ static void ctdm_report_alarms(ftdm_channel_t *channel) 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"); } @@ -128,6 +130,7 @@ static void ctdm_report_alarms(ftdm_channel_t *channel) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); } + switch_event_fire(&event); return; } @@ -146,6 +149,7 @@ 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; @@ -183,7 +187,7 @@ static void ctdm_event_handler(switch_event_t *event) return; } - ctdm_report_alarms(channel); + ctdm_report_alarms(channel, mg_profile_name); } } break; diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index 9056ee1bdc..7e13fbaebe 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -175,6 +175,9 @@ switch_status_t megaco_prepare_tdm_termination(mg_termination_t *term) switch_status_t megaco_check_tdm_termination(mg_termination_t *term) { switch_event_t *event = NULL; + + if(!term || !term->profile) return SWITCH_STATUS_FALSE; + if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to create NOTIFY event\n"); return SWITCH_STATUS_FALSE; @@ -183,6 +186,7 @@ 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; @@ -237,6 +241,42 @@ 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) +{ + void *val = NULL; + switch_hash_index_t *hi = NULL; + mg_termination_t *term = NULL; + int found = 0x00; + const void *var; + + if(!span_name || !chan_number){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"Invalid span_name/chan_number \n"); + return NULL; + } + + for (hi = switch_hash_first(NULL, profile->terminations); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + term = (mg_termination_t *) val; + if(!term) continue; + if(MG_TERM_TDM != term->type) continue; + + 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); + found = 0x01; + break; + } + } + + 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); + } + + return term; +} + mg_termination_t *megaco_find_termination(megaco_profile_t *profile, const char *name) { mg_termination_t *term = switch_core_hash_find_rdlock(profile->terminations, name, profile->terminations_rwlock); @@ -568,6 +608,35 @@ switch_status_t megaco_profile_destroy(megaco_profile_t **profile) return SWITCH_STATUS_SUCCESS; } + +switch_status_t mgco_init_ins_service_change(SuId suId) +{ + megaco_profile_t* profile = NULL; + void *val = NULL; + const void *key = NULL; + switch_ssize_t keylen; + switch_hash_index_t *hi = NULL; + mg_termination_t *term = NULL; + + + if(NULL == (profile = megaco_get_profile_by_suId(suId))){ + return SWITCH_STATUS_FALSE; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, + "mgco_init_ins_service_change : Initiating terminations service change for profile: %s\n", profile->name); + + /* loop through all termination and post get status Event */ + for (hi = switch_hash_first(NULL, profile->terminations); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &key, &keylen, &val); + term = (mg_termination_t *) val; + if(!term) continue; + megaco_check_tdm_termination(term); + } + + return SWITCH_STATUS_SUCCESS; +} + switch_status_t megaco_peer_profile_destroy(mg_peer_profile_t **profile) { 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 f9ae4fe90a..ca2209b087 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,6 +2288,45 @@ 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) +{ + 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); + + if(!term || !term->profile){ + return SWITCH_STATUS_FALSE; + } + + switch(term_state) + { + case MG_TERM_SERVICE_STATE_IN_SERVICE: + { + ret = mg_send_ins_service_change(term->profile, term->name, 0x00 ); + break; + } + case MG_TERM_SERVICE_STATE_OUT_OF_SERVICE: + { + ret = mg_send_oos_service_change(term->profile, term->name, 0x00 ); + break; + } + default: + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," Invalid term_state[%d]\n", term_state); + return SWITCH_STATUS_FALSE; + } + } + + return ret; +} +/*****************************************************************************************************************************/ /* Note : API to send Service Change when termination is coming up(in-service) */ /* INPUT : MG Profile structure and termination name */ /* wild flag will tell if service change request needs to be in W-SC format as we can have W-SC=A01* or SC=A01* */ 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 20354b0ccb..3e2ec81bdb 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_stack.h @@ -52,6 +52,13 @@ typedef enum{ SNG_MG_ENCODING_TEXT, }sng_mg_encoding_types_e; +typedef enum{ + MG_TERM_SERVICE_STATE_UNKNOWN, + MG_TERM_SERVICE_STATE_IN_SERVICE, + MG_TERM_SERVICE_STATE_OUT_OF_SERVICE, + MG_TERM_SERVICE_STATE_INVALID, +}mg_term_states_e; + #define PRNT_ENCODING_TYPE(_val)\ ((_val == SNG_MG_ENCODING_TEXT)?"SNG_MG_ENCODING_TEXT":\ (_val == SNG_MG_ENCODING_BINARY)?"SNG_MG_ENCODING_BINARY":\ @@ -157,6 +164,8 @@ 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 sng_mgco_cfg(megaco_profile_t* profile); @@ -183,6 +192,7 @@ 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); void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand *cmd); +switch_status_t mgco_init_ins_service_change(SuId suId); switch_status_t mg_send_modify_rsp(SuId suId, MgMgcoCommand *req); switch_status_t mg_send_subtract_rsp(SuId suId, MgMgcoCommand *req); diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway_stack_alarms.c b/src/mod/endpoints/mod_media_gateway/media_gateway_stack_alarms.c index 4564468e96..f392203db1 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_stack_alarms.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_stack_alarms.c @@ -25,8 +25,8 @@ void handle_mg_alarm(Pst *pst, MgMngmt *usta) memset(&prBuf[0], 0, sizeof(prBuf)); - len = len + sprintf(prBuf+len,"MG Status Indication: received with Category = %d, Event = %d, Cause = %d \n", - usta->t.usta.alarm.category, usta->t.usta.alarm.event, + len = len + sprintf(prBuf+len,"MG Status Indication: received for sapId[%d] with Category = %d, Event = %d, Cause = %d \n", + usta->t.usta.alarmInfo.sapId, usta->t.usta.alarm.category, usta->t.usta.alarm.event, usta->t.usta.alarm.cause); len = len + sprintf(prBuf+len, "Category ( "); @@ -218,9 +218,8 @@ void handle_mg_alarm(Pst *pst, MgMngmt *usta) case LMG_EVENT_PEER_ENABLED: { len = len + sprintf(prBuf+len, "gateway enabled"); - /* gateway enabled now we can send termination service change */ - /*TODO - probably we cannt immediate send Service change - we have to find proper place */ - /*mg_send_service_change(0x01, "A01", MGT_SVCCHGMETH_RESTART,MG_SVC_REASON_900_RESTORED );*/ + /* gateway enabled now we can send termination service change for all terminations */ + mgco_init_ins_service_change( usta->t.usta.alarmInfo.sapId ); break; } case LMG_EVENT_PEER_DISCOVERED: 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 1b8173aa1e..6c87afa780 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway_xml.c @@ -84,7 +84,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload) char *channel_map_dup = strdup(channel_map); char *chanmap[24]; int chanmap_count, i; - chanmap_count = switch_split(channel_map_dup, ' ', chanmap); + chanmap_count = switch_split(channel_map_dup, ',', chanmap); for (i = 0; i < chanmap_count; i++) { char *p = strchr(chanmap[i], '-'); if (p) { 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 00f5e9760f..97158fdcea 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.c @@ -64,9 +64,18 @@ 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; } @@ -74,9 +83,19 @@ static void mg_event_handler(switch_event_t *event) 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); } else if (!strcmp(cond, "ftdm-alarm-clear")) { - /* @KAPIL: TDM alarm cleared, notify MGC */ + 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); } } break; From a3b4f3ad4ddd307bd72e30888cafb71026ccfeec Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Sun, 29 Jul 2012 22:28:10 -0400 Subject: [PATCH 12/12] Added mod_opal --- build/modules.conf.in | 1 + 1 file changed, 1 insertion(+) diff --git a/build/modules.conf.in b/build/modules.conf.in index 559b06e8ea..83986b996c 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -7,6 +7,7 @@ applications/mod_hash applications/mod_spandsp dialplans/mod_dialplan_xml endpoints/mod_sofia +endpoints/mod_opal #endpoints/mod_media_gateway ../../libs/freetdm/mod_freetdm xml_int/mod_xml_cdr