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

This commit is contained in:
David Yat Sin 2012-07-30 11:08:12 -04:00
commit 6571b88e15
14 changed files with 1172 additions and 56 deletions

View File

@ -7,6 +7,7 @@ applications/mod_hash
applications/mod_spandsp applications/mod_spandsp
dialplans/mod_dialplan_xml dialplans/mod_dialplan_xml
endpoints/mod_sofia endpoints/mod_sofia
endpoints/mod_opal
#endpoints/mod_media_gateway #endpoints/mod_media_gateway
../../libs/freetdm/mod_freetdm ../../libs/freetdm/mod_freetdm
xml_int/mod_xml_cdr xml_int/mod_xml_cdr

View File

@ -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) static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
{ {
uint32_t chanid, spanid; uint32_t chanid, spanid;
switch_event_t *event = NULL; switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
chanid = ftdm_channel_get_id(sigmsg->channel); chanid = ftdm_channel_get_id(sigmsg->channel);
@ -2200,9 +2200,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
break; 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-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, "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)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel));

View File

@ -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_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 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 = { switch_state_handler_table_t ctdm_state_handlers = {
.on_init = channel_on_init, .on_init = channel_on_init,
.on_destroy = channel_on_destroy .on_destroy = channel_on_destroy
@ -81,6 +84,119 @@ switch_io_routines_t ctdm_io_routines = {
.receive_message = channel_receive_message .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) void ctdm_init(switch_loadable_module_interface_t *module_interface)
{ {
switch_endpoint_interface_t *endpoint_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->io_routines = &ctdm_io_routines;
endpoint_interface->state_handler = &ctdm_state_handlers; endpoint_interface->state_handler = &ctdm_state_handlers;
ctdm.endpoint_interface = endpoint_interface; 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, 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; const char *dname;
ftdm_codec_t codec; ftdm_codec_t codec;
uint32_t interval; uint32_t interval;
ctdm_private_t *tech_pvt = NULL; ctdm_private_t *tech_pvt = NULL;
if (zstr(szchanid) || zstr(span_name)) { 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"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n");
goto fail; goto fail;
@ -128,7 +318,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
goto fail; goto fail;
} }
if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { 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"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n");
goto fail; goto fail;

View File

@ -5618,16 +5618,68 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const
return status; 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) FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
{ {
ftdm_status_t status = FTDM_FAIL; ftdm_status_t status = FTDM_FAIL;
ftdm_mutex_lock(span->mutex); ftdm_mutex_lock(span->mutex);
if (ftdm_test_flag(span, FTDM_SPAN_STARTED)) { if (ftdm_test_flag(span, FTDM_SPAN_STARTED)) {
status = FTDM_EINVAL; status = FTDM_EINVAL;
goto done; 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) { if (!span->start) {
status = FTDM_ENOSYS; status = FTDM_ENOSYS;
@ -5643,7 +5695,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
if (status == FTDM_SUCCESS) { if (status == FTDM_SUCCESS) {
ftdm_set_flag_locked(span, FTDM_SPAN_STARTED); ftdm_set_flag_locked(span, FTDM_SPAN_STARTED);
} }
done: done:
ftdm_mutex_unlock(span->mutex); ftdm_mutex_unlock(span->mutex);
return status; 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) 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); if (!span->signal_cb) {
return status; 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) static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)

View File

@ -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); 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) * \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); FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span);
/*! /*!
* \brief Stop the span signaling (must call ftdm_span_start first) * \brief Stop the span signaling (must call ftdm_span_start first)
* \note certain signalings (boost signaling) does not support granular span start/stop * \note certain signalings (boost signaling) does not support granular span start/stop

View File

@ -155,6 +155,43 @@ done:
return SWITCH_STATUS_SUCCESS; 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_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix)
{ {
mg_termination_type_t termtype; mg_termination_type_t termtype;
@ -204,6 +241,42 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
return term; 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 *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); 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; 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) switch_status_t megaco_peer_profile_destroy(mg_peer_profile_t **profile)
{ {

View File

@ -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; CmSdpMedProtoFmts *format;
TknU8 *fmt; 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; break;
} }
@ -313,7 +313,7 @@ switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *
remote = &mediaPar->u.remote; remote = &mediaPar->u.remote;
sdp = remote->sdp.info[0]; sdp = remote->sdp.info[0];
/* for Matt - same like local descriptor */ /* 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; break;
} }
@ -406,12 +406,12 @@ switch_status_t mg_prc_descriptors(megaco_profile_t* mg_profile, MgMgcoCommand *
if (mgStream->sl.remote.pres.pres) { if (mgStream->sl.remote.pres.pres) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got remote stream media description:\n"); 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) { if (mgStream->sl.local.pres.pres) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got local stream media description:\n"); 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; break;
@ -500,7 +500,7 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i
mg_context_t* mg_ctxt; mg_context_t* mg_ctxt;
int mediaId; int mediaId;
MgMgcoLocalDesc *local = NULL; MgMgcoLocalDesc *local = NULL;
CmSdpInfoSet *psdp = NULL; /*CmSdpInfoSet *psdp = NULL;*/
/* TODO - Kapil dummy line , will need to add with proper code */ /* 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*/ /* 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 */ /* only for RTP */
if(is_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 */ /* build local descriptors */
/*MgMgcoStreamDesc *stream;*/ /*MgMgcoStreamDesc *stream;*/
char* ipAddress[4];// = "192.168.1.1"; 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); psdp = &(local->sdp);
if (mgUtlGrowList((void ***)&psdp->info, sizeof(CmSdpInfo), if((NOTPRSNT == local->sdp.numComp.pres) || (0 == local->sdp.numComp.val)){
&psdp->numComp, &rsp.u.mgCmdRsp[0]->memCp) != ROK)
{ if (mgUtlGrowList((void ***)&psdp->info, sizeof(CmSdpInfo),
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR,"Grow List failed\n"); &psdp->numComp, &rsp.u.mgCmdRsp[0]->memCp) != ROK)
return SWITCH_STATUS_FALSE; {
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; 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]->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 */ /* Fill attribute if reqd */
{ {
@ -893,6 +914,7 @@ switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *i
free(dup); free(dup);
} }
#endif
/* We will always send one command at a time..*/ /* 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 */ /* SDP updated to termination */
megaco_activate_termination(term); 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 */ /* 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; 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) */ /* Note : API to send Service Change when termination is coming up(in-service) */
/* INPUT : MG Profile structure and termination name */ /* 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* */ /* 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* */

View File

@ -52,6 +52,13 @@ typedef enum{
SNG_MG_ENCODING_TEXT, SNG_MG_ENCODING_TEXT,
}sng_mg_encoding_types_e; }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)\ #define PRNT_ENCODING_TYPE(_val)\
((_val == SNG_MG_ENCODING_TEXT)?"SNG_MG_ENCODING_TEXT":\ ((_val == SNG_MG_ENCODING_TEXT)?"SNG_MG_ENCODING_TEXT":\
(_val == SNG_MG_ENCODING_BINARY)?"SNG_MG_ENCODING_BINARY":\ (_val == SNG_MG_ENCODING_BINARY)?"SNG_MG_ENCODING_BINARY":\
@ -141,7 +148,7 @@ typedef enum {
(_reqId)->id.val = 0xFFFFFFFF; (_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_sng_log(uint8_t level, char *fmt, ...);
void handle_mgco_sta_ind(Pst *pst, SuId suId, MgMgtSta* msg); void handle_mgco_sta_ind(Pst *pst, SuId suId, MgMgtSta* msg);
void handle_mgco_txn_sta_ind(Pst *pst, SuId suId, MgMgcoInd* 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); int mg_disable_logging(void);
void mg_util_set_err_string ( MgStr *errTxt, char* str); 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_cfg(megaco_profile_t* profile);
switch_status_t sng_mgco_init(sng_mg_event_interface_t* event); 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_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); 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); 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_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); 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 handle_mg_audit_cmd(SuId suId, MgMgcoCommand *auditReq);
switch_status_t mg_stack_termination_is_in_service(char* term_str, int len); switch_status_t mg_stack_termination_is_in_service(char* term_str, int len);
void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand *cmd); 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_modify_rsp(SuId suId, MgMgcoCommand *req);
switch_status_t mg_send_subtract_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); 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_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_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_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); switch_status_t mg_send_ins_service_change(megaco_profile_t* mg_profile, const char* term_name, int wild);

