|
|
|
|
@ -15,21 +15,12 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
|
|
|
|
|
--- a/modules/debugger/Makefile
|
|
|
|
|
+++ b/modules/debugger/Makefile
|
|
|
|
|
@@ -7,6 +7,15 @@
|
|
|
|
|
NAME=debugger.so
|
|
|
|
|
LIBS=
|
|
|
|
|
|
|
|
|
|
+BUILDER = $(shell which pkg-config)
|
|
|
|
|
+ifeq ($(BUILDER),)
|
|
|
|
|
+ DEFS+=-I/usr/include/json -I$(LOCALBASE)/include/json \
|
|
|
|
|
+ -I$(LOCALBASE)/include
|
|
|
|
|
+ LIBS+=-L$(SYSBASE)/include/lib -L$(LOCALBASE)/lib -ljson
|
|
|
|
|
+else
|
|
|
|
|
+ DEFS+= $(shell pkg-config --cflags json)
|
|
|
|
|
+ LIBS+= $(shell pkg-config --libs json)
|
|
|
|
|
+endif
|
|
|
|
|
@@ -9,4 +9,6 @@
|
|
|
|
|
|
|
|
|
|
DEFS+=-DKAMAILIO_MOD_INTERFACE
|
|
|
|
|
|
|
|
|
|
+SERLIBPATH=../../lib
|
|
|
|
|
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
|
|
|
|
|
include ../../Makefile.modules
|
|
|
|
|
--- a/modules/debugger/README
|
|
|
|
|
+++ b/modules/debugger/README
|
|
|
|
|
@ -46,7 +37,7 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
4. Functions
|
|
|
|
|
|
|
|
|
|
4.1. dbg_breakpoint(mode)
|
|
|
|
|
+ 4.2. dbg_pv_dump()
|
|
|
|
|
+ 4.2. dbg_pv_dump(mask)
|
|
|
|
|
|
|
|
|
|
5. Exported RPC Functions
|
|
|
|
|
|
|
|
|
|
@ -62,7 +53,7 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
4. Functions
|
|
|
|
|
|
|
|
|
|
4.1. dbg_breakpoint(mode)
|
|
|
|
|
+ 4.2. dbg_pv_dump()
|
|
|
|
|
+ 4.2. dbg_pv_dump(mask)
|
|
|
|
|
|
|
|
|
|
5. Exported RPC Functions
|
|
|
|
|
|
|
|
|
|
@ -70,32 +61,43 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
4. Functions
|
|
|
|
|
|
|
|
|
|
4.1. dbg_breakpoint(mode)
|
|
|
|
|
+ 4.2. dbg_pv_dump()
|
|
|
|
|
+ 4.2. dbg_pv_dump(mask)
|
|
|
|
|
|
|
|
|
|
4.1. dbg_breakpoint(mode)
|
|
|
|
|
|
|
|
|
|
@@ -242,6 +246,26 @@
|
|
|
|
|
@@ -242,6 +246,37 @@
|
|
|
|
|
dbg_breakpoint("1");
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
+4.2. dbg_pv_dump()
|
|
|
|
|
+4.2. dbg_pv_dump(mask)
|
|
|
|
|
+
|
|
|
|
|
+ Prints the content of pv_cache on json format
|
|
|
|
|
+ Prints the content of pv_cache on json format controled by mask value
|
|
|
|
|
+#define DBG_DP_NULL 1
|
|
|
|
|
+#define DBG_DP_AVP 2
|
|
|
|
|
+#define DBG_DP_SCRIPTVAR 4
|
|
|
|
|
+#define DBG_DP_OTHER 8
|
|
|
|
|
+
|
|
|
|
|
+ Example 1.9. dbg_pv_dump usage
|
|
|
|
|
+...
|
|
|
|
|
+$var(temp) = 2;
|
|
|
|
|
+$var(temp) = 1;
|
|
|
|
|
+$avp(s:more_avp) = 2;
|
|
|
|
|
+$avp(s:more_avp) = 3;
|
|
|
|
|
+$xavp(x=>more) = "bye";
|
|
|
|
|
+$xavp(x[0]=>more) = "hi";
|
|
|
|
|
+$xavp(x[0]=>other) = 1;
|
|
|
|
|
+$xavp(x[0]=>other) = 2;
|
|
|
|
|
+$xavp(x=>different) = "foo";
|
|
|
|
|
+$var(empty) = $null;
|
|
|
|
|
+
|
|
|
|
|
+dbg_pv_dump();
|
|
|
|
|
+dbg_pv_dump(14);
|
|
|
|
|
+...
|
|
|
|
|
+
|
|
|
|
|
+ Output
|
|
|
|
|
+...
|
|
|
|
|
+ 4(24310) DEBUG: debugger [debugger_api.c:1335]: dbg_dump_json(): { "$var(temp)
|
|
|
|
|
+": 2, "$avp(s:more_avp)": 3, "$xavp(x[0]=>more)": "hi" }
|
|
|
|
|
+
|
|
|
|
|
+ 4(30943) DEBUG: debugger [debugger_api.c:1613]: dbg_dump_json(): {"$sp":37597,"
|
|
|
|
|
+$var(rc)":0,"$var(temp)":1,"$avp(more_avp)":[3,2],"$si":"127.0.0.1","$rc":0,"$xa
|
|
|
|
|
+vp(x)":[{"different":["foo"]},{"other":[2,1],"more":["hi","bye"]}],"$T_branch_id
|
|
|
|
|
+x":0,"$var(empty)":0}
|
|
|
|
|
+ ...
|
|
|
|
|
+
|
|
|
|
|
5. Exported RPC Functions
|
|
|
|
|
@ -103,70 +105,360 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
5.1. dbg.ls
|
|
|
|
|
--- a/modules/debugger/debugger_api.c
|
|
|
|
|
+++ b/modules/debugger/debugger_api.c
|
|
|
|
|
@@ -25,6 +25,7 @@
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
+#include <json.h>
|
|
|
|
|
|
|
|
|
|
#include "../../dprint.h"
|
|
|
|
|
#include "../../ut.h"
|
|
|
|
|
@@ -1078,3 +1079,56 @@
|
|
|
|
|
@@ -36,7 +36,10 @@
|
|
|
|
|
#include "../../route_struct.h"
|
|
|
|
|
#include "../../mem/shm_mem.h"
|
|
|
|
|
#include "../../locking.h"
|
|
|
|
|
-
|
|
|
|
|
+#include "../../lib/srutils/srjson.h"
|
|
|
|
|
+#include "../../xavp.h"
|
|
|
|
|
+#include "../pv/pv_xavp.h"
|
|
|
|
|
+
|
|
|
|
|
#include "debugger_act.h"
|
|
|
|
|
#include "debugger_api.h"
|
|
|
|
|
|
|
|
|
|
@@ -1078,3 +1081,342 @@
|
|
|
|
|
return;
|
|
|
|
|
set_module_debug_level_cb(dbg_get_mod_debug_level);
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+int dbg_dump_json(struct sip_msg* msg, pv_elem_p list)
|
|
|
|
|
+int _dbg_get_array_avp_vals(struct sip_msg *msg,
|
|
|
|
|
+ pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj,
|
|
|
|
|
+ str *item_name)
|
|
|
|
|
+{
|
|
|
|
|
+ pv_value_t value;
|
|
|
|
|
+ pv_elem_p el = list;
|
|
|
|
|
+ json_object * jobj = NULL;
|
|
|
|
|
+ json_object *jstring = NULL;
|
|
|
|
|
+ json_object *jint = NULL;
|
|
|
|
|
+ char sname[100];
|
|
|
|
|
+ char svalue[100];
|
|
|
|
|
+
|
|
|
|
|
+ jobj = json_object_new_object();
|
|
|
|
|
+ if(jobj==NULL){
|
|
|
|
|
+ LM_ERR("Can not create a new json object\n");
|
|
|
|
|
+ struct usr_avp *avp;
|
|
|
|
|
+ unsigned short name_type;
|
|
|
|
|
+ int_str avp_name;
|
|
|
|
|
+ int_str avp_value;
|
|
|
|
|
+ struct search_state state;
|
|
|
|
|
+ srjson_t *jobjt;
|
|
|
|
|
+ memset(&state, 0, sizeof(struct search_state));
|
|
|
|
|
+
|
|
|
|
|
+ if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("invalid name\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ *jobj = srjson_CreateArray(jdoc);
|
|
|
|
|
+ if(*jobj==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto ok;
|
|
|
|
|
+ }
|
|
|
|
|
+ do
|
|
|
|
|
+ {
|
|
|
|
|
+ if(avp->flags & AVP_VAL_STR)
|
|
|
|
|
+ {
|
|
|
|
|
+ jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len);
|
|
|
|
|
+ if(jobjt==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ jobjt = srjson_CreateNumber(jdoc, avp_value.n);
|
|
|
|
|
+ if(jobjt==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ srjson_AddItemToArray(jdoc, *jobj, jobjt);
|
|
|
|
|
+ } while ((avp=search_next_avp(&state, &avp_value))!=0);
|
|
|
|
|
+ok:
|
|
|
|
|
+ item_name->s = avp_name.s.s;
|
|
|
|
|
+ item_name->len = avp_name.s.len;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+#define DBG_XAVP_DUMP_SIZE 32
|
|
|
|
|
+static str* _dbg_xavp_dump[DBG_XAVP_DUMP_SIZE];
|
|
|
|
|
+int _dbg_xavp_dump_lookup(pv_param_t *param)
|
|
|
|
|
+{
|
|
|
|
|
+ unsigned int i = 0;
|
|
|
|
|
+ pv_xavp_name_t *xname;
|
|
|
|
|
+
|
|
|
|
|
+ if(param==NULL)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ xname = (pv_xavp_name_t*)param->pvn.u.dname;
|
|
|
|
|
+
|
|
|
|
|
+ while(_dbg_xavp_dump[i]!=NULL&&i<DBG_XAVP_DUMP_SIZE)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(_dbg_xavp_dump[i]->len==xname->name.len)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(strncmp(_dbg_xavp_dump[i]->s, xname->name.s, xname->name.len)==0)
|
|
|
|
|
+ return 1; /* already dump before */
|
|
|
|
|
+ }
|
|
|
|
|
+ i++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(i==DBG_XAVP_DUMP_SIZE)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_WARN("full _dbg_xavp_dump cache array\n");
|
|
|
|
|
+ return 0; /* end cache names */
|
|
|
|
|
+ }
|
|
|
|
|
+ _dbg_xavp_dump[i] = &xname->name;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void _dbg_get_obj_xavp_val(sr_xavp_t *avp, srjson_doc_t *jdoc, srjson_t **jobj)
|
|
|
|
|
+{
|
|
|
|
|
+ static char _pv_xavp_buf[128];
|
|
|
|
|
+ int result = 0;
|
|
|
|
|
+
|
|
|
|
|
+ switch(avp->val.type) {
|
|
|
|
|
+ case SR_XTYPE_NULL:
|
|
|
|
|
+ *jobj = srjson_CreateNull(jdoc);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_INT:
|
|
|
|
|
+ *jobj = srjson_CreateNumber(jdoc, avp->val.v.i);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_STR:
|
|
|
|
|
+ *jobj = srjson_CreateStr(jdoc, avp->val.v.s.s, avp->val.v.s.len);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_TIME:
|
|
|
|
|
+ result = snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_LONG:
|
|
|
|
|
+ result = snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_LLONG:
|
|
|
|
|
+ result = snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_XAVP:
|
|
|
|
|
+ result = snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SR_XTYPE_DATA:
|
|
|
|
|
+ result = snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ LM_WARN("unknown data type\n");
|
|
|
|
|
+ *jobj = srjson_CreateNull(jdoc);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(result<0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot convert to str\n");
|
|
|
|
|
+ *jobj = srjson_CreateNull(jdoc);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(*jobj==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ *jobj = srjson_CreateStr(jdoc, _pv_xavp_buf, 128);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int _dbg_get_obj_avp_vals(str name, sr_xavp_t *xavp, srjson_doc_t *jdoc, srjson_t **jobj)
|
|
|
|
|
+{
|
|
|
|
|
+ sr_xavp_t *avp = NULL;
|
|
|
|
|
+ srjson_t *jobjt = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ *jobj = srjson_CreateArray(jdoc);
|
|
|
|
|
+ if(*jobj==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ avp = xavp;
|
|
|
|
|
+ while(avp!=NULL&&!STR_EQ(avp->name,name))
|
|
|
|
|
+ {
|
|
|
|
|
+ avp = avp->next;
|
|
|
|
|
+ }
|
|
|
|
|
+ while(avp!=NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ _dbg_get_obj_xavp_val(avp, jdoc, &jobjt);
|
|
|
|
|
+ srjson_AddItemToArray(jdoc, *jobj, jobjt);
|
|
|
|
|
+ jobjt = NULL;
|
|
|
|
|
+ avp = xavp_get_next(avp);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int _dbg_get_obj_xavp_vals(struct sip_msg *msg,
|
|
|
|
|
+ pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobjr,
|
|
|
|
|
+ str *item_name)
|
|
|
|
|
+{
|
|
|
|
|
+ pv_xavp_name_t *xname = (pv_xavp_name_t*)param->pvn.u.dname;
|
|
|
|
|
+ sr_xavp_t *xavp = NULL;
|
|
|
|
|
+ sr_xavp_t *avp = NULL;
|
|
|
|
|
+ srjson_t *jobj = NULL;
|
|
|
|
|
+ srjson_t *jobjt = NULL;
|
|
|
|
|
+ struct str_list *keys;
|
|
|
|
|
+ struct str_list *k;
|
|
|
|
|
+
|
|
|
|
|
+ *jobjr = srjson_CreateArray(jdoc);
|
|
|
|
|
+ if(*jobjr==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ item_name->s = xname->name.s;
|
|
|
|
|
+ item_name->len = xname->name.len;
|
|
|
|
|
+ xavp = xavp_get_by_index(&xname->name, 0, NULL);
|
|
|
|
|
+ do
|
|
|
|
|
+ {
|
|
|
|
|
+ if(xavp->val.type==SR_XTYPE_XAVP)
|
|
|
|
|
+ {
|
|
|
|
|
+ avp = xavp->val.v.xavp;
|
|
|
|
|
+ jobj = srjson_CreateObject(jdoc);
|
|
|
|
|
+ keys = xavp_get_list_key_names(xavp);
|
|
|
|
|
+ if(keys!=NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ do
|
|
|
|
|
+ {
|
|
|
|
|
+ _dbg_get_obj_avp_vals(keys->s, avp, jdoc, &jobjt);
|
|
|
|
|
+ srjson_AddStrItemToObject(jdoc, jobj, keys->s.s,
|
|
|
|
|
+ keys->s.len, jobjt);
|
|
|
|
|
+ k = keys;
|
|
|
|
|
+ keys = keys->next;
|
|
|
|
|
+ pkg_free(k);
|
|
|
|
|
+ jobjt = NULL;
|
|
|
|
|
+ }while(keys!=NULL);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ srjson_AddItemToArray(jdoc, *jobjr, jobj);
|
|
|
|
|
+ jobj = NULL;
|
|
|
|
|
+ }while((xavp = xavp_get_next(xavp))!=0);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#define DBG_DP_NULL 1
|
|
|
|
|
+#define DBG_DP_AVP 2
|
|
|
|
|
+#define DBG_DP_SCRIPTVAR 4
|
|
|
|
|
+#define DBG_DP_OTHER 8
|
|
|
|
|
+
|
|
|
|
|
+int dbg_dump_json(struct sip_msg* msg, pv_elem_p list, unsigned int mask)
|
|
|
|
|
+{
|
|
|
|
|
+ pv_value_t value;
|
|
|
|
|
+ pv_elem_p el = list;
|
|
|
|
|
+ srjson_doc_t jdoc;
|
|
|
|
|
+ srjson_t *jobj = NULL;
|
|
|
|
|
+ char *output = NULL;
|
|
|
|
|
+ str item_name = STR_NULL;
|
|
|
|
|
+ int result = -1;
|
|
|
|
|
+
|
|
|
|
|
+ memset(_dbg_xavp_dump, 0, sizeof(str*)*DBG_XAVP_DUMP_SIZE);
|
|
|
|
|
+ srjson_InitDoc(&jdoc, NULL);
|
|
|
|
|
+ if(jdoc.root==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ jdoc.root = srjson_CreateObject(&jdoc);
|
|
|
|
|
+ if(jdoc.root==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json root\n");
|
|
|
|
|
+ goto error;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ while(el)
|
|
|
|
|
+ {
|
|
|
|
|
+ /*LM_DBG("el->spec[%p][%d] el->text[%.*s]\n", el->spec,
|
|
|
|
|
+ el->spec->type, el->text.len, el->text.s);*/
|
|
|
|
|
+ jobj = NULL;
|
|
|
|
|
+ item_name.len = 0;
|
|
|
|
|
+ item_name.s = 0;
|
|
|
|
|
+ if(!(el->spec->type==PVT_AVP||
|
|
|
|
|
+ el->spec->type==PVT_SCRIPTVAR||
|
|
|
|
|
+ el->spec->type==PVT_OTHER))
|
|
|
|
|
+ el->spec->type==PVT_OTHER)||
|
|
|
|
|
+ !((el->spec->type==PVT_AVP&&mask&DBG_DP_AVP)||
|
|
|
|
|
+ (el->spec->type==PVT_SCRIPTVAR&&mask&DBG_DP_SCRIPTVAR)||
|
|
|
|
|
+ (el->spec->type==PVT_OTHER&&mask&DBG_DP_OTHER))||
|
|
|
|
|
+ (el->spec->trans!=NULL))
|
|
|
|
|
+ {
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(pv_get_spec_value(msg, el->spec, &value)!=0)
|
|
|
|
|
+ if(el->spec->type==PVT_AVP)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("can't get value\n");
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if(el->spec->pvp.pvi.type==PV_IDX_ALL||
|
|
|
|
|
+ (el->spec->pvp.pvi.type==PV_IDX_INT&&el->spec->pvp.pvi.u.ival!=0))
|
|
|
|
|
+ {
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if(_dbg_get_array_avp_vals(msg, &el->spec->pvp, &jdoc, &jobj, &item_name)!=0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("can't get value[%.*s]\n", el->text.len, el->text.s);
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
|
|
|
|
|
+ {
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ snprintf(sname, 100, "%.*s", el->text.len, el->text.s);
|
|
|
|
|
+ if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE)){
|
|
|
|
|
+ jstring = json_object_new_string("$null");
|
|
|
|
|
+ json_object_object_add(jobj, sname, jstring);
|
|
|
|
|
+ }else if(value.flags&(PV_VAL_INT)){
|
|
|
|
|
+ jint = json_object_new_int(value.ri);
|
|
|
|
|
+ json_object_object_add(jobj, sname, jint);
|
|
|
|
|
+ }else if(value.flags&(PV_VAL_STR)){
|
|
|
|
|
+ snprintf(svalue, 100, "%.*s", value.rs.len, value.rs.s);
|
|
|
|
|
+ jstring = json_object_new_string(svalue);
|
|
|
|
|
+ json_object_object_add(jobj, sname, jstring);
|
|
|
|
|
+ else if(el->spec->type==PVT_OTHER&&
|
|
|
|
|
+ el->spec->pvp.pvn.type==PV_NAME_PVAR)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(_dbg_xavp_dump_lookup(&el->spec->pvp)!=0)
|
|
|
|
|
+ {
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ switch(_dbg_get_obj_xavp_vals(msg, &el->spec->pvp, &jdoc, &jobj, &item_name))
|
|
|
|
|
+ {
|
|
|
|
|
+ case 1: /* empty */
|
|
|
|
|
+ if(!(mask&DBG_DP_NULL))
|
|
|
|
|
+ {
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ case -1:
|
|
|
|
|
+ LM_ERR("can't get value[%.*s]\n", el->text.len, el->text.s);
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if(pv_get_spec_value(msg, el->spec, &value)!=0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("can't get value[%.*s]\n", el->text.len, el->text.s);
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE)
|
|
|
|
|
+ && mask&DBG_DP_NULL){
|
|
|
|
|
+ jobj = srjson_CreateNull(&jdoc);
|
|
|
|
|
+ }else if(value.flags&(PV_VAL_INT)){
|
|
|
|
|
+ jobj = srjson_CreateNumber(&jdoc, value.ri);
|
|
|
|
|
+ }else if(value.flags&(PV_VAL_STR)){
|
|
|
|
|
+ jobj = srjson_CreateStr(&jdoc, value.rs.s, value.rs.len);
|
|
|
|
|
+ }
|
|
|
|
|
+ item_name.s = el->text.s;
|
|
|
|
|
+ item_name.len = el->text.len;
|
|
|
|
|
+ if(jobj==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
|
+ goto error;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(jobj!=NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ srjson_AddStrItemToObject(&jdoc, jdoc.root,
|
|
|
|
|
+ item_name.s, item_name.len, jobj);
|
|
|
|
|
+ }
|
|
|
|
|
+ el = el->next;
|
|
|
|
|
+ }
|
|
|
|
|
+ LM_DBG("%s\n", json_object_to_json_string(jobj));
|
|
|
|
|
+ json_object_put(jobj);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ output = srjson_PrintUnformatted(&jdoc, jdoc.root);
|
|
|
|
|
+ if(output==NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ LM_ERR("cannot print json doc\n");
|
|
|
|
|
+ goto error;
|
|
|
|
|
+ }
|
|
|
|
|
+ LM_DBG("%s\n", output);
|
|
|
|
|
+ result = 0;
|
|
|
|
|
+
|
|
|
|
|
+error:
|
|
|
|
|
+ if(output!=NULL) jdoc.free_fn(output);
|
|
|
|
|
+ srjson_DestroyDoc(&jdoc);
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
--- a/modules/debugger/debugger_api.h
|
|
|
|
|
+++ b/modules/debugger/debugger_api.h
|
|
|
|
|
@ -174,7 +466,7 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel);
|
|
|
|
|
void dbg_enable_mod_levels(void);
|
|
|
|
|
|
|
|
|
|
+int dbg_dump_json(struct sip_msg* msg, pv_elem_p list);
|
|
|
|
|
+int dbg_dump_json(struct sip_msg* msg, pv_elem_p list, unsigned int mask);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
--- a/modules/debugger/debugger_mod.c
|
|
|
|
|
@ -192,8 +484,8 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
static cmd_export_t cmds[]={
|
|
|
|
|
{"dbg_breakpoint", (cmd_function)w_dbg_breakpoint, 1,
|
|
|
|
|
fixup_dbg_breakpoint, 0, ANY_ROUTE},
|
|
|
|
|
+ {"dbg_pv_dump", (cmd_function)w_dbg_dump, 0,
|
|
|
|
|
+ 0, 0, ANY_ROUTE},
|
|
|
|
|
+ {"dbg_pv_dump", (cmd_function)w_dbg_dump, 1,
|
|
|
|
|
+ fixup_uint_null, 0, ANY_ROUTE},
|
|
|
|
|
{0, 0, 0, 0, 0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -201,11 +493,11 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int w_dbg_dump(struct sip_msg* msg, char* point, char* str2)
|
|
|
|
|
+static int w_dbg_dump(struct sip_msg* msg, char* mask, char* str2)
|
|
|
|
|
+{
|
|
|
|
|
+ pv_elem_t *list = pv_cache_dump(msg);
|
|
|
|
|
+ if(list==NULL) return 0;
|
|
|
|
|
+ dbg_dump_json(msg, list);
|
|
|
|
|
+ dbg_dump_json(msg, list, (unsigned int)(unsigned long)mask);
|
|
|
|
|
+ pv_elem_free_all(list);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
@ -215,7 +507,7 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
*/
|
|
|
|
|
--- a/modules/debugger/doc/debugger_admin.xml
|
|
|
|
|
+++ b/modules/debugger/doc/debugger_admin.xml
|
|
|
|
|
@@ -250,7 +250,35 @@
|
|
|
|
|
@@ -250,7 +250,46 @@
|
|
|
|
|
</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
</section>
|
|
|
|
|
@ -223,27 +515,38 @@ It dumps the content of pv_cache on json format.
|
|
|
|
|
+
|
|
|
|
|
+ <section>
|
|
|
|
|
+ <title>
|
|
|
|
|
+ <function moreinfo="none">dbg_pv_dump()</function>
|
|
|
|
|
+ <function moreinfo="none">dbg_pv_dump(mask)</function>
|
|
|
|
|
+ </title>
|
|
|
|
|
+ <para>
|
|
|
|
|
+ Prints the content of pv_cache on json format
|
|
|
|
|
+ Prints the content of pv_cache on json format controled by mask value
|
|
|
|
|
+ </para>
|
|
|
|
|
+ <programlisting format="linespecific">
|
|
|
|
|
+#define DBG_DP_NULL 1
|
|
|
|
|
+#define DBG_DP_AVP 2
|
|
|
|
|
+#define DBG_DP_SCRIPTVAR 4
|
|
|
|
|
+#define DBG_DP_OTHER 8
|
|
|
|
|
+ </programlisting>
|
|
|
|
|
+ <example>
|
|
|
|
|
+ <title><function>dbg_pv_dump</function> usage</title>
|
|
|
|
|
+ <programlisting format="linespecific">
|
|
|
|
|
+...
|
|
|
|
|
+$var(temp) = 2;
|
|
|
|
|
+$var(temp) = 1;
|
|
|
|
|
+$avp(s:more_avp) = 2;
|
|
|
|
|
+$avp(s:more_avp) = 3;
|
|
|
|
|
+$xavp(x=>more) = "bye";
|
|
|
|
|
+$xavp(x[0]=>more) = "hi";
|
|
|
|
|
+$xavp(x[0]=>other) = 1;
|
|
|
|
|
+$xavp(x[0]=>other) = 2;
|
|
|
|
|
+$xavp(x=>different) = "foo";
|
|
|
|
|
+$var(empty) = $null;
|
|
|
|
|
+
|
|
|
|
|
+dbg_pv_dump();
|
|
|
|
|
+dbg_pv_dump(14);
|
|
|
|
|
+...
|
|
|
|
|
+</programlisting>
|
|
|
|
|
+ <para>Output</para>
|
|
|
|
|
+ <programlisting format="linespecific">
|
|
|
|
|
+...
|
|
|
|
|
+ 4(24310) DEBUG: debugger [debugger_api.c:1335]: dbg_dump_json(): { "$var(temp)": 2, "$avp(s:more_avp)": 3, "$xavp(x[0]=>more)": "hi" }
|
|
|
|
|
+
|
|
|
|
|
+ 4(30943) DEBUG: debugger [debugger_api.c:1613]: dbg_dump_json(): {"$sp":37597,"$var(rc)":0,"$var(temp)":1,"$avp(more_avp)":[3,2],"$si":"127.0.0.1","$rc":0,"$xavp(x)":[{"different":["foo"]},{"other":[2,1],"more":["hi","bye"]}],"$T_branch_idx":0,"$var(empty)":0}
|
|
|
|
|
+ ...
|
|
|
|
|
+</programlisting>
|
|
|
|
|
+ </example>
|
|
|
|
|
|