Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sip2json pvar #3311

Merged
merged 3 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions modules/sipmsgops/doc/sipmsgops_admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,37 @@ list_hdr_add_option("Supported", "optionX");
</example>
</section>

<section id="sip_to_json" xreflabel="sip_to_json()">
<title>
<function moreinfo="none">sip_to_json(out_var)</function>
</title>
<para>
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.
</para>
<para>Meaning of the parameters is as follows:</para>
<itemizedlist>
<listitem>
<para><emphasis>out_var (string)</emphasis> - the output JSON formatted SIP message variable
</para>
</listitem>
</itemizedlist>
<para>
This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
FAILURE_ROUTE, BRANCH_ROUTE and LOCAL_ROUTE.
</para>
<example>
<title><function>sip_to_json</function> usage</title>
<programlisting format="linespecific">
...
if (sip_to_json($var(out_sip_json))) {
xlog("The JSON format for the current SIP message is $var(out_sip_json) \n");
}
...
</programlisting>
</example>
</section>


</section>
<section>
Expand Down
102 changes: 102 additions & 0 deletions modules/sipmsgops/sipmsgops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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}
};
Expand Down Expand Up @@ -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;
}
Loading