|
@@ -38,6 +38,9 @@
|
|
#include "../../locking.h"
|
|
#include "../../locking.h"
|
|
#include "../../lvalue.h"
|
|
#include "../../lvalue.h"
|
|
#include "../../hashes.h"
|
|
#include "../../hashes.h"
|
|
|
|
+#include "../../lib/srutils/srjson.h"
|
|
|
|
+#include "../../xavp.h"
|
|
|
|
+#include "../pv/pv_xavp.h"
|
|
|
|
|
|
#include "debugger_act.h"
|
|
#include "debugger_act.h"
|
|
#include "debugger_api.h"
|
|
#include "debugger_api.h"
|
|
@@ -1280,3 +1283,376 @@ int dbg_level_mode_fixup(void *temp_handle,
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+int _dbg_get_array_avp_vals(struct sip_msg *msg,
|
|
|
|
+ pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj,
|
|
|
|
+ str *item_name)
|
|
|
|
+{
|
|
|
|
+ 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);
|
|
|
|
+ if(xavp==NULL)
|
|
|
|
+ {
|
|
|
|
+ return 0; /* empty */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ do
|
|
|
|
+ {
|
|
|
|
+ if(xavp->val.type==SR_XTYPE_XAVP)
|
|
|
|
+ {
|
|
|
|
+ avp = xavp->val.v.xavp;
|
|
|
|
+ jobj = srjson_CreateObject(jdoc);
|
|
|
|
+ if(jobj==NULL)
|
|
|
|
+ {
|
|
|
|
+ LM_ERR("cannot create json object\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(jobj!=NULL)
|
|
|
|
+ {
|
|
|
|
+ srjson_AddItemToArray(jdoc, *jobjr, jobj);
|
|
|
|
+ jobj = NULL;
|
|
|
|
+ }
|
|
|
|
+ }while((xavp = xavp_get_next(xavp))!=0);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int dbg_dump_json(struct sip_msg* msg, unsigned int mask, int level)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+ pv_value_t value;
|
|
|
|
+ pv_cache_t **_pv_cache = pv_cache_get_table();
|
|
|
|
+ pv_cache_t *el = NULL;
|
|
|
|
+ srjson_doc_t jdoc;
|
|
|
|
+ srjson_t *jobj = NULL;
|
|
|
|
+ char *output = NULL;
|
|
|
|
+ str item_name = STR_NULL;
|
|
|
|
+ static char iname[128];
|
|
|
|
+ int result = -1;
|
|
|
|
+
|
|
|
|
+ if(_pv_cache==NULL)
|
|
|
|
+ {
|
|
|
|
+ LM_ERR("cannot access pv_cache\n");
|
|
|
|
+ return -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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for(i=0;i<PV_CACHE_SIZE;i++)
|
|
|
|
+ {
|
|
|
|
+ el = _pv_cache[i];
|
|
|
|
+ while(el)
|
|
|
|
+ {
|
|
|
|
+ if(!(el->spec.type==PVT_AVP||
|
|
|
|
+ el->spec.type==PVT_SCRIPTVAR||
|
|
|
|
+ el->spec.type==PVT_XAVP||
|
|
|
|
+ el->spec.type==PVT_OTHER)||
|
|
|
|
+ !((el->spec.type==PVT_AVP&&mask&DBG_DP_AVP)||
|
|
|
|
+ (el->spec.type==PVT_XAVP&&mask&DBG_DP_XAVP)||
|
|
|
|
+ (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;
|
|
|
|
+ }
|
|
|
|
+ jobj = NULL;
|
|
|
|
+ item_name.len = 0;
|
|
|
|
+ item_name.s = 0;
|
|
|
|
+ iname[0] = '\0';
|
|
|
|
+ if(el->spec.type==PVT_AVP)
|
|
|
|
+ {
|
|
|
|
+ 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_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
|
|
|
|
+ {
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if(el->spec.type==PVT_XAVP)
|
|
|
|
+ {
|
|
|
|
+ if(_dbg_xavp_dump_lookup(&el->spec.pvp)!=0)
|
|
|
|
+ {
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if(_dbg_get_obj_xavp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
|
|
|
|
+ {
|
|
|
|
+ LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
|
|
|
|
+ {
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if(pv_get_spec_value(msg, &el->spec, &value)!=0)
|
|
|
|
+ {
|
|
|
|
+ LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE))
|
|
|
|
+ {
|
|
|
|
+ if(mask&DBG_DP_NULL)
|
|
|
|
+ {
|
|
|
|
+ jobj = srjson_CreateNull(&jdoc);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ }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);
|
|
|
|
+ }else {
|
|
|
|
+ LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s,
|
|
|
|
+ value.flags);
|
|
|
|
+ el = el->next;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if(jobj==NULL)
|
|
|
|
+ {
|
|
|
|
+ LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len,
|
|
|
|
+ el->pvname.s);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s);
|
|
|
|
+ }
|
|
|
|
+ if(jobj!=NULL)
|
|
|
|
+ {
|
|
|
|
+ srjson_AddItemToObject(&jdoc, jdoc.root, iname, jobj);
|
|
|
|
+ }
|
|
|
|
+ el = el->next;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ output = srjson_PrintUnformatted(&jdoc, jdoc.root);
|
|
|
|
+ if(output==NULL)
|
|
|
|
+ {
|
|
|
|
+ LM_ERR("cannot print json doc\n");
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ LOG(level, "%s\n", output);
|
|
|
|
+ result = 0;
|
|
|
|
+
|
|
|
|
+error:
|
|
|
|
+ if(output!=NULL) jdoc.free_fn(output);
|
|
|
|
+ srjson_DestroyDoc(&jdoc);
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+}
|