mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
424 lines
9.5 KiB
424 lines
9.5 KiB
/**
|
|
*
|
|
* Copyright (C) 2013-2015 Victor Seva (sipwise.com)
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* This file is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
#include <stdio.h>
|
|
|
|
#include "../../pvar.h"
|
|
#include "../../mem/shm_mem.h"
|
|
#include "../../xavp.h"
|
|
#include "../pv/pv_xavp.h"
|
|
|
|
#include "debugger_api.h"
|
|
#include "debugger_json.h"
|
|
|
|
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(i<DBG_XAVP_DUMP_SIZE && _dbg_xavp_dump[i]!=NULL)
|
|
{
|
|
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_get_json(struct sip_msg* msg, unsigned int mask, srjson_doc_t *jdoc,
|
|
srjson_t *head)
|
|
{
|
|
int i;
|
|
pv_value_t value;
|
|
pv_cache_t **_pv_cache = pv_cache_get_table();
|
|
pv_cache_t *el = NULL;
|
|
srjson_t *jobj = NULL;
|
|
str item_name = STR_NULL;
|
|
static char iname[128];
|
|
|
|
if(_pv_cache==NULL)
|
|
{
|
|
LM_ERR("cannot access pv_cache\n");
|
|
return -1;
|
|
}
|
|
if(jdoc==NULL){
|
|
LM_ERR("jdoc is null\n");
|
|
return -1;
|
|
}
|
|
if(head==NULL){
|
|
LM_ERR("head is null\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(_dbg_xavp_dump, 0, sizeof(str*)*DBG_XAVP_DUMP_SIZE);
|
|
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, head, iname, jobj);
|
|
}
|
|
el = el->next;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
srjson_Delete(jdoc, head);
|
|
return -1;
|
|
}
|
|
|
|
int dbg_dump_json(struct sip_msg* msg, unsigned int mask, int level)
|
|
{
|
|
char *output = NULL;
|
|
srjson_doc_t jdoc;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
if(dbg_get_json(msg, mask, &jdoc, jdoc.root)<0) goto error;
|
|
output = srjson_PrintUnformatted(&jdoc, jdoc.root);
|
|
if(output==NULL)
|
|
{
|
|
LM_ERR("cannot print json doc\n");
|
|
srjson_DestroyDoc(&jdoc);
|
|
}
|
|
LOG(level, "%s\n", output);
|
|
jdoc.free_fn(output);
|
|
srjson_DestroyDoc(&jdoc);
|
|
return 0;
|
|
|
|
error:
|
|
srjson_DestroyDoc(&jdoc);
|
|
return -1;
|
|
}
|