Browse Source

message shooter module added

This is a small module for sending out SIP messages
outside of the current transaction. The ruri, from, to, additional
headers, and optionally the body can be specified which make up the
SIP message that is sent out.
Miklos Tirpak 14 năm trước cách đây
mục cha
commit
9c9609dd2e

+ 16 - 0
modules/msg_shooter/Makefile

@@ -0,0 +1,16 @@
+#
+# msg_shooter module Makefile
+#
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+COREPATH ?= ../..
+include $(COREPATH)/Makefile.defs
+
+NAME=msg_shooter.so
+
+auto_gen=
+
+DEFS += -I$(COREPATH) -DSER_MOD_INTERFACE
+
+include $(COREPATH)/Makefile.modules
+

+ 125 - 0
modules/msg_shooter/README

@@ -0,0 +1,125 @@
+msg shooter module
+
+   Copyright (C) 2011 iptelorg GmbH
+   Created and maintained by Miklos Tirpak
+
+        1.1. Overview
+        1.2. Dependencies
+
+              1.2.1. SER Modules
+
+        1.3. Exported Parameters
+
+        1.4. Exported Functions
+
+              1.4.1. smsg_from_to(from, to)
+              1.4.2. smsg_create(method)
+              1.4.3. smsg_append_hdrs(headers, [body])
+              1.4.4. smsg_on_reply(route_name)
+              1.4.5. shoot_msg([ruri, [destination] ])
+
+        1.5. Example
+
+     _________________________________________________________
+
+1.1. Overview
+
+   The module can be used to send SIP requests outside of the
+   current transaction. For example it can send REGISTER requests
+   to another registrar server as notifications.
+
+   The module creates a UAC and may append additional headers
+   and body to it. Finaly the constructed request can be sent to
+   several destinations.
+
+     _________________________________________________________
+
+1.2. Dependencies
+
+1.2.1. SER Modules
+
+   The following modules must be loaded before this module:
+
+     * tm module
+     _________________________________________________________
+
+1.3. Exported Parameters
+
+   None
+
+   _________________________________________________________
+   
+1.4. Exported Functions
+
+1.4.1. smsg_from_to(from, to)
+
+   Sets the From and To URIs of the UAC, must be called before
+   smsg_create(). Parameters can be string, AVP or select call.
+
+   _________________________________________________________
+
+1.4.2. smsg_create(method)
+
+   Creates an UAC and sets the method of the request.
+   method must be static string.
+
+   Can be called multiple times, but destroys the previously
+   created UAC.
+
+   _________________________________________________________
+
+1.4.3. smsg_append_hdrs(headers, [body])
+
+   Appends additional headers and body to the request.
+   Parameters can be string, AVP or select call.
+
+   _________________________________________________________
+
+1.4.4. smsg_on_reply(route_name)
+
+   Sets onreply_route block which will be executed upon a reply
+   is received for the shooted request. Must be called before
+   every shoot_msg() function if required.
+
+   Note that failure_route is curretly not supported (neither for
+   negative responses nor for timer hit)!
+
+   Also note that the transaction created by the new request does not
+   contain the AVPs of the old transaction, thus onreply_route will
+   not have any AVPs.
+
+   _________________________________________________________
+
+1.4.5. shoot_msg([ruri, [destination] ])
+
+   Shoots the request with the previously created UAC.
+   ruri and destination can be string, AVP or select call.
+   To HF is used for ruri when ruri parameter is not defined.
+
+   Can be called multiple times with the same UAC.
+
+   _________________________________________________________
+
+1.5. Example
+
+   The following example creates 2 UACs and sends the requests
+   to 3 different destinations
+
+onreply_route[notification] {
+
+	smsg_from_to("@from.uri", "@to.uri");
+	smsg_create("REGISTER");
+	$hdrs = "Contact: sip:[email protected]\r\nP-info: created by msg_shooter\r\n";
+	smsg_append_hdrs("$hdrs");
+
+	smsg_on_reply("first");
+	shoot_msg("sip:[email protected]", "sip:192.168.1.1");
+
+	smsg_on_reply("second");
+	shoot_msg("sip:[email protected]");
+
+	smsg_create("NOTIFY");
+	smsg_append_hdrs("P-info: another request\r\n", "Fake body\r\n");
+	shoot_msg("sip:[email protected]");
+
+}

