mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-15 13:58:32 +00:00
849 lines
33 KiB
C
849 lines
33 KiB
C
/*
|
|
* Copyright (c) 2012, Sangoma Technologies
|
|
* Mathieu Rene <mrene@avgs.ca>
|
|
* All rights reserved.
|
|
*
|
|
* <Insert license here>
|
|
*/
|
|
|
|
#include "mod_media_gateway.h"
|
|
#include "media_gateway_stack.h"
|
|
|
|
|
|
/**************************************************************************************************************/
|
|
struct megaco_globals megaco_globals;
|
|
static sng_mg_event_interface_t sng_event;
|
|
|
|
/**************************************************************************************************************/
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_media_gateway_load);
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_media_gateway_shutdown);
|
|
SWITCH_MODULE_DEFINITION(mod_media_gateway, mod_media_gateway_load, mod_media_gateway_shutdown, NULL);
|
|
|
|
/**************************************************************************************************************/
|
|
|
|
SWITCH_STANDARD_API(megaco_function)
|
|
{
|
|
return mg_process_cli_cmd(cmd, stream);
|
|
}
|
|
|
|
SWITCH_STANDARD_APP(mg_notify_function)
|
|
{
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
|
mg_termination_t *term = switch_channel_get_private(channel, PVT_MG_TERM);
|
|
|
|
if (!term) {
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "mg_notify called on a non-supported channel.\n");
|
|
return;
|
|
}
|
|
|
|
if (!strcmp(data, "cng")) {
|
|
mg_send_t38_cng_notify(term->profile, term->name);
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent CNG notify\n");
|
|
switch_channel_set_variable(channel, "mg_cng_detected", "true");
|
|
}
|
|
}
|
|
|
|
static switch_status_t console_complete_hashtable(switch_hash_t *hash, const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
|
{
|
|
switch_hash_index_t *hi;
|
|
void *val;
|
|
const void *vvar;
|
|
switch_console_callback_match_t *my_matches = NULL;
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
for (hi = switch_hash_first(NULL, hash); hi; hi = switch_hash_next(hi)) {
|
|
switch_hash_this(hi, &vvar, NULL, &val);
|
|
switch_console_push_match(&my_matches, (const char *) vvar);
|
|
}
|
|
|
|
if (my_matches) {
|
|
*matches = my_matches;
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
|
{
|
|
switch_status_t status;
|
|
switch_thread_rwlock_rdlock(megaco_globals.profile_rwlock);
|
|
status = console_complete_hashtable(megaco_globals.profile_hash, line, cursor, matches);
|
|
switch_thread_rwlock_unlock(megaco_globals.profile_rwlock);
|
|
return status;
|
|
}
|
|
|
|
static void mg_event_handler(switch_event_t *event)
|
|
{
|
|
switch(event->event_id) {
|
|
case SWITCH_EVENT_TRAP:
|
|
{
|
|
const char *span_name = NULL;
|
|
const char *chan_number = NULL;
|
|
const char *cond = NULL;
|
|
|
|
cond = switch_event_get_header(event, "condition");
|
|
if (zstr(cond)) {
|
|
return;
|
|
}
|
|
|
|
span_name = switch_event_get_header(event, "span-name");
|
|
chan_number = switch_event_get_header(event, "chan-number");
|
|
|
|
if (!strcmp(cond, "ftdm-alarm-trap")) {
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
|
"ftdm-alarm-trap for span_name[%s] chan_number[%s]\n", span_name,chan_number);
|
|
mg_send_term_service_change((char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_OUT_OF_SERVICE);
|
|
} else if (!strcmp(cond, "ftdm-alarm-clear")) {
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
|
"ftdm-alarm-clear for span_name[%s] chan_number[%s] \n", span_name,chan_number);
|
|
mg_send_term_service_change( (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;
|
|
switch_application_interface_t *app_interface;
|
|
|
|
memset(&megaco_globals, 0, sizeof(megaco_globals));
|
|
megaco_globals.pool = pool;
|
|
|
|
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
|
|
|
switch_core_hash_init(&megaco_globals.profile_hash, pool);
|
|
switch_thread_rwlock_create(&megaco_globals.profile_rwlock, pool);
|
|
|
|
switch_core_hash_init(&megaco_globals.peer_profile_hash, pool);
|
|
switch_thread_rwlock_create(&megaco_globals.peer_profile_rwlock, pool);
|
|
|
|
SWITCH_ADD_API(api_interface, "mg", "media_gateway", megaco_function, MEGACO_FUNCTION_SYNTAX);
|
|
SWITCH_ADD_APP(app_interface, "mg_notify", "<type>", "sends a notify to the mgc", mg_notify_function, "", 0);
|
|
|
|
switch_console_set_complete("add mg profile ::mg::list_profiles start");
|
|
switch_console_set_complete("add mg profile ::mg::list_profiles stop");
|
|
switch_console_set_complete("add mg profile ::mg::list_profiles status");
|
|
switch_console_set_complete("add mg profile ::mg::list_profiles xmlstatus");
|
|
switch_console_set_complete("add mg profile ::mg::list_profiles peerxmlstatus");
|
|
switch_console_set_complete("add mg logging ::mg::list_profiles enable");
|
|
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;
|
|
sng_event.mg.sng_mgco_txn_sta_ind = handle_mgco_txn_sta_ind;
|
|
sng_event.mg.sng_mgco_sta_ind = handle_mgco_sta_ind;
|
|
sng_event.mg.sng_mgco_cntrl_cfm = handle_mgco_cntrl_cfm;
|
|
sng_event.mg.sng_mgco_audit_cfm = handle_mgco_audit_cfm;
|
|
/* Alarm CB */
|
|
sng_event.sm.sng_mg_alarm = handle_mg_alarm;
|
|
sng_event.sm.sng_tucl_alarm = handle_tucl_alarm;
|
|
/* 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 */
|
|
if(SWITCH_STATUS_FALSE == sng_mgco_init(&sng_event)){
|
|
return SWITCH_STATUS_FALSE;
|
|
}
|
|
|
|
if(SWITCH_STATUS_FALSE == megaco_start_all_profiles()){
|
|
return SWITCH_STATUS_FALSE;
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
}
|
|
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_media_gateway_shutdown)
|
|
{
|
|
void *val = NULL;
|
|
const void *key = NULL;
|
|
switch_ssize_t keylen;
|
|
switch_hash_index_t *hi = NULL;
|
|
megaco_profile_t* profile = NULL;
|
|
mg_peer_profile_t* peer_profile = NULL;
|
|
|
|
/* destroy all the mg profiles */
|
|
while ((hi = switch_hash_first(NULL, megaco_globals.profile_hash))) {
|
|
switch_hash_this(hi, &key, &keylen, &val);
|
|
profile = (megaco_profile_t *) val;
|
|
if(profile->inact_tmr_task_id){
|
|
switch_scheduler_del_task_id(profile->inact_tmr_task_id);
|
|
profile->inact_tmr_task_id = 0x00;
|
|
}
|
|
megaco_profile_destroy(&profile);
|
|
profile = NULL;
|
|
}
|
|
|
|
hi = NULL;
|
|
key = NULL;
|
|
val = NULL;
|
|
/* destroy all the mg peer profiles */
|
|
while ((hi = switch_hash_first(NULL, megaco_globals.peer_profile_hash))) {
|
|
switch_hash_this(hi, &key, &keylen, &val);
|
|
peer_profile = (mg_peer_profile_t *) val;
|
|
megaco_peer_profile_destroy(&peer_profile);
|
|
peer_profile = NULL;
|
|
}
|
|
|
|
sng_mgco_stack_shutdown();
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
switch_status_t megaco_start_all_profiles()
|
|
{
|
|
switch_xml_t cfg, xml, mg_interfaces, mg_interface ;
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
const char *file = "media_gateway.conf";
|
|
|
|
if (!(xml = switch_xml_open_cfg(file, &cfg, NULL))) {
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open %s\n", file);
|
|
status = SWITCH_STATUS_FALSE;
|
|
goto done;
|
|
}
|
|
|
|
if (!(mg_interfaces = switch_xml_child(cfg, "mg_profiles"))) {
|
|
status = SWITCH_STATUS_FALSE;
|
|
goto done;
|
|
}
|
|
|
|
for (mg_interface = switch_xml_child(mg_interfaces, "mg_profile"); mg_interface; mg_interface = mg_interface->next) {
|
|
const char *name = switch_xml_attr_soft(mg_interface, "name");
|
|
|
|
if(SWITCH_STATUS_FALSE == megaco_profile_start(name)){
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error starting MEGACO profile %s\n", name);
|
|
status = SWITCH_STATUS_FALSE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
done:
|
|
if (xml) {
|
|
switch_xml_free(xml);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
void handle_sng_log(uint8_t level, char *fmt, ...)
|
|
{
|
|
int log_level;
|
|
char print_buf[1024];
|
|
va_list ptr;
|
|
|
|
memset(&print_buf[0],0,sizeof(1024));
|
|
|
|
va_start(ptr, fmt);
|
|
|
|
switch(level)
|
|
{
|
|
case SNG_LOGLEVEL_DEBUG: log_level = SWITCH_LOG_DEBUG; break;
|
|
case SNG_LOGLEVEL_INFO: log_level = SWITCH_LOG_INFO; break;
|
|
case SNG_LOGLEVEL_WARN: log_level = SWITCH_LOG_WARNING; break;
|
|
case SNG_LOGLEVEL_ERROR: log_level = SWITCH_LOG_ERROR; break;
|
|
case SNG_LOGLEVEL_CRIT: log_level = SWITCH_LOG_CRIT; break;
|
|
default: log_level = SWITCH_LOG_DEBUG; break;
|
|
};
|
|
|
|
vsprintf(&print_buf[0], fmt, ptr);
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, log_level, " MOD_MEGACO: %s \n", &print_buf[0]);
|
|
|
|
va_end(ptr);
|
|
}
|
|
/*****************************************************************************************************************************/
|
|
|
|
|
|
/* KAPIL- NOTE : We are using Command mode operation of MEGACO stack, so we will always get command indication instead of transaction */
|
|
/* Below API is not useful ... just leaving as it is...*/
|
|
|
|
void handle_mgco_txn_ind(Pst *pst, SuId suId, MgMgcoMsg* msg)
|
|
{
|
|
size_t txnIter;
|
|
switch_memory_pool_t *pool;
|
|
|
|
switch_core_new_memory_pool(&pool);
|
|
|
|
/*TODO*/
|
|
if(msg->body.type.val == MGT_TXN)
|
|
{
|
|
/* Loop over transaction list */
|
|
for(txnIter=0;txnIter<msg->body.u.tl.num.val;txnIter++)
|
|
{
|
|
|
|
switch(msg->body.u.tl.txns[txnIter]->type.val) {
|
|
case MGT_TXNREQ:
|
|
{
|
|
MgMgcoTxnReq* txnReq;
|
|
/*MgMgcoTransId transId; *//* XXX */
|
|
int axnIter;
|
|
txnReq = &(msg->body.u.tl.txns[txnIter]->u.req);
|
|
|
|
/* Loop over action list */
|
|
for (axnIter=0;axnIter<txnReq->al.num.val;axnIter++) {
|
|
MgMgcoActionReq *actnReq;
|
|
MgMgcoContextId ctxId;
|
|
int cmdIter;
|
|
|
|
actnReq = txnReq->al.actns[axnIter];
|
|
ctxId = actnReq->cxtId; /* XXX */
|
|
|
|
if (actnReq->pres.pres == NOTPRSNT) {
|
|
continue;
|
|
}
|
|
|
|
/* Loop over command list */
|
|
for (cmdIter=0; cmdIter < (actnReq->cl.num.val); cmdIter++) {
|
|
MgMgcoCommandReq *cmdReq = actnReq->cl.cmds[cmdIter];
|
|
/*MgMgcoTermId *term_id = NULLP;*/
|
|
/* The reply we'll send */
|
|
MgMgcoCommand mgCmd;
|
|
memset(&mgCmd, 0, sizeof(mgCmd));
|
|
mgCmd.peerId = msg->lcl.id;
|
|
mgCmd.u.mgCmdInd[0] = cmdReq;
|
|
|
|
|
|
/* XXX Handle choose context before this */
|
|
|
|
mgCmd.contextId = ctxId;
|
|
/*mgCmd.transId = transId;*/
|
|
|
|
mgCmd.cmdStatus.pres = PRSNT_NODEF;
|
|
|
|
if(cmdIter == (actnReq->cl.num.val -1))
|
|
{
|
|
mgCmd.cmdStatus.val = CH_CMD_STATUS_END_OF_AXN;
|
|
if(axnIter == (txnReq->al.num.val-1))
|
|
{
|
|
mgCmd.cmdStatus.val= CH_CMD_STATUS_END_OF_TXN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mgCmd.cmdStatus.val = CH_CMD_STATUS_PENDING;
|
|
}
|
|
|
|
/* XXX handle props */
|
|
mgCmd.cmdType.pres = PRSNT_NODEF;
|
|
mgCmd.cmdType.val = CH_CMD_TYPE_REQ;
|
|
mgCmd.u.mgCmdReq[0] = cmdReq;
|
|
sng_mgco_send_cmd(suId, &mgCmd);
|
|
|
|
|
|
switch (cmdReq->cmd.type.val) {
|
|
case MGT_ADD:
|
|
{
|
|
MgMgcoAmmReq *addReq = &cmdReq->cmd.u.add;
|
|
int descId;
|
|
for (descId = 0; descId < addReq->dl.num.val; descId++) {
|
|
switch (addReq->dl.descs[descId]->type.val) {
|
|
case MGT_MEDIADESC:
|
|
{
|
|
int mediaId;
|
|
for (mediaId = 0; mediaId < addReq->dl.descs[descId]->u.media.num.val; mediaId++) {
|
|
MgMgcoMediaPar *mediaPar = addReq->dl.descs[descId]->u.media.parms[mediaId];
|
|
switch (mediaPar->type.val) {
|
|
case MGT_MEDIAPAR_LOCAL:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MGT_MEDIAPAR_LOCAL");
|
|
break;
|
|
}
|
|
case MGT_MEDIAPAR_REMOTE:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MGT_MEDIAPAR_REMOTE");
|
|
break;
|
|
}
|
|
|
|
case MGT_MEDIAPAR_LOCCTL:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MGT_MEDIAPAR_LOCCTL");
|
|
break;
|
|
}
|
|
case MGT_MEDIAPAR_TERMST:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MGT_MEDIAPAR_TERMST");
|
|
break;
|
|
}
|
|
case MGT_MEDIAPAR_STRPAR:
|
|
{
|
|
// MgMgcoStreamDesc *mgStream = &mediaPar->u.stream;
|
|
//
|
|
// if (mgStream->sl.remote.pres.pres) {
|
|
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got remote stream media description:\n");
|
|
// mgco_print_sdp(&mgStream->sl.remote.sdp);
|
|
// }
|
|
//
|
|
// if (mgStream->sl.local.pres.pres) {
|
|
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got local stream media description:\n");
|
|
// mgco_print_sdp(&mgStream->sl.local.sdp);
|
|
// }
|
|
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case MGT_MODEMDESC:
|
|
case MGT_MUXDESC:
|
|
case MGT_REQEVTDESC:
|
|
case MGT_EVBUFDESC:
|
|
case MGT_SIGNALSDESC:
|
|
case MGT_DIGMAPDESC:
|
|
case MGT_AUDITDESC:
|
|
case MGT_STATSDESC:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
}
|
|
case MGT_MODIFY:
|
|
{
|
|
/*MgMgcoAmmReq *addReq = &cmdReq->cmd.u.mod;*/
|
|
break;
|
|
}
|
|
case MGT_MOVE:
|
|
{
|
|
/*MgMgcoAmmReq *addReq = &cmdReq->cmd.u.move;*/
|
|
break;
|
|
|
|
}
|
|
case MGT_SUB:
|
|
{
|
|
/*MgMgcoSubAudReq *addReq = &cmdReq->cmd.u.sub;*/
|
|
}
|
|
case MGT_SVCCHG:
|
|
case MGT_NTFY:
|
|
case MGT_AUDITCAP:
|
|
case MGT_AUDITVAL:
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MGT_TXNREPLY:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MGT_TXNREPLY\n");
|
|
break;
|
|
}
|
|
default:
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received unknown command %d in transaction\n", msg->body.u.tl.txns[txnIter]->type.val);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
|
|
{
|
|
MgMgcoContextId out_ctxt;
|
|
U32 txn_id = 0x00;
|
|
MgMgcoInd *mgErr;
|
|
MgStr errTxt;
|
|
MgMgcoContextId ctxtId;
|
|
MgMgcoContextId *inc_context;
|
|
MgMgcoTermIdLst* termLst;
|
|
MgMgcoTermId *termId;
|
|
int count;
|
|
int err_code;
|
|
megaco_profile_t* mg_profile;
|
|
|
|
memset(&out_ctxt,0,sizeof(out_ctxt));
|
|
|
|
inc_context = &cmd->contextId;
|
|
memcpy(&out_ctxt, inc_context,sizeof(MgMgcoContextId));
|
|
|
|
/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"%s: Received Command Type[%s] \n", __PRETTY_FUNCTION__, PRNT_MG_CMD_TYPE(cmd->cmdType.val));*/
|
|
|
|
/*get mg profile associated with SuId */
|
|
if(NULL == (mg_profile = megaco_get_profile_by_suId(suId))){
|
|
goto error1;
|
|
}
|
|
|
|
/* first thing - restart ito timer */
|
|
mg_restart_inactivity_timer(mg_profile);
|
|
|
|
/* validate Transaction Id */
|
|
if (NOTPRSNT != cmd->transId.pres){
|
|
txn_id = cmd->transId.val;
|
|
} else {
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s: Transaction Id not present, rejecting\n", __PRETTY_FUNCTION__);
|
|
|
|
/*-- Send Error to MG Stack --*/
|
|
MG_ZERO(&ctxtId, sizeof(MgMgcoContextId));
|
|
ctxtId.type.pres = NOTPRSNT;
|
|
ctxtId.val.pres = NOTPRSNT;
|
|
|
|
mg_util_set_txn_string(&errTxt, &txn_id);
|
|
err_code = MGT_MGCO_RSP_CODE_INVLD_IDENTIFIER;
|
|
goto error;
|
|
}
|
|
|
|
/* Get the termination Id list from the command(Note: GCP_2_1 has termination list , else it will be termination Id) */
|
|
termLst = mg_get_term_id_list(cmd);
|
|
if ((NULL == termLst) || (NOTPRSNT == termLst->num.pres)) {
|
|
/* termination-id not present , error */
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Termination-Id Not received..rejecting command \n");
|
|
|
|
/*-- Send Error to MG Stack --*/
|
|
MG_ZERO(&ctxtId, sizeof(MgMgcoContextId));
|
|
ctxtId.type.pres = NOTPRSNT;
|
|
ctxtId.val.pres = NOTPRSNT;
|
|
mg_util_set_txn_string(&errTxt, &txn_id);
|
|
err_code = MGT_MGCO_RSP_CODE_INVLD_IDENTIFIER;
|
|
goto error;
|
|
}
|
|
|
|
termId = termLst->terms[0];
|
|
|
|
|
|
/* Not sure - IF Stack fills term type properly..but adding code just to be sure ...*/
|
|
if ((PRSNT_NODEF == termId->type.pres) &&
|
|
(MGT_TERMID_OTHER == termId->type.val)) {
|
|
/* Checking the $ in the pathname */
|
|
if ((PRSNT_NODEF == termId->name.pres.pres) &&
|
|
(PRSNT_NODEF == termId->name.lcl.pres)) {
|
|
for (count = 0; count < termId->name.lcl.len; count++) {
|
|
if (termId->name.lcl.val[count] == '$') {
|
|
termId->type.val = MGT_TERMID_CHOOSE;
|
|
break;
|
|
}
|
|
|
|
if (termId->name.lcl.val[count] == '*') {
|
|
termId->type.val = MGT_TERMID_ALL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"Termination-Id received..value[%s] type[%d] \n", termId->name.lcl.val, termId->type.val);*/
|
|
|
|
/*If term type is other then check if that term is configured with us..for term type CHOOSE/ALL , no need to check */
|
|
/* check is only if command is not AUDIT */
|
|
if ((CH_CMD_TYPE_IND == cmd->cmdType.val) &&
|
|
(MGT_TERMID_OTHER == termId->type.val) &&
|
|
(MGT_AUDITVAL != cmd->u.mgCmdInd[0]->cmd.type.val)){
|
|
if(SWITCH_STATUS_FALSE == mg_stack_termination_is_in_service(mg_profile, (char*)termId->name.lcl.val, termId->name.lcl.len)){
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Termination[%s] not in service \n", (char*)termId->name.lcl.val);
|
|
mg_util_set_term_string(&errTxt, termId);
|
|
err_code = MGT_MGCO_RSP_CODE_UNKNOWN_TERM_ID;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
|
|
/* Validate Context - if context is specified then check if its present with us */
|
|
MG_ZERO(&ctxtId, sizeof(MgMgcoContextId));
|
|
memcpy(&ctxtId, inc_context, sizeof(MgMgcoContextId));
|
|
|
|
if(NOTPRSNT == inc_context->type.pres){
|
|
goto ctxt_error;
|
|
|
|
}else if(MGT_CXTID_OTHER == inc_context->type.pres){
|
|
|
|
if(NOTPRSNT != inc_context->val.pres){
|
|
#ifdef BIT_64
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"Context specific request for contextId[%d]\n",inc_context->val.val);
|
|
#else
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"Context specific request for contextId[%ld]\n",inc_context->val.val);
|
|
#endif
|
|
/* check if context present with us */
|
|
if(NULL == megaco_find_context_by_suid(suId, inc_context->val.val)){
|
|
goto ctxt_error;
|
|
}
|
|
}else{
|
|
/* context id value not present - in case of type OTHER we should have context value */
|
|
goto ctxt_error;
|
|
}
|
|
}
|
|
|
|
|
|
/*mgAccEvntPrntMgMgcoCommand(cmd, stdout);*/
|
|
|
|
|
|
switch(cmd->cmdType.val)
|
|
{
|
|
case CH_CMD_TYPE_IND:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: Received Command indication for command[%s]\n",
|
|
__PRETTY_FUNCTION__,PRNT_MG_CMD(cmd->u.mgCmdInd[0]->cmd.type.val));
|
|
|
|
switch(cmd->u.mgCmdInd[0]->cmd.type.val)
|
|
{
|
|
case MGT_ADD:
|
|
{
|
|
handle_mg_add_cmd(mg_profile, cmd, &out_ctxt);
|
|
/*mg_send_add_rsp(suId, cmd);*/
|
|
break;
|
|
}
|
|
|
|
case MGT_MODIFY:
|
|
{
|
|
/*MgMgcoAmmReq *addReq = &cmdReq->cmd.u.mod;*/
|
|
handle_mg_modify_cmd(mg_profile, cmd);
|
|
/*mg_send_modify_rsp(suId, cmd);*/
|
|
break;
|
|
}
|
|
case MGT_MOVE:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MOVE Method Not Yet Supported\n");
|
|
err_code = MGT_MGCO_RSP_CODE_UNSUPPORTED_CMD;
|
|
mg_util_set_cmd_name_string(&errTxt, cmd);
|
|
goto error;
|
|
}
|
|
case MGT_SUB:
|
|
{
|
|
/*MgMgcoSubAudReq *addReq = &cmdReq->cmd.u.sub;*/
|
|
handle_mg_subtract_cmd(mg_profile, cmd);
|
|
/*mg_send_subtract_rsp(suId, cmd);*/
|
|
break;
|
|
}
|
|
case MGT_SVCCHG:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Service-Change Method Not Yet Supported\n");
|
|
break;
|
|
}
|
|
case MGT_NTFY:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOTIFY Method Not Yet Supported\n");
|
|
break;
|
|
}
|
|
case MGT_AUDITCAP:
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Audit-Capability Method Not Yet Supported\n");
|
|
err_code = MGT_MGCO_RSP_CODE_UNSUPPORTED_CMD;
|
|
mg_util_set_cmd_name_string(&errTxt, cmd);
|
|
goto error;
|
|
}
|
|
case MGT_AUDITVAL:
|
|
{
|
|
handle_mg_audit_cmd(mg_profile, cmd);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CH_CMD_TYPE_REQ:
|
|
{
|
|
break;
|
|
}
|
|
case CH_CMD_TYPE_RSP:
|
|
{
|
|
break;
|
|
}
|
|
case CH_CMD_TYPE_CFM:
|
|
{
|
|
#ifdef BIT_64
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received Command[%s] txn[%d] Response/Confirmation \n",
|
|
PRNT_MG_CMD(cmd->u.mgCmdCfm[0]->type.val), txn_id);
|
|
#else
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received Command[%s] txn[%ld] Response/Confirmation \n",
|
|
PRNT_MG_CMD(cmd->u.mgCmdCfm[0]->type.val), txn_id);
|
|
#endif
|
|
switch(cmd->u.mgCmdCfm[0]->type.val)
|
|
{
|
|
case MGT_NTFY:
|
|
{
|
|
MgMgcoNtfyReply* ntfy = &cmd->u.mgCmdCfm[0]->u.ntfy;
|
|
MgMgcoTermId* term = NULL;
|
|
char term_name[32];
|
|
memset(&term_name[0], 0x00,32);
|
|
|
|
strcpy(&term_name[0], "Invalid");
|
|
|
|
#ifdef GCP_VER_2_1
|
|
if((NOTPRSNT != ntfy->termIdLst.num.pres) &&
|
|
(0 != ntfy->termIdLst.num.val)){
|
|
term = ntfy->termIdLst.terms[0];
|
|
}
|
|
#else
|
|
term = &ntfy->termId;
|
|
|
|
#endif
|
|
if(NOTPRSNT != term->type.pres){
|
|
if(MGT_TERMID_ROOT == term->type.val){
|
|
strcpy(&term_name[0],"ROOT");
|
|
}
|
|
else if(MGT_TERMID_OTHER == term->type.val){
|
|
strcpy(&term_name[0], (char*)term->name.lcl.val);
|
|
}else if(MGT_TERMID_ALL == term->type.val){
|
|
strcpy(&term_name[0],"ALL Termination");
|
|
}else if(MGT_TERMID_CHOOSE == term->type.val){
|
|
strcpy(&term_name[0],"CHOOSE Termination");
|
|
}
|
|
}
|
|
|
|
if(NOTPRSNT != ntfy->pres.pres){
|
|
if((NOTPRSNT != ntfy->err.pres.pres) &&
|
|
(NOTPRSNT != ntfy->err.code.pres)){
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"Received NOTIFY command response with ErroCode[%d] for Termination[%s] \n",
|
|
ntfy->err.code.val, &term_name[0]);
|
|
}
|
|
else{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"Received Successful NOTIFY command response for Termination[%s] \n", &term_name[0]);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MGT_SVCCHG:
|
|
{
|
|
MgMgcoSvcChgReply* svc = &cmd->u.mgCmdCfm[0]->u.svc;
|
|
MgMgcoTermId* term = NULL;
|
|
char term_name[32];
|
|
memset(&term_name[0], 0x00, 32);
|
|
|
|
strcpy(&term_name[0], "Invalid");
|
|
|
|
#ifdef GCP_VER_2_1
|
|
if((NOTPRSNT != svc->termIdLst.num.pres) &&
|
|
(0 != svc->termIdLst.num.val)){
|
|
term = svc->termIdLst.terms[0];
|
|
}
|
|
#else
|
|
term = &svc->termId;
|
|
|
|
#endif
|
|
if(NOTPRSNT != term->type.pres){
|
|
if(MGT_TERMID_ROOT == term->type.val){
|
|
strcpy(&term_name[0],"ROOT");
|
|
}
|
|
else if(MGT_TERMID_OTHER == term->type.val){
|
|
strcpy(&term_name[0], (char*)term->name.lcl.val);
|
|
}else if(MGT_TERMID_ALL == term->type.val){
|
|
strcpy(&term_name[0],"ALL Termination");
|
|
}else if(MGT_TERMID_CHOOSE == term->type.val){
|
|
strcpy(&term_name[0],"CHOOSE Termination");
|
|
}
|
|
}
|
|
|
|
if(NOTPRSNT != svc->pres.pres){
|
|
|
|
if((NOTPRSNT != svc->res.type.pres) &&
|
|
(MGT_ERRDESC == svc->res.type.val)){
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"Received Service-Change command response with ErroCode[%d] for Termination[%s] \n",
|
|
svc->res.u.err.code.val, &term_name[0]);
|
|
}
|
|
else{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
|
"Received Successful Service-Change command response for Termination[%s] \n", &term_name[0]);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
#ifdef BIT_64
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid command type[%d]\n",cmd->cmdType.val);
|
|
#else
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid command type[%d]\n",cmd->cmdType.val);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/* END OF TXN received - means last command in txn to process.
|
|
* Send response to peer */
|
|
if(CH_CMD_TYPE_IND == cmd->cmdType.val){
|
|
/*if(CH_CMD_STATUS_END_OF_TXN == cmd->cmdStatus.val)*/
|
|
mg_send_end_of_axn(suId, &cmd->transId, &out_ctxt, &cmd->peerId);
|
|
}
|
|
|
|
return;
|
|
|
|
ctxt_error:
|
|
err_code = MGT_MGCO_RSP_CODE_UNKNOWN_CTXT;
|
|
|
|
error:
|
|
if (SWITCH_STATUS_SUCCESS ==
|
|
mg_build_mgco_err_request(&mgErr, txn_id, &ctxtId, err_code, &errTxt)) {
|
|
sng_mgco_send_err(suId, mgErr);
|
|
}
|
|
if(CH_CMD_STATUS_END_OF_TXN == cmd->cmdStatus.val){
|
|
mg_send_end_of_axn(suId, &cmd->transId, &out_ctxt, &cmd->peerId);
|
|
}
|
|
error1:
|
|
mg_free_cmd(cmd);
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
void handle_mgco_sta_ind(Pst *pst, SuId suId, MgMgtSta* sta)
|
|
{
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", __PRETTY_FUNCTION__); /*TODO*/
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
|
|
void handle_mgco_txn_sta_ind(Pst *pst, SuId suId, MgMgcoInd* txn_sta_ind)
|
|
{
|
|
/*TODO*/
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", __PRETTY_FUNCTION__);
|
|
|
|
/*dump information*/
|
|
mgAccEvntPrntMgMgcoInd(txn_sta_ind, stdout);
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
void handle_mgco_cntrl_cfm(Pst *pst, SuId suId, MgMgtCntrl* cntrl, Reason reason)
|
|
{
|
|
/*TODO*/
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
/*****************************************************************************************************************************/
|
|
void handle_mgco_audit_cfm(Pst *pst, SuId suId, MgMgtAudit* audit, Reason reason)
|
|
{
|
|
/*TODO*/
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
/*****************************************************************************************************************************/
|
|
|
|
/*****************************************************************************************************************************/
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c
|
|
* indent-tabs-mode:t
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
|
*/
|