/** * * 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 #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(ilen==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, "<>", avp->val.v.xavp); break; case SR_XTYPE_DATA: result = snprintf(_pv_xavp_buf, 128, "<>", 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;ispec.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; }