debugger_mod.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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. /* anyhow, should fail before */
  129. if (!dbg_cfg) {
  130. return -1;
  131. }
  132. LM_DBG("cfg level_mode:%d hash_size:%d\n",
  133. cfg_get(dbg, dbg_cfg, mod_level_mode),
  134. cfg_get(dbg, dbg_cfg, mod_hash_size));
  135. if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
  136. {
  137. LM_ERR("failed to init per module log level\n");
  138. return -1;
  139. }
  140. if(_dbg_log_assign>0)
  141. {
  142. if(dbg_init_pvcache()!=0)
  143. {
  144. LM_ERR("failed to create pvcache\n");
  145. return -1;
  146. }
  147. }
  148. if(_dbg_reset_msgid==1)
  149. {
  150. unsigned int ALL = REQUEST_CB+FAILURE_CB+ONREPLY_CB
  151. +BRANCH_CB+ONSEND_CB+ERROR_CB+LOCAL_CB+EVENT_CB+BRANCH_FAILURE_CB;
  152. if (register_script_cb(dbg_msgid_filter, PRE_SCRIPT_CB|ALL, 0) != 0) {
  153. LM_ERR("could not insert callback");
  154. return -1;
  155. }
  156. }
  157. return dbg_init_bp_list();
  158. }
  159. /**
  160. * child init function
  161. */
  162. static int child_init(int rank)
  163. {
  164. LM_DBG("rank is (%d)\n", rank);
  165. if (rank==PROC_INIT) {
  166. dbg_enable_mod_levels();
  167. dbg_enable_log_assign();
  168. return dbg_init_pid_list();
  169. }
  170. return dbg_init_mypid();
  171. }
  172. /**
  173. * destroy module function
  174. */
  175. static void mod_destroy(void)
  176. {
  177. dbg_cfg = NULL;
  178. }
  179. /**
  180. * cfg wrapper to set breakpoint (not implemented yet)
  181. */
  182. static int w_dbg_breakpoint(struct sip_msg* msg, char* point, char* str2)
  183. {
  184. return 1;
  185. }
  186. /**
  187. * fixup for cfg dbg_pv_dump
  188. */
  189. static int fixup_dbg_pv_dump(void** param, int param_no)
  190. {
  191. unsigned int mask;
  192. int level;
  193. str s = STR_NULL;
  194. switch(param_no)
  195. {
  196. case 2:
  197. switch(((char*)(*param))[2])
  198. {
  199. case 'A': level = L_ALERT; break;
  200. case 'B': level = L_BUG; break;
  201. case 'C': level = L_CRIT2; break;
  202. case 'E': level = L_ERR; break;
  203. case 'W': level = L_WARN; break;
  204. case 'N': level = L_NOTICE; break;
  205. case 'I': level = L_INFO; break;
  206. case 'D': level = L_DBG; break;
  207. default:
  208. LM_ERR("unknown log level\n");
  209. return E_UNSPEC;
  210. }
  211. *param = (void*)(long)level;
  212. break;
  213. case 1:
  214. s.s = *param;
  215. s.len = strlen(s.s);
  216. if(str2int(&s, &mask) == 0) {
  217. *param = (void*)(long)mask;
  218. }
  219. else return E_UNSPEC;
  220. break;
  221. }
  222. return 0;
  223. }
  224. /**
  225. * dump pv_cache contents as json
  226. */
  227. static int w_dbg_dump(struct sip_msg* msg, char* mask, char* level)
  228. {
  229. unsigned int umask = DBG_DP_ALL;
  230. int ilevel = L_DBG;
  231. if(level!=NULL){
  232. ilevel = (int)(long)level;
  233. }
  234. if(mask!=NULL){
  235. umask = (unsigned int)(unsigned long)mask;
  236. }
  237. dbg_dump_json(msg, umask, ilevel);
  238. return 1;
  239. }
  240. /**
  241. * get the pointer to action structure
  242. */
  243. static struct action *dbg_fixup_get_action(void **param, int param_no)
  244. {
  245. struct action *ac, ac2;
  246. action_u_t *au, au2;
  247. /* param points to au->u.string, get pointer to au */
  248. au = (void*) ((char *)param - ((char *)&au2.u.string-(char *)&au2));
  249. au = au - 1 - param_no;
  250. ac = (void*) ((char *)au - ((char *)&ac2.val-(char *)&ac2));
  251. return ac;
  252. }
  253. /**
  254. * fixup for cfg set breakpoint function
  255. */
  256. static int fixup_dbg_breakpoint(void** param, int param_no)
  257. {
  258. struct action *a;
  259. char *p;
  260. if(param_no!=1)
  261. return -1;
  262. a = dbg_fixup_get_action(param, param_no);
  263. p = (char*)(*param);
  264. return dbg_add_breakpoint(a, (*p=='0')?0:1);
  265. }
  266. static int dbg_mod_level_param(modparam_t type, void *val)
  267. {
  268. char *p;
  269. str s;
  270. int l;
  271. if(val==NULL)
  272. return -1;
  273. p = strchr((char*)val, '=');
  274. if(p==NULL) {
  275. LM_ERR("invalid parameter value: %s\n", (char*)val);
  276. return -1;
  277. }
  278. s.s = p + 1;
  279. s.len = strlen(s.s);
  280. if(str2sint(&s, &l)<0) {
  281. LM_ERR("invalid parameter - level value: %s\n", (char*)val);
  282. return -1;
  283. }
  284. s.s = (char*)val;
  285. s.len = p - s.s;
  286. if (!dbg_cfg) {
  287. return -1;
  288. }
  289. LM_DBG("cfg level_mode:%d hash_size:%d\n",
  290. cfg_get(dbg, dbg_cfg, mod_level_mode),
  291. cfg_get(dbg, dbg_cfg, mod_hash_size));
  292. if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
  293. {
  294. LM_ERR("failed to init per module log level\n");
  295. return -1;
  296. }
  297. if(dbg_set_mod_debug_level(s.s, s.len, &l)<0)
  298. {
  299. LM_ERR("cannot store parameter: %s\n", (char*)val);
  300. return -1;
  301. }
  302. return 0;
  303. }