View File

@ -25,8 +25,8 @@ void handle_mg_alarm(Pst *pst, MgMngmt *usta)
memset(&prBuf[0], 0, sizeof(prBuf)); memset(&prBuf[0], 0, sizeof(prBuf));
len = len + sprintf(prBuf+len,"MG Status Indication: received with Category = %d, Event = %d, Cause = %d \n", len = len + sprintf(prBuf+len,"MG Status Indication: received for sapId[%d] with Category = %d, Event = %d, Cause = %d \n",
usta->t.usta.alarm.category, usta->t.usta.alarm.event, usta->t.usta.alarmInfo.sapId, usta->t.usta.alarm.category, usta->t.usta.alarm.event,
usta->t.usta.alarm.cause); usta->t.usta.alarm.cause);
len = len + sprintf(prBuf+len, "Category ( "); len = len + sprintf(prBuf+len, "Category ( ");
@ -218,9 +218,8 @@ void handle_mg_alarm(Pst *pst, MgMngmt *usta)
case LMG_EVENT_PEER_ENABLED: case LMG_EVENT_PEER_ENABLED:
{ {
len = len + sprintf(prBuf+len, "gateway enabled"); len = len + sprintf(prBuf+len, "gateway enabled");
/* gateway enabled now we can send termination service change */ /* gateway enabled now we can send termination service change for all terminations */
/*TODO - probably we cannt immediate send Service change - we have to find proper place */ mgco_init_ins_service_change( usta->t.usta.alarmInfo.sapId );
/*mg_send_service_change(0x01, "A01", MGT_SVCCHGMETH_RESTART,MG_SVC_REASON_900_RESTORED );*/
break; break;
} }
case LMG_EVENT_PEER_DISCOVERED: case LMG_EVENT_PEER_DISCOVERED:

