debugger_api.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811
  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. lock_release(&_dbg_mod_table[idx].lock);
  1101. /* not found - add */
  1102. if(mlevel==NULL) {
  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. return -1;
  1109. }
  1110. memset(itn, 0, sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char));
  1111. itn->level = *mlevel;
  1112. itn->hashid = hid;
  1113. itn->name.s = (char*)(itn) + sizeof(dbg_mod_level_t);
  1114. itn->name.len = mnlen;
  1115. strncpy(itn->name.s, mname, mnlen);
  1116. itn->name.s[itn->name.len] = '\0';
  1117. lock_get(&_dbg_mod_table[idx].lock);
  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 (!dbg_cfg) {
  1140. return -1;
  1141. }
  1142. if(cfg_get(dbg, dbg_cfg, mod_level_mode)==0)
  1143. return -1;
  1144. if(_dbg_get_mod_debug_level!=0)
  1145. return -1;
  1146. _dbg_get_mod_debug_level = 1;
  1147. hid = dbg_compute_hash(mname, mnlen);
  1148. idx = hid&(_dbg_mod_table_size-1);
  1149. lock_get(&_dbg_mod_table[idx].lock);
  1150. it = _dbg_mod_table[idx].first;
  1151. while(it!=NULL && it->hashid < hid)
  1152. it = it->next;
  1153. while(it!=NULL && it->hashid == hid)
  1154. {
  1155. if(mnlen==it->name.len
  1156. && strncmp(mname, it->name.s, mnlen)==0)
  1157. {
  1158. /* found */
  1159. *mlevel = it->level;
  1160. lock_release(&_dbg_mod_table[idx].lock);
  1161. _dbg_get_mod_debug_level = 0;
  1162. return 0;
  1163. }
  1164. it = it->next;
  1165. }
  1166. lock_release(&_dbg_mod_table[idx].lock);
  1167. _dbg_get_mod_debug_level = 0;
  1168. return -1;
  1169. }
  1170. /**
  1171. *
  1172. */
  1173. void dbg_enable_mod_levels(void)
  1174. {
  1175. if(_dbg_mod_table==NULL)
  1176. return;
  1177. set_module_debug_level_cb(dbg_get_mod_debug_level);
  1178. }
  1179. #define DBG_PVCACHE_SIZE 32
  1180. typedef struct _dbg_pvcache {
  1181. pv_spec_t *spec;
  1182. str *pvname;
  1183. struct _dbg_pvcache *next;
  1184. } dbg_pvcache_t;
  1185. static dbg_pvcache_t **_dbg_pvcache = NULL;
  1186. int dbg_init_pvcache()
  1187. {
  1188. _dbg_pvcache = (dbg_pvcache_t**)pkg_malloc(sizeof(dbg_pvcache_t*)*DBG_PVCACHE_SIZE);
  1189. if(_dbg_pvcache==NULL)
  1190. {
  1191. LM_ERR("no more memory.\n");
  1192. return -1;
  1193. }
  1194. memset(_dbg_pvcache, 0, sizeof(dbg_pvcache_t*)*DBG_PVCACHE_SIZE);
  1195. return 0;
  1196. }
  1197. int dbg_assign_add(str *name, pv_spec_t *spec)
  1198. {
  1199. dbg_pvcache_t *pvn, *last, *next;
  1200. unsigned int pvid;
  1201. if(name==NULL||spec==NULL)
  1202. return -1;
  1203. if(_dbg_pvcache==NULL)
  1204. return -1;
  1205. pvid = get_hash1_raw((char *)&spec, sizeof(pv_spec_t*));
  1206. pvn = (dbg_pvcache_t*)pkg_malloc(sizeof(dbg_pvcache_t));
  1207. if(pvn==NULL)
  1208. {
  1209. LM_ERR("no more memory\n");
  1210. return -1;
  1211. }
  1212. memset(pvn, 0, sizeof(dbg_pvcache_t));
  1213. pvn->pvname = name;
  1214. pvn->spec = spec;
  1215. next = _dbg_pvcache[pvid%DBG_PVCACHE_SIZE];
  1216. if(next==NULL)
  1217. {
  1218. _dbg_pvcache[pvid%DBG_PVCACHE_SIZE] = pvn;
  1219. }
  1220. else
  1221. {
  1222. while(next)
  1223. {
  1224. last = next;
  1225. next = next->next;
  1226. }
  1227. last->next = pvn;
  1228. }
  1229. return 0;
  1230. }
  1231. str *_dbg_pvcache_lookup(pv_spec_t *spec)
  1232. {
  1233. dbg_pvcache_t *pvi;
  1234. unsigned int pvid;
  1235. str *name = NULL;
  1236. if(spec==NULL)
  1237. return NULL;
  1238. if(_dbg_pvcache==NULL)
  1239. return NULL;
  1240. pvid = get_hash1_raw((char *)&spec, sizeof(pv_spec_t*));
  1241. pvi = _dbg_pvcache[pvid%DBG_PVCACHE_SIZE];
  1242. while(pvi)
  1243. {
  1244. if(pvi->spec==spec) {
  1245. return pvi->pvname;
  1246. }
  1247. pvi = pvi->next;
  1248. }
  1249. name = pv_cache_get_name(spec);
  1250. if(name!=NULL)
  1251. {
  1252. /*LM_DBG("Add name[%.*s] to pvcache\n", name->len, name->s);*/
  1253. dbg_assign_add(name, spec);
  1254. }
  1255. return name;
  1256. }
  1257. int _dbg_log_assign_action_avp(struct sip_msg* msg, struct lvalue* lv)
  1258. {
  1259. int_str avp_val;
  1260. avp_t* avp;
  1261. avp_spec_t* avp_s = &lv->lv.avps;
  1262. avp = search_avp_by_index(avp_s->type, avp_s->name,
  1263. &avp_val, avp_s->index);
  1264. if (likely(avp)){
  1265. if (avp->flags&(AVP_VAL_STR)){
  1266. LM_DBG("%.*s:\"%.*s\"\n", avp_s->name.s.len, avp_s->name.s.s,
  1267. avp_val.s.len, avp_val.s.s);
  1268. }else{
  1269. LM_DBG("%.*s:%d\n", avp_s->name.s.len, avp_s->name.s.s,
  1270. avp_val.n);
  1271. }
  1272. }
  1273. return 0;
  1274. }
  1275. int _dbg_log_assign_action_pvar(struct sip_msg* msg, struct lvalue* lv)
  1276. {
  1277. pv_value_t value;
  1278. pv_spec_t* pvar = lv->lv.pvs;
  1279. str def_name = {"unknown", 7};
  1280. str *name = _dbg_pvcache_lookup(pvar);
  1281. if(name==NULL)
  1282. name = &def_name;
  1283. if(pv_get_spec_value(msg, pvar, &value)!=0)
  1284. {
  1285. LM_ERR("can't get value\n");
  1286. return -1;
  1287. }
  1288. if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE)){
  1289. LM_DBG("%.*s: $null\n", name->len, name->s);
  1290. }else if(value.flags&(PV_VAL_INT)){
  1291. LM_DBG("%.*s:%d\n", name->len, name->s, value.ri);
  1292. }else if(value.flags&(PV_VAL_STR)){
  1293. LM_DBG("%.*s:\"%.*s\"\n", name->len, name->s, value.rs.len, value.rs.s);
  1294. }
  1295. return 0;
  1296. }
  1297. int dbg_log_assign(struct sip_msg* msg, struct lvalue *lv)
  1298. {
  1299. if(lv==NULL)
  1300. {
  1301. LM_ERR("left value is NULL\n");
  1302. return -1;
  1303. }
  1304. switch(lv->type){
  1305. case LV_AVP:
  1306. return _dbg_log_assign_action_avp(msg, lv);
  1307. break;
  1308. case LV_PVAR:
  1309. return _dbg_log_assign_action_pvar(msg, lv);
  1310. break;
  1311. case LV_NONE:
  1312. break;
  1313. }
  1314. return 0;
  1315. }
  1316. void dbg_enable_log_assign(void)
  1317. {
  1318. if(_dbg_pvcache==NULL)
  1319. return;
  1320. set_log_assign_action_cb(dbg_log_assign);
  1321. }
  1322. int dbg_level_mode_fixup(void *temp_handle,
  1323. str *group_name, str *var_name, void **value){
  1324. if(_dbg_mod_table==NULL)
  1325. {
  1326. LM_ERR("mod_hash_size must be set on start\n");
  1327. return -1;
  1328. }
  1329. return 0;
  1330. }
  1331. int _dbg_get_array_avp_vals(struct sip_msg *msg,
  1332. pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj,
  1333. str *item_name)
  1334. {
  1335. struct usr_avp *avp;
  1336. unsigned short name_type;
  1337. int_str avp_name;
  1338. int_str avp_value;
  1339. struct search_state state;
  1340. srjson_t *jobjt;
  1341. memset(&state, 0, sizeof(struct search_state));
  1342. if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
  1343. {
  1344. LM_ERR("invalid name\n");
  1345. return -1;
  1346. }
  1347. *jobj = srjson_CreateArray(jdoc);
  1348. if(*jobj==NULL)
  1349. {
  1350. LM_ERR("cannot create json object\n");
  1351. return -1;
  1352. }
  1353. if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0)
  1354. {
  1355. goto ok;
  1356. }
  1357. do
  1358. {
  1359. if(avp->flags & AVP_VAL_STR)
  1360. {
  1361. jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len);
  1362. if(jobjt==NULL)
  1363. {
  1364. LM_ERR("cannot create json object\n");
  1365. return -1;
  1366. }
  1367. } else {
  1368. jobjt = srjson_CreateNumber(jdoc, avp_value.n);
  1369. if(jobjt==NULL)
  1370. {
  1371. LM_ERR("cannot create json object\n");
  1372. return -1;
  1373. }
  1374. }
  1375. srjson_AddItemToArray(jdoc, *jobj, jobjt);
  1376. } while ((avp=search_next_avp(&state, &avp_value))!=0);
  1377. ok:
  1378. item_name->s = avp_name.s.s;
  1379. item_name->len = avp_name.s.len;
  1380. return 0;
  1381. }
  1382. #define DBG_XAVP_DUMP_SIZE 32
  1383. static str* _dbg_xavp_dump[DBG_XAVP_DUMP_SIZE];
  1384. int _dbg_xavp_dump_lookup(pv_param_t *param)
  1385. {
  1386. unsigned int i = 0;
  1387. pv_xavp_name_t *xname;
  1388. if(param==NULL)
  1389. return -1;
  1390. xname = (pv_xavp_name_t*)param->pvn.u.dname;
  1391. while(_dbg_xavp_dump[i]!=NULL&&i<DBG_XAVP_DUMP_SIZE)
  1392. {
  1393. if(_dbg_xavp_dump[i]->len==xname->name.len)
  1394. {
  1395. if(strncmp(_dbg_xavp_dump[i]->s, xname->name.s, xname->name.len)==0)
  1396. return 1; /* already dump before */
  1397. }
  1398. i++;
  1399. }
  1400. if(i==DBG_XAVP_DUMP_SIZE)
  1401. {
  1402. LM_WARN("full _dbg_xavp_dump cache array\n");
  1403. return 0; /* end cache names */
  1404. }
  1405. _dbg_xavp_dump[i] = &xname->name;
  1406. return 0;
  1407. }
  1408. void _dbg_get_obj_xavp_val(sr_xavp_t *avp, srjson_doc_t *jdoc, srjson_t **jobj)
  1409. {
  1410. static char _pv_xavp_buf[128];
  1411. int result = 0;
  1412. switch(avp->val.type) {
  1413. case SR_XTYPE_NULL:
  1414. *jobj = srjson_CreateNull(jdoc);
  1415. break;
  1416. case SR_XTYPE_INT:
  1417. *jobj = srjson_CreateNumber(jdoc, avp->val.v.i);
  1418. break;
  1419. case SR_XTYPE_STR:
  1420. *jobj = srjson_CreateStr(jdoc, avp->val.v.s.s, avp->val.v.s.len);
  1421. break;
  1422. case SR_XTYPE_TIME:
  1423. result = snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t);
  1424. break;
  1425. case SR_XTYPE_LONG:
  1426. result = snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l);
  1427. break;
  1428. case SR_XTYPE_LLONG:
  1429. result = snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll);
  1430. break;
  1431. case SR_XTYPE_XAVP:
  1432. result = snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp);
  1433. break;
  1434. case SR_XTYPE_DATA:
  1435. result = snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data);
  1436. break;
  1437. default:
  1438. LM_WARN("unknown data type\n");
  1439. *jobj = srjson_CreateNull(jdoc);
  1440. }
  1441. if(result<0)
  1442. {
  1443. LM_ERR("cannot convert to str\n");
  1444. *jobj = srjson_CreateNull(jdoc);
  1445. }
  1446. else if(*jobj==NULL)
  1447. {
  1448. *jobj = srjson_CreateStr(jdoc, _pv_xavp_buf, 128);
  1449. }
  1450. }
  1451. int _dbg_get_obj_avp_vals(str name, sr_xavp_t *xavp, srjson_doc_t *jdoc, srjson_t **jobj)
  1452. {
  1453. sr_xavp_t *avp = NULL;
  1454. srjson_t *jobjt = NULL;
  1455. *jobj = srjson_CreateArray(jdoc);
  1456. if(*jobj==NULL)
  1457. {
  1458. LM_ERR("cannot create json object\n");
  1459. return -1;
  1460. }
  1461. avp = xavp;
  1462. while(avp!=NULL&&!STR_EQ(avp->name,name))
  1463. {
  1464. avp = avp->next;
  1465. }
  1466. while(avp!=NULL)
  1467. {
  1468. _dbg_get_obj_xavp_val(avp, jdoc, &jobjt);
  1469. srjson_AddItemToArray(jdoc, *jobj, jobjt);
  1470. jobjt = NULL;
  1471. avp = xavp_get_next(avp);
  1472. }
  1473. return 0;
  1474. }
  1475. int _dbg_get_obj_xavp_vals(struct sip_msg *msg,
  1476. pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobjr,
  1477. str *item_name)
  1478. {
  1479. pv_xavp_name_t *xname = (pv_xavp_name_t*)param->pvn.u.dname;
  1480. sr_xavp_t *xavp = NULL;
  1481. sr_xavp_t *avp = NULL;
  1482. srjson_t *jobj = NULL;
  1483. srjson_t *jobjt = NULL;
  1484. struct str_list *keys;
  1485. struct str_list *k;
  1486. *jobjr = srjson_CreateArray(jdoc);
  1487. if(*jobjr==NULL)
  1488. {
  1489. LM_ERR("cannot create json object\n");
  1490. return -1;
  1491. }
  1492. item_name->s = xname->name.s;
  1493. item_name->len = xname->name.len;
  1494. xavp = xavp_get_by_index(&xname->name, 0, NULL);
  1495. if(xavp==NULL)
  1496. {
  1497. return 0; /* empty */
  1498. }
  1499. do
  1500. {
  1501. if(xavp->val.type==SR_XTYPE_XAVP)
  1502. {
  1503. avp = xavp->val.v.xavp;
  1504. jobj = srjson_CreateObject(jdoc);
  1505. if(jobj==NULL)
  1506. {
  1507. LM_ERR("cannot create json object\n");
  1508. return -1;
  1509. }
  1510. keys = xavp_get_list_key_names(xavp);
  1511. if(keys!=NULL)
  1512. {
  1513. do
  1514. {
  1515. _dbg_get_obj_avp_vals(keys->s, avp, jdoc, &jobjt);
  1516. srjson_AddStrItemToObject(jdoc, jobj, keys->s.s,
  1517. keys->s.len, jobjt);
  1518. k = keys;
  1519. keys = keys->next;
  1520. pkg_free(k);
  1521. jobjt = NULL;
  1522. }while(keys!=NULL);
  1523. }
  1524. }
  1525. if(jobj!=NULL)
  1526. {
  1527. srjson_AddItemToArray(jdoc, *jobjr, jobj);
  1528. jobj = NULL;
  1529. }
  1530. }while((xavp = xavp_get_next(xavp))!=0);
  1531. return 0;
  1532. }
  1533. int dbg_dump_json(struct sip_msg* msg, unsigned int mask, int level)
  1534. {
  1535. int i;
  1536. pv_value_t value;
  1537. pv_cache_t **_pv_cache = pv_cache_get_table();
  1538. pv_cache_t *el = NULL;
  1539. srjson_doc_t jdoc;
  1540. srjson_t *jobj = NULL;
  1541. char *output = NULL;
  1542. str item_name = STR_NULL;
  1543. static char iname[128];
  1544. int result = -1;
  1545. if(_pv_cache==NULL)
  1546. {
  1547. LM_ERR("cannot access pv_cache\n");
  1548. return -1;
  1549. }
  1550. memset(_dbg_xavp_dump, 0, sizeof(str*)*DBG_XAVP_DUMP_SIZE);
  1551. srjson_InitDoc(&jdoc, NULL);
  1552. if(jdoc.root==NULL)
  1553. {
  1554. jdoc.root = srjson_CreateObject(&jdoc);
  1555. if(jdoc.root==NULL)
  1556. {
  1557. LM_ERR("cannot create json root\n");
  1558. goto error;
  1559. }
  1560. }
  1561. for(i=0;i<PV_CACHE_SIZE;i++)
  1562. {
  1563. el = _pv_cache[i];
  1564. while(el)
  1565. {
  1566. if(!(el->spec.type==PVT_AVP||
  1567. el->spec.type==PVT_SCRIPTVAR||
  1568. el->spec.type==PVT_XAVP||
  1569. el->spec.type==PVT_OTHER)||
  1570. !((el->spec.type==PVT_AVP&&mask&DBG_DP_AVP)||
  1571. (el->spec.type==PVT_XAVP&&mask&DBG_DP_XAVP)||
  1572. (el->spec.type==PVT_SCRIPTVAR&&mask&DBG_DP_SCRIPTVAR)||
  1573. (el->spec.type==PVT_OTHER&&mask&DBG_DP_OTHER))||
  1574. (el->spec.trans!=NULL))
  1575. {
  1576. el = el->next;
  1577. continue;
  1578. }
  1579. jobj = NULL;
  1580. item_name.len = 0;
  1581. item_name.s = 0;
  1582. iname[0] = '\0';
  1583. if(el->spec.type==PVT_AVP)
  1584. {
  1585. if(el->spec.pvp.pvi.type==PV_IDX_ALL||
  1586. (el->spec.pvp.pvi.type==PV_IDX_INT&&el->spec.pvp.pvi.u.ival!=0))
  1587. {
  1588. el = el->next;
  1589. continue;
  1590. }
  1591. else
  1592. {
  1593. if(_dbg_get_array_avp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
  1594. {
  1595. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1596. el = el->next;
  1597. continue;
  1598. }
  1599. if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
  1600. {
  1601. el = el->next;
  1602. continue;
  1603. }
  1604. snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s);
  1605. }
  1606. }
  1607. else if(el->spec.type==PVT_XAVP)
  1608. {
  1609. if(_dbg_xavp_dump_lookup(&el->spec.pvp)!=0)
  1610. {
  1611. el = el->next;
  1612. continue;
  1613. }
  1614. if(_dbg_get_obj_xavp_vals(msg, &el->spec.pvp, &jdoc, &jobj, &item_name)!=0)
  1615. {
  1616. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1617. el = el->next;
  1618. continue;
  1619. }
  1620. if(srjson_GetArraySize(&jdoc, jobj)==0 && !(mask&DBG_DP_NULL))
  1621. {
  1622. el = el->next;
  1623. continue;
  1624. }
  1625. snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s);
  1626. }
  1627. else
  1628. {
  1629. if(pv_get_spec_value(msg, &el->spec, &value)!=0)
  1630. {
  1631. LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
  1632. el = el->next;
  1633. continue;
  1634. }
  1635. if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE))
  1636. {
  1637. if(mask&DBG_DP_NULL)
  1638. {
  1639. jobj = srjson_CreateNull(&jdoc);
  1640. }
  1641. else
  1642. {
  1643. el = el->next;
  1644. continue;
  1645. }
  1646. }else if(value.flags&(PV_VAL_INT)){
  1647. jobj = srjson_CreateNumber(&jdoc, value.ri);
  1648. }else if(value.flags&(PV_VAL_STR)){
  1649. jobj = srjson_CreateStr(&jdoc, value.rs.s, value.rs.len);
  1650. }else {
  1651. LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s,
  1652. value.flags);
  1653. el = el->next;
  1654. continue;
  1655. }
  1656. if(jobj==NULL)
  1657. {
  1658. LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len,
  1659. el->pvname.s);
  1660. goto error;
  1661. }
  1662. snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s);
  1663. }
  1664. if(jobj!=NULL)
  1665. {
  1666. srjson_AddItemToObject(&jdoc, jdoc.root, iname, jobj);
  1667. }
  1668. el = el->next;
  1669. }
  1670. }
  1671. output = srjson_PrintUnformatted(&jdoc, jdoc.root);
  1672. if(output==NULL)
  1673. {
  1674. LM_ERR("cannot print json doc\n");
  1675. goto error;
  1676. }
  1677. LOG(level, "%s\n", output);
  1678. result = 0;
  1679. error:
  1680. if(output!=NULL) jdoc.free_fn(output);
  1681. srjson_DestroyDoc(&jdoc);
  1682. return result;
  1683. }