提交 6571b88e authored 作者: David Yat Sin's avatar David Yat Sin

Merge branch 'nsg-4.3' of ssh://git.sangoma.com/smg_freeswitch into nsg-4.3

......@@ -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
......
......@@ -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));
......
......@@ -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,119 @@ switch_io_routines_t ctdm_io_routines = {
.receive_message = channel_receive_message
};
static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_name)
{
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");
}
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");
}
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");
const char *mg_profile_name = switch_event_get_header(event, "mg-profile-name");
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, mg_profile_name);
}
}
break;
default:
break;
}
return;
}
void ctdm_init(switch_loadable_module_interface_t *module_interface)
{
switch_endpoint_interface_t *endpoint_interface;
......@@ -90,7 +206,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,9 +302,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
const char *dname;
ftdm_codec_t codec;
uint32_t interval;
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;
......@@ -128,7 +318,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
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;
......
......@@ -5618,16 +5618,68 @@ 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_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;
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;
}
//ftdm_report_initial_channels_alarms(span);
ftdm_set_flag_locked(span, FTDM_SPAN_STARTED);
goto done;
}
if (!span->start) {
status = FTDM_ENOSYS;
......@@ -5643,7 +5695,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;
......@@ -5828,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)
......
......@@ -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
......
......@@ -155,6 +155,43 @@ done:
return SWITCH_STATUS_SUCCESS;
}
switch_status_t megaco_prepare_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-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(!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;
}
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;
}
mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix)
{
mg_termination_type_t termtype;
......@@ -204,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);
......@@ -535,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)
{
......
......@@ -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;
......@@ -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 */
......@@ -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*/
......@@ -707,6 +714,17 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i
/* only for RTP */
if(is_rtp){
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){
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 +780,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 +896,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 +914,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..*/
......@@ -1052,13 +1074,22 @@ 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;
/* TODO delete RTP termination */
goto error;
}
/* 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 */
......@@ -2257,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* */
......
......@@ -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":\
......@@ -141,7 +148,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);
......@@ -155,6 +162,11 @@ 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 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);
switch_status_t sng_mgco_init(sng_mg_event_interface_t* event);
......@@ -163,7 +175,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);
......@@ -180,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);
......@@ -193,6 +206,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);
......
......@@ -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:
......
......@@ -74,7 +74,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
// <map termination-id-prefix="Term1/" termination-id-base="1" tech="freetdm" channel-prefix="wp2" channel-map"1-15,17-31"/>
const char *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
//const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base");
//const char *tech = switch_xml_attr(mg_term, "tech");
const char *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");
......@@ -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) {
......@@ -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);
......@@ -110,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);
}
}
}
......@@ -260,6 +263,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()
};
......
......@@ -56,6 +56,54 @@ 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;
const char *mg_profile_name = NULL;
cond = switch_event_get_header(event, "condition");
if (zstr(cond)) {
printf("Condition NULL, returning \n");
return;
}
mg_profile_name = switch_event_get_header(event, "mg-profile-name");
if (zstr(mg_profile_name)) {
printf("mg_profile_name NULL, returning \n");
return;
}
span_name = switch_event_get_header(event, "span-name");
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")) {
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;
default:
break;
}
}
SWITCH_MODULE_LOAD_FUNCTION(mod_media_gateway_load)
{
switch_api_interface_t *api_interface;
......@@ -82,7 +130,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 +143,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);
}
......
......@@ -112,7 +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 */
union {
struct {
......@@ -235,6 +237,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);
......@@ -253,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 */
......
......@@ -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)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论