From fb695c528e4aed68aef520c877e1ddd0011a684b Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 18 Jun 2019 14:56:57 +0000 Subject: [PATCH] FS-11893 [core] add switch_dial_handle_create_json() and switch_dial_handle_serialize_json() for dial handle/json conversions --- src/include/switch_ivr.h | 4 + src/switch_ivr_originate.c | 162 ++++++++++++++++++++++++++++++ tests/unit/switch_ivr_originate.c | 60 +++++++++++ 3 files changed, 226 insertions(+) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 061da0705b..ab01aa49c0 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -1036,7 +1036,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_video_write_overlay_session(switch_co SWITCH_DECLARE(switch_status_t) switch_ivr_capture_text(switch_core_session_t *session, switch_bool_t on); SWITCH_DECLARE(switch_status_t) switch_dial_handle_create(switch_dial_handle_t **handle); +SWITCH_DECLARE(switch_status_t) switch_dial_handle_create_json_obj(switch_dial_handle_t **handle, cJSON *json); +SWITCH_DECLARE(switch_status_t) switch_dial_handle_create_json(switch_dial_handle_t **handle, const char *handle_string); SWITCH_DECLARE(void) switch_dial_handle_destroy(switch_dial_handle_t **handle); +SWITCH_DECLARE(switch_status_t) switch_dial_handle_serialize_json_obj(switch_dial_handle_t *handle, cJSON **json); +SWITCH_DECLARE(switch_status_t) switch_dial_handle_serialize_json(switch_dial_handle_t *handle, char **str); SWITCH_DECLARE(void) switch_dial_handle_add_leg_list(switch_dial_handle_t *handle, switch_dial_leg_list_t **leg_listP); SWITCH_DECLARE(void) switch_dial_leg_list_add_leg(switch_dial_leg_list_t *parent, switch_dial_leg_t **legP, const char *dial_string); SWITCH_DECLARE(void) switch_dial_leg_list_add_leg_printf(switch_dial_leg_list_t *parent, switch_dial_leg_t **legP, const char *fmt, ...); diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index bb3bf27abf..0ed6f0644f 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -4384,6 +4384,168 @@ SWITCH_DECLARE(switch_event_t *) switch_dial_leg_get_vars(switch_dial_leg_t *leg } +static switch_status_t vars_serialize_json_obj(switch_event_t *event, cJSON **json) +{ + switch_event_header_t *hp; + *json = cJSON_CreateObject(); + for (hp = event->headers; hp; hp = hp->next) { + if (hp->name && hp->value) { + cJSON_AddItemToObject(*json, hp->name, cJSON_CreateString(hp->value)); + } + } + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t leg_serialize_json_obj(switch_dial_leg_t *leg, cJSON **json) +{ + cJSON *vars_json = NULL; + *json = cJSON_CreateObject(); + if (leg->dial_string) { + cJSON_AddStringToObject(*json, "dial_string", leg->dial_string); + } + if (leg->leg_vars && vars_serialize_json_obj(leg->leg_vars, &vars_json) == SWITCH_STATUS_SUCCESS && vars_json) { + cJSON_AddItemToObject(*json, "vars", vars_json); + } + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t leg_list_serialize_json_obj(switch_dial_leg_list_t *ll, cJSON **json) +{ + int i; + cJSON *legs_json = cJSON_CreateArray(); + *json = cJSON_CreateObject(); + cJSON_AddItemToObject(*json, "legs", legs_json); + for (i = 0; i < ll->leg_idx; i++) { + switch_dial_leg_t *leg = ll->legs[i]; + cJSON *leg_json = NULL; + if (leg_serialize_json_obj(leg, &leg_json) == SWITCH_STATUS_SUCCESS && leg_json) { + cJSON_AddItemToArray(legs_json, leg_json); + } + } + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(switch_status_t) switch_dial_handle_serialize_json_obj(switch_dial_handle_t *handle, cJSON **json) +{ + int i; + cJSON *global_vars_json = NULL; + cJSON *leg_lists_json = NULL; + if (!handle) { + return SWITCH_STATUS_FALSE; + } + *json = cJSON_CreateObject(); + if (handle->global_vars && vars_serialize_json_obj(handle->global_vars, &global_vars_json) == SWITCH_STATUS_SUCCESS && global_vars_json) { + cJSON_AddItemToObject(*json, "vars", global_vars_json); + } + + leg_lists_json = cJSON_CreateArray(); + cJSON_AddItemToObject(*json, "leg_lists", leg_lists_json); + for (i = 0; i < handle->leg_list_idx; i++) { + switch_dial_leg_list_t *ll = handle->leg_lists[i]; + cJSON *leg_list_json = NULL; + if (leg_list_serialize_json_obj(ll, &leg_list_json) == SWITCH_STATUS_SUCCESS && leg_list_json) { + cJSON_AddItemToArray(leg_lists_json, leg_list_json); + } + } + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(switch_status_t) switch_dial_handle_serialize_json(switch_dial_handle_t *handle, char **str) +{ + cJSON *json = NULL; + if (switch_dial_handle_serialize_json_obj(handle, &json) == SWITCH_STATUS_SUCCESS && json) { + *str = cJSON_PrintUnformatted(json); + cJSON_Delete(json); + return SWITCH_STATUS_SUCCESS; + } + return SWITCH_STATUS_FALSE; +} + + +SWITCH_DECLARE(switch_status_t) switch_dial_handle_create_json_obj(switch_dial_handle_t **handle, cJSON *json) +{ + cJSON *vars_json = NULL; + cJSON *var_json = NULL; + cJSON *leg_lists_json = NULL; + if (!json) { + return SWITCH_STATUS_FALSE; + } + switch_dial_handle_create(handle); + + leg_lists_json = cJSON_GetObjectItem(json, "leg_lists"); + if (leg_lists_json && leg_lists_json->type == cJSON_Array) { + cJSON *leg_list_json = NULL; + cJSON_ArrayForEach(leg_list_json, leg_lists_json) { + cJSON *legs_json = cJSON_GetObjectItem(leg_list_json, "legs"); + cJSON *leg_json = NULL; + switch_dial_leg_list_t *ll = NULL; + if (!legs_json || legs_json->type != cJSON_Array) { + continue; + } + switch_dial_handle_add_leg_list(*handle, &ll); + cJSON_ArrayForEach(leg_json, legs_json) { + switch_dial_leg_t *leg = NULL; + const char *dial_string = NULL; + if (!leg_json || leg_json->type != cJSON_Object) { + continue; + } + dial_string = cJSON_GetObjectCstr(leg_json, "dial_string"); + if (!dial_string) { + continue; + } + switch_dial_leg_list_add_leg(ll, &leg, dial_string); + + vars_json = cJSON_GetObjectItem(leg_json, "vars"); + if (vars_json && vars_json->type == cJSON_Object) { + cJSON_ArrayForEach(var_json, vars_json) { + if (!var_json || var_json->type != cJSON_String || !var_json->valuestring || !var_json->string) { + continue; + } + switch_dial_handle_add_leg_var(leg, var_json->string, var_json->valuestring); + } + } + } + } + } + + vars_json = cJSON_GetObjectItem(json, "vars"); + if (vars_json && vars_json->type == cJSON_Object) { + cJSON_ArrayForEach(var_json, vars_json) { + if (!var_json || var_json->type != cJSON_String || !var_json->valuestring || !var_json->string) { + continue; + } + switch_dial_handle_add_global_var(*handle, var_json->string, var_json->valuestring); + } + } + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(switch_status_t) switch_dial_handle_create_json(switch_dial_handle_t **handle, const char *handle_string) +{ + switch_status_t status; + cJSON *handle_json = NULL; + + if (zstr(handle_string)) { + return SWITCH_STATUS_FALSE; + } + + handle_json = cJSON_Parse(handle_string); + if (!handle_json) { + return SWITCH_STATUS_FALSE; + } + + status = switch_dial_handle_create_json_obj(handle, handle_json); + cJSON_Delete(handle_json); + return status; +} + + static switch_status_t o_bridge_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) { char *str = (char *) buf; diff --git a/tests/unit/switch_ivr_originate.c b/tests/unit/switch_ivr_originate.c index 1b7ff19a4a..8cbdfa2a9d 100644 --- a/tests/unit/switch_ivr_originate.c +++ b/tests/unit/switch_ivr_originate.c @@ -137,6 +137,66 @@ FST_CORE_BEGIN("./conf") fst_check(destroy == 2); } FST_TEST_END() + + FST_TEST_BEGIN(dial_handle_create_json) + { + const char *dh_str = "{\n" + " \"vars\": {\n" + " \"foo\": \"bar\",\n" + " \"absolute_codec_string\": \"opus,pcmu,pcma\",\n" + " \"ignore_early_media\": \"true\"\n" + " },\n" + " \"leg_lists\": [\n" + " { \"legs\": [\n" + " { \n" + " \"dial_string\": \"loopback/dest\", \n" + " \"vars\": {\n" + " \"bar\": \"bar\"\n" + " }\n" + " },\n" + " { \n" + " \"dial_string\": \"sofia/gateway/gw/12345\"\n" + " }\n" + " ] },\n" + " { \"legs\": [\n" + " {\n" + " \"dial_string\": \"sofia/external/foo@example.com^5551231234\",\n" + " \"vars\": {\n" + " \"sip_h_X-Custom\": \"my val\"\n" + " }\n" + " }\n" + " ] },\n" + " { \"legs\": [\n" + " {\n" + " \"dial_string\": \"group/my_group\"\n" + " }\n" + " ] }\n" + " ]\n" + "}"; + + // create dial handle from json string, convert back to json and compare + switch_dial_handle_t *dh = NULL; + char *dh_str2 = NULL; + char *dh_str3 = NULL; + cJSON *dh_json = NULL; + fst_requires(switch_dial_handle_create_json(&dh, dh_str) == SWITCH_STATUS_SUCCESS); + fst_requires(dh != NULL); + fst_requires(switch_dial_handle_serialize_json_obj(dh, &dh_json) == SWITCH_STATUS_SUCCESS); + fst_requires(dh_json != NULL); + fst_requires(switch_dial_handle_serialize_json(dh, &dh_str2) == SWITCH_STATUS_SUCCESS); + fst_requires(dh_str2 != NULL); + fst_check_string_equals(dh_str2, "{\"vars\":{\"foo\":\"bar\",\"absolute_codec_string\":\"opus,pcmu,pcma\",\"ignore_early_media\":\"true\"},\"leg_lists\":[{\"legs\":[{\"dial_string\":\"loopback/dest\",\"vars\":{\"bar\":\"bar\"}},{\"dial_string\":\"sofia/gateway/gw/12345\"}]},{\"legs\":[{\"dial_string\":\"sofia/external/foo@example.com^5551231234\",\"vars\":{\"sip_h_X-Custom\":\"my val\"}}]},{\"legs\":[{\"dial_string\":\"group/my_group\"}]}]}"); + + dh_str3 = cJSON_PrintUnformatted(dh_json); + fst_requires(dh_str3); + fst_check_string_equals(dh_str2, dh_str3); + + switch_safe_free(dh_str2); + switch_safe_free(dh_str3); + cJSON_Delete(dh_json); + switch_dial_handle_destroy(&dh); + } + FST_TEST_END(); } FST_SUITE_END() }