+ 303 - 0
modules/msg_shooter/msg_shooter.c

@@ -0,0 +1,303 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mem/mem.h"
+#include "str.h"
+#include "sr_module.h"
+#include "msg_shooter_mod.h"
+#include "smsg_routes.h"
+#include "msg_shooter.h"
+
+/* method points to a static char buffer, all of the others are
+dinamically allocated */
+static str	method = {0, 0};
+static str	from = {0, 0};
+static str	to = {0, 0};
+static str	hdrs = {0, 0};
+static str	body = {0, 0};
+static dlg_t	*UAC = 0;
+/* onreply route index */
+static int	onreply_idx = -1;
+
+/* get method of the request */
+int smsg_create(struct sip_msg *_msg, char *_param1, char *_param2)
+{
+	/* check the required information */
+	if (!from.len || !to.len) {
+		LOG(L_ERR, "ERROR: smsg_create(): mandatory headers are missing\n");
+		LOG(L_ERR, "ERROR: smsg_create(): have you forgot to call smsg_from_to() function?\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&method, _msg, (fparam_t*)_param1)) {
+		LOG(L_ERR, "ERROR: smsg_create(): cannot get parameter\n");
+		return -1;
+	}
+	/* method is just a static char buffer, needless to copy it */
+
+	/* previous UAC still exists -- destroy it first */
+	if (UAC) {
+		LOG(L_DBG, "DEBUG: smsg_create(): destroying previous UAC\n");
+		tmb.free_dlg(UAC);
+		UAC = 0;
+		/* better to free also hdrs and body now */
+		if (hdrs.s) {
+			pkg_free(hdrs.s);
+			hdrs.s = 0;
+			hdrs.len = 0;
+		}
+		if (body.s) {
+			pkg_free(body.s);
+			body.s = 0;
+			body.len = 0;
+		}
+	}
+
+	/* create UAC */
+	if (tmb.new_dlg_uac(0, 0, 0, &from, &to, &UAC) < 0) {
+		LOG(L_ERR, "ERROR: smsg_create(): cannot create UAC\n");
+		return -1;
+	}
+	return 1;
+}
+
+/* free allocated memory */
+void smsg_destroy(void)
+{
+	method.s = 0;
+	method.len = 0;
+	if (from.s) {
+		pkg_free(from.s);
+		from.s = 0;
+		from.len = 0;
+	}
+	if (to.s) {
+		pkg_free(to.s);
+		to.s = 0;
+		to.len = 0;
+	}
+	if (hdrs.s) {
+		pkg_free(hdrs.s);
+		hdrs.s = 0;
+		hdrs.len = 0;
+	}
+	if (body.s) {
+		pkg_free(body.s);
+		body.s = 0;
+		body.len = 0;
+	}
+	if (UAC) {
+		tmb.free_dlg(UAC);
+		UAC = 0;
+	}
+	onreply_idx = -1;
+}
+
+/* clone an str structure */
+static int clone_str(str *_s, str *_d)
+{
+	if (_d->s) pkg_free(_d->s);
+
+	if (_s->len == 0) {
+		/* empty string */
+		_d->s = 0;
+		_d->len = 0;
+		return 0;
+	}
+
+	_d->s = (char *)pkg_malloc(_s->len * sizeof(char));
+	if (!_d->s) {
+		LOG(L_ERR, "ERROR: clone_str(): not enough memory\n");
+		return -1;
+	}
+	memcpy(_d->s, _s->s, _s->len);
+	_d->len = _s->len;
+
+	return 0;
+}
+
+/* set From and To headers of the request */
+int smsg_from_to(struct sip_msg *_msg, char *_param1, char *_param2)
+{
+	str	s;
+
+	if (get_str_fparam(&s, _msg, (fparam_t*)_param1)) {
+		LOG(L_ERR, "ERROR: smsg_from_to(): cannot get parameter\n");
+		return -1;
+	}
+	/* select and AVP result can change, we need a private copy of the buffer */
+	if (clone_str(&s, &from)) return -1;
+
+	if (get_str_fparam(&s, _msg, (fparam_t*)_param2)) {
+		LOG(L_ERR, "ERROR: smsg_from_to(): cannot get parameter\n");
+		return -1;
+	}
+	/* select and AVP result can change, we need a private copy of the buffer */
+	if (clone_str(&s, &to)) return -1;
+
+	return 1;
+}
+
+/* append headers and optionally body to the request */
+int smsg_append_hdrs(struct sip_msg *_msg, char *_param1, char *_param2)
+{
+	str	s;
+
+	if (get_str_fparam(&s, _msg, (fparam_t*)_param1)) {
+		LOG(L_ERR, "ERROR: smsg_append_hdrs(): cannot get parameter\n");
+		return -1;
+	}
+	/* select and AVP result can change, we need a private copy of the buffer */
+	if (clone_str(&s, &hdrs)) return -1;
+
+	if (_param2) {
+		if (get_str_fparam(&s, _msg, (fparam_t*)_param2)) {
+			LOG(L_ERR, "ERROR: smsg_append_hdrs(): cannot get parameter\n");
+			return -1;
+		}
+		/* select and AVP result can change, we need a private copy of the buffer */
+		if (clone_str(&s, &body)) return -1;
+	} else {
+		if (body.s) {
+			pkg_free(body.s);
+			body.s = 0;
+			body.len = 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * callback function for TM module
+ * it is called on TMCB_LOCAL_COMPLETED
+ */
+static void tmcb_func(struct cell *_t, int _type, struct tmcb_params *_ps)
+{
+	int	index;
+
+	if (_type & (TMCB_LOCAL_COMPLETED)) {
+		if ((!_ps->rpl) || (_ps->rpl == FAKED_REPLY)) {
+			/* timer hit  -- on_failure route is not supported */
+			LOG(L_DBG, "DEBUG: tmcb_func(): transaction completed with failure (timer hit),"
+				" but msg_shooter module does not support failure_route currently\n");
+		} else {
+			/* reply received */
+			if (_ps->code >= 400) {
+				LOG(L_DBG, "DEBUG: tmcb_func(): transaction completed with failure (code=%d),"
+					" but msg_shooter module does not support failure_route currently\n",
+					_ps->code);
+			}
+			if (!_ps->param) {
+				LOG(L_ERR, "ERROR: tmcb_func(): parameter is missing\n");
+				return;		
+			}
+			index = (int)(long)(*_ps->param);
+			run_reply_route(_ps->rpl, _t, index);
+		}
+	}
+}
+
+
+static avp_list_t def_avp_list = 0;
+
+/* shoots a request to a destination outside of a dialog */
+int smsg(struct sip_msg *_msg, char *_param1, char *_param2)
+{
+	int	ret = 1;
+	str	ruri = {0, 0};
+	str	dst = {0, 0};
+	avp_list_t	*backup_uri_from, *backup_uri_to;
+	avp_list_t	*backup_user_from, *backup_user_to;
+	avp_list_t	*backup_domain_from, *backup_domain_to;
+	uac_req_t	uac_r;
+
+	/* check the required information */
+	if (!UAC) {
+		LOG(L_ERR, "ERROR: smsg(): UAC is missing\n");
+		LOG(L_ERR, "ERROR: smsg(): have you forgot to call smsg_from_to() and smsg_create() functions?\n");
+		return -1;
+	}
+
+	if (_param1 && get_str_fparam(&ruri, _msg, (fparam_t*)_param1)) {
+		LOG(L_ERR, "ERROR: smsg(): cannot get parameter\n");
+		return -1;
+	}
+
+	if (_param2 && get_str_fparam(&dst, _msg, (fparam_t*)_param2)) {
+		LOG(L_ERR, "ERROR: smsg(): cannot get parameter\n");
+		return -1;
+	}
+
+	LOG(L_DBG, "DEBUG: smsg(): sending %.*s request "
+			"(from=%.*s, to=%.*s, ruri=%.*s, dst=%.*s)\n",
+			method.len, method.s,
+			from.len, from.s,
+			to.len, to.s,
+			ruri.len, ruri.s,
+			dst.len, dst.s);
+
+
+	if (ruri.len) {
+		if (tmb.set_dlg_target(UAC, &ruri, &dst) < 0) {
+			LOG(L_ERR, "ERROR: smsg(): cannot set remote target\n");
+			return -1;
+		}
+	}
+
+	/* reset user AVP lists, otherwise TM would free the memory twice cousing crash */
+	backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &def_avp_list);
+	backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &def_avp_list);
+	backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &def_avp_list);
+	backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &def_avp_list);
+	backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &def_avp_list);
+	backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &def_avp_list);
+
+	set_uac_req(&uac_r,
+			&method,
+			(hdrs.len) ? &hdrs : 0,
+			(body.len) ? &body : 0,
+			UAC,
+			(onreply_idx < 0) ? 0 : TMCB_LOCAL_COMPLETED,
+			(onreply_idx < 0) ? 0 : tmcb_func,
+			(onreply_idx < 0) ? 0 : (void *)(long)onreply_idx
+		);
+
+	if (tmb.t_uac(&uac_r) < 0) {
+		LOG(L_ERR, "ERROR: smsg(): request could not be sent\n");
+		ret = -1;
+	}
+
+	/* restore AVP lists */
+	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from);
+	set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to);
+	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from);
+	set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to);
+	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from);
+	set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to);
+
+	/* reset smsg_on_reply */
+	onreply_idx = -1;
+	return ret;
+}
+
+/* sents on_reply route which will be called later */
+int smsg_on_reply(struct sip_msg *_msg, char *_param1, char *_param2)
+{
+	onreply_idx = (int)(long)(_param1);
+	return 1;
+}

