Module: sip-router
Branch: pd/outbound
Commit: 4bbd8718667d5fed76b7b97b3e915647cf80e611
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=4bbd871…
Author: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Date: Sun Dec 30 19:27:24 2012 +0000
modules_k/rr: added decoding and using of flow token to loose_route()
---
modules_k/rr/loose.c | 179 ++++++++++++++++++++++++++++++++++----------------
1 files changed, 122 insertions(+), 57 deletions(-)
diff --git a/modules_k/rr/loose.c b/modules_k/rr/loose.c
index f5d869f..5699607 100644
--- a/modules_k/rr/loose.c
+++ b/modules_k/rr/loose.c
@@ -486,6 +486,53 @@ static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_
}
}
+/* Largest route URI is of the form:
+ sip:[1234:5678:9012:3456:7890:1234:5678:9012]:12345;transport=sctp
+ this is 66 characters long */
+#define MAX_ROUTE_URI_LEN 66
+static char uri_buf[MAX_ROUTE_URI_LEN];
+
+static inline int process_outbound(struct sip_msg *_m, str flow_token,
+ str *dst_uri)
+{
+ struct receive_info rcv;
+ struct socket_info *si;
+
+ if (!rr_obb.decode_flow_token)
+ return 0;
+
+ if (rr_obb.decode_flow_token(&rcv, flow_token) == 0) {
+
+ /* First, force the local socket */
+ si = find_si(&rcv.dst_ip, rcv.dst_port, rcv.proto);
+ if (si)
+ set_force_socket(_m, si);
+ else {
+ LM_ERR("cannot find socket from flow token\n");
+ return -1;
+ }
+
+ /* Second, override the destination URI */
+ dst_uri->s = uri_buf;
+ dst_uri->len = 0;
+
+ dst_uri->len += snprintf(dst_uri->s + dst_uri->len,
+ MAX_ROUTE_URI_LEN - dst_uri->len,
+ "sip:%s",
+ rcv.src_ip.af == AF_INET6 ? "[" : "");
+ dst_uri->len += ip_addr2sbuf(&rcv.src_ip,
+ dst_uri->s + dst_uri->len,
+ MAX_ROUTE_URI_LEN - dst_uri->len);
+ dst_uri->len += snprintf(dst_uri->s + dst_uri->len,
+ MAX_ROUTE_URI_LEN - dst_uri->len,
+ "%s:%d;transport=%s",
+ rcv.src_ip.af == AF_INET6 ? "]" : "",
+ rcv.src_port,
+ get_proto_name(rcv.proto));
+ }
+
+ return 1;
+}
/*!
* \brief Previous hop was a strict router, handle this case
@@ -501,6 +548,7 @@ static inline int after_strict(struct sip_msg* _m)
char* rem_off;
str uri;
struct socket_info *si;
+ int use_ob, next_is_strict;
hdr = _m->route;
rt = (rr_t*)hdr->parsed;
@@ -516,7 +564,11 @@ static inline int after_strict(struct sip_msg* _m)
return RR_ERROR;
}
- if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
+ next_is_strict = is_strict(&puri.params);
+ if ((use_ob = process_outbound(_m, puri.user, &uri) < 0))
+ return RR_ERROR;
+
+ if (!use_ob && enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
/* double route may occure due different IP and port, so force as
* send interface the one advertise in second Route */
si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
@@ -553,7 +605,8 @@ static inline int after_strict(struct sip_msg* _m)
LM_ERR("failed to parse URI\n");
return RR_ERROR;
}
- }
+ next_is_strict = is_strict(&puri.params);
+ }
/* set the hooks for the param
* important note: RURI is already parsed by the above function, so
@@ -561,7 +614,7 @@ static inline int after_strict(struct sip_msg* _m)
routed_msg_id = _m->id;
routed_params = _m->parsed_uri.params;
- if (is_strict(&puri.params)) {
+ if (next_is_strict) {
LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
/* Previous hop was a strict router and the next hop is strict
* router too. There is no need to save R-URI again because it
@@ -572,9 +625,11 @@ static inline int after_strict(struct sip_msg* _m)
* always be a strict router because endpoints don't use ;lr parameter
* In this case we will simply put the URI in R-URI and forward it,
* which will work perfectly */
- if(get_maddr_uri(&uri, &puri)!=0) {
- LM_ERR("failed to check maddr\n");
- return RR_ERROR;
+ if (!use_ob) {
+ if(get_maddr_uri(&uri, &puri)!=0) {
+ LM_ERR("failed to check maddr\n");
+ return RR_ERROR;
+ }
}
if (rewrite_uri(_m, &uri) < 0) {
LM_ERR("failed to rewrite request URI\n");
@@ -596,9 +651,11 @@ static inline int after_strict(struct sip_msg* _m)
LM_DBG("Next hop: '%.*s' is loose router\n",
uri.len, ZSW(uri.s));
- if(get_maddr_uri(&uri, &puri)!=0) {
- LM_ERR("failed to check maddr\n");
- return RR_ERROR;
+ if (!use_ob) {
+ if(get_maddr_uri(&uri, &puri)!=0) {
+ LM_ERR("failed to check maddr\n");
+ return RR_ERROR;
+ }
}
if (set_dst_uri(_m, &uri) < 0) {
LM_ERR("failed to set dst_uri\n");
@@ -680,9 +737,9 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
rr_t* rt;
int res;
int status;
- int ret;
str uri;
struct socket_info *si;
+ int uri_is_myself, use_ob, next_is_strict;
hdr = _m->route;
rt = (rr_t*)hdr->parsed;
@@ -690,23 +747,25 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
/* reset rr handling static vars for safety in error case */
routed_msg_id = 0;
- routed_params.s = NULL;
- routed_params.len = 0;
if (parse_uri(uri.s, uri.len, &puri) < 0) {
LM_ERR("failed to parse the first route URI\n");
return RR_ERROR;
}
+ next_is_strict = is_strict(&puri.params);
+ routed_params = puri.params;
+ uri_is_myself = is_myself(&puri);
+ if ((use_ob = process_outbound(_m, puri.user, &uri) < 0))
+ return RR_ERROR;
+
/* IF the URI was added by me, remove it */
- ret=is_myself(&puri);
- if (ret>0)
+ if (uri_is_myself>0)
{
LM_DBG("Topmost route URI: '%.*s' is me\n",
uri.len, ZSW(uri.s));
/* set the hooks for the params */
routed_msg_id = _m->id;
- routed_params = puri.params;
if (!rt->next) {
/* No next route in the same header, remove the whole header
@@ -728,59 +787,63 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
}
rt = (rr_t*)hdr->parsed;
} else rt = rt->next;
-
- if (enable_double_rr && is_2rr(&puri.params)) {
- /* double route may occure due different IP and port, so force as
- * send interface the one advertise in second Route */
- if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
- LM_ERR("failed to parse the double route URI\n");
- return RR_ERROR;
- }
- si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
- if (si) {
- set_force_socket(_m, si);
- } else {
- if (enable_socket_mismatch_warning)
- LM_WARN("no socket found for match second RR\n");
- }
- if (!rt->next) {
- /* No next route in the same header, remove the whole header
- * field immediately */
- if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
- LM_ERR("failed to remove Route HF\n");
- return RR_ERROR;
- }
- res = find_next_route(_m, &hdr);
- if (res < 0) {
- LM_ERR("failed to find next route\n");
+ if (!use_ob) {
+ if (enable_double_rr && is_2rr(&puri.params)) {
+ /* double route may occure due different IP and port, so force as
+ * send interface the one advertise in second Route */
+ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
+ LM_ERR("failed to parse the double route URI\n");
return RR_ERROR;
}
- if (res > 0) { /* No next route found */
- LM_DBG("no next URI found\n");
- status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
- goto done;
+ si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
+ if (si) {
+ set_force_socket(_m, si);
+ } else {
+ if (enable_socket_mismatch_warning)
+ LM_WARN("no socket found for match second RR\n");
}
- rt = (rr_t*)hdr->parsed;
- } else rt = rt->next;
- }
-
- uri = rt->nameaddr.uri;
- if (parse_uri(uri.s, uri.len, &puri) < 0) {
- LM_ERR("failed to parse the first route URI\n");
- return RR_ERROR;
+
+ if (!rt->next) {
+ /* No next route in the same header, remove the whole header
+ * field immediately */
+ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
+ LM_ERR("failed to remove Route HF\n");
+ return RR_ERROR;
+ }
+ res = find_next_route(_m, &hdr);
+ if (res < 0) {
+ LM_ERR("failed to find next route\n");
+ return RR_ERROR;
+ }
+ if (res > 0) { /* No next route found */
+ LM_DBG("no next URI found\n");
+ status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
+ goto done;
+ }
+ rt = (rr_t*)hdr->parsed;
+ } else rt = rt->next;
+ }
+
+ uri = rt->nameaddr.uri;
+ if (parse_uri(uri.s, uri.len, &puri) < 0) {
+ LM_ERR("failed to parse the first route URI\n");
+ return RR_ERROR;
+ }
}
} else {
#ifdef ENABLE_USER_CHECK
/* check if it the ignored user */
- if(ret < 0)
+ if(uri_is_myself < 0)
return NOT_RR_DRIVEN;
#endif
LM_DBG("Topmost URI is NOT myself\n");
+ routed_params.s = NULL;
+ routed_params.len = 0;
}
LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
- if (is_strict(&puri.params)) {
+ if (next_is_strict) {
LM_DBG("Next URI is a strict router\n");
if (handle_sr(_m, hdr, rt) < 0) {
LM_ERR("failed to handle strict router\n");
@@ -790,9 +853,11 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
/* Next hop is loose router */
LM_DBG("Next URI is a loose router\n");
- if(get_maddr_uri(&uri, &puri)!=0) {
- LM_ERR("checking maddr failed\n");
- return RR_ERROR;
+ if (!use_ob) {
+ if(get_maddr_uri(&uri, &puri)!=0) {
+ LM_ERR("checking maddr failed\n");
+ return RR_ERROR;
+ }
}
if (set_dst_uri(_m, &uri) < 0) {
LM_ERR("failed to set dst_uri\n");