debugger_mod.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. *
  14. * This file is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. #include <stdio.h>
  25. #include <unistd.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include "../../sr_module.h"
  29. #include "../../dprint.h"
  30. #include "../../ut.h"
  31. #include "../../mod_fix.h"
  32. #include "../../parser/parse_param.h"
  33. #include "../../shm_init.h"
  34. #include "../../script_cb.h"
  35. #include "debugger_api.h"
  36. #include "debugger_config.h"
  37. MODULE_VERSION
  38. static int mod_init(void);
  39. static int child_init(int rank);
  40. static void mod_destroy(void);
  41. static int w_dbg_breakpoint(struct sip_msg* msg, char* point, char* str2);
  42. static int fixup_dbg_breakpoint(void** param, int param_no);
  43. static int dbg_mod_level_param(modparam_t type, void *val);
  44. static int fixup_dbg_pv_dump(void** param, int param_no);
  45. static int w_dbg_dump(struct sip_msg* msg, char* mask, char* level);
  46. /* parameters */
  47. extern int _dbg_cfgtrace;
  48. extern int _dbg_cfgpkgcheck;
  49. extern int _dbg_breakpoint;
  50. extern int _dbg_cfgtrace_level;
  51. extern int _dbg_cfgtrace_facility;
  52. extern char *_dbg_cfgtrace_prefix;
  53. extern char *_dbg_cfgtrace_lname;
  54. extern int _dbg_step_usleep;
  55. extern int _dbg_step_loops;
  56. extern int _dbg_reset_msgid;
  57. static char * _dbg_cfgtrace_facility_str = 0;
  58. static int _dbg_log_assign = 0;
  59. static cmd_export_t cmds[]={
  60. {"dbg_breakpoint", (cmd_function)w_dbg_breakpoint, 1,
  61. fixup_dbg_breakpoint, 0, ANY_ROUTE},
  62. {"dbg_pv_dump", (cmd_function)w_dbg_dump, 0,
  63. fixup_dbg_pv_dump, 0, ANY_ROUTE},
  64. {"dbg_pv_dump", (cmd_function)w_dbg_dump, 1,
  65. fixup_dbg_pv_dump, 0, ANY_ROUTE},
  66. {"dbg_pv_dump", (cmd_function)w_dbg_dump, 2,
  67. fixup_dbg_pv_dump, 0, ANY_ROUTE},
  68. {0, 0, 0, 0, 0, 0}
  69. };
  70. static param_export_t params[]={
  71. {"cfgtrace", INT_PARAM, &_dbg_cfgtrace},
  72. {"breakpoint", INT_PARAM, &_dbg_breakpoint},
  73. {"log_level", INT_PARAM, &_dbg_cfgtrace_level},
  74. {"log_facility", PARAM_STRING, &_dbg_cfgtrace_facility_str},
  75. {"log_prefix", PARAM_STRING, &_dbg_cfgtrace_prefix},
  76. {"log_level_name", PARAM_STRING, &_dbg_cfgtrace_lname},
  77. {"log_assign", INT_PARAM, &_dbg_log_assign},
  78. {"step_usleep", INT_PARAM, &_dbg_step_usleep},
  79. {"step_loops", INT_PARAM, &_dbg_step_loops},
  80. {"mod_hash_size", INT_PARAM, &default_dbg_cfg.mod_hash_size},
  81. {"mod_level_mode", INT_PARAM, &default_dbg_cfg.mod_level_mode},
  82. {"mod_level", PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_level_param},
  83. {"reset_msgid", INT_PARAM, &_dbg_reset_msgid},
  84. {"cfgpkgcheck", INT_PARAM, &_dbg_cfgpkgcheck},
  85. {0, 0, 0}
  86. };
  87. struct module_exports exports = {
  88. "debugger",
  89. DEFAULT_DLFLAGS, /* dlopen flags */
  90. cmds,
  91. params,
  92. 0,
  93. 0, /* exported MI functions */
  94. 0, /* exported pseudo-variables */
  95. 0, /* extra processes */
  96. mod_init, /* module initialization function */
  97. 0, /* response function */
  98. mod_destroy, /* destroy function */
  99. child_init /* per child init function */
  100. };
  101. /**
  102. * init module function
  103. */
  104. static int mod_init(void)
  105. {
  106. int fl;
  107. if (_dbg_cfgtrace_facility_str!=NULL)
  108. {
  109. fl = str2facility(_dbg_cfgtrace_facility_str);
  110. if (fl != -1)
  111. {
  112. _dbg_cfgtrace_facility = fl;
  113. } else {
  114. LM_ERR("invalid log facility configured");
  115. return -1;
  116. }
  117. }
  118. if(dbg_init_rpc()!=0)
  119. {
  120. LM_ERR("failed to register RPC commands\n");
  121. return -1;
  122. }
  123. if(cfg_declare("dbg", dbg_cfg_def, &default_dbg_cfg, cfg_sizeof(dbg), &dbg_cfg))
  124. {
  125. LM_ERR("Fail to declare the configuration\n");
  126. return -1;
  127. }
  128. LM_DBG("cfg level_mode:%d hash_size:%d\n",
  129. cfg_get(dbg, dbg_cfg, mod_level_mode),
  130. cfg_get(dbg, dbg_cfg, mod_hash_size));
  131. if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
  132. {
  133. LM_ERR("failed to init per module log level\n");
  134. return -1;
  135. }
  136. if(_dbg_log_assign>0)
  137. {
  138. if(dbg_init_pvcache()!=0)
  139. {
  140. LM_ERR("failed to create pvcache\n");
  141. return -1;
  142. }
  143. }
  144. if(_dbg_reset_msgid==1)
  145. {
  146. unsigned int ALL = REQUEST_CB+FAILURE_CB+ONREPLY_CB
  147. +BRANCH_CB+ONSEND_CB+ERROR_CB+LOCAL_CB+EVENT_CB+BRANCH_FAILURE_CB;
  148. if (register_script_cb(dbg_msgid_filter, PRE_SCRIPT_CB|ALL, 0) != 0) {
  149. LM_ERR("could not insert callback");
  150. return -1;
  151. }
  152. }
  153. return dbg_init_bp_list();
  154. }
  155. /**
  156. * child init function
  157. */
  158. static int child_init(int rank)
  159. {
  160. LM_DBG("rank is (%d)\n", rank);
  161. if (rank==PROC_INIT) {
  162. dbg_enable_mod_levels();
  163. dbg_enable_log_assign();
  164. return dbg_init_pid_list();
  165. }
  166. return dbg_init_mypid();
  167. }
  168. /**
  169. * destroy module function
  170. */
  171. static void mod_destroy(void)
  172. {
  173. }
  174. /**
  175. * cfg wrapper to set breakpoint (not implemented yet)
  176. */
  177. static int w_dbg_breakpoint(struct sip_msg* msg, char* point, char* str2)
  178. {
  179. return 1;
  180. }
  181. /**
  182. * fixup for cfg dbg_pv_dump
  183. */
  184. static int fixup_dbg_pv_dump(void** param, int param_no)
  185. {
  186. unsigned int mask;
  187. int level;
  188. str s = STR_NULL;
  189. switch(param_no)
  190. {
  191. case 2:
  192. switch(((char*)(*param))[2])
  193. {
  194. case 'A': level = L_ALERT; break;
  195. case 'B': level = L_BUG; break;
  196. case 'C': level = L_CRIT2; break;
  197. case 'E': level = L_ERR; break;
  198. case 'W': level = L_WARN; break;
  199. case 'N': level = L_NOTICE; break;
  200. case 'I': level = L_INFO; break;
  201. case 'D': level = L_DBG; break;
  202. default:
  203. LM_ERR("unknown log level\n");
  204. return E_UNSPEC;
  205. }
  206. *param = (void*)(long)level;
  207. break;
  208. case 1:
  209. s.s = *param;
  210. s.len = strlen(s.s);
  211. if(str2int(&s, &mask) == 0) {
  212. *param = (void*)(long)mask;
  213. }
  214. else return E_UNSPEC;
  215. break;
  216. }
  217. return 0;
  218. }
  219. /**
  220. * dump pv_cache contents as json
  221. */
  222. static int w_dbg_dump(struct sip_msg* msg, char* mask, char* level)
  223. {
  224. unsigned int umask = DBG_DP_ALL;
  225. int ilevel = L_DBG;
  226. if(level!=NULL){
  227. ilevel = (int)(long)level;
  228. }
  229. if(mask!=NULL){
  230. umask = (unsigned int)(unsigned long)mask;
  231. }
  232. dbg_dump_json(msg, umask, ilevel);
  233. return 1;
  234. }
  235. /**
  236. * get the pointer to action structure
  237. */
  238. static struct action *dbg_fixup_get_action(void **param, int param_no)
  239. {
  240. struct action *ac, ac2;
  241. action_u_t *au, au2;
  242. /* param points to au->u.string, get pointer to au */
  243. au = (void*) ((char *)param - ((char *)&au2.u.string-(char *)&au2));
  244. au = au - 1 - param_no;
  245. ac = (void*) ((char *)au - ((char *)&ac2.val-(char *)&ac2));
  246. return ac;
  247. }
  248. /**
  249. * fixup for cfg set breakpoint function
  250. */
  251. static int fixup_dbg_breakpoint(void** param, int param_no)
  252. {
  253. struct action *a;
  254. char *p;
  255. if(param_no!=1)
  256. return -1;
  257. a = dbg_fixup_get_action(param, param_no);
  258. p = (char*)(*param);
  259. return dbg_add_breakpoint(a, (*p=='0')?0:1);
  260. }
  261. static int dbg_mod_level_param(modparam_t type, void *val)
  262. {
  263. char *p;
  264. str s;
  265. int l;
  266. if(val==NULL)
  267. return -1;
  268. p = strchr((char*)val, '=');
  269. if(p==NULL) {
  270. LM_ERR("invalid parameter value: %s\n", (char*)val);
  271. return -1;
  272. }
  273. s.s = p + 1;
  274. s.len = strlen(s.s);
  275. if(str2sint(&s, &l)<0) {
  276. LM_ERR("invalid parameter - level value: %s\n", (char*)val);
  277. return -1;
  278. }
  279. s.s = (char*)val;
  280. s.len = p - s.s;
  281. LM_DBG("cfg level_mode:%d hash_size:%d\n",
  282. cfg_get(dbg, dbg_cfg, mod_level_mode),
  283. cfg_get(dbg, dbg_cfg, mod_hash_size));
  284. if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
  285. {
  286. LM_ERR("failed to init per module log level\n");
  287. return -1;
  288. }
  289. if(dbg_set_mod_debug_level(s.s, s.len, &l)<0)
  290. {
  291. LM_ERR("cannot store parameter: %s\n", (char*)val);
  292. return -1;
  293. }
  294. return 0;
  295. }