+ 42 - 0
modules/msg_shooter/msg_shooter.h

@@ -0,0 +1,42 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _MSG_SHOOTER_H
+#define _MSG_SHOOTER_H
+
+#include "parser/msg_parser.h"
+
+/* get method of the request */
+int smsg_create(struct sip_msg *_msg, char *_param1, char *_param2);
+
+/* free allocated memory */
+void smsg_destroy(void);
+
+/* set From and To headers of the request */
+int smsg_from_to(struct sip_msg *_msg, char *_param1, char *_param2);
+
+/* append headers and optionally body to the request */
+int smsg_append_hdrs(struct sip_msg *_msg, char *_param1, char *_param2);
+
+/* shoots a request to a destination outside of a dialog */
+int smsg(struct sip_msg *_msg, char *_param1, char *_param2);
+
+/* sents on_reply route which will be called later */
+int smsg_on_reply(struct sip_msg *_msg, char *_param1, char *_param2);
+
+#endif /* _MSG_SHOOTER_H */

+ 124 - 0
modules/msg_shooter/msg_shooter_mod.c

@@ -0,0 +1,124 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include "sr_module.h"
+#include "script_cb.h"
+#include "route.h"
+#include "modules/tm/tm_load.h"
+#include "msg_shooter.h"
+#include "msg_shooter_mod.h"
+
+MODULE_VERSION
+
+struct tm_binds	tmb;
+
+/* Module management function prototypes */
+static int mod_init(void);
+static int w_smsg_destroy(struct sip_msg *_msg, unsigned int flags, void *_param);
+static int fixup_smsg_on_reply(void** _param, int _param_no);
+
+/* Exported functions */
+static cmd_export_t cmds[] = {
+	{"shoot_msg",	smsg,		0, 0,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"shoot_msg",	smsg,		1, fixup_var_str_1,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"shoot_msg",	smsg,		2, fixup_var_str_12,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"smsg_create",	smsg_create, 	1, fixup_str_1,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"smsg_from_to",	smsg_from_to, 2, fixup_var_str_12,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"smsg_append_hdrs", 	smsg_append_hdrs, 1, fixup_var_str_1,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"smsg_append_hdrs", 	smsg_append_hdrs, 2, fixup_var_str_12,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{"smsg_on_reply", 	smsg_on_reply,	1, fixup_smsg_on_reply,
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},
+
+	{0, 0, 0, 0, 0}
+};
+
+/* Module interface */
+struct module_exports exports = {
+	"msg_shooter",
+	cmds,		/* Exported functions */
+	0,		/* RPC methods */	
+	0,		/* Exported parameters */
+	mod_init,	/* module initialization function */
+	0,		/* response function */
+	0,		/* destroy function */
+	0,		/* oncancel function */
+	0		/* child initialization function */
+};
+
+/* module initialization function */
+static int mod_init(void)
+{
+	load_tm_f	load_tm;
+
+	LOG(L_DBG, "DEBUG: mod_init(): Initializing msg_shooter module\n");
+
+	/* import the TM auto-loading function */
+	if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
+		LOG(L_ERR, "ERROR: mod_init(): can't import load_tm\n");
+		return -1;
+	}
+	/* let the auto-loading function load all TM stuff */
+	if (load_tm( &tmb )==-1) return -1;
+
+	if (register_script_cb(w_smsg_destroy,
+			REQUEST_CB | FAILURE_CB | ONREPLY_CB | BRANCH_CB | POST_SCRIPT_CB,
+			0) < 0
+	)
+		return -1;
+
+	return 0;
+}
+
+/* free allocated memory */
+static int w_smsg_destroy(struct sip_msg *_msg, unsigned int flags, void *_param)
+{
+	smsg_destroy();
+	return 1;
+}
+
+/* fixup function to convert route name to index */
+static int fixup_smsg_on_reply(void** _param, int _param_no)
+{
+	int index;
+
+	if (_param_no != 1) return 0;
+
+	index = route_lookup(&onreply_rt, (char*)(*_param));
+	if (index < 0) {
+		LOG(L_ERR, "ERROR: fixup_smsg_on_reply(): unknown on_reply route name: %s\n",
+				(char*)(*_param));
+		return -1;
+	}
+	pkg_free(*_param);
+	*_param = (void *)(long)index;
+	return 0;
+}