View File

@ -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; int i=0x00;
if (s->numComp.pres) { 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", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\t PTIME = %ld \n",
(NOTPRSNT != a->u.ptime.pres)?a->u.ptime.val:-1); (NOTPRSNT != a->u.ptime.pres)?a->u.ptime.val:-1);
#endif #endif
if(MG_TERM_RTP == term->type){
term->u.rtp.ptime = a->u.ptime.val;
}
break; break;
} }
case CM_SDP_ATTR_RECVONLY: 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); 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; int i=0x00;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "***** Media Parameter *********** \n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "***** Media Parameter *********** \n");
@ -837,6 +863,27 @@ 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;
term->u.rtp.pt = r->fmts[0]->val.val;
}
}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; break;
} }
@ -854,7 +901,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"); 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; int i;
@ -1021,7 +1068,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e
/************************************************************************************************************************/ /************************************************************************************************************************/
/* Attribute Set */ /* Attribute Set */
mgco_print_sdp_attr_set(&s->attrSet); mgco_handle_sdp_attr_set(&s->attrSet, term);
/************************************************************************************************************************/ /************************************************************************************************************************/
/* Media Descriptor Set */ /* Media Descriptor Set */
@ -1077,7 +1124,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e
break; 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 */ /*info */
@ -1097,7 +1144,7 @@ void mgco_handle_sdp(CmSdpInfoSet *sdp, mg_termination_t* term, mgco_sdp_types_e
} }
/* attribute set */ /* 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 && if (desc->field.mediaType.val == CM_SDP_MEDIA_AUDIO &&
@ -1441,3 +1488,515 @@ void mg_print_time()
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO,"Current Time = %s", ctime(&now)); 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++)
{
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 */
/* 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;
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);
}
}
}
}
}
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;
}
/*****************************************************************************************************************************/
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; i<out->num.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;
}
}
}
}
}
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, "-", 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]));
/**********************************************************************************************************************************/
/* 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;
}

View File

@ -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"/> // <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 *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
//const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base"); //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_prefix = switch_xml_attr(mg_term, "channel-prefix");
const char *channel_map = switch_xml_attr(mg_term, "channel-map"); 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 *channel_map_dup = strdup(channel_map);
char *chanmap[24]; char *chanmap[24];
int chanmap_count, i; 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++) { for (i = 0; i < chanmap_count; i++) {
char *p = strchr(chanmap[i], '-'); char *p = strchr(chanmap[i], '-');
if (p) { 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->type = MG_TERM_TDM;
term->profile = profile; term->profile = profile;
term->mg_ctxt = NULL; 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->name = switch_core_sprintf(pool, "%s%d", prefix, j);
term->u.tdm.channel = j; term->u.tdm.channel = j;
term->u.tdm.span_name = switch_core_strdup(pool, channel_prefix); 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; 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); 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-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-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("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() SWITCH_CONFIG_ITEM_END()
}; };

View File

@ -56,6 +56,54 @@ static switch_status_t list_profiles(const char *line, const char *cursor, switc
return status; 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_MODULE_LOAD_FUNCTION(mod_media_gateway_load)
{ {
switch_api_interface_t *api_interface; 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_set_complete("add mg logging ::mg::list_profiles disable");
switch_console_add_complete_func("::mg::list_profiles", list_profiles); switch_console_add_complete_func("::mg::list_profiles", list_profiles);
/* Initialize MEGACO Stack */ /* Initialize MEGACO Stack */
sng_event.mg.sng_mgco_txn_ind = handle_mgco_txn_ind; sng_event.mg.sng_mgco_txn_ind = handle_mgco_txn_ind;
sng_event.mg.sng_mgco_cmd_ind = handle_mgco_cmd_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 */ /* Log */
sng_event.sm.sng_log = handle_sng_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 */ /* initualize MEGACO stack */
return sng_mgco_init(&sng_event); return sng_mgco_init(&sng_event);
} }

