/* * Copyright (c) 2012, Sangoma Technologies * Mathieu Rene * All rights reserved. * * */ #include "mod_megaco.h" struct megaco_globals megaco_globals; static sng_isup_event_interface_t sng_event; SWITCH_MODULE_LOAD_FUNCTION(mod_megaco_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_megaco_shutdown); SWITCH_MODULE_DEFINITION(mod_megaco, mod_megaco_load, mod_megaco_shutdown, NULL); #define MEGACO_FUNCTION_SYNTAX "profile [name] [start | stop]" SWITCH_STANDARD_API(megaco_function) { int argc; char *argv[10]; char *dup = NULL; if (zstr(cmd)) { goto usage; } dup = strdup(cmd); argc = switch_split(dup, ' ', argv); if (argc < 1 || zstr(argv[0])) { goto usage; } if (!strcmp(argv[0], "profile")) { if (zstr(argv[1]) || zstr(argv[2])) { goto usage; } if (!strcmp(argv[2], "start")) { megaco_profile_t *profile = megaco_profile_locate(argv[1]); if (profile) { megaco_profile_release(profile); stream->write_function(stream, "-ERR Profile %s is already started\n", argv[2]); } else { megaco_profile_start(argv[1]); stream->write_function(stream, "+OK\n"); } } else if (!strcmp(argv[2], "stop")) { megaco_profile_t *profile = megaco_profile_locate(argv[1]); if (profile) { megaco_profile_release(profile); megaco_profile_destroy(&profile); stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR No such profile\n"); } } } goto done; usage: stream->write_function(stream, "-ERR Usage: "MEGACO_FUNCTION_SYNTAX"\n"); done: switch_safe_free(dup); return SWITCH_STATUS_SUCCESS; } 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; } SWITCH_MODULE_LOAD_FUNCTION(mod_megaco_load) { switch_api_interface_t *api_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_ADD_API(api_interface, "megaco", "megaco", megaco_function, MEGACO_FUNCTION_SYNTAX); switch_console_set_complete("add megaco profile ::megaco::list_profiles start"); switch_console_set_complete("add megaco profile ::megaco::list_profiles stop"); switch_console_add_complete_func("::megaco::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; /* initalize sng_mg library */ sng_isup_init_gen(&sng_event); return SWITCH_STATUS_SUCCESS; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_megaco_shutdown) { /* TODO: Kapil: Insert stack global shutdown code here */ return SWITCH_STATUS_SUCCESS; } /*****************************************************************************************************************************/ 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, log_level, " MOD_MEGACO: %s \n", &print_buf[0]); va_end(ptr); } /*****************************************************************************************************************************/ void handle_mgco_txn_ind(Pst *pst, SuId suId, MgMgcoMsg* msg) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mgco_sta_ind(Pst *pst, SuId suId, MgMgtSta* sta) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mgco_txn_sta_ind(Pst *pst, SuId suId, MgMgcoInd* txn_sta_ind) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mgco_cntrl_cfm(Pst *pst, SuId suId, MgMgtCntrl* cntrl, Reason reason) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mgco_audit_cfm(Pst *pst, SuId suId, MgMgtAudit* audit, Reason reason) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_mg_alarm(Pst *pst, MgMngmt *sta) { /*TODO*/ } /*****************************************************************************************************************************/ void handle_tucl_alarm(Pst *pst, HiMngmt *sta) { /*TODO*/ } /*****************************************************************************************************************************/ /* 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: */