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");
+
+
+ sip_to_json(out_var)
+
+
+ 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.
+
+
+ sip_to_json 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;
+}