+ 26 - 0
modules/msg_shooter/msg_shooter_mod.h

@@ -0,0 +1,26 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _MSG_SHOOTER_MOD_H
+#define _MSG_SHOOTER_MOD_H
+
+#include "modules/tm/tm_load.h"
+
+extern struct tm_binds	tmb;
+
+#endif /* _MSG_SHOOTER_MOD_H */

+ 54 - 0
modules/msg_shooter/smsg_routes.c

@@ -0,0 +1,54 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "action.h"
+#include "route.h"
+#include "modules/tm/h_table.h"
+#include "smsg_routes.h"
+
+/* run reply route functions */
+int run_reply_route(struct sip_msg *_rpl, struct cell *_t, int index)
+{
+	avp_list_t	*backup_uri_from, *backup_uri_to;
+	avp_list_t	*backup_user_from, *backup_user_to;
+	avp_list_t	*backup_domain_from, *backup_domain_to;
+	struct run_act_ctx	ra_ctx;
+
+	if (!_t || (index < 0)) return -1;
+
+	/* set the avp_list the one from transaction */
+	backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &_t->uri_avps_from );
+	backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &_t->uri_avps_to );
+	backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &_t->user_avps_from );
+	backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &_t->user_avps_to );
+	backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &_t->domain_avps_from );
+	backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &_t->domain_avps_to );
+
+	init_run_actions_ctx(&ra_ctx);
+	if (run_actions(&ra_ctx, onreply_rt.rlist[index], _rpl)<0)
+		LOG(L_ERR, "ERROR: run_reply_route(): on_reply processing failed\n");
+
+	/* restore original avp list */
+	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
+	set_avp_list( AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
+	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from );
+	set_avp_list( AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
+	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
+	set_avp_list( AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );
+
+	return 0;
+}

+ 26 - 0
modules/msg_shooter/smsg_routes.h

@@ -0,0 +1,26 @@
+/*$Id$
+ *
+ * Copyright (C) 2011 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _ROUTES_H
+#define _ROUTES_H
+
+/* run reply route functions */
+int run_reply_route(struct sip_msg *res, struct cell *t, int index);
+
+
+#endif /* _ROUTES_H */