View File

@ -112,7 +112,9 @@ struct mg_termination_s {
MgMgcoReqEvtDesc *active_events; /* !< active megaco events */ MgMgcoReqEvtDesc *active_events; /* !< active megaco events */
mg_termination_t *next; /*!< List for physical terminations */ mg_termination_t *next; /*!< List for physical terminations */
mg_context_t* mg_ctxt; mg_context_t* mg_ctxt;
int *mg_error_code; /* MEGACO error code */
uint32_t flags; uint32_t flags;
const char *tech; /* Endpoint controlling the TDM interface - only FreeTDM tested so far */
union { union {
struct { 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_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_context_sub_all_termination(mg_context_t *ctx);
switch_status_t megaco_activate_termination(mg_termination_t *term); 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_choose_termination(megaco_profile_t *profile, const char *prefix);
mg_termination_t *megaco_find_termination(megaco_profile_t *profile, const char *name); 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_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_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 */ #endif /* MOD_MEGACO_H */

View File

@ -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"); const char *command = switch_event_get_header(event, "command");
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
crtp_private_t *tech_pvt = switch_core_session_get_private(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")) { if (!zstr(command) && !strcasecmp(command, "media_modify")) {
/* Compare parameters */ /* Compare parameters */
if (compare_var(event, channel, kREMOTEADDR) || if (compare_var(event, channel, kREMOTEADDR) ||
compare_var(event, channel, kREMOTEPORT)) { compare_var(event, channel, kREMOTEPORT)) {
char *remote_addr = switch_event_get_header(event, kREMOTEADDR); char *remote_addr = switch_event_get_header(event, kREMOTEADDR);
char *szremote_port = switch_event_get_header(event, kREMOTEPORT); char *szremote_port = switch_event_get_header(event, kREMOTEPORT);
switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0;
const char *err; const char *err;
switch_channel_set_variable(channel, kREMOTEADDR, remote_addr); switch_channel_set_variable(channel, kREMOTEADDR, remote_addr);
switch_channel_set_variable(channel, kREMOTEPORT, szremote_port); 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) || if (compare_var(event, channel, kCODEC) ||
compare_var(event, channel, kPTIME) || compare_var(event, channel, kPTIME) ||
compare_var(event, channel, kPT) || compare_var(event, channel, kPT) ||
compare_var(event, channel, kRATE)) { compare_var(event, channel, kRATE)) {
/* Reset codec */ /* Reset codec */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Switching codec not yet implemented\n"); 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)) { if (compare_var(event, channel, kRFC2833PT)) {
const char *szpt = switch_channel_get_variable(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; 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) static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)