Hi
the inline patch adds a new module called 'histinfo'. it implements
a subset of the History-Info header as defined in RFC 4244. the main
purpose of the module was to implement the extension of RFC 4244,
defined in draft-rosenberg-sip-target-uri-delivery-00
we would like to commit the module to CVS, but would really like
some input from the SER community first. the module also requires
some changes in the `tm' module which must be reviewed carefully.
summary of changes:
- new module 'histinfo'
- tm module: save current processed branch, export t_get_branch()
I also envision that we can implement full support for RFC 4244
in this module, adding new script functions. This will keep all
history-info related code in one place.
it would be nice if you all could review the script functions:
histinfo_add_target() - Append H-I to a SIP request
histinfo_copy() - Copy H-I from SIP request to response
histinfo_add_reply() - Prepend H-I to a SIP response
comments are welcome!
/alfred
---
--- sip_router-orig/modules/histinfo/histinfo.c 1970-01-01 01:00:00.000000000
+0100
+++ sip_router/modules/histinfo/histinfo.c 2008-12-08 14:06:04.000000000
+0100
@@ -0,0 +1,599 @@
+/*
+ * History-Info Module
+ *
+ * Copyright (C) 2008 Alfred E. Heggestad
+ * Copyright (C) 2008 Telio Telecom
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ * [EMAIL PROTECTED]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../../sr_module.h"
+#include "../../mem/mem.h"
+#include "../../data_lump.h"
+#include "../../data_lump_rpl.h"
+#include "../../parser/parse_uri.h"
+#include "../../parser/msg_parser.h"
+#include "../tm/tm_load.h"
+#include "../tm/t_lookup.h"
+
+
+MODULE_VERSION
+#define DBG_PRFX "histinfo: "
+
+/*
+ * Implements an extension to History-Info (RFC 4244)
+ * draft-rosenberg-sip-target-uri-delivery-00
+ *
+ * TODO: implement the complete RFC 4244
+ */
+
+
+#ifndef STR_STATIC_INIT
+#define STR_STATIC_INIT(v) {(v), sizeof((v)) - 1}
+#endif
+
+#ifndef STR_FMT
+#define STR_FMT(_pstr_) \
+ (((_pstr_) != (str *)0) ? (_pstr_)->len : 0), \
+ (((_pstr_) != (str *)0) ? (_pstr_)->s : "")
+#endif
+
+
+static struct tm_binds tmb;
+static const str str_histinfo = STR_STATIC_INIT("History-Info");
+
+
+/*
+ * Utility functions
+ */
+
+
+/**
+ * Compare two `str' strings and return 1 if match
+ */
+static inline int str_casecmp(const str *a, const str *b)
+{
+ if (!a || !b)
+ return 0;
+
+ if (a->len != b->len)
+ return 0;
+
+ return 0 == strncasecmp(a->s, b->s, a->len);
+}
+
+
+/**
+ * Duplicate a `str' string to a char string, return NULL if fail
+ *
+ * NOTE: returned string is NOT null-terminated!
+ */
+static char *str_dup(const str *str)
+{
+ char *s;
+
+ if (!str)
+ return NULL;
+
+ s = pkg_malloc(str->len);
+ if (!s)
+ return NULL;
+
+ memcpy(s, str->s, str->len);
+ return s;
+}
+
+
+/**
+ * Append a header to the SIP message
+ */
+static int append_hf(struct sip_msg *msg, const str *str1)
+{
+ struct lump *anchor;
+ char *s;
+
+ if (!msg || !str1)
+ return -1;
+
+ if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
+ LOG(L_ERR, "append_hf(): Error while parsing message\n");
+ return -1;
+ }
+
+ anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
+ if (anchor == 0) {
+ LOG(L_ERR, "append_hf(): Can't get anchor\n");
+ return -1;
+ }
+
+ s = str_dup(str1);
+ if (!s) {
+ LOG(L_ERR, "append_hf(): No memory left\n");
+ return -1;
+ }
+
+ if (insert_new_lump_before(anchor, s, str1->len, 0) == 0) {
+ LOG(L_ERR, "append_hf(): Can't insert lump\n");
+ pkg_free(s);
+ return -1;
+ }
+ return 1;
+}
+
+
+/**
+ * Prepend a header to a SIP message
+ */
+static int prepend_hf(struct sip_msg *msg, const str *hname, const str *str1)
+{
+ const struct hdr_field *hf;
+ struct lump *l;
+ char *s = NULL;
+
+ if (!msg || !hname || !str1)
+ return -1;
+
+ if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
+ LOG(L_ERR, "prepend_hf(): parse headers EOH failed\n");
+ return -1;
+ }
+
+ /* Find first header */
+ for (hf = msg->headers; hf; hf = hf->next) {
+ if (str_casecmp(&hf->name, hname))
+ break;
+ }
+
+ if (hf) {
+ /* header found, add ours in front of that */
+ l = anchor_lump(msg, hf->name.s - msg->buf, 0, 0);
+ }
+ else {
+ /* no header found, append to message */
+ l = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
+ }
+
+ if (!l) {
+ LOG(L_ERR, "prepend_hf(): no anchor found\n");
+ goto err;
+ }
+
+ s = str_dup(str1);
+ if (!s) {
+ LOG(L_ERR, "prepend_hf(): No memory left\n");
+ goto err;
+ }
+
+ if (insert_new_lump_before(l, s, str1->len, 0) == 0) {
+ LOG(L_ERR, "prepend_hf(): Can't insert lump\n");
+ goto err;
+ }
+
+ return 1;
+
+ err:
+ if (s)
+ pkg_free(s);
+
+ return -1;
+}
+
+
+/**
+ * Check if the header-field exist in a SIP message
+ */
+static int hf_exist(struct sip_msg *msg, const str *str_hf)
+{
+ struct hdr_field *hf;
+
+ if (!msg || !str_hf)
+ return 0;
+
+ /* we need to be sure we have seen all HFs */
+ parse_headers(msg, HDR_EOH_F, 0);
+
+ for (hf=msg->headers; hf; hf=hf->next) {
+
+ if (str_casecmp(&hf->name, str_hf))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Copy all `hdr' headers from SIP Message src to dst
+ */
+static void cpy_hfs(struct sip_msg *dst, struct sip_msg *src, const str *hdr)
+{
+ const struct hdr_field *hf;
+ str tmp_str;
+
+ if (!dst || !src)
+ return;
+
+ if (parse_headers(src, HDR_EOH_F, 0) < 0) {
+ LOG(L_ERR, DBG_PRFX "parse_headers() failed\n");
+ return;
+ }
+
+ /* Copy all History-Info headers from request to response */
+ for (hf=src->headers; hf; hf=hf->next) {
+
+ if (!str_casecmp(&hf->name, hdr))
+ continue;
+
+ tmp_str.s = hf->name.s;
+ tmp_str.len = hf->len;
+
+ /* FIXME this is inefficient */
+ if (append_hf(dst, &tmp_str) < 0) {
+ LOG(L_ERR, DBG_PRFX "append_hf() failed\n");
+ }
+ }
+}
+
+
+/**
+ * Make a History-Info header, return length or <0 if fail
+ */
+static int hi_mk(char *buf, int sz, const str *ouri,
+ const struct sip_uri *iuri, int branch)
+{
+ int l;
+
+ if (!buf || !sz || !ouri || !iuri || branch < 0)
+ return -1;
+
+ l = snprintf(buf, sz, "%.*s: <sip:[EMAIL PROTECTED]>;target;index=1,"
+ " <%.*s>;target;index=1.%d\r\n", STR_FMT(&str_histinfo),
+ STR_FMT(&iuri->user), STR_FMT(&iuri->host),
+ STR_FMT(ouri), branch+1);
+ if (l < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_mk: snprintf() failed %d\n", l);
+ return -1;
+ }
+ buf[sz-1] = '\0';
+
+ return l;
+}
+
+
+/**
+ * Append a History-Info header to a SIP message
+ */
+static int hi_append(struct sip_msg *msg, const str *ouri,
+ const struct sip_uri *iuri, int branch)
+{
+ char s[512];
+ str h = {s, 0};
+
+ h.len = hi_mk(s, sizeof(s), ouri, iuri, branch);
+ if (h.len < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_append: hi_mk() failed\n");
+ return -1;
+ }
+
+ if (append_hf(msg, &h) < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_append: append_hf() failed\n");
+ return -1;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Prepend a History-Info header to a SIP message
+ */
+static int hi_prepend(struct sip_msg *msg, const str *ouri,
+ const struct sip_uri *iuri, int branch)
+{
+ char s[512];
+ str h = {s, 0};
+
+ h.len = hi_mk(s, sizeof(s), ouri, iuri, branch);
+ if (h.len < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_append: hi_mk() failed\n");
+ return -1;
+ }
+
+ if (prepend_hf(msg, &str_histinfo, &h) < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_prepend: append_hf() failed\n");
+ return -1;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Find the outgoing request for the corresponding transaction/branch
+ *
+ * NOTE: request is allocated and must be free'd
+ */
+static struct sip_msg *find_uac_request(const struct cell *t, int branch)
+{
+ const struct retr_buf *rbuf;
+ struct sip_msg *req = NULL;
+
+ rbuf = &t->uac[branch].request;
+
+ req = pkg_malloc(sizeof(*req));
+ if (!req)
+ return NULL;
+
+ memset(req, 0, sizeof(*req));
+ req->buf = rbuf->buffer;
+ req->len = rbuf->buffer_len;
+
+ if (parse_msg(rbuf->buffer, rbuf->buffer_len, req) != 0){
+ LOG(L_ERR, DBG_PRFX "find_request: parse_msg() failed\n");
+ goto err;
+ }
+
+ return req;
+
+ err:
+ if (req) {
+ free_sip_msg(req);
+ pkg_free(req);
+ }
+ return NULL;
+}
+
+
+#if 0
+static void print_uris(const char *prfx, struct sip_msg *msg)
+{
+ const struct sip_uri *iuri;
+ const str *ouri;
+
+ /* Get the outgoing-ruri */
+ ouri = GET_RURI(msg);
+
+ if (parse_orig_ruri(msg) < 0)
+ return;
+
+ /* Get the incoming-ruri */
+ iuri = &msg->parsed_orig_ruri;
+
+ printf(" %s: iuri=<[EMAIL PROTECTED]>\n", prfx,
+ STR_FMT(&iuri->user), STR_FMT(&iuri->host));
+
+ printf(" %s: ouri=<%.*s>\n", prfx, STR_FMT(ouri));
+
+ if (SIP_REQUEST == msg->first_line.type) {
+ printf(" %s: request_uri=<%.*s>\n", prfx,
+ STR_FMT(&msg->first_line.u.request.uri));
+ }
+}
+#endif
+
+
+/*
+ * Module functions
+ */
+
+
+static int mod_init(void)
+{
+ load_tm_f load_tm;
+
+ /* import the TM auto-loading function */
+ load_tm = (load_tm_f)find_export("load_tm", NO_SCRIPT, 0);
+ if (!load_tm) {
+ LOG(L_ERR, DBG_PRFX "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;
+
+ return 0;
+}
+
+
+static void mod_destroy(void)
+{
+}
+
+
+/**
+ * Append History-Info headers with target info to SIP Request
+ *
+ * Both forms are valid:
+ *
+ * History-Info: <sip:incoming-ruri>;target;index=1,
+ * <sip:outgoing-ruri>;target;index=1.1
+ *
+ * History-Info: <sip:incoming-ruri>;target;index=1
+ * History-Info: <sip:outgoing-ruri>;target;index=1.1
+ */
+static int hi_add_trg(struct sip_msg *req, char *p1, char *p2)
+{
+ const str *ouri;
+ const struct sip_uri *iuri;
+ int branch;
+
+ /* Get branch */
+ branch = tmb.t_get_branch();
+ if (branch < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_add_trg: invalid branch %d\n", branch);
+ return -1;
+ }
+
+ /* Get the outgoing-ruri */
+ ouri = GET_RURI(req);
+
+ /* We need to find the original Request URI */
+ if (parse_orig_ruri(req) < 0) {
+ LOG(L_ERR, DBG_PRFX "parse_orig_ruri() failed\n");
+ return -1;
+ }
+
+ /* Get the incoming-ruri */
+ iuri = &req->parsed_orig_ruri;
+
+ LOG(L_INFO, DBG_PRFX "Request: iuri=<[EMAIL PROTECTED]> ouri=<%.*s>\n",
+ STR_FMT(&iuri->user), STR_FMT(&iuri->host), STR_FMT(ouri));
+
+ if (hi_append(req, ouri, iuri, branch) < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_append() failed\n");
+ return -1;
+ }
+
+ /* returns >0 if ok , <0 on error, 0 to stop processing (==DROP) */
+ return 1;
+}
+
+
+/**
+ * Copy History-Info from SIP Request to SIP Response, if not present
+ * in the SIP Response.
+ */
+static int hi_copy_trg(struct sip_msg *resp, char *p1, char *p2)
+{
+ struct cell *t;
+ struct sip_msg *req = NULL;
+ int branch;
+
+ /* Skip if already present in SIP Response */
+ if (hf_exist(resp, &str_histinfo))
+ return 1;
+
+ /* Get transaction */
+ t = tmb.t_gett();
+ if (!t)
+ goto out;
+
+ /* Get branch */
+ branch = tmb.t_get_branch();
+ if (branch < 0) {
+ LOG(L_ERR, DBG_PRFX "hi_copy_trg: invalid branch %d\n",
+ branch);
+ goto out;
+ }
+
+ LOG(L_INFO, DBG_PRFX "Response: %u branch %d\n",
+ resp->first_line.u.reply.statuscode, branch);
+
+ req = find_uac_request(t, branch);
+ if (!req)
+ goto out;
+
+ cpy_hfs(resp, req, &str_histinfo);
+
+ out:
+ if (req) {
+ free_sip_msg(req);
+ pkg_free(req);
+ }
+
+ return 1;
+}
+
+
+/**
+ * Add History-Info header to a final SIP Response
+ */
+static int hi_add_reply(struct sip_msg *resp, char *p1, char *p2)
+{
+ struct cell *t;
+ struct sip_msg *req_uac = NULL, *req_uas = NULL;
+ const struct sip_uri *iuri;
+ const str *ouri;
+ int branch;
+
+ /* Get transaction */
+ t = tmb.t_gett();
+ if (!t) {
+ LOG(L_ERR, DBG_PRFX "add_reply: could not get transaction\n");
+ goto out;
+ }
+
+ /* Get branch */
+ branch = tmb.t_get_branch();
+ if (branch < 0) {
+ LOG(L_ERR, DBG_PRFX "add_reply: invalid branch %d\n", branch);
+ goto out;
+ }
+
+ /* Get the incoming-ruri from the UAS Request */
+ req_uas = t->uas.request;
+ if (parse_orig_ruri(req_uas) < 0) {
+ LOG(L_ERR, DBG_PRFX "add_reply: parse_orig_ruri() failed\n");
+ goto out;
+ }
+ iuri = &req_uas->parsed_orig_ruri;
+
+ /* Find corresponding outgoing UAC request */
+ req_uac = find_uac_request(t, branch);
+ if (!req_uac) {
+ LOG(L_ERR, DBG_PRFX "add_reply: could not find uac request\n");
+ }
+ ouri = GET_RURI(req_uac);
+
+ /* Prepend History-Info header to 200 OK response */
+
+ LOG(L_INFO, DBG_PRFX "add_reply: branch %d: iuri=<[EMAIL PROTECTED]>"
+ " ouri=<%.*s>\n", branch, STR_FMT(&iuri->user),
+ STR_FMT(&iuri->host), STR_FMT(ouri));
+
+ if (hi_prepend(resp, ouri, iuri, branch) < 0) {
+ LOG(L_ERR, DBG_PRFX "add_reply: hi_append() failed\n");
+ goto out;
+ }
+
+ out:
+ if (req_uac) {
+ free_sip_msg(req_uac);
+ pkg_free(req_uac);
+ }
+
+ /* returns >0 if ok , <0 on error, 0 to stop processing (==DROP) */
+ return 1;
+}
+
+
+static cmd_export_t cmds[] = {
+ {"histinfo_add_target", hi_add_trg, 0, 0, REQUEST_ROUTE},
+ {"histinfo_copy", hi_copy_trg, 0, 0, ONREPLY_ROUTE},
+ {"histinfo_add_reply", hi_add_reply, 0, 0, ONREPLY_ROUTE},
+ {}
+};
+
+struct module_exports exports = {
+ "histinfo",
+ cmds,
+ NULL,
+ NULL,
+ mod_init,
+ 0,
+ mod_destroy,
+ 0,
+ 0
+};
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/histinfo/Makefile
sip_router/modules/histinfo/Makefile
--- sip_router-orig/modules/histinfo/Makefile 1970-01-01 01:00:00.000000000
+0100
+++ sip_router/modules/histinfo/Makefile 2008-12-08 13:35:17.000000000
+0100
@@ -0,0 +1,7 @@
+include ../../Makefile.defs
+
+auto_gen=
+NAME=histinfo.so
+LIBS=
+
+include ../../Makefile.modules
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/histinfo/README
sip_router/modules/histinfo/README
--- sip_router-orig/modules/histinfo/README 1970-01-01 01:00:00.000000000
+0100
+++ sip_router/modules/histinfo/README 2008-12-08 13:56:26.000000000 +0100
@@ -0,0 +1,63 @@
+histinfo module
+---------------
+
+ *** NOTE NOTE NOTE! This module is in development ***
+
+
+This module implements an extension of History-Info as defined in RFC 4244.
+It also implements an extension called `target' which is currently
+loosely defined here:
+
+ draft-rosenberg-sip-target-uri-delivery-00
+
+
+The module can be used to add information in the signalling path about
+which final target, in call scenarios like call forwarding and other
+retargetting services.
+
+
+The format of the History-Info header is as follows:
+
+ History-Info: <sip:incoming-ruri>;target;index=1,
+ <sip:outgoing-ruri>;target;index=1.1
+
+If the function histinfo_add_reply() is invoked from the onreply_route[]
+it will prepend this header to the response. The incoming-uri means the
+original request-uri coming in to the proxy, and the outgoing-uri means
+the outgoing request-uri after the messages has been proxied.
+
+
+------------------------------------------------------------------------------
+Example ser.cfg:
+
+
+route {
+
+ # Call forwarding from B -> C
+ if (uri =~ "sip:b") {
+
+ # Must be called to set onreply_route
+ t_on_reply("1");
+
+ # Set RETARGET flag
+ setflag(7);
+
+ rewriteuri("sip:[EMAIL PROTECTED]");
+
+ route(1);
+ break;
+ }
+}
+
+
+onreply_route[1]
+{
+ if (status =~ "2[0-9][0-9]") {
+
+ # Prepend History-Info header to response
+ if (isflagset(7)) {
+ histinfo_add_reply();
+ }
+ }
+}
+------------------------------------------------------------------------------
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/histinfo/ser.cfg
sip_router/modules/histinfo/ser.cfg
--- sip_router-orig/modules/histinfo/ser.cfg 1970-01-01 01:00:00.000000000
+0100
+++ sip_router/modules/histinfo/ser.cfg 2008-12-08 13:35:17.000000000 +0100
@@ -0,0 +1,218 @@
+#
+# $Id: ser.cfg,v 1.1.1.1 2005/09/08 08:25:03 janakj Exp $
+#
+# simple quick-start config script
+#
+
+# ----------- global configuration parameters ------------------------
+
+listen=127.0.0.1
+#debug=3 # debug level (cmd line: -dddddddddd)
+#fork=yes
+#log_stderror=no # (cmd line: -E)
+
+/* Uncomment these lines to enter debugging mode
+fork=no
+log_stderror=yes
+*/
+
+check_via=no # (cmd. line: -v)
+dns=no # (cmd. line: -r)
+rev_dns=no # (cmd. line: -R)
+#port=5060
+#children=4
+fifo="/tmp/ser_fifo"
+
+# ------------------ module loading ----------------------------------
+
+# Uncomment this if you want to use SQL database
+#loadmodule "/usr/local/lib/ser/modules/mysql.so"
+
+loadmodule "/usr/lib/ser/modules/sl.so"
+loadmodule "/usr/lib/ser/modules/tm.so"
+loadmodule "/usr/lib/ser/modules/rr.so"
+loadmodule "/usr/lib/ser/modules/maxfwd.so"
+loadmodule "/usr/lib/ser/modules/usrloc.so"
+loadmodule "/usr/lib/ser/modules/registrar.so"
+loadmodule "/usr/lib/ser/modules/textops.so"
+loadmodule "/usr/lib/ser/modules/xlog.so"
+loadmodule "/usr/lib/ser/modules/histinfo.so"
+
+# Uncomment this if you want digest authentication
+# mysql.so must be loaded !
+#loadmodule "/usr/local/lib/ser/modules/auth.so"
+#loadmodule "/usr/local/lib/ser/modules/auth_db.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- usrloc params --
+
+modparam("usrloc", "db_mode", 0)
+
+# Uncomment this if you want to use SQL database
+# for persistent storage and comment the previous line
+#modparam("usrloc", "db_mode", 2)
+
+# -- auth params --
+# Uncomment if you are using auth module
+#
+#modparam("auth_db", "calculate_ha1", yes)
+#
+# If you set "calculate_ha1" parameter to yes (which true in this config),
+# uncomment also the following parameter)
+#
+#modparam("auth_db", "password_column", "password")
+
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+
+# ------------------------- request routing logic -------------------
+
+# main routing logic
+
+route{
+
+ # initial sanity checks -- messages with
+ # max_forwards==0, or excessively long requests
+ if (!mf_process_maxfwd_header("10")) {
+ sl_send_reply("483","Too Many Hops");
+ break;
+ };
+ if (msg:len >= 2048 ) {
+ sl_send_reply("513", "Message too big");
+ break;
+ };
+
+ #
+ # XXX: This section is only for testing of histinfo module
+ #
+ if (method == "INVITE") {
+
+ # Must be called to set onreply_route
+ t_on_reply("1");
+
+ #
+ # Fork X to E and F
+ #
+ if (uri =~ "sip:x") {
+ xlog("L_NOTICE", "redirect X -> E and F\n");
+
+ # Set RETARGET flag
+ setflag(7);
+
+ rewriteuri("sip:[EMAIL PROTECTED]");
+ append_branch();
+
+ rewriteuri("sip:[EMAIL PROTECTED]");
+ append_branch();
+
+ route(1);
+ break;
+ }
+
+ #
+ # Test one level of retargetting
+ #
+ if (uri =~ "sip:c") {
+ xlog("L_NOTICE", "redirect C -> B\n");
+
+ # Set RETARGET flag
+ setflag(7);
+
+ rewriteuri("sip:[EMAIL PROTECTED]");
+
+ route(1);
+ break;
+ }
+
+ #
+ # Test two levels of nested retargetting (D -> C -> B)
+ #
+ if (uri =~ "sip:d") {
+ xlog("L_NOTICE", "redirect D -> C\n");
+
+ # Set RETARGET flag
+ setflag(7);
+
+ rewriteuri("sip:[EMAIL PROTECTED]");
+
+ route(1);
+ break;
+ }
+ }
+
+ # we record-route all messages -- to make sure that
+ # subsequent messages will go through our proxy; that's
+ # particularly good if upstream and downstream entities
+ # use different transport protocol
+ if (!method=="REGISTER") record_route();
+
+ # subsequent messages withing a dialog should take the
+ # path determined by record-routing
+ if (loose_route()) {
+ # mark routing logic in request
+ append_hf("P-hint: rr-enforced\r\n");
+ route(1);
+ break;
+ };
+
+ if (!uri==myself) {
+ # mark routing logic in request
+ append_hf("P-hint: outbound\r\n");
+ route(1);
+ break;
+ };
+
+ # if the request is for other domain use UsrLoc
+ # (in case, it does not work, use the following command
+ # with proper names and addresses in it)
+ if (uri==myself) {
+
+ if (method=="REGISTER") {
+
+# Uncomment this if you want to use digest authentication
+# if (!www_authorize("iptel.org", "subscriber")) {
+# www_challenge("iptel.org", "0");
+# break;
+# };
+
+ save("location");
+ break;
+ };
+
+ lookup("aliases");
+ if (!uri==myself) {
+ append_hf("P-hint: outbound alias\r\n");
+ route(1);
+ break;
+ };
+
+ # native SIP destinations are handled using our USRLOC DB
+ if (!lookup("location")) {
+ sl_send_reply("404", "Not Found");
+ break;
+ };
+ };
+ append_hf("P-hint: usrloc applied\r\n");
+ route(1);
+}
+
+route[1]
+{
+ # send it out now; use stateful forwarding as it works reliably
+ # even for UDP2TCP
+ if (!t_relay()) {
+ sl_reply_error();
+ };
+}
+
+onreply_route[1]
+{
+ if (status =~ "2[0-9][0-9]") {
+
+ if (isflagset(7)) {
+ histinfo_add_reply();
+ }
+ }
+}
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/tm/t_lookup.c
sip_router/modules/tm/t_lookup.c
--- sip_router-orig/modules/tm/t_lookup.c 2008-03-31 18:26:08.000000000
+0200
+++ sip_router/modules/tm/t_lookup.c 2008-12-08 13:35:17.000000000 +0100
@@ -173,7 +173,10 @@
*/
unsigned int global_msg_id;
-
+/* For reply processing, we may need the branch as well and thus store
+ * it in a global variable, too.
+ */
+static int global_branch;
struct cell *get_t() { return T; }
void set_t(struct cell *t) { T=t; }
@@ -1026,7 +1029,6 @@
*/
int t_check( struct sip_msg* p_msg , int *param_branch )
{
- int local_branch;
int canceled;
/* is T still up-to-date ? */
@@ -1089,8 +1091,7 @@
}
}
- t_reply_matching( p_msg ,
- param_branch!=0?param_branch:&local_branch );
+ t_reply_matching (p_msg, &global_branch);
}
#ifdef EXTRA_DEBUG
@@ -1109,7 +1110,18 @@
DBG("DEBUG: t_check: T previously sought and not
found\n");
}
- return T ? (T==T_UNDEFINED ? -1 : 1 ) : 0;
+ if (T == NULL) {
+ return 0;
+ }
+ else if (T == T_UNDEFINED) {
+ return -1;
+ }
+ else {
+ if (param_branch != NULL) {
+ *param_branch = global_branch;
+ }
+ return 1;
+ }
}
int init_rb( struct retr_buf *rb, struct sip_msg *msg)
@@ -1262,6 +1274,7 @@
#endif
insert_into_hash_table_unsafe( new_cell, p_msg->hash_index );
set_t(new_cell);
+ global_branch = -1;
#ifndef TM_DEL_UNREF
INIT_REF_UNSAFE(T);
#endif
@@ -1789,3 +1802,8 @@
return 1;
}
+
+int t_get_branch(void)
+{
+ return global_branch;
+}
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/tm/t_lookup.h
sip_router/modules/tm/t_lookup.h
--- sip_router-orig/modules/tm/t_lookup.h 2008-03-31 20:19:50.000000000
+0200
+++ sip_router/modules/tm/t_lookup.h 2008-12-08 13:35:17.000000000 +0100
@@ -118,4 +118,7 @@
unsigned int *hash_index, unsigned int *label);
#endif /* WITH_AS_SUPPORT */
+typedef int (*t_get_branch_f)(void);
+int t_get_branch(void);
+
#endif
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X
/home/alfredh/svn/.priv/exclude sip_router-orig/modules/tm/tm.c
sip_router/modules/tm/tm.c
--- sip_router-orig/modules/tm/tm.c 2008-11-10 13:47:02.000000000 +0100
+++ sip_router/modules/tm/tm.c 2008-12-08 13:35:17.000000000 +0100
@@ -402,6 +402,7 @@
#endif
{"t_suspend", (cmd_function)t_suspend, NO_SCRIPT, 0,
0},
{"t_continue", (cmd_function)t_continue, NO_SCRIPT, 0,
0},
+ {"t_get_branch", (cmd_function)t_get_branch, NO_SCRIPT, 0,
0},
{0,0,0,0,0}
};
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/tm/tm_load.c
sip_router/modules/tm/tm_load.c
--- sip_router-orig/modules/tm/tm_load.c 2008-11-10 13:47:02.000000000
+0100
+++ sip_router/modules/tm/tm_load.c 2008-12-08 13:35:17.000000000 +0100
@@ -226,5 +226,10 @@
LOG( L_ERR, LOAD_ERROR "'t_continue' not found\n");
return -1;
}
+ if (! (tmb->t_get_branch=(t_get_branch_f)find_export("t_get_branch",
+ NO_SCRIPT,0))) {
+ LOG( L_ERR, LOAD_ERROR "'t_get_branch' not found\n");
+ return -1;
+ }
return 1;
}
diff -Naur --exclude ip_set_rpc.c --exclude lex.yy.c --exclude ser-oob.cfg -X /home/alfredh/svn/.priv/exclude sip_router-orig/modules/tm/tm_load.h
sip_router/modules/tm/tm_load.h
--- sip_router-orig/modules/tm/tm_load.h 2008-11-10 13:47:02.000000000
+0100
+++ sip_router/modules/tm/tm_load.h 2008-12-08 13:35:17.000000000 +0100
@@ -132,6 +132,7 @@
#endif
t_suspend_f t_suspend;
t_continue_f t_continue;
+ t_get_branch_f t_get_branch;
};
extern int tm_init;
_______________________________________________
Serdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/serdev