浏览代码

sipdump: option to run event_route[sipdump:msg] on rcv/snd messages

- new modparam mode to control the behaviour, its values can be built
from flags:
  - 1 - write to files (the existing behaviour), default
  - 2 - execute event route
- inside event route, $sipdump(...) variable is available to get the
buffer content and other related attributes
- new modparam event_callback to set the KEMI function to be run instead
of the event route
Daniel-Constantin Mierla 5 年之前
父节点
当前提交
801eaa92b0
共有 2 个文件被更改,包括 202 次插入7 次删除
  1. 199 7
      src/modules/sipdump/sipdump_mod.c
  2. 3 0
      src/modules/sipdump/sipdump_write.h

+ 199 - 7
src/modules/sipdump/sipdump_mod.c

@@ -34,6 +34,7 @@
 #include "../../core/pt.h"
 #include "../../core/timer_proc.h"
 #include "../../core/mod_fix.h"
+#include "../../core/fmsg.h"
 #include "../../core/events.h"
 #include "../../core/kemi.h"
 
@@ -46,6 +47,10 @@ int sipdump_rotate = 7200;
 static int sipdump_wait = 100;
 static str sipdump_folder = str_init("/tmp");
 static str sipdump_fprefix = str_init("kamailio-sipdump-");
+static int sipdump_mode = SIPDUMP_MODE_WFILE;
+static str sipdump_event_callback = STR_NULL;
+
+static int sipdump_event_route_idx = -1;
 
 static int mod_init(void);
 static int child_init(int);
@@ -56,6 +61,10 @@ static int w_sipdump_send(sip_msg_t *msg, char *ptag, char *str2);
 int sipdump_msg_received(sr_event_param_t *evp);
 int sipdump_msg_sent(sr_event_param_t *evp);
 
+int pv_parse_sipdump_name(pv_spec_t *sp, str *in);
+int pv_get_sipdump(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res);
+
 /* clang-format off */
 static cmd_export_t cmds[]={
 	{"sipdump_send", (cmd_function)w_sipdump_send, 1, fixup_spve_null,
@@ -64,21 +73,32 @@ static cmd_export_t cmds[]={
 };
 
 static param_export_t params[]={
-	{"enable",   PARAM_INT,   &sipdump_enable},
-	{"wait",     PARAM_INT,   &sipdump_wait},
-	{"rotate",   PARAM_INT,   &sipdump_rotate},
-	{"folder",   PARAM_STR,   &sipdump_folder},
-	{"fprefix",  PARAM_STR,   &sipdump_fprefix},
+	{"enable",         PARAM_INT,   &sipdump_enable},
+	{"wait",           PARAM_INT,   &sipdump_wait},
+	{"rotate",         PARAM_INT,   &sipdump_rotate},
+	{"folder",         PARAM_STR,   &sipdump_folder},
+	{"fprefix",        PARAM_STR,   &sipdump_fprefix},
+	{"mode",           PARAM_INT,   &sipdump_mode},
+	{"event_callback", PARAM_STR,   &sipdump_event_callback},
+
 	{0, 0, 0}
 };
 
+static pv_export_t mod_pvs[] = {
+
+	{ {"sipdump", (sizeof("sipdump")-1)}, PVT_OTHER, pv_get_sipdump, 0,
+		pv_parse_sipdump_name, 0, 0, 0 },
+
+	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
+};
+
 struct module_exports exports = {
 	"sipdump",      /* module name */
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	cmds,           /* exported functions */
 	params,         /* exported parameters */
 	0,              /* exported rpc functions */
-	0,              /* exported pseudo-variables */
+	mod_pvs,        /* exported pseudo-variables */
 	0,              /* response handling function */
 	mod_init,       /* module init function */
 	child_init,     /* per child init function */
@@ -92,6 +112,11 @@ struct module_exports exports = {
  */
 static int mod_init(void)
 {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WFILE | SIPDUMP_MODE_EVROUTE))) {
+		LM_ERR("invalid mode parameter\n");
+		return -1;
+	}
+
 	if(sipdump_rpc_init()<0) {
 		LM_ERR("failed to register rpc commands\n");
 		return -1;
@@ -107,7 +132,18 @@ static int mod_init(void)
 		return -1;
 	}
 
-	register_basic_timers(1);
+	if(sipdump_mode & SIPDUMP_MODE_EVROUTE) {
+		sipdump_event_route_idx = route_lookup(&event_rt, "sipdump:msg");
+		if (sipdump_event_route_idx>=0 && event_rt.rlist[sipdump_event_route_idx]==0) {
+			sipdump_event_route_idx = -1; /* disable */
+		}
+		faked_msg_init();
+	}
+
+	if(sipdump_mode & SIPDUMP_MODE_WFILE) {
+		register_basic_timers(1);
+	}
+
 	sr_event_register_cb(SREV_NET_DATA_IN, sipdump_msg_received);
 	sr_event_register_cb(SREV_NET_DATA_OUT, sipdump_msg_sent);
 
@@ -123,6 +159,10 @@ static int child_init(int rank)
 	if(rank != PROC_MAIN)
 		return 0;
 
+	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+		return 0;
+	}
+
 	if(fork_basic_utimer(PROC_TIMER, "SIPDUMP WRITE TIMER", 1 /*socks flag*/,
 			   sipdump_timer_exec, NULL, sipdump_wait /*usec*/)
 				< 0) {
@@ -207,6 +247,11 @@ int ki_sipdump_send(sip_msg_t *msg, str *stag)
 	if(!sipdump_enabled())
 		return 1;
 
+	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+		LM_WARN("writing to file is disabled - ignoring\n");
+		return 1;
+	}
+
 	memset(&sdi, 0, sizeof(sipdump_info_t));
 
 	sdi.buf.s = msg->buf;
@@ -266,6 +311,45 @@ static int w_sipdump_send(sip_msg_t *msg, char *ptag, char *str2)
 	return ki_sipdump_send(msg, &stag);
 }
 
