From 614bc42e2ce07492ec8410d4046521a4a6ed6cac Mon Sep 17 00:00:00 2001 From: lazedo Date: Tue, 30 Oct 2018 19:58:00 +0000 Subject: [PATCH] [FS-11607] [mod_sofia] add a json api to collect info --- src/mod/endpoints/mod_sofia/Makefile.am | 2 +- src/mod/endpoints/mod_sofia/mod_sofia.c | 8 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 5 + src/mod/endpoints/mod_sofia/sofia_json_api.c | 229 +++++++++++++++++++ 4 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 src/mod/endpoints/mod_sofia/sofia_json_api.c diff --git a/src/mod/endpoints/mod_sofia/Makefile.am b/src/mod/endpoints/mod_sofia/Makefile.am index 9d98a976a3..3adcb8ccea 100644 --- a/src/mod/endpoints/mod_sofia/Makefile.am +++ b/src/mod/endpoints/mod_sofia/Makefile.am @@ -9,7 +9,7 @@ SOFIAUA_BUILDDIR=$(SOFIA_BUILDDIR)/libsofia-sip-ua SOFIALA=$(SOFIAUA_BUILDDIR)/libsofia-sip-ua.la mod_LTLIBRARIES = mod_sofia.la -mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h +mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_json_api.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h mod_sofia_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_CMD_LINE_CFLAGS) mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/bnf -I$(SOFIAUA_BUILDDIR)/bnf mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/http -I$(SOFIAUA_BUILDDIR)/http diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 0c7a27534d..85d4485981 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2626,7 +2626,7 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream); -static const char *sofia_state_names[] = { +const char *sofia_state_names[] = { "UNREGED", "TRYING", "REGISTER", @@ -2754,7 +2754,7 @@ static int sql2str_callback(void *pArg, int argc, char **argv, char **columnName return 0; } -static uint32_t sofia_profile_reg_count(sofia_profile_t *profile) +uint32_t sofia_profile_reg_count(sofia_profile_t *profile) { struct cb_helper_sql2str cb; char reg_count[80] = ""; @@ -4362,6 +4362,8 @@ SWITCH_STANDARD_API(sofia_function) func = cmd_status; } else if (!strcasecmp(argv[0], "xmlstatus")) { func = cmd_xml_status; + } else if (!strcasecmp(argv[0], "jsonstatus")) { + func = cmd_json_status; } else if (!strcasecmp(argv[0], "filter")) { if (argc > 1) { if (!strcasecmp(argv[1],"off")) { @@ -6264,6 +6266,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) management_interface->relative_oid = "1001"; management_interface->management_function = sofia_manage; + add_sofia_json_apis(module_interface); + SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function", "private sofia sla function", sofia_sla_function, "", SAF_NONE); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index cdb311f35a..46d215a2d5 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -1163,6 +1163,11 @@ void sofia_glue_restart_all_profiles(void); const char *sofia_state_string(int state); void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); +/* sofia api */ +switch_status_t cmd_json_status(char **argv, int argc, switch_stream_handle_t *stream); +uint32_t sofia_profile_reg_count(sofia_profile_t *profile); +void add_sofia_json_apis(switch_loadable_module_interface_t **module_interface); + /* * Logging control functions */ diff --git a/src/mod/endpoints/mod_sofia/sofia_json_api.c b/src/mod/endpoints/mod_sofia/sofia_json_api.c new file mode 100644 index 0000000000..49005b2021 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/sofia_json_api.c @@ -0,0 +1,229 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2014, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Ken Rice + * Paul D. Tinsley + * Bret McDanel + * Raymond Chandler + * Emmanuel Schmidbauer + * Kathleen King + * + * + * mod_sofia.c -- SOFIA SIP Endpoint + * + */ + +/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/ +/*************************************************************************************************************************************************************/ +#include "mod_sofia.h" + + +typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream); + +extern const char *sofia_state_names[]; + +switch_status_t build_sofia_status_json(cJSON * container) +{ + sofia_profile_t *profile = NULL; + sofia_gateway_t *gp; + switch_hash_index_t *hi; + void *val; + const void *vvar; + switch_mutex_lock(mod_sofia_globals.hash_mutex); + for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) { + cJSON * jprofile = cJSON_CreateObject(); + cJSON * jstatus = cJSON_CreateObject(); + switch_core_hash_this(hi, &vvar, NULL, &val); + cJSON_AddItemToObject(container, (const char *)vvar, jprofile); + cJSON_AddItemToObject(jprofile, "status", jstatus); + profile = (sofia_profile_t *) val; + if (strcmp(vvar, profile->name)) { + cJSON_AddItemToObject(jstatus, "type", cJSON_CreateString("alias")); + cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->name)); + cJSON_AddItemToObject(jstatus, "state", cJSON_CreateString("ALIASED")); + } else { + cJSON_AddItemToObject(jstatus, "type", cJSON_CreateString("profile")); + cJSON_AddItemToObject(jstatus, "state", cJSON_CreateString(sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN")); + cJSON_AddItemToObject(jstatus, "in-use", cJSON_CreateNumber(profile->inuse)); + if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) { + cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->url)); + } else if (sofia_test_pflag(profile, PFLAG_TLS)) { + cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->tls_url)); + cJSON_AddItemToObject(jstatus, "transport", cJSON_CreateString("tls")); + } else if (profile->ws_bindurl) { + cJSON_AddItemToObject(jprofile, "data", cJSON_CreateString(profile->ws_bindurl)); + cJSON_AddItemToObject(jprofile, "transport", cJSON_CreateString("ws")); + } else if (profile->wss_bindurl) { + cJSON_AddItemToObject(jprofile, "data", cJSON_CreateString(profile->wss_bindurl)); + cJSON_AddItemToObject(jprofile, "transport", cJSON_CreateString("wss")); + } + + if (profile->gateways) { + cJSON *gateways = cJSON_CreateObject(); + cJSON_AddItemToObject(jprofile, "gateways", gateways); + for (gp = profile->gateways; gp; gp = gp->next) { + cJSON *gateway = cJSON_CreateObject(); + cJSON_AddItemToObject(gateways, gp->name, gateway); + switch_assert(gp->state < REG_STATE_LAST); + cJSON_AddItemToObject(gateway, "type", cJSON_CreateString("gateway")); + cJSON_AddItemToObject(gateway, "data", cJSON_CreateString(gp->register_to)); + cJSON_AddItemToObject(gateway, "state", cJSON_CreateString(sofia_state_names[gp->state])); + if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) { + time_t now = switch_epoch_time_now(NULL); + if (gp->retry > now) { + cJSON_AddItemToObject(gateway, "retry", cJSON_CreateNumber(gp->retry - now)); + } else { + cJSON_AddItemToObject(gateway, "retry", cJSON_CreateString("never")); + } + } + } + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t build_sofia_profile_info_json(cJSON * container) +{ + sofia_profile_t *profile = NULL; + cJSON *item, *iter = container->child; + while(iter) { + if ( (profile = sofia_glue_find_profile(iter->string))) { + cJSON *info = cJSON_CreateObject(); + cJSON_AddItemToObject(iter, "info", info); + + cJSON_AddItemToObject(info, "domain-name", cJSON_CreateString(profile->domain_name ? profile->domain_name : "N/A")); + if (strcasecmp(iter->string, profile->name)) { + cJSON_AddItemToObject(info, "alias-of", cJSON_CreateString(switch_str_nil(profile->name))); + } + + cJSON_AddItemToObject(info, "auto-nat", cJSON_CreateString(sofia_test_pflag(profile, PFLAG_AUTO_NAT) ? "true" : "false")); + cJSON_AddItemToObject(info, "db-name", cJSON_CreateString(profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn))); + cJSON_AddItemToObject(info, "pres-hosts", cJSON_CreateString(switch_str_nil(profile->presence_hosts))); + cJSON_AddItemToObject(info, "dialplan", cJSON_CreateString(switch_str_nil(profile->dialplan))); + cJSON_AddItemToObject(info, "context", cJSON_CreateString(switch_str_nil(profile->context))); + cJSON_AddItemToObject(info, "challenge-realm", cJSON_CreateString(zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm)); + + item = cJSON_CreateStringArray((const char **)profile->rtpip, profile->rtpip_index); + cJSON_AddItemToObject(info, "rtp-ip", item); + + cJSON_AddItemToObject(info, "ext-rtp-ip", cJSON_CreateString(profile->extrtpip)); + cJSON_AddItemToObject(info, "sip-ip", cJSON_CreateString(switch_str_nil(profile->sipip))); + cJSON_AddItemToObject(info, "ext-sip-ip", cJSON_CreateString(switch_str_nil(profile->extsipip))); + + if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) { + cJSON_AddItemToObject(info, "url", cJSON_CreateString(switch_str_nil(profile->url))); + cJSON_AddItemToObject(info, "bind-url", cJSON_CreateString(switch_str_nil(profile->bindurl))); + } + if (sofia_test_pflag(profile, PFLAG_TLS)) { + cJSON_AddItemToObject(info, "tls-url", cJSON_CreateString(switch_str_nil(profile->tls_url))); + cJSON_AddItemToObject(info, "tls-bind-url", cJSON_CreateString(switch_str_nil(profile->tls_bindurl))); + } + if (profile->ws_bindurl) { + cJSON_AddItemToObject(info, "ws-bind-url", cJSON_CreateString(switch_str_nil(profile->ws_bindurl))); + } + if (profile->wss_bindurl) { + cJSON_AddItemToObject(info, "wss-bind-url", cJSON_CreateString(switch_str_nil(profile->wss_bindurl))); + } + + cJSON_AddItemToObject(info, "hold-music", cJSON_CreateString(switch_str_nil(profile->hold_music))); + cJSON_AddItemToObject(info, "outbound-proxy", cJSON_CreateString(zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy)); + + sofia_glue_release_profile(profile); + + } + + iter = iter->next; + + } + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_JSON_API(sofia_status_json_function) +{ + cJSON *ret = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateObject(); + cJSON_AddItemToObject(ret, "profiles", profiles); + build_sofia_status_json(profiles); + + *json_reply = ret; + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_JSON_API(sofia_status_info_json_function) +{ + cJSON *ret = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateObject(); + cJSON_AddItemToObject(ret, "profiles", profiles); + build_sofia_status_json(profiles); + build_sofia_profile_info_json(profiles); + + *json_reply = ret; + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t cmd_json_status(char **argv, int argc, switch_stream_handle_t *stream) +{ + char * json; + cJSON *ret = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateObject(); + cJSON_AddItemToObject(ret, "profiles", profiles); + build_sofia_status_json(profiles); + build_sofia_profile_info_json(profiles); + + json = cJSON_Print(ret); + stream->write_function(stream, "%s\n", json); + + switch_safe_free(json); + cJSON_Delete(ret); + + return SWITCH_STATUS_SUCCESS; +} + +void add_sofia_json_apis(switch_loadable_module_interface_t **module_interface) +{ + switch_json_api_interface_t *json_api_interface; + SWITCH_ADD_JSON_API(json_api_interface, "sofia.status", "sofia status JSON API", sofia_status_json_function, ""); + SWITCH_ADD_JSON_API(json_api_interface, "sofia.status.info", "sofia status JSON API", sofia_status_info_json_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 noet: + */