Module: sip-router Branch: pd/outbound Commit: 4bbd8718667d5fed76b7b97b3e915647cf80e611 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=4bbd8718...
Author: Peter Dunkley peter.dunkley@crocodile-rcs.com Committer: Peter Dunkley peter.dunkley@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");