+/**
+ *
+ */
+static sipdump_info_t* sipdump_event_info = NULL;
+
+/**
+ *
+ */
+void sipdump_event_route(sipdump_info_t* sdi)
+{
+	int backup_rt;
+	run_act_ctx_t ctx;
+	run_act_ctx_t *bctx;
+	sr_kemi_eng_t *keng = NULL;
+	str evname = str_init("sipdump:msg");
+	sip_msg_t *fmsg = NULL;
+
+	backup_rt = get_route_type();
+	set_route_type(EVENT_ROUTE);
+	init_run_actions_ctx(&ctx);
+	fmsg = faked_msg_next();
+	sipdump_event_info = sdi;
+
+	if(sipdump_event_route_idx>=0) {
+		run_top_route(event_rt.rlist[sipdump_event_route_idx], fmsg, 0);
+	} else {
+		keng = sr_kemi_eng_get();
+		if (keng!=NULL) {
+			bctx = sr_kemi_act_ctx_get();
+			sr_kemi_act_ctx_set(&ctx);
+			(void)sr_kemi_route(keng, fmsg, EVENT_ROUTE,
+						&sipdump_event_callback, &evname);
+			sr_kemi_act_ctx_set(bctx);
+		}
+	}
+	sipdump_event_info = NULL;
+	set_route_type(backup_rt);
+}
+
 /**
  *
  */
@@ -306,6 +390,15 @@ int sipdump_msg_received(sr_event_param_t *evp)
 	sdi.proto.s = "none";
 	sdi.proto.len = 4;
 	get_valid_proto_string(evp->rcv->proto, 0, 0, &sdi.proto);
