debugger_api.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * This file is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * This file is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #include "../../dprint.h"
  28. #include "../../ut.h"
  29. #include "../../pt.h"
  30. #include "../../events.h"
  31. #include "../../pvar.h"
  32. #include "../../rpc.h"
  33. #include "../../rpc_lookup.h"
  34. #include "../../route_struct.h"
  35. #include "../../mem/shm_mem.h"
  36. #include "../../locking.h"
  37. #include "../../lvalue.h"
  38. #include "../../hashes.h"
  39. #include "../../lib/srutils/srjson.h"
  40. #include "../../xavp.h"
  41. #include "../pv/pv_xavp.h"
  42. #include "debugger_act.h"
  43. #include "debugger_api.h"
  44. #include "debugger_config.h"
  45. #define DBG_CMD_SIZE 256
  46. #define DBG_STATE_INIT 0
  47. #define DBG_STATE_WAIT 1
  48. #define DBG_STATE_NEXT 2
  49. static str _dbg_state_list[] = {
  50. str_init("unknown"),
  51. str_init("init"),
  52. str_init("wait"),
  53. str_init("next"),
  54. {0, 0}
  55. };
  56. str *dbg_get_state_name(int t)
  57. {
  58. switch(t) {
  59. case DBG_STATE_INIT:
  60. return &_dbg_state_list[1];
  61. case DBG_STATE_WAIT:
  62. return &_dbg_state_list[2];
  63. case DBG_STATE_NEXT:
  64. return &_dbg_state_list[3];
  65. }
  66. return &_dbg_state_list[0];
  67. }
  68. #define DBG_CFGTRACE_ON (1<<0)
  69. #define DBG_ABKPOINT_ON (1<<1)
  70. #define DBG_LBKPOINT_ON (1<<2)
  71. static str _dbg_status_list[] = {
  72. str_init("cfgtrace-on"),
  73. str_init("cfgtrace-off"),
  74. str_init("abkpoint-on"),
  75. str_init("abkpoint-off"),
  76. str_init("lbkpoint-on"),
  77. str_init("lbkpoint-off"),
  78. {0, 0}
  79. };
  80. str *dbg_get_status_name(int t)
  81. {
  82. if(t&DBG_CFGTRACE_ON)
  83. return &_dbg_status_list[0];
  84. if(t&DBG_ABKPOINT_ON)
  85. return &_dbg_status_list[2];
  86. if(t&DBG_LBKPOINT_ON)
  87. return &_dbg_status_list[4];
  88. return &_dbg_state_list[0];
  89. }
  90. #define DBG_CMD_NOP 0
  91. #define DBG_CMD_ERR 1
  92. #define DBG_CMD_READ 2
  93. #define DBG_CMD_NEXT 3
  94. #define DBG_CMD_MOVE 4
  95. #define DBG_CMD_SHOW 5
  96. #define DBG_CMD_PVEVAL 6
  97. #define DBG_CMD_PVLOG 7
  98. static str _dbg_cmd_list[] = {
  99. str_init("nop"),
  100. str_init("err"),
  101. str_init("read"),
  102. str_init("next"),
  103. str_init("move"),
  104. str_init("show"),
  105. str_init("pveval"),
  106. str_init("pvlog"),
  107. {0, 0}
  108. };
  109. str *dbg_get_cmd_name(int t)
  110. {
  111. switch(t) {
  112. case DBG_CMD_NOP:
  113. return &_dbg_cmd_list[0];
  114. case DBG_CMD_ERR:
  115. return &_dbg_cmd_list[1];
  116. case DBG_CMD_READ:
  117. return &_dbg_cmd_list[2];
  118. case DBG_CMD_NEXT:
  119. return &_dbg_cmd_list[3];
  120. case DBG_CMD_MOVE:
  121. return &_dbg_cmd_list[4];
  122. case DBG_CMD_SHOW:
  123. return &_dbg_cmd_list[5];
  124. case DBG_CMD_PVEVAL:
  125. return &_dbg_cmd_list[6];
  126. case DBG_CMD_PVLOG:
  127. return &_dbg_cmd_list[7];
  128. }
  129. return &_dbg_state_list[0];
  130. }
  131. /**
  132. *
  133. */
  134. int _dbg_cfgtrace = 0;
  135. /**
  136. *
  137. */
  138. int _dbg_cfgpkgcheck = 0;
  139. /**
  140. *
  141. */
  142. int _dbg_breakpoint = 0;
  143. /**
  144. *
  145. */
  146. int _dbg_cfgtrace_level = L_ERR;
  147. /**
  148. *
  149. */
  150. int _dbg_cfgtrace_facility = DEFAULT_FACILITY;
  151. /**
  152. *
  153. */
  154. char *_dbg_cfgtrace_prefix = "*** cfgtrace:";
  155. /**
  156. *
  157. */
  158. char *_dbg_cfgtrace_lname = NULL;
  159. /**
  160. *
  161. */
  162. int _dbg_step_usleep = 100000;
  163. /**
  164. *
  165. */
  166. int _dbg_step_loops = 200;
  167. /**
  168. * disabled by default
  169. */
  170. int _dbg_reset_msgid = 0;
  171. /**
  172. *
  173. */
  174. typedef struct _dbg_cmd
  175. {
  176. unsigned int pid;
  177. unsigned int cmd;
  178. char buf[DBG_CMD_SIZE];
  179. } dbg_cmd_t;
  180. /**
  181. *
  182. */
  183. typedef struct _dbg_pid
  184. {
  185. unsigned int pid;
  186. unsigned int set;
  187. unsigned int state;
  188. dbg_cmd_t in;
  189. dbg_cmd_t out;
  190. gen_lock_t *lock;
  191. unsigned int reset_msgid; /* flag to reset the id */
  192. unsigned int msgid_base; /* real id since the reset */
  193. } dbg_pid_t;
  194. /**
  195. *
  196. */
  197. static dbg_pid_t *_dbg_pid_list = NULL;
  198. /**
  199. *
  200. */
  201. static int _dbg_pid_no = 0;
  202. /**
  203. *
  204. */
  205. typedef struct _dbg_bp
  206. {
  207. str cfile;
  208. int cline;
  209. int set;
  210. struct _dbg_bp *next;
  211. } dbg_bp_t;
  212. /**
  213. *
  214. */
  215. static dbg_bp_t *_dbg_bp_list = NULL;
  216. /* defined later */
  217. int dbg_get_pid_index(unsigned int pid);
  218. /*!
  219. * \brief Callback function that checks if reset_msgid is set
  220. * and modifies msg->id if necessary.
  221. * \param msg SIP message
  222. * \param flags unused
  223. * \param bar unused
  224. * \return 1 on success, -1 on failure
  225. */
  226. int dbg_msgid_filter(struct sip_msg *msg, unsigned int flags, void *bar)
  227. {
  228. unsigned int process_no = my_pid();
  229. int indx = dbg_get_pid_index(process_no);
  230. unsigned int msgid_base = 0;
  231. unsigned int msgid_new = 0;
  232. if(indx<0) return -1;
  233. LM_DBG("process_no:%d indx:%d\n", process_no, indx);
  234. lock_get(_dbg_pid_list[indx].lock);
  235. if(_dbg_pid_list[indx].reset_msgid==1)
  236. {
  237. LM_DBG("reset_msgid! msgid_base:%d\n", msg->id);
  238. _dbg_pid_list[indx].reset_msgid = 0;
  239. _dbg_pid_list[indx].msgid_base = msg->id - 1;
  240. }
  241. msgid_base = _dbg_pid_list[indx].msgid_base;
  242. lock_release(_dbg_pid_list[indx].lock);
  243. if(msg->id > msgid_base)
  244. {
  245. msgid_new = msg->id - msgid_base;
  246. LM_DBG("msg->id:%d msgid_base:%d -> %d\n",
  247. msg->id, msgid_base, msgid_new);
  248. msg->id = msgid_new;
  249. }
  250. else
  251. {
  252. LM_DBG("msg->id:%d already processed\n", msg->id);
  253. }
  254. return 1;
  255. }
  256. char* get_current_route_type_name()
  257. {
  258. switch(route_type){
  259. case REQUEST_ROUTE:
  260. return "request_route";
  261. case FAILURE_ROUTE:
  262. return "failure_route";
  263. case TM_ONREPLY_ROUTE:
  264. case CORE_ONREPLY_ROUTE:
  265. case ONREPLY_ROUTE:
  266. return "onreply_route";
  267. case BRANCH_ROUTE:
  268. return "branch_route";
  269. case ONSEND_ROUTE:
  270. return "onsend_route";
  271. case ERROR_ROUTE:
  272. return "error_route";
  273. case LOCAL_ROUTE:
  274. return "local_route";
  275. case BRANCH_FAILURE_ROUTE:
  276. return "branch_failure_route";
  277. default:
  278. return "unknown_route";
  279. }
  280. }
  281. /**
  282. * callback executed for each cfg action
  283. */
  284. int dbg_cfg_trace(void *data)
  285. {
  286. struct action *a;
  287. struct sip_msg *msg;
  288. int loop;
  289. int olen;
  290. str pvn;
  291. pv_spec_t pvs;
  292. pv_value_t val;
  293. void **srevp;
  294. str *an;
  295. srevp = (void**)data;
  296. a = (struct action *)srevp[0];
  297. msg = (struct sip_msg *)srevp[1];
  298. if(a==NULL || msg==NULL || _dbg_pid_list==NULL)
  299. return 0;
  300. an = dbg_get_action_name(a);
  301. if(_dbg_cfgpkgcheck!=0)
  302. {
  303. #if defined (PKG_MEMORY) && defined (q_malloc_h)
  304. LM_DBG("checking pkg memory before action %.*s (line %d)\n",
  305. an->len, an->s, a->cline);
  306. qm_check(mem_block);
  307. #else
  308. LM_DBG("cfg pkg check is disbled due to missing qm handler\n");
  309. #endif
  310. }
  311. if(_dbg_pid_list[process_no].set&DBG_CFGTRACE_ON)
  312. {
  313. if(is_printable(_dbg_cfgtrace_level))
  314. {
  315. LOG__(_dbg_cfgtrace_facility, _dbg_cfgtrace_level,
  316. _dbg_cfgtrace_lname, _dbg_cfgtrace_prefix,
  317. "%s=[%s] c=[%s] l=%d a=%d n=%.*s\n",
  318. get_current_route_type_name(), ZSW(a->rname),
  319. ZSW(a->cfile), a->cline,
  320. a->type, an->len, ZSW(an->s)
  321. );
  322. }
  323. }
  324. if(!(_dbg_pid_list[process_no].set&DBG_ABKPOINT_ON))
  325. {
  326. /* no breakpoints to be considered */
  327. return 0;
  328. }
  329. if(_dbg_pid_list[process_no].state==DBG_STATE_INIT)
  330. {
  331. LOG(_dbg_cfgtrace_level,
  332. "breakpoint hit: p=[%u] c=[%s] l=%d a=%d n=%.*s\n",
  333. _dbg_pid_list[process_no].pid,
  334. ZSW(a->cfile), a->cline, a->type, an->len, ZSW(an->s)
  335. );
  336. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  337. _dbg_pid_list[process_no].state = DBG_STATE_WAIT;
  338. }
  339. loop = 1;
  340. while(loop)
  341. {
  342. switch(_dbg_pid_list[process_no].in.cmd)
  343. {
  344. case DBG_CMD_NOP:
  345. sleep_us(_dbg_step_usleep);
  346. break;
  347. case DBG_CMD_MOVE:
  348. loop = 0;
  349. _dbg_pid_list[process_no].state=DBG_STATE_INIT;
  350. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  351. _dbg_pid_list[process_no].in.pid = 0;
  352. break;
  353. case DBG_CMD_NEXT:
  354. loop = 0;
  355. if(_dbg_pid_list[process_no].state==DBG_STATE_WAIT)
  356. _dbg_pid_list[process_no].state=DBG_STATE_NEXT;
  357. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  358. olen = snprintf(_dbg_pid_list[process_no].out.buf,
  359. DBG_CMD_SIZE,
  360. "exec [%s:%d] a=%d n=%.*s",
  361. ZSW(a->cfile), a->cline, a->type, an->len, ZSW(an->s));
  362. if(olen<0)
  363. {
  364. _dbg_pid_list[process_no].out.cmd = DBG_CMD_ERR;
  365. break;
  366. }
  367. _dbg_pid_list[process_no].out.cmd = DBG_CMD_READ;
  368. break;
  369. case DBG_CMD_PVEVAL:
  370. case DBG_CMD_PVLOG:
  371. loop = _dbg_pid_list[process_no].in.cmd;
  372. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  373. pvn.s = _dbg_pid_list[process_no].in.buf;
  374. pvn.len = strlen(pvn.s);
  375. if(pvn.len<=0)
  376. {
  377. LM_ERR("no pv to eval\n");
  378. break;
  379. }
  380. LM_DBG("pv to eval: %s\n", pvn.s);
  381. if(pv_parse_spec(&pvn, &pvs)<0)
  382. {
  383. LM_ERR("unable to parse pv [%s]\n", pvn.s);
  384. break;
  385. }
  386. memset(&val, 0, sizeof(pv_value_t));
  387. if(pv_get_spec_value(msg, &pvs, &val) != 0)
  388. {
  389. LM_ERR("unable to get pv value for [%s]\n", pvn.s);
  390. break;
  391. }
  392. if(val.flags&PV_VAL_NULL)
  393. {
  394. if(loop==DBG_CMD_PVEVAL)
  395. {
  396. olen = snprintf(_dbg_pid_list[process_no].out.buf,
  397. DBG_CMD_SIZE,
  398. "%s : t=null",
  399. pvn.s);
  400. if(olen<0)
  401. {
  402. _dbg_pid_list[process_no].out.cmd = DBG_CMD_ERR;
  403. break;
  404. }
  405. _dbg_pid_list[process_no].out.cmd = DBG_CMD_READ;
  406. } else {
  407. LOG(_dbg_cfgtrace_level,
  408. "breakpoint eval: %s : t=null\n",
  409. pvn.s
  410. );
  411. }
  412. break;
  413. }
  414. if(val.flags&PV_TYPE_INT)
  415. {
  416. if(loop==DBG_CMD_PVEVAL)
  417. {
  418. olen = snprintf(_dbg_pid_list[process_no].out.buf,
  419. DBG_CMD_SIZE,
  420. "%s : t=int v=%d",
  421. pvn.s, val.ri);
  422. if(olen<0)
  423. {
  424. _dbg_pid_list[process_no].out.cmd = DBG_CMD_ERR;
  425. break;
  426. }
  427. _dbg_pid_list[process_no].out.cmd = DBG_CMD_READ;
  428. } else {
  429. LOG(_dbg_cfgtrace_level,
  430. "breakpoint eval: %s : t=int v=%d\n",
  431. pvn.s, val.ri
  432. );
  433. }
  434. break;
  435. }
  436. if(loop==DBG_CMD_PVEVAL)
  437. {
  438. olen = snprintf(_dbg_pid_list[process_no].out.buf,
  439. DBG_CMD_SIZE,
  440. "%s : t=str v=%.*s",
  441. pvn.s, val.rs.len, val.rs.s);
  442. if(olen<0)
  443. {
  444. _dbg_pid_list[process_no].out.cmd = DBG_CMD_ERR;
  445. break;
  446. }
  447. _dbg_pid_list[process_no].out.cmd = DBG_CMD_READ;
  448. } else {
  449. LOG(_dbg_cfgtrace_level,
  450. "breakpoint eval: %s : t=str v=%.*s\n",
  451. pvn.s, val.rs.len, val.rs.s
  452. );
  453. }
  454. break;
  455. case DBG_CMD_SHOW:
  456. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  457. _dbg_pid_list[process_no].out.cmd = DBG_CMD_NOP;
  458. olen = snprintf(_dbg_pid_list[process_no].out.buf,
  459. DBG_CMD_SIZE,
  460. "at bkp [%s:%d] a=%d n=%.*s",
  461. a->cfile, a->cline, a->type, an->len, an->s);
  462. if(olen<0)
  463. {
  464. _dbg_pid_list[process_no].out.cmd = DBG_CMD_ERR;
  465. break;
  466. }
  467. _dbg_pid_list[process_no].out.cmd = DBG_CMD_READ;
  468. break;
  469. default:
  470. /* unknown command?!? - exit loop */
  471. _dbg_pid_list[process_no].in.cmd = DBG_CMD_NOP;
  472. _dbg_pid_list[process_no].state=DBG_STATE_INIT;
  473. loop = 0;
  474. }
  475. }
  476. return 0;
  477. }
  478. /**
  479. *
  480. */
  481. int dbg_init_bp_list(void)
  482. {
  483. if(_dbg_bp_list!=NULL)
  484. return -1;
  485. _dbg_bp_list = (dbg_bp_t*)shm_malloc(sizeof(dbg_bp_t));
  486. if(_dbg_bp_list==NULL)
  487. return -1;
  488. memset(_dbg_bp_list, 0, sizeof(dbg_bp_t));
  489. if(_dbg_breakpoint==1)
  490. _dbg_bp_list->set |= DBG_ABKPOINT_ON;
  491. if(_dbg_cfgtrace==1)
  492. _dbg_bp_list->set |= DBG_CFGTRACE_ON;
  493. sr_event_register_cb(SREV_CFG_RUN_ACTION, dbg_cfg_trace);
  494. return 0;
  495. }
  496. /**
  497. *
  498. */
  499. int dbg_add_breakpoint(struct action *a, int bpon)
  500. {
  501. int len;
  502. dbg_bp_t *nbp = NULL;
  503. if(_dbg_bp_list==NULL)
  504. return -1;
  505. len = strlen(a->cfile);
  506. len += sizeof(dbg_bp_t) + 1;
  507. nbp = (dbg_bp_t*)shm_malloc(len);
  508. if(nbp==NULL)
  509. return -1;
  510. memset(nbp, 0, len);
  511. nbp->set |= (bpon)?DBG_ABKPOINT_ON:0;
  512. nbp->cline = a->cline;
  513. nbp->cfile.s = (char*)nbp + sizeof(dbg_bp_t);
  514. strcpy(nbp->cfile.s, a->cfile);
  515. nbp->cfile.len = strlen(nbp->cfile.s);
  516. nbp->next = _dbg_bp_list->next;
  517. _dbg_bp_list->next = nbp;
  518. return 0;
  519. }
  520. /**
  521. *
  522. */
  523. int dbg_init_pid_list(void)
  524. {
  525. _dbg_pid_no = get_max_procs();
  526. if(_dbg_pid_no<=0)
  527. return -1;
  528. if(_dbg_pid_list!=NULL)
  529. return -1;
  530. _dbg_pid_list = (dbg_pid_t*)shm_malloc(_dbg_pid_no*sizeof(dbg_pid_t));
  531. if(_dbg_pid_list==NULL)
  532. return -1;
  533. memset(_dbg_pid_list, 0, _dbg_pid_no*sizeof(dbg_pid_t));
  534. return 0;
  535. }
  536. /**
  537. *
  538. */
  539. int dbg_init_mypid(void)
  540. {
  541. if(_dbg_pid_list==NULL)
  542. return -1;
  543. if(process_no>=_dbg_pid_no)
  544. return -1;
  545. _dbg_pid_list[process_no].pid = (unsigned int)my_pid();
  546. if(_dbg_breakpoint==1)
  547. _dbg_pid_list[process_no].set |= DBG_ABKPOINT_ON;
  548. if(_dbg_cfgtrace==1)
  549. _dbg_pid_list[process_no].set |= DBG_CFGTRACE_ON;
  550. if(_dbg_reset_msgid==1)
  551. {
  552. LM_DBG("[%d] create locks\n", process_no);
  553. _dbg_pid_list[process_no].lock = lock_alloc();
  554. if(_dbg_pid_list[process_no].lock==NULL)
  555. {
  556. LM_ERR("cannot allocate the lock\n");
  557. return -1;
  558. }
  559. if(lock_init(_dbg_pid_list[process_no].lock)==NULL)
  560. {
  561. LM_ERR("cannot init the lock\n");
  562. lock_dealloc(_dbg_pid_list[process_no].lock);
  563. return -1;
  564. }
  565. }
  566. return 0;
  567. }
  568. /**
  569. *
  570. */
  571. int dbg_get_pid_index(unsigned int pid)
  572. {
  573. int i;
  574. for(i=0; i<_dbg_pid_no; i++)
  575. {
  576. if(_dbg_pid_list[i].pid == pid)
  577. return i;
  578. }
  579. return -1;
  580. }
  581. /**
  582. *
  583. */
  584. static const char* dbg_rpc_bp_doc[2] = {
  585. "Breakpoint command",
  586. 0
  587. };
  588. /**
  589. *
  590. */
  591. static void dbg_rpc_bp(rpc_t* rpc, void* ctx)
  592. {
  593. int i;
  594. int limit;
  595. int lpid;
  596. str cmd;
  597. str val;
  598. int loop;
  599. if(_dbg_pid_list==NULL)
  600. {
  601. rpc->fault(ctx, 500, "Not initialized");
  602. return;
  603. }
  604. if (rpc->scan(ctx, "S", &cmd) < 1)
  605. {
  606. rpc->fault(ctx, 500, "Config breakpoint command missing");
  607. return;
  608. }
  609. i = 0;
  610. limit = _dbg_pid_no;
  611. if (rpc->scan(ctx, "*d", &lpid) == 1)
  612. {
  613. i = dbg_get_pid_index((unsigned int)lpid);
  614. if(i<0)
  615. {
  616. rpc->fault(ctx, 500, "No such pid");
  617. return;
  618. }
  619. limit = i + 1;
  620. } else {
  621. lpid = -1;
  622. }
  623. if(cmd.len==2 && strncmp(cmd.s, "on", 2)==0)
  624. {
  625. for(; i<limit; i++)
  626. {
  627. _dbg_pid_list[i].set |= DBG_ABKPOINT_ON;
  628. _dbg_pid_list[i].state=DBG_STATE_INIT;
  629. }
  630. } else if(cmd.len==3 && strncmp(cmd.s, "off", 3)==0) {
  631. for(; i<limit; i++)
  632. {
  633. _dbg_pid_list[i].set &= ~DBG_ABKPOINT_ON;
  634. _dbg_pid_list[i].state=DBG_STATE_INIT;
  635. }
  636. } else if(cmd.len==7 && strncmp(cmd.s, "release", 7)==0) {
  637. for(; i<limit; i++)
  638. {
  639. if(_dbg_pid_list[i].state!=DBG_STATE_WAIT)
  640. {
  641. _dbg_pid_list[i].set &= ~DBG_ABKPOINT_ON;
  642. _dbg_pid_list[i].state=DBG_STATE_INIT;
  643. }
  644. }
  645. } else if(cmd.len==4 && strncmp(cmd.s, "keep", 4)==0) {
  646. if(lpid==-1)
  647. {
  648. rpc->fault(ctx, 500, "Missing pid parameter");
  649. return;
  650. }
  651. for(loop=0; loop<_dbg_pid_no; loop++)
  652. {
  653. if(i!=loop)
  654. {
  655. _dbg_pid_list[loop].set &= ~DBG_ABKPOINT_ON;
  656. if(_dbg_pid_list[loop].state!=DBG_STATE_INIT)
  657. {
  658. _dbg_pid_list[loop].in.pid = my_pid();
  659. _dbg_pid_list[loop].in.cmd = DBG_CMD_MOVE;
  660. }
  661. }
  662. }
  663. } else if(cmd.len==4 && strncmp(cmd.s, "move", 4)==0) {
  664. if(lpid==-1)
  665. {
  666. rpc->fault(ctx, 500, "Missing pid parameter");
  667. return;
  668. }
  669. for(; i<limit; i++)
  670. {
  671. if(_dbg_pid_list[i].state!=DBG_STATE_INIT)
  672. {
  673. _dbg_pid_list[i].set &= ~DBG_ABKPOINT_ON;
  674. _dbg_pid_list[i].in.pid = my_pid();
  675. _dbg_pid_list[i].in.cmd = DBG_CMD_MOVE;
  676. }
  677. }
  678. } else if(cmd.len==4 && strncmp(cmd.s, "next", 4)==0) {
  679. if(lpid==-1)
  680. {
  681. rpc->fault(ctx, 500, "Missing pid parameter");
  682. return;
  683. }
  684. _dbg_pid_list[i].in.pid = my_pid();
  685. _dbg_pid_list[i].in.cmd = DBG_CMD_NEXT;
  686. for(loop=0; loop<_dbg_step_loops; loop++)
  687. {
  688. sleep_us(_dbg_step_usleep);
  689. if(_dbg_pid_list[i].out.cmd == DBG_CMD_READ)
  690. {
  691. rpc->add(ctx, "s", _dbg_pid_list[i].out.buf);
  692. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  693. return;
  694. } else if(_dbg_pid_list[i].out.cmd == DBG_CMD_ERR) {
  695. rpc->add(ctx, "s", "cmd execution error");
  696. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  697. return;
  698. }
  699. }
  700. /* nothing to read ... err?!? */
  701. } else if(cmd.len==4 && strncmp(cmd.s, "show", 4)==0) {
  702. if(lpid==-1)
  703. {
  704. rpc->fault(ctx, 500, "Missing pid parameter");
  705. return;
  706. }
  707. _dbg_pid_list[i].in.pid = my_pid();
  708. _dbg_pid_list[i].in.cmd = DBG_CMD_SHOW;
  709. for(loop=0; loop<_dbg_step_loops; loop++)
  710. {
  711. sleep_us(_dbg_step_usleep);
  712. if(_dbg_pid_list[i].out.cmd == DBG_CMD_READ)
  713. {
  714. rpc->add(ctx, "s", _dbg_pid_list[i].out.buf);
  715. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  716. return;
  717. } else if(_dbg_pid_list[i].out.cmd == DBG_CMD_ERR) {
  718. rpc->add(ctx, "s", "cmd execution error");
  719. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  720. return;
  721. }
  722. }
  723. /* nothing to read ... err?!? */
  724. } else if(cmd.len==4 && strncmp(cmd.s, "eval", 4)==0) {
  725. if(lpid==-1)
  726. {
  727. rpc->fault(ctx, 500, "Missing pid parameter");
  728. return;
  729. }
  730. if (rpc->scan(ctx, "S", &val) < 1)
  731. {
  732. rpc->fault(ctx, 500, "pv param missing");
  733. return;
  734. }
  735. if (val.len < 2 || val.len>=DBG_CMD_SIZE)
  736. {
  737. rpc->fault(ctx, 500, "invalid pv param");
  738. return;
  739. }
  740. strncpy(_dbg_pid_list[i].in.buf, val.s, val.len);
  741. _dbg_pid_list[i].in.buf[val.len] = '\0';
  742. _dbg_pid_list[i].in.pid = my_pid();
  743. _dbg_pid_list[i].in.cmd = DBG_CMD_PVEVAL;
  744. for(loop=0; loop<_dbg_step_loops; loop++)
  745. {
  746. sleep_us(_dbg_step_usleep);
  747. if(_dbg_pid_list[i].out.cmd == DBG_CMD_READ)
  748. {
  749. rpc->add(ctx, "s", _dbg_pid_list[i].out.buf);
  750. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  751. return;
  752. } else if(_dbg_pid_list[i].out.cmd == DBG_CMD_ERR) {
  753. rpc->add(ctx, "s", "cmd execution error");
  754. _dbg_pid_list[i].out.cmd = DBG_CMD_NOP;
  755. return;
  756. }
  757. }
  758. /* nothing to read ... err?!? */
  759. } else if(cmd.len==3 && strncmp(cmd.s, "log", 3)==0) {
  760. if(lpid==-1)
  761. {
  762. rpc->fault(ctx, 500, "Missing pid parameter");
  763. return;
  764. }
  765. if (rpc->scan(ctx, "S", &val) < 1)
  766. {
  767. rpc->fault(ctx, 500, "pv param missing");
  768. return;
  769. }
  770. if (val.len < 2 || val.len>=DBG_CMD_SIZE)
  771. {
  772. rpc->fault(ctx, 500, "invalid pv param");
  773. return;
  774. }
  775. strncpy(_dbg_pid_list[i].in.buf, val.s, val.len);
  776. _dbg_pid_list[i].in.buf[val.len] = '\0';
  777. _dbg_pid_list[i].in.pid = my_pid();
  778. _dbg_pid_list[i].in.cmd = DBG_CMD_PVLOG;
  779. } else {
  780. rpc->fault(ctx, 500, "Unknown inner command");
  781. }
  782. rpc->add(ctx, "s", "200 ok");
  783. }
  784. /**
  785. *
  786. */
  787. static const char* dbg_rpc_list_doc[2] = {
  788. "List debugging process array",
  789. 0
  790. };
  791. /**
  792. *
  793. */
  794. static void dbg_rpc_list(rpc_t* rpc, void* ctx)
  795. {
  796. int i;
  797. int limit;
  798. int lpid;
  799. void* th;
  800. if(_dbg_pid_list==NULL)
  801. {
  802. rpc->fault(ctx, 500, "Not initialized");
  803. return;
  804. }
  805. i = 0;
  806. limit = _dbg_pid_no;
  807. if (rpc->scan(ctx, "*d", &lpid) == 1)
  808. {
  809. i = dbg_get_pid_index((unsigned int)lpid);
  810. if(i<0)
  811. {
  812. rpc->fault(ctx, 500, "No such pid");
  813. return;
  814. }
  815. limit = i + 1;
  816. }
  817. for(; i<limit; i++)
  818. {
  819. /* add entry node */
  820. if (rpc->add(ctx, "{", &th) < 0)
  821. {
  822. rpc->fault(ctx, 500, "Internal error creating rpc");
  823. return;
  824. }
  825. if(rpc->struct_add(th, "dddddd",
  826. "entry", i,
  827. "pid", _dbg_pid_list[i].pid,
  828. "set", _dbg_pid_list[i].set,
  829. "state", _dbg_pid_list[i].state,
  830. "in.pid", _dbg_pid_list[i].in.pid,
  831. "in.cmd", _dbg_pid_list[i].in.cmd
  832. )<0)
  833. {
  834. rpc->fault(ctx, 500, "Internal error creating rpc");
  835. return;
  836. }
  837. }
  838. }
  839. /**
  840. *
  841. */
  842. static const char* dbg_rpc_trace_doc[2] = {
  843. "Config trace command",
  844. 0
  845. };
  846. /**
  847. *
  848. */
  849. static void dbg_rpc_trace(rpc_t* rpc, void* ctx)
  850. {
  851. int i;
  852. int limit;
  853. int lpid;
  854. str cmd;
  855. if(_dbg_pid_list==NULL)
  856. {
  857. rpc->fault(ctx, 500, "Not initialized");
  858. return;
  859. }
  860. if (rpc->scan(ctx, "S", &cmd) < 1)
  861. {
  862. rpc->fault(ctx, 500, "Config trace command missing");
  863. return;
  864. }
  865. i = 0;
  866. limit = _dbg_pid_no;
  867. if (rpc->scan(ctx, "*d", &lpid) == 1)
  868. {
  869. i = dbg_get_pid_index((unsigned int)lpid);
  870. if(i<0)
  871. {
  872. rpc->fault(ctx, 500, "No such pid");
  873. return;
  874. }
  875. limit = i + 1;
  876. }
  877. if(cmd.len!=2 && cmd.len!=3)
  878. {
  879. rpc->fault(ctx, 500, "Unknown trace command");
  880. return;
  881. }
  882. if(cmd.len==2)
  883. {
  884. if(strncmp(cmd.s, "on", 2)!=0)
  885. {
  886. rpc->fault(ctx, 500, "Unknown trace command");
  887. return;
  888. }
  889. } else {
  890. if(strncmp(cmd.s, "off", 3)!=0)
  891. {
  892. rpc->fault(ctx, 500, "Unknown trace command");
  893. return;
  894. }
  895. }
  896. for(; i<limit; i++)
  897. {
  898. if(cmd.len==2)
  899. {
  900. _dbg_pid_list[i].set |= DBG_CFGTRACE_ON;
  901. } else {
  902. _dbg_pid_list[i].set &= ~DBG_CFGTRACE_ON;
  903. }
  904. }
  905. rpc->add(ctx, "s", "200 ok");
  906. }
  907. /**
  908. *
  909. */
  910. static const char* dbg_rpc_mod_level_doc[2] = {
  911. "Specify module log level",
  912. 0
  913. };
  914. static void dbg_rpc_mod_level(rpc_t* rpc, void* ctx){
  915. int l;
  916. str value = {0,0};
  917. if (rpc->scan(ctx, "Sd", &value, &l) < 1)
  918. {
  919. rpc->fault(ctx, 500, "invalid parameters");
  920. return;
  921. }
  922. if(dbg_set_mod_debug_level(value.s, value.len, &l)<0)
  923. {
  924. rpc->fault(ctx, 500, "cannot store parameter\n");
  925. return;
  926. }
  927. rpc->add(ctx, "s", "200 ok");
  928. }
  929. /**
  930. *
  931. */
  932. static const char* dbg_rpc_reset_msgid_doc[2] = {
  933. "Reset msgid on all process",
  934. 0
  935. };
  936. static void dbg_rpc_reset_msgid(rpc_t* rpc, void* ctx){
  937. int i;
  938. if (_dbg_reset_msgid==0)
  939. {
  940. rpc->fault(ctx, 500, "reset_msgid is 0. Set it to 1 to enable.");
  941. return;
  942. }
  943. if(_dbg_pid_list==NULL)
  944. {
  945. rpc->fault(ctx, 500, "_dbg_pid_list is NULL");
  946. return;
  947. }
  948. LM_DBG("set reset_msgid\n");
  949. for(i=0; i<_dbg_pid_no; i++)
  950. {
  951. if (_dbg_pid_list[i].lock!=NULL)
  952. {
  953. lock_get(_dbg_pid_list[i].lock);
  954. _dbg_pid_list[i].reset_msgid = 1;
  955. lock_release(_dbg_pid_list[i].lock);
  956. }
  957. }
  958. rpc->add(ctx, "s", "200 ok");
  959. }
  960. /**
  961. *
  962. */
  963. rpc_export_t dbg_rpc[] = {
  964. {"dbg.bp", dbg_rpc_bp, dbg_rpc_bp_doc, 0},
  965. {"dbg.ls", dbg_rpc_list, dbg_rpc_list_doc, 0},
  966. {"dbg.trace", dbg_rpc_trace, dbg_rpc_trace_doc, 0},
  967. {"dbg.mod_level", dbg_rpc_mod_level, dbg_rpc_mod_level_doc, 0},
  968. {"dbg.reset_msgid", dbg_rpc_reset_msgid, dbg_rpc_reset_msgid_doc, 0},
  969. {0, 0, 0, 0}
  970. };
  971. /**
  972. *
  973. */
  974. int dbg_init_rpc(void)
  975. {
  976. if (rpc_register_array(dbg_rpc)!=0)
  977. {
  978. LM_ERR("failed to register RPC commands\n");
  979. return -1;
  980. }
  981. return 0;
  982. }
  983. typedef struct _dbg_mod_level {
  984. str name;
  985. unsigned int hashid;
  986. int level;
  987. struct _dbg_mod_level *next;
  988. } dbg_mod_level_t;
  989. typedef struct _dbg_mod_slot
  990. {
  991. dbg_mod_level_t *first;
  992. gen_lock_t lock;
  993. } dbg_mod_slot_t;
  994. static dbg_mod_slot_t *_dbg_mod_table = NULL;
  995. static unsigned int _dbg_mod_table_size = 0;
  996. /**
  997. *
  998. */
  999. int dbg_init_mod_levels(int dbg_mod_hash_size)
  1000. {
  1001. int i;
  1002. if(dbg_mod_hash_size<=0)
  1003. return 0;
  1004. if(_dbg_mod_table!=NULL)
  1005. return 0;
  1006. _dbg_mod_table_size = 1 << dbg_mod_hash_size;
  1007. _dbg_mod_table = (dbg_mod_slot_t*)shm_malloc(_dbg_mod_table_size*sizeof(dbg_mod_slot_t));
  1008. if(_dbg_mod_table==NULL)
  1009. {
  1010. LM_ERR("no more shm.\n");
  1011. return -1;
  1012. }
  1013. memset(_dbg_mod_table, 0, _dbg_mod_table_size*sizeof(dbg_mod_slot_t));
  1014. for(i=0; i<_dbg_mod_table_size; i++)
  1015. {
  1016. if(lock_init(&_dbg_mod_table[i].lock)==0)
  1017. {
  1018. LM_ERR("cannot initalize lock[%d]\n", i);
  1019. i--;
  1020. while(i>=0)
  1021. {
  1022. lock_destroy(&_dbg_mod_table[i].lock);
  1023. i--;
  1024. }
  1025. shm_free(_dbg_mod_table);
  1026. _dbg_mod_table = NULL;
  1027. return -1;
  1028. }
  1029. }
  1030. return 0;
  1031. }
  1032. /*
  1033. * case insensitive hashing - clone here to avoid usage of LOG*()
  1034. * - s1 - str to hash
  1035. * - s1len - len of s1
  1036. * return computed hash id
  1037. */
  1038. #define dbg_ch_h_inc h+=v^(v>>3)
  1039. #define dbg_ch_icase(_c) (((_c)>='A'&&(_c)<='Z')?((_c)|0x20):(_c))
  1040. static inline unsigned int dbg_compute_hash(char *s1, int s1len)
  1041. {
  1042. char *p, *end;
  1043. register unsigned v;
  1044. register unsigned h;
  1045. h=0;
  1046. end=s1+s1len;
  1047. for ( p=s1 ; p<=(end-4) ; p+=4 ){
  1048. v=(dbg_ch_icase(*p)<<24)+(dbg_ch_icase(p[1])<<16)+(dbg_ch_icase(p[2])<<8)
  1049. + dbg_ch_icase(p[3]);
  1050. dbg_ch_h_inc;
  1051. }
  1052. v=0;
  1053. for (; p<end ; p++){ v<<=8; v+=dbg_ch_icase(*p);}
  1054. dbg_ch_h_inc;
  1055. h=((h)+(h>>11))+((h>>13)+(h>>23));
  1056. return h;
  1057. }
  1058. int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel)
  1059. {
  1060. unsigned int idx;
  1061. unsigned int hid;
  1062. dbg_mod_level_t *it;
  1063. dbg_mod_level_t *itp;
  1064. dbg_mod_level_t *itn;
  1065. if(_dbg_mod_table==NULL)
  1066. return -1;
  1067. hid = dbg_compute_hash(mname, mnlen);
  1068. idx = hid&(_dbg_mod_table_size-1);
  1069. lock_get(&_dbg_mod_table[idx].lock);
  1070. it = _dbg_mod_table[idx].first;
  1071. itp = NULL;
  1072. while(it!=NULL && it->hashid < hid) {
  1073. itp = it;
  1074. it = it->next;
  1075. }
  1076. while(it!=NULL && it->hashid==hid)
  1077. {
  1078. if(mnlen==it->name.len
  1079. && strncmp(mname, it->name.s, mnlen)==0)
  1080. {
  1081. /* found */
  1082. if(mlevel==NULL) {
  1083. /* remove */
  1084. if(itp!=NULL) {
  1085. itp->next = it->next;
  1086. } else {
  1087. _dbg_mod_table[idx].first = it->next;
  1088. }
  1089. shm_free(it);
  1090. } else {
  1091. /* set */
  1092. it->level = *mlevel;
  1093. }
  1094. lock_release(&_dbg_mod_table[idx].lock);
  1095. return 0;
  1096. }
  1097. itp = it;
  1098. it = it->next;
  1099. }
  1100. /* not found - add */
  1101. if(mlevel==NULL) {
  1102. lock_release(&_dbg_mod_table[idx].lock);
  1103. return 0;
  1104. }
  1105. itn = (dbg_mod_level_t*)shm_malloc(sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char));
  1106. if(itn==NULL) {
  1107. LM_ERR("no more shm\n");
  1108. lock_release(&_dbg_mod_table[idx].lock);
  1109. return -1;
  1110. }
  1111. memset(itn, 0, sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char));
  1112. itn->level = *mlevel;
  1113. itn->hashid = hid;
  1114. itn->name.s = (char*)(itn) + sizeof(dbg_mod_level_t);
  1115. itn->name.len = mnlen;
  1116. strncpy(itn->name.s, mname, mnlen);
  1117. itn->name.s[itn->name.len] = '\0';
  1118. if(itp==NULL) {
  1119. itn->next = _dbg_mod_table[idx].first;
  1120. _dbg_mod_table[idx].first = itn;
  1121. } else {
  1122. itn->next = itp->next;
  1123. itp->next = itn;
  1124. }
  1125. lock_release(&_dbg_mod_table[idx].lock);
  1126. return 0;
  1127. }
  1128. static int _dbg_get_mod_debug_level = 0;
  1129. int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
  1130. {
  1131. unsigned int idx;
  1132. unsigned int hid;
  1133. dbg_mod_level_t *it;
  1134. /* no LOG*() usage in this function and those executed insite it
  1135. * - use fprintf(stderr, ...) if need for troubleshooting
  1136. * - it will loop otherwise */
  1137. if(_dbg_mod_table==NULL)
  1138. return -1;
  1139. if(cfg_get(dbg, dbg_cfg, mod_level_mode)==0)
  1140. return -1;
  1141. if(_dbg_get_mod_debug_level!=0)
  1142. return -1;
  1143. _dbg_get_mod_debug_level = 1;
  1144. hid = dbg_compute_hash(mname, mnlen);
  1145. idx = hid&(_dbg_mod_table_size-1);
  1146. lock_get(&_dbg_mod_table[idx].lock);
  1147. it = _dbg_mod_table[idx].first;
  1148. while(it!=NULL && it->hashid < hid)
  1149. it = it->next;
  1150. while(it!=NULL && it->hashid == hid)
  1151. {
  1152. if(mnlen==it->name.len
  1153. && strncmp(mname, it->name.s, mnlen)==0)
  1154. {
  1155. /* found */
  1156. *mlevel = it->level;
  1157. lock_release(&_dbg_mod_table[idx].lock);
  1158. _dbg_get_mod_debug_level = 0;
  1159. return 0;
  1160. }
  1161. it = it->next;
  1162. }
  1163. lock_release(&_dbg_mod_table[idx].lock);
  1164. _dbg_get_mod_debug_level = 0;
  1165. return -1;
  1166. }
  1167. /**
  1168. *
  1169. */
  1170. void dbg_enable_mod_levels(void)
  1171. {
  1172. if(_dbg_mod_table==NULL)
  1173. return;
  1174. set_module_debug_level_cb(dbg_get_mod_debug_level);
  1175. }
  1176. #define DBG_PVCACHE_SIZE 32
  1177. typedef struct _dbg_pvcache {
  1178. pv_spec_t *spec;
  1179. str *pvname;
  1180. struct _dbg_pvcache *next;
  1181. } dbg_pvcache_t;
  1182. static dbg_pvcache_t **_dbg_pvcache = NULL;
  1183. int dbg_init_pvcache()
  1184. {
  1185. _dbg_pvcache = (dbg_pvcache_t**)pkg_malloc(sizeof(dbg_pvcache_t*)*DBG_PVCACHE_SIZE);
  1186. if(_dbg_pvcache==NULL)
  1187. {
  1188. LM_ERR("no more memory.\n");
  1189. return -1;
  1190. }
  1191. memset(_dbg_pvcache, 0, sizeof(dbg_pvcache_t*)*DBG_PVCACHE_SIZE);
  1192. return 0;
  1193. }
  1194. int dbg_assign_add(str *name, pv_spec_t *spec)
  1195. {
  1196. dbg_pvcache_t *pvn, *last, *next;
  1197. unsigned int pvid;
  1198. if(name==NULL||spec==NULL)
  1199. return -1;
  1200. if(_dbg_pvcache==NULL)
  1201. return -1;
  1202. pvid = get_hash1_raw((char *)&spec, sizeof(pv_spec_t*));
  1203. pvn = (dbg_pvcache_t*)pkg_malloc(sizeof(dbg_pvcache_t));
  1204. if(pvn==NULL)
  1205. {
  1206. LM_ERR("no more memory\n");
  1207. return -1;
  1208. }
  1209. memset(pvn, 0, sizeof(dbg_pvcache_t));
  1210. pvn->pvname = name;
  1211. pvn->spec = spec;
  1212. next = _dbg_pvcache[pvid%DBG_PVCACHE_SIZE];
  1213. if(next==NULL)
  1214. {
  1215. _dbg_pvcache[pvid%DBG_PVCACHE_SIZE] = pvn;
  1216. }
  1217. else
  1218. {
  1219. while(next)
  1220. {
  1221. last = next;
  1222. next = next->next;
  1223. }
  1224. last->next = pvn;
  1225. }
  1226. return 0;
  1227. }
  1228. str *_dbg_pvcache_lookup(pv_spec_t *spec)
  1229. {
  1230. dbg_pvcache_t *pvi;
  1231. unsigned int pvid;
  1232. str *name = NULL;
  1233. if(spec==NULL)
  1234. return NULL;
  1235. if(_dbg_pvcache==NULL)
  1236. return NULL;
  1237. pvid = get_hash1_raw((char *)&spec, sizeof(pv_spec_t*));
  1238. pvi = _dbg_pvcache[pvid%DBG_PVCACHE_SIZE];
  1239. while(pvi)
  1240. {
  1241. if(pvi->spec==spec) {
  1242. return pvi->pvname;
  1243. }
  1244. pvi = pvi->next;
  1245. }
  1246. name = pv_cache_get_name(spec);
  1247. if(name!=NULL)
  1248. {
  1249. /*LM_DBG("Add name[%.*s] to pvcache\n", name->len, name->s);*/
  1250. dbg_assign_add(name, spec);
  1251. }
  1252. return name;
  1253. }
  1254. int _dbg_log_assign_action_avp(struct sip_msg* msg, struct lvalue* lv)
  1255. {
  1256. int_str avp_val;
  1257. avp_t* avp;
  1258. avp_spec_t* avp_s = &lv->lv.avps;
  1259. avp = search_avp_by_index(avp_s->type, avp_s->name,
  1260. &avp_val, avp_s->index);
  1261. if (likely(avp)){
  1262. if (avp->flags&(AVP_VAL_STR)){
  1263. LM_DBG("%.*s:\"%.*s\"\n", avp_s->name.s.len, avp_s->name.s.s,
  1264. avp_val.s.len, avp_val.s.s);
  1265. }else{
  1266. LM_DBG("%.*s:%d\n", avp_s->name.s.len, avp_s->name.s.s,
  1267. avp_val.n);
  1268. }
  1269. }
  1270. return 0;
  1271. }
  1272. int _dbg_log_assign_action_pvar(struct sip_msg* msg, struct lvalue* lv)
  1273. {
  1274. pv_value_t value;
  1275. pv_spec_t* pvar = lv->lv.pvs;
  1276. str def_name = {"unknown", 7};
  1277. str *name = _dbg_pvcache_lookup(pvar);
  1278. if(name==NULL)
  1279. name = &def_name;
  1280. if(pv_get_spec_value(msg, pvar, &value)!=0)
  1281. {
  1282. LM_ERR("can't get value\n");
  1283. return -1;
  1284. }
  1285. if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE)){
  1286. LM_DBG("%.*s: $null\n", name->len, name->s);
  1287. }else if(value.flags&(PV_VAL_INT)){
  1288. LM_DBG("%.*s:%d\n", name->len, name->s, value.ri);
  1289. }else if(value.flags&(PV_VAL_STR)){
  1290. LM_DBG("%.*s:\"%.*s\"\n", name->len, name->s, value.rs.len, value.rs.s);
  1291. }
  1292. return 0;
  1293. }
  1294. int dbg_log_assign(struct sip_msg* msg, struct lvalue *lv)
  1295. {
  1296. if(lv==NULL)
  1297. {
  1298. LM_ERR("left value is NULL\n");
  1299. return -1;
  1300. }
  1301. switch(lv->type){
  1302. case LV_AVP:
  1303. return _dbg_log_assign_action_avp(msg, lv);
  1304. break;
  1305. case LV_PVAR:
  1306. return _dbg_log_assign_action_pvar(msg, lv);
  1307. break;
  1308. case LV_NONE:
  1309. break;
  1310. }
  1311. return 0;
  1312. }
  1313. void dbg_enable_log_assign(void)
  1314. {
  1315. if(_dbg_pvcache==NULL)
  1316. return;
  1317. set_log_assign_action_cb(dbg_log_assign);
  1318. }
  1319. int dbg_level_mode_fixup(void *temp_handle,
  1320. str *group_name, str *var_name, void **value){
  1321. if(_dbg_mod_table==NULL)
  1322. {
  1323. LM_ERR("mod_hash_size must be set on start\n");
  1324. return -1;
  1325. }
  1326. return 0;
  1327. }
  1328. int _dbg_get_array_avp_vals(struct sip_msg *msg,
  1329. pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj,
  1330. str *item_name)
  1331. {
  1332. struct usr_avp *avp;
  1333. unsigned short name_type;
  1334. int_str avp_name;
  1335. int_str avp_value;
  1336. struct search_state state;
  1337. srjson_t *jobjt;
  1338. memset(&state, 0, sizeof(struct search_state));
  1339. if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
  1340. {
  1341. LM_ERR("invalid name\n");
  1342. return -1;
  1343. }
  1344. *jobj = srjson_CreateArray(jdoc);
  1345. if(*jobj==NULL)
  1346. {
  1347. LM_ERR("cannot create json object\n");
  1348. return -1;
  1349. }
  1350. if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0)
  1351. {
  1352. goto ok;
  1353. }
  1354. do
  1355. {
  1356. if(avp->flags & AVP_VAL_STR)
  1357. {
  1358. jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len);
  1359. if(jobjt==NULL)
  1360. {
  1361. LM_ERR("cannot create json object\n");
  1362. return -1;
  1363. }
  1364. } else {
  1365. jobjt = srjson_CreateNumber(jdoc, avp_value.n);
  1366. if(jobjt==NULL)
  1367. {
  1368. LM_ERR("cannot create json object\n");
  1369. return -1;
  1370. }
  1371. }
  1372. srjson_AddItemToArray(jdoc, *jobj, jobjt);
  1373. } while ((avp=search_next_avp(&state, &avp_value))!=0);
  1374. ok:
  1375. item_name->s = avp_name.s.s;
  1376. item_name->len = avp_name.s.len;
  1377. return 0;
  1378. }
  1379. #define DBG_XAVP_DUMP_SIZE 32
  1380. static str* _dbg_xavp_dump[DBG_XAVP_DUMP_SIZE];
  1381. int _dbg_xavp_dump_lookup(pv_param_t *param)
  1382. {
  1383. unsigned int i = 0;
  1384. pv_xavp_name_t *xname;
  1385. if(param==NULL)
  1386. return -1;
  1387. xname = (pv_xavp_name_t*)param->pvn.u.dname;
  1388. while(_dbg_xavp_dump[i]!=NULL&&i<DBG_XAVP_DUMP_SIZE)
  1389. {
  1390. if(_dbg_xavp_dump[i]->len==xname->name.len)
  1391. {
  1392. if(strncmp(_dbg_xavp_dump[i]->s, xname->name.s, xname->name.len)==0)
  1393. return 1; /* already dump before */
  1394. }
  1395. i++;
  1396. }
  1397. if(i==DBG_XAVP_DUMP_SIZE)
  1398. {
  1399. LM_WARN("full _dbg_xavp_dump cache array\n");
  1400. return 0; /* end cache names */
  1401. }
  1402. _dbg_xavp_dump[i] = &xname->name;
  1403. return 0;
  1404. }
  1405. void _dbg_get_obj_xavp_val(sr_xavp_t *avp, srjson_doc_t *jdoc, srjson_t **jobj)
  1406. {
  1407. static char _pv_xavp_buf[128];
  1408. int result = 0;
  1409. switch(avp->val.type) {
  1410. case SR_XTYPE_NULL:
  1411. *jobj = srjson_CreateNull(jdoc);
  1412. break;
  1413. case SR_XTYPE_INT:
  1414. *jobj = srjson_CreateNumber(jdoc, avp->val.v.i);
  1415. break;
  1416. case SR_XTYPE_STR:
  1417. *jobj = srjson_CreateStr(jdoc, avp->val.v.s.s, avp->val.v.s.len);
  1418. break;
  1419. case SR_XTYPE_TIME:
  1420. result = snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t);
  1421. break;
  1422. case SR_XTYPE_LONG:
  1423. result = snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l);
  1424. break;
  1425. case SR_XTYPE_LLONG:
  1426. result = snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll);
  1427. break;
  1428. case SR_XTYPE_XAVP:
  1429. result = snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp);
  1430. break;
  1431. case SR_XTYPE_DATA:
  1432. result = snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data);
  1433. break;
  1434. default:
  1435. LM_WARN("unknown data type\n");
  1436. *jobj = srjson_CreateNull(jdoc);
  1437. }
  1438. if(result<0)
  1439. {
  1440. LM_ERR("cannot convert to str\n");
  1441. *jobj = srjson_CreateNull(jdoc);
  1442. }
  1443. else if(*jobj==NULL)
  1444. {
  1445. *jobj = srjson_CreateStr(jdoc, _pv_xavp_buf, 128);
  1446. }
  1447. }
  1448. int _dbg_get_obj_avp_vals(str name, sr_xavp_t *xavp, srjson_doc_t *jdoc, srjson_t **jobj)
  1449. {
  1450. sr_xavp_t *avp = NULL;
  1451. srjson_t *jobjt = NULL;
  1452. *jobj = srjson_CreateArray(jdoc);
  1453. if(*jobj==NULL)
  1454. {
  1455. LM_ERR("cannot create json object\n");
  1456. return -1;
  1457. }
  1458. avp = xavp;
  1459. while(avp!=NULL&&!STR_EQ(avp->name,name))
  1460. {
  1461. avp = avp->next;
  1462. }
  1463. while(avp!=NULL)
  1464. {
  1465. _dbg_get_obj_xavp_val(avp, jdoc, &jobjt);
  1466. srjson_AddItemToArray(jdoc, *jobj, jobjt);
  1467. jobjt = NULL;
  1468. avp = xavp_get_next(avp);
  1469. }
  1470. return 0;
  1471. }
  1472. int _dbg_get_obj_xavp_vals(struct sip_msg *msg,
  1473. pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobjr,
  1474. str *item_name)
  1475. {
  1476. pv_xavp_name_t *xname = (pv_xavp_name_t*)param->pvn.u.dname;
  1477. sr_xavp_t *xavp = NULL;
  1478. sr_xavp_t *avp = NULL;
  1479. srjson_t *jobj = NULL;
  1480. srjson_t *jobjt = NULL;
  1481. struct str_list *keys;
  1482. struct str_list *k;
  1483. *jobjr = srjson_CreateArray(jdoc);
  1484. if(*jobjr==NULL)
  1485. {
  1486. LM_ERR("cannot create json object\n");
  1487. return -1;
  1488. }
  1489. item_name->s = xname->name.s;
  1490. item_name->len = xname->name.len;
  1491. xavp = xavp_get_by_index(&xname->name, 0, NULL);
  1492. if(xavp==NULL)
  1493. {
  1494. return 0; /* empty */
  1495. }
  1496. do
  1497. {
  1498. if(xavp->val.type==SR_XTYPE_XAVP)
  1499. {
  1500. avp = xavp->val.v.xavp;
  1501. jobj = srjson_CreateObject(jdoc);
  1502. if(jobj==NULL)
  1503. {
  1504. LM_ERR("cannot create json object\n");
  1505. return -1;
  1506. }
  1507. keys = xavp_get_list_key_names(xavp);
  1508. if(keys!=NULL)
  1509. {
  1510. do
  1511. {
  1512. _dbg_get_obj_avp_vals(keys->s, avp, jdoc, &jobjt);
  1513. srjson_AddStrItemToObject(jdoc, jobj, keys->s.s,
  1514. keys->s.len, jobjt);
  1515. k = keys;
  1516. keys = keys->next;
  1517. pkg_free(k);
  1518. jobjt = NULL;
  1519. }while(keys!=NULL);
  1520. }
  1521. }
  1522. if(jobj!=NULL)
  1523. {
  1524. srjson_AddItemToArray(jdoc, *jobjr, jobj);
  1525. jobj = NULL;
  1526. }
  1527. }while((xavp = xavp_get_next(xavp))!=0);
  1528. return 0;
  1529. }
  1530. int dbg_dump_json(struct sip_msg* msg, unsigned int mask, int level)
  1531. {
  1532. int i;
  1533. pv_value_t value;
  1534. pv_cache_t **_pv_cache = pv_cache_get_table();
  1535. pv_cache_t *el = NULL;
  1536. srjson_doc_t jdoc;
  1537. srjson_t *jobj = NULL;
  1538. char *output = NULL;
  1539. str item_name = STR_NULL;
  1540. static char iname[128];
  1541. int result = -1;
  1542. if(_pv_cache==NULL)
  1543. {
  1544. LM_ERR("cannot access pv_cache\n");
  1545. return -1;
  1546. }
  1547. memset(_dbg_xavp_dump, 0, sizeof(str*)*DBG_XAVP_DUMP_SIZE);
  1548. srjson_InitDoc(&jdoc, NULL);
  1549. if(jdoc.root==NULL)
  1550. {
  1551. jdoc.root = srjson_CreateObject(&jdoc);
  1552. if(jdoc.root==NULL)
  1553. {
  1554. LM_ERR("cannot create json root\n");
  1555. goto error;
  1556. }
  1557. }
  1558. for(i=0;i<PV_CACHE_SIZE;i++)
  1559. {
  1560. el = _pv_cache[i];
  1561. while(el)
  1562. {
  1563. if(!(el->spec.type==PVT_AVP||
  1564. el->spec.type==PVT_SCRIPTVAR||
  1565. el->spec.type==PVT_XAVP||
  1566. el->spec.type==PVT_OTHER)||
  1567. !((el->spec.type==PVT_AVP&&mask&DBG_DP_AVP)||
  1568. (el->spec.type==PVT_XAVP&&mask&DBG_DP_XAVP)||
  1569. (el->spec.type==PVT_SCRIPTVAR&&mask&DBG_DP_SCRIPTVAR)||
  1570. (el->spec.type==PVT_OTHER&&mask&DBG_DP_OTHER))||
  1571. (el->spec.trans!=NULL))
  1572. {
  1573. el = el->next;
  1574. continue;
  1575. }
  1576. jobj = NULL;
  1577. item_name.len = 0;
  1578. item_name.s = 0;
  1579. iname[0] = '\0';
  1580. if(el->spec.type==PVT_AVP)
  1581. {
  1582. if(el->spec.pvp.pvi.type==PV_IDX_ALL||
  1583. (el->spec.pvp.pvi.type==PV_IDX_INT&&el->spec.pvp.pvi.u.ival!=0))
  1584. {
  1585. el = el->next;
  1586. continue;
  1587. }
  1588. else
  1589. {
  1590. if(_dbg_get_array_avp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
  1591. {
  1592. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1593. el = el->next;
  1594. continue;
  1595. }
  1596. if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
  1597. {
  1598. el = el->next;
  1599. continue;
  1600. }
  1601. snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s);
  1602. }
  1603. }
  1604. else if(el->spec.type==PVT_XAVP)
  1605. {
  1606. if(_dbg_xavp_dump_lookup(&el->spec.pvp)!=0)
  1607. {
  1608. el = el->next;
  1609. continue;
  1610. }
  1611. if(_dbg_get_obj_xavp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
  1612. {
  1613. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1614. el = el->next;
  1615. continue;
  1616. }
  1617. if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
  1618. {
  1619. el = el->next;
  1620. continue;
  1621. }
  1622. snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s);
  1623. }
  1624. else
  1625. {
  1626. if(pv_get_spec_value(msg, &el->spec, &value)!=0)
  1627. {
  1628. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1629. el = el->next;
  1630. continue;
  1631. }
  1632. if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE))
  1633. {
  1634. if(mask&DBG_DP_NULL)
  1635. {
  1636. jobj = srjson_CreateNull(&jdoc);
  1637. }
  1638. else
  1639. {
  1640. el = el->next;
  1641. continue;
  1642. }
  1643. }else if(value.flags&(PV_VAL_INT)){
  1644. jobj = srjson_CreateNumber(&jdoc, value.ri);
  1645. }else if(value.flags&(PV_VAL_STR)){
  1646. jobj = srjson_CreateStr(&jdoc, value.rs.s, value.rs.len);
  1647. }else {
  1648. LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s,
  1649. value.flags);
  1650. el = el->next;
  1651. continue;
  1652. }
  1653. if(jobj==NULL)
  1654. {
  1655. LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len,
  1656. el->pvname.s);
  1657. goto error;
  1658. }
  1659. snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s);
  1660. }
  1661. if(jobj!=NULL)
  1662. {
  1663. srjson_AddItemToObject(&jdoc, jdoc.root, iname, jobj);
  1664. }
  1665. el = el->next;
  1666. }
  1667. }
  1668. output = srjson_PrintUnformatted(&jdoc, jdoc.root);
  1669. if(output==NULL)
  1670. {
  1671. LM_ERR("cannot print json doc\n");
  1672. goto error;
  1673. }
  1674. LOG(level, "%s\n", output);
  1675. result = 0;
  1676. error:
  1677. if(output!=NULL) jdoc.free_fn(output);
  1678. srjson_DestroyDoc(&jdoc);
  1679. return result;
  1680. }