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;