diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index b9534b8177..a9a459c054 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1409,6 +1409,36 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam return 0; } +static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **columnNames) +{ + struct cb_helper *cb = (struct cb_helper *) pArg; + char exp_buf[128] = ""; + switch_time_exp_t tm; + const int buflen = 2048; + char xmlbuf[buflen]; + + if (argv[6]) { + switch_time_t etime = atoi(argv[6]); + switch_size_t retsize; + + switch_time_exp_lt(&tm, switch_time_from_sec(etime)); + switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm); + } + + cb->stream->write_function(cb->stream, + "\n" + "%s\n" + "%s@%s\n" + "%s\n" + "%s\n" + "%s(%s) EXP(%s)\n" + "%s\n" + "\n", + switch_str_nil(argv[0]), switch_str_nil(argv[1]), switch_str_nil(argv[2]), switch_amp_encode(switch_str_nil(argv[3]),xmlbuf,buflen), + switch_str_nil(argv[7]), switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, switch_str_nil(argv[11])); + return 0; +} + static const char *status_names[] = { "DOWN", "UP", NULL }; static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream) @@ -1594,6 +1624,194 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t return SWITCH_STATUS_SUCCESS; } +static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handle_t *stream) +{ + sofia_profile_t *profile = NULL; + sofia_gateway_t *gp; + switch_hash_index_t *hi; + void *val; + const void *vvar; + const int buflen = 2096; + char xmlbuf[buflen]; + int c = 0; + int ac = 0; + const char *header = ""; + + if (argc > 0) { + if (argc == 1) { + stream->write_function(stream, "Invalid Syntax!\n"); + return SWITCH_STATUS_SUCCESS; + } + if (!strcasecmp(argv[0], "gateway")) { + if ((gp = sofia_reg_find_gateway(argv[1]))) { + switch_assert(gp->state < REG_STATE_LAST); + stream->write_function(stream, "%s\n", header); + stream->write_function(stream, "\n"); + stream->write_function(stream, "%s\n", switch_str_nil(gp->name)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_scheme)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_realm)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_username)); + stream->write_function(stream, "%s\n", switch_strlen_zero(gp->register_password) ? "no" : "yes"); + stream->write_function(stream, "%s\n", switch_amp_encode(switch_str_nil(gp->register_from),xmlbuf,buflen)); + stream->write_function(stream, "%s\n", switch_amp_encode(switch_str_nil(gp->register_contact),xmlbuf,buflen)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_to)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_proxy)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->register_context)); + stream->write_function(stream, "%s\n", switch_str_nil(gp->expires_str)); + stream->write_function(stream, "%d\n", gp->freq); + stream->write_function(stream, "%d\n", gp->ping); + stream->write_function(stream, "%d\n", gp->ping_freq); + stream->write_function(stream, "%s\n", sofia_state_names[gp->state]); + stream->write_function(stream, "%s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : ""); + stream->write_function(stream, "\n"); + sofia_reg_release_gateway(gp); + } else { + stream->write_function(stream, "Invalid Gateway!\n"); + } + } else if (!strcasecmp(argv[0], "profile")) { + struct cb_helper cb; + char *sql = NULL; + + if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1]))) { + if (!argv[2] || strcasecmp(argv[2], "reg")) { + stream->write_function(stream, "%s\n", header); + stream->write_function(stream, "\n"); + stream->write_function(stream, "\n"); + stream->write_function(stream, "%s\n", switch_str_nil(argv[1])); + stream->write_function(stream, "%s\n", profile->domain_name ? profile->domain_name : "N/A"); + if (strcasecmp(argv[1], profile->name)) { + stream->write_function(stream, "%s\n", switch_str_nil(profile->name)); + } + stream->write_function(stream, "%s\n", switch_str_nil(profile->dbname)); + stream->write_function(stream, "%s\n", switch_str_nil(profile->presence_hosts)); + stream->write_function(stream, "%s\n", switch_str_nil(profile->dialplan)); + stream->write_function(stream, "%s\n", switch_str_nil(profile->context)); + stream->write_function(stream, "%s\n", + switch_strlen_zero(profile->challenge_realm) ? "auto_to" : profile->challenge_realm); + stream->write_function(stream, "%s\n", switch_str_nil(profile->rtpip)); + if (profile->extrtpip) { + stream->write_function(stream, "%s\n", profile->extrtpip); + } + + stream->write_function(stream, "%s\n", switch_str_nil(profile->sipip)); + if (profile->extsipip) { + stream->write_function(stream, "%s\n", profile->extsipip); + } + stream->write_function(stream, "%s\n", switch_str_nil(profile->url)); + stream->write_function(stream, "%s\n", switch_str_nil(profile->bindurl)); + if (sofia_test_pflag(profile, PFLAG_TLS)) { + stream->write_function(stream, "%s\n", switch_str_nil(profile->tls_url)); + stream->write_function(stream, "%s\n", switch_str_nil(profile->tls_bindurl)); + } + stream->write_function(stream, "%s\n", switch_strlen_zero(profile->hold_music) ? "N/A" : profile->hold_music); + stream->write_function(stream, "%s\n", switch_str_nil(profile->codec_string)); + stream->write_function(stream, "%d\n", profile->te); + if (profile->dtmf_type == DTMF_2833) { + stream->write_function(stream, "rfc2833\n"); + } else if (profile->dtmf_type == DTMF_INFO) { + stream->write_function(stream, "info\n"); + } else { + stream->write_function(stream, "none\n"); + } + stream->write_function(stream, "%d\n", profile->cng_pt); + stream->write_function(stream, "%d\n", profile->session_timeout); + stream->write_function(stream, "%d\n", profile->max_proceeding); + stream->write_function(stream, "%s\n", switch_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false"); + stream->write_function(stream, "%s\n", switch_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false"); + stream->write_function(stream, "%s\n", switch_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false"); + stream->write_function(stream, "%s\n", sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false"); + stream->write_function(stream, "%s\n", sofia_test_pflag(profile, PFLAG_STUN_ENABLED) ? "true" : "false"); + stream->write_function(stream, "%s\n", sofia_test_pflag(profile, PFLAG_STUN_AUTO_DISABLE) ? "true" : "false"); + } + stream->write_function(stream, "\n"); + stream->write_function(stream, "\n"); + + cb.profile = profile; + cb.stream = stream; + + if (argv[3]) { + if (argv[4]) { + if (!strcasecmp(argv[3], "pres")) { + sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status," + "rpid,expires,user_agent,server_user,server_host,profile_name,hostname" + " from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", + profile->name, argv[4]); + } + } else { + sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status," + "rpid,expires,user_agent,server_user,server_host,profile_name,hostname" + " from sip_registrations where profile_name='%q' and contact like '%%%q%%'", + profile->name, argv[3]); + } + } + + if (!sql) { + sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status," + "rpid,expires,user_agent,server_user,server_host,profile_name,hostname" + " from sip_registrations where profile_name='%q'", + profile->name); + } + + sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, show_reg_callback_xml, &cb); + free(sql); + + stream->write_function(stream, "\n"); + stream->write_function(stream, "\n"); + + sofia_glue_release_profile(profile); + } else { + stream->write_function(stream, "Invalid Profile!\n"); + } + } else { + stream->write_function(stream, "Invalid Syntax!\n"); + } + + return SWITCH_STATUS_SUCCESS; + } + + stream->write_function(stream, "%s\n", header); + stream->write_function(stream, "\n"); + switch_mutex_lock(mod_sofia_globals.hash_mutex); + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &vvar, NULL, &val); + profile = (sofia_profile_t *) val; + if (sofia_test_pflag(profile, PFLAG_RUNNING)) { + + if (strcmp(vvar, profile->name)) { + ac++; + stream->write_function(stream, "\n%s\n%s\n%s\n%s\n\n", vvar, "alias", profile->name, "ALIASED"); + } else { + stream->write_function(stream, "\n%s\n%s\n%s\n%s (%u)\n\n", profile->name, "profile", profile->url, + sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN", profile->inuse); + + if (sofia_test_pflag(profile, PFLAG_TLS)) { + stream->write_function(stream, "\n%s\n%s\n%s\n%s (%u) (TLS)\n\n", profile->name, "profile", profile->tls_url, + sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN", profile->inuse); + } + + c++; + + for (gp = profile->gateways; gp; gp = gp->next) { + switch_assert(gp->state < REG_STATE_LAST); + stream->write_function(stream, "\n%s\n%s\n%s\n%s\n\n", gp->name, "gateway", gp->register_to, sofia_state_names[gp->state]); + if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) { + time_t now = switch_timestamp(NULL); + if (gp->retry > now) { + stream->write_function(stream, " (retry: %ds)", gp->retry - now); + } else { + stream->write_function(stream, " (retry: NEVER)"); + } + } + stream->write_function(stream, "\n"); + } + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + stream->write_function(stream, "\n"); + return SWITCH_STATUS_SUCCESS; +} + static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t *stream) { sofia_profile_t *profile = NULL; @@ -1983,6 +2201,8 @@ SWITCH_STANDARD_API(sofia_function) func = cmd_profile; } else if (!strcasecmp(argv[0], "status")) { func = cmd_status; + } else if (!strcasecmp(argv[0], "xmlstatus")) { + func = cmd_xml_status; } else if (!strcasecmp(argv[0], "loglevel")) { if (argc > 1 && argv[1]) { int level;