From 7a879ab8a3c8f35ef3f2bd995a785a5a9a8425f3 Mon Sep 17 00:00:00 2001 From: Dudu Ben Moshe Date: Fri, 23 Feb 2024 12:11:18 +0000 Subject: [PATCH 1/2] Add sip2json pvar --- pvar.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pvar.h | 2 ++ 2 files changed, 70 insertions(+) diff --git a/pvar.c b/pvar.c index 5f4e67d71ac..e9738d20199 100644 --- a/pvar.c +++ b/pvar.c @@ -3618,6 +3618,71 @@ static int pv_get_xlog_level(struct sip_msg *msg, pv_param_t *param, pv_value_t return 0; } +static int pv_get_sip2json(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res) +{ + cJSON *ret, *aux, *aux2, *arr; + struct hdr_field* it; + char hdr_name_buf[255]; + str json_ret; + + if(msg==NULL) + return -1; + + if(parse_headers(msg, HDR_EOH_F, 0) < 0) + return pv_get_null(msg, param, res); + + ret = cJSON_CreateObject(); + + /* first line */ + aux = cJSON_CreateStr(msg->buf,msg->first_line.len); + if (!aux) { + return pv_get_null(msg, param, res); + } + cJSON_AddItemToObject(ret,"first_line",aux); + + /* headers */ + aux = cJSON_CreateObject(); + for (it=msg->headers;it;it=it->next) { + memcpy(hdr_name_buf,it->name.s,it->name.len); + hdr_name_buf[it->name.len] = 0; + + arr = cJSON_GetObjectItem(aux, hdr_name_buf); + if (!arr) { + arr = cJSON_CreateArray(); + cJSON_AddItemToObject(aux,hdr_name_buf,arr); + } + + aux2 = cJSON_CreateStr(it->body.s,it->body.len); + if (!aux2) { + return pv_get_null(msg, param, res); + } + + cJSON_AddItemToArray(arr,aux2); + } + cJSON_AddItemToObject(ret,"headers",aux); + + /* body */ + if (msg->body) { + aux = cJSON_CreateStr(msg->body->body.s,msg->body->body.len); + if (!aux) { + return pv_get_null(msg, param, res); + } + cJSON_AddItemToObject(ret,"body",aux); + } + + json_ret.s = cJSON_Print(ret); + if (!json_ret.s) { + return pv_get_null(msg, param, res); + } + cJSON_Minify(json_ret.s); + json_ret.len = strlen(json_ret.s); + + cJSON_Delete(ret); + return pv_get_strval(msg, param, res, &json_ret); +} + + /************** Boolean consts *****************/ static const pv_value_t pv_true = { @@ -4201,6 +4266,9 @@ const pv_export_t _pv_names_table[] = { 0, 0, 0, 0 }, {str_const_init("xlog_level"), PVT_XLOG_LEVEL, pv_get_xlog_level, pv_set_xlog_level, 0, 0, 0, 0 }, + {{"sip2json", (sizeof("sip2json")-1)}, /* */ + PVT_SIP2JSON, pv_get_sip2json, 0, + 0, 0, 0, 0}, {{0,0}, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/pvar.h b/pvar.h index 5a7900758d7..3b3c8a611e0 100644 --- a/pvar.h +++ b/pvar.h @@ -136,6 +136,8 @@ enum _pv_type { PVT_JSON, /* registered by xml module */ PVT_XML, + /* sip 2 json pvar */ + PVT_SIP2JSON, PVT_EXTRA /* keep it last */ }; From 67f890117d53941efeb24721875e6ccdef77f392 Mon Sep 17 00:00:00 2001 From: Vlad Paiu Date: Wed, 8 May 2024 14:02:56 +0300 Subject: [PATCH 2/2] Move implementation to sipmsgops --- modules/sipmsgops/doc/sipmsgops_admin.xml | 31 +++++++ modules/sipmsgops/sipmsgops.c | 102 ++++++++++++++++++++++ pvar.c | 68 --------------- pvar.h | 2 - 4 files changed, 133 insertions(+), 70 deletions(-) diff --git a/modules/sipmsgops/doc/sipmsgops_admin.xml b/modules/sipmsgops/doc/sipmsgops_admin.xml index e93a40b6b40..027feb8d654 100644 --- a/modules/sipmsgops/doc/sipmsgops_admin.xml +++ b/modules/sipmsgops/doc/sipmsgops_admin.xml @@ -1684,6 +1684,37 @@ list_hdr_add_option("Supported", "optionX"); +
+ + <function moreinfo="none">sip_to_json(out_var)</function> + + + Returns a JSON formatted representation of the current SIP message, containing first_line , headers and body json members + Useful in cases when you want to pass a generic SIP message to a SIP agnostic entity, but still want to provide some layer of SIP parsing before sending the full message further. + + Meaning of the parameters is as follows: + + + out_var (string) - the output JSON formatted SIP message variable + + + + + This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, + FAILURE_ROUTE, BRANCH_ROUTE and LOCAL_ROUTE. + + + <function>sip_to_json</function> usage + +... + if (sip_to_json($var(out_sip_json))) { + xlog("The JSON format for the current SIP message is $var(out_sip_json) \n"); + } +... + + +
+
diff --git a/modules/sipmsgops/sipmsgops.c b/modules/sipmsgops/sipmsgops.c index 0a99fea4027..ee839218760 100644 --- a/modules/sipmsgops/sipmsgops.c +++ b/modules/sipmsgops/sipmsgops.c @@ -53,6 +53,7 @@ #include "../../msg_translator.h" #include "../../mod_fix.h" #include "../../trim.h" +#include "../../lib/cJSON.h" #include "codecs.h" #include "list_hdr.h" @@ -101,6 +102,7 @@ static int add_body_part_f(struct sip_msg *msg, str *body, str *mime, static int get_updated_body_part_f(struct sip_msg *msg, int *type,pv_spec_t* out); static int is_audio_on_hold_f(struct sip_msg *msg); static int w_sip_validate(struct sip_msg *msg, void *flags, pv_spec_t* err_txt); +static int w_sip_to_json(struct sip_msg *msg, pv_spec_t* out_json); static int fixup_parse_hname(void** param); @@ -303,6 +305,9 @@ static const cmd_export_t cmds[]={ {CMD_PARAM_VAR, 0, 0}, {0, 0, 0}}, REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE}, + {"sip_to_json", (cmd_function)w_sip_to_json, { + {CMD_PARAM_VAR, 0, 0}, {0, 0, 0}}, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE}, {0,0,{{0,0,0}},0} }; @@ -2072,3 +2077,100 @@ static int get_glob_headers_values(struct sip_msg* msg, str* pattern,pv_spec_t* } return cnt==0 ? -1 : 1; } + +static int w_sip_to_json(struct sip_msg *msg, pv_spec_t* out_json) +{ + cJSON *ret=NULL, *aux, *aux2, *arr; + struct hdr_field* it; + char hdr_name_buf[255]; + str json_ret = {0,0}; + pv_value_t pv_val; + + if (!msg) { + LM_ERR("No SIP msg, can't convert to json\n"); + return -1; + } + + if(parse_headers(msg, HDR_EOH_F, 0) < 0) { + LM_ERR("Failed to parse all SIP msg \n"); + return -1; + } + + ret = cJSON_CreateObject(); + + /* first line */ + aux = cJSON_CreateStr(msg->buf,msg->first_line.len); + if (!aux) { + LM_ERR("Failed to create 1st line json \n"); + goto error; + } + + cJSON_AddItemToObject(ret,"first_line",aux); + + /* headers */ + aux = cJSON_CreateObject(); + if (!aux) { + LM_ERR("Failed to create headers json \n"); + goto error; + } + + for (it=msg->headers;it;it=it->next) { + memcpy(hdr_name_buf,it->name.s,it->name.len); + hdr_name_buf[it->name.len] = 0; + + arr = cJSON_GetObjectItem(aux, hdr_name_buf); + if (!arr) { + arr = cJSON_CreateArray(); + cJSON_AddItemToObject(aux,hdr_name_buf,arr); + } + + aux2 = cJSON_CreateStr(it->body.s,it->body.len); + if (!aux2) { + LM_ERR("Failed to create individual header json\n"); + goto error; + } + + cJSON_AddItemToArray(arr,aux2); + } + cJSON_AddItemToObject(ret,"headers",aux); + + /* body */ + if (msg->body) { + aux = cJSON_CreateStr(msg->body->body.s,msg->body->body.len); + if (!aux) { + LM_ERR("Failed to create body json\n"); + goto error; + } + cJSON_AddItemToObject(ret,"body",aux); + } + + json_ret.s = cJSON_Print(ret); + if (!json_ret.s) { + LM_ERR("Failed to print json to string obj\n"); + goto error; + } + + cJSON_Minify(json_ret.s); + json_ret.len = strlen(json_ret.s); + + pv_val.flags = PV_VAL_STR; + pv_val.rs = json_ret; + + if (pv_set_value(msg,out_json,0,&pv_val) != 0) { + LM_ERR("Failed to set out json pvar \n"); + goto error; + } + + pkg_free(json_ret.s); + cJSON_Delete(ret); + + return 1; + +error: + if (ret) + cJSON_Delete(ret); + if (json_ret.s) + pkg_free(json_ret.s); + + return -1; +} diff --git a/pvar.c b/pvar.c index e9738d20199..5f4e67d71ac 100644 --- a/pvar.c +++ b/pvar.c @@ -3618,71 +3618,6 @@ static int pv_get_xlog_level(struct sip_msg *msg, pv_param_t *param, pv_value_t return 0; } -static int pv_get_sip2json(struct sip_msg *msg, pv_param_t *param, - pv_value_t *res) -{ - cJSON *ret, *aux, *aux2, *arr; - struct hdr_field* it; - char hdr_name_buf[255]; - str json_ret; - - if(msg==NULL) - return -1; - - if(parse_headers(msg, HDR_EOH_F, 0) < 0) - return pv_get_null(msg, param, res); - - ret = cJSON_CreateObject(); - - /* first line */ - aux = cJSON_CreateStr(msg->buf,msg->first_line.len); - if (!aux) { - return pv_get_null(msg, param, res); - } - cJSON_AddItemToObject(ret,"first_line",aux); - - /* headers */ - aux = cJSON_CreateObject(); - for (it=msg->headers;it;it=it->next) { - memcpy(hdr_name_buf,it->name.s,it->name.len); - hdr_name_buf[it->name.len] = 0; - - arr = cJSON_GetObjectItem(aux, hdr_name_buf); - if (!arr) { - arr = cJSON_CreateArray(); - cJSON_AddItemToObject(aux,hdr_name_buf,arr); - } - - aux2 = cJSON_CreateStr(it->body.s,it->body.len); - if (!aux2) { - return pv_get_null(msg, param, res); - } - - cJSON_AddItemToArray(arr,aux2); - } - cJSON_AddItemToObject(ret,"headers",aux); - - /* body */ - if (msg->body) { - aux = cJSON_CreateStr(msg->body->body.s,msg->body->body.len); - if (!aux) { - return pv_get_null(msg, param, res); - } - cJSON_AddItemToObject(ret,"body",aux); - } - - json_ret.s = cJSON_Print(ret); - if (!json_ret.s) { - return pv_get_null(msg, param, res); - } - cJSON_Minify(json_ret.s); - json_ret.len = strlen(json_ret.s); - - cJSON_Delete(ret); - return pv_get_strval(msg, param, res, &json_ret); -} - - /************** Boolean consts *****************/ static const pv_value_t pv_true = { @@ -4266,9 +4201,6 @@ const pv_export_t _pv_names_table[] = { 0, 0, 0, 0 }, {str_const_init("xlog_level"), PVT_XLOG_LEVEL, pv_get_xlog_level, pv_set_xlog_level, 0, 0, 0, 0 }, - {{"sip2json", (sizeof("sip2json")-1)}, /* */ - PVT_SIP2JSON, pv_get_sip2json, 0, - 0, 0, 0, 0}, {{0,0}, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/pvar.h b/pvar.h index 3b3c8a611e0..5a7900758d7 100644 --- a/pvar.h +++ b/pvar.h @@ -136,8 +136,6 @@ enum _pv_type { PVT_JSON, /* registered by xml module */ PVT_XML, - /* sip 2 json pvar */ - PVT_SIP2JSON, PVT_EXTRA /* keep it last */ };