+
+	if(sipdump_mode & SIPDUMP_MODE_EVROUTE) {
+		sipdump_event_route(&sdi);
+	}
+
+	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+		return 0;
+	}
+
 	if(sipdump_buffer_write(&sdi, &wdata)<0) {
 		LM_ERR("failed to write to buffer\n");
 		return -1;
@@ -354,6 +447,14 @@ int sipdump_msg_sent(sr_event_param_t *evp)
 	sdi.proto.len = 4;
 	get_valid_proto_string(evp->dst->proto, 0, 0, &sdi.proto);
 
+	if(sipdump_mode & SIPDUMP_MODE_EVROUTE) {
+		sipdump_event_route(&sdi);
+	}
+
+	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+		return 0;
+	}
+
 	if(sipdump_buffer_write(&sdi, &wdata)<0) {
 		LM_ERR("failed to write to buffer\n");
 		return -1;
@@ -381,6 +482,97 @@ static sr_kemi_t sr_kemi_sipdump_exports[] = {
 };
 /* clang-format on */
 
+/**
+ *
+ */
+int pv_parse_sipdump_name(pv_spec_t *sp, str *in)
+{
+	if(sp==NULL || in==NULL || in->len<=0)
+		return -1;
+
+	switch(in->len)
+	{
+		case 2:
+			if(strncmp(in->s, "af", 2)==0)
+				sp->pvp.pvn.u.isname.name.n = 3;
+			else goto error;
+		break;
+		case 3:
+			if(strncmp(in->s, "buf", 3)==0)
+				sp->pvp.pvn.u.isname.name.n = 1;
+			else if(strncmp(in->s, "len", 3)==0)
+				sp->pvp.pvn.u.isname.name.n = 2;
+			else if(strncmp(in->s, "tag", 3)==0)
+				sp->pvp.pvn.u.isname.name.n = 0;
+			else goto error;
+		break;
+		case 5:
+			if(strncmp(in->s, "proto", 5)==0)
+				sp->pvp.pvn.u.isname.name.n = 4;
+			else goto error;
+		break;
+		case 6:
+			if(strncmp(in->s, "sproto", 6)==0)
+				sp->pvp.pvn.u.isname.name.n = 5;
+			else if(strncmp(in->s, "src_ip", 6)==0)
+				sp->pvp.pvn.u.isname.name.n = 6;
+			else if(strncmp(in->s, "dst_ip", 6)==0)
+				sp->pvp.pvn.u.isname.name.n = 7;
+			else goto error;
+		break;
+		case 8:
+			if(strncmp(in->s, "src_port", 8)==0)
+				sp->pvp.pvn.u.isname.name.n = 8;
+			if(strncmp(in->s, "dst_port", 8)==0)
+				sp->pvp.pvn.u.isname.name.n = 9;
+			else goto error;
+		break;
+		default:
+			goto error;
+	}
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+	sp->pvp.pvn.u.isname.type = 0;
+
+	return 0;
+
+error:
+	LM_ERR("unknown PV snd name %.*s\n", in->len, in->s);
+	return -1;
+}
+
+/**
+ *
+ */
+int pv_get_sipdump(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	if (sipdump_event_info==NULL) {
+		return pv_get_null(msg, param, res);
+	}
+
+	switch(param->pvn.u.isname.name.n) {
+		case 1: /* buf */
+			return pv_get_strval(msg, param, res, &sipdump_event_info->buf);
+		case 2: /* len */
+			return pv_get_uintval(msg, param, res, sipdump_event_info->buf.len);
+		case 3: /* af */
+			return pv_get_strval(msg, param, res, &sipdump_event_info->af);
+		case 4: /* proto */
+			return pv_get_strval(msg, param, res, &sipdump_event_info->proto);
+		case 6: /* src_ip*/
+			return pv_get_strval(msg, param, res, &sipdump_event_info->src_ip);
+		case 7: /* dst_ip*/
+			return pv_get_strval(msg, param, res, &sipdump_event_info->dst_ip);
+		case 8: /* src_port */
+			return pv_get_uintval(msg, param, res, sipdump_event_info->src_port);
+		case 9: /* dst_port */
+			return pv_get_uintval(msg, param, res, sipdump_event_info->dst_port);
+		default:
+			/* 0 - tag */
+			return pv_get_strval(msg, param, res, &sipdump_event_info->tag);
+	}
+}
+
 /**
  *
  */

+ 3 - 0
src/modules/sipdump/sipdump_write.h

@@ -26,6 +26,9 @@
 #include "../../core/str.h"
 #include "../../core/locking.h"
 
+#define SIPDUMP_MODE_WFILE (1<<0)
+#define SIPDUMP_MODE_EVROUTE (1<<1)
+
 typedef struct sipdump_data {
 	str data;
 	struct sipdump_data *next;