i now have alias_contact()/handle_alias() ready for testing. a new modules_k/nathelper/nathelper.c for sr_3.0 that includes those functions is available for limited time as:
http://box.tutpro.com/tmp/nathelper.c
/* * Adds ;alias=ip:port param to cotact uri containing received ip:port * if contact uri ip:port does not match received ip:port. */ static int alias_contact_f(struct sip_msg* msg, char* str1, char* str2)
/* * Checks if r-uri has alias param and if so, removes it and sets $du * based on its value. */ static int handle_alias_f(struct sip_msg* msg, char* str1, char* str2)
usage instructions:
- call alias_contact() for all other incoming requests except register and for all incoming replies, for example:
route [OTHER_REQUESTS] { # handle other than REGISTER requests if (!alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; }; ...
onreply_route [REPLY] { # handle all replies if (!alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad reply"); exit; }; ...
- call handle_alias() for all in-dialog requests before t_relaying them, for example:
route [IN_DIALOG_REQUESTS] { # handle all in-dialog requests ... handle_alias(); switch ($rc) { case -1: xlog("L_ERR", "Failed to handle alias of R-URI <$ru>\n"); send_reply("400", "Bad request"); exit; case 1: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$du>\n"); break; case 2: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$ru>\n"); break; } if (!t_relay()) { ...
- do NOT call fix_nated_contact() on anything.
- call fix_nated_register() on register requests, if registering ua is behind nat OR is using tcp, for example:
if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location");
that is it. my config got much simper than what is was before.
i'm on the road and have been able to test this only using twinkle and sems. so more testing with different UAs is very welcome.
i consider these two functions a bug fix and would like to include them into sr3.0. but fix, because using current means, some in-dialog requests will have wrong contact uri, i.e., not the one the ua advertised.
-- juha
El Lunes, 9 de Noviembre de 2009, Juha Heinanen escribió:
that is it. my config got much simper than what is was before.
i'm on the road and have been able to test this only using twinkle and sems. so more testing with different UAs is very welcome.
i consider these two functions a bug fix and would like to include them into sr3.0. but fix, because using current means, some in-dialog requests will have wrong contact uri, i.e., not the one the ua advertised.
Really great, it looks very simple, correct and doesn't break original Contact URI.
Thanks a lot.
Iñaki Baz Castillo writes:
Really great, it looks very simple, correct and doesn't break original Contact URI.
inaki,
i went to walk and it occurred to me that alias_contact() should not be called if request comes from another proxy, because it is that proxy's job to do whatever it needs to to. so the condition on calling alias_contact() on initial requests is:
route [OTHER_REQUESTS] { # handle other initial requests than REGISTER
if (!is_present_hf("Record-Route") && !alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; };
same thing if reply to initial request comes from another proxy. the test could then be if the topmost rr header has been added by this proxy, but i haven't had time yet to think how to implement the test.
and the same for in-dialog requests.
perhaps you have ideas here.
-- juha
El Lunes, 9 de Noviembre de 2009, Juha Heinanen escribió:
Iñaki Baz Castillo writes:
Really great, it looks very simple, correct and doesn't break original Contact URI.
inaki,
i went to walk and it occurred to me that alias_contact() should not be called if request comes from another proxy, because it is that proxy's job to do whatever it needs to to. so the condition on calling alias_contact() on initial requests is:
route [OTHER_REQUESTS] { # handle other initial requests than REGISTER
if (!is_present_hf("Record-Route") && !alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; };
same thing if reply to initial request comes from another proxy. the test could then be if the topmost rr header has been added by this proxy, but i haven't had time yet to think how to implement the test.
and the same for in-dialog requests.
There is a problem here as Record-Route are not needed for in-dialog request (the proxy can add it but the UAS should ignore it as RR just makes sense in the initial request and response forming the dialog).
So if proxy A doesn't append RR for an in-dialog request (and it shouldn't do it as per RFC 3261) then your "if" statement would fail (proxy B would apply alias_contact).
perhaps you have ideas here.
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
1) The IP in Contact is private. 2) There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
I think it should fix the issue, opinions?
Iñaki Baz Castillo writes:
There is a problem here as Record-Route are not needed for in-dialog request (the proxy can add it but the UAS should ignore it as RR just makes sense in the initial request and response forming the dialog).
yes, i meant that the rr test would only be used on initial request.
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
- The IP in Contact is private.
- There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
i can add test (2) to alias_contact() function itself. but (1) is not enough, since alias_contact() definitely needs to be called also when request arrives over tcp.
-- juha
El Lunes, 9 de Noviembre de 2009, Juha Heinanen escribió:
Iñaki Baz Castillo writes:
There is a problem here as Record-Route are not needed for in-dialog request (the proxy can add it but the UAS should ignore it as RR just makes sense in the initial request and response forming the dialog).
yes, i meant that the rr test would only be used on initial request.
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
- The IP in Contact is private.
- There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
i can add test (2) to alias_contact() function itself. but (1) is not enough, since alias_contact() definitely needs to be called also when request arrives over tcp.
If proxy B receives a TCP request from proxy A, why should proxy B call alias_contact()?
Note that in-dialog request from proxy B to proxy A would be sent using route set mechanism.
Iñaki Baz Castillo writes:
If proxy B receives a TCP request from proxy A, why should proxy B call alias_contact()?
no, you got me wrong. alias_contact() is never called when request comes from another proxy, but should always be called when request comes over tcp from an ua.
-- juha
Iñaki Baz Castillo schrieb:
El Lunes, 9 de Noviembre de 2009, Juha Heinanen escribió:
Iñaki Baz Castillo writes:
There is a problem here as Record-Route are not needed for in-dialog request (the proxy can add it but the UAS should ignore it as RR just makes sense in the initial request and response forming the dialog).
yes, i meant that the rr test would only be used on initial request.
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
- The IP in Contact is private.
- There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
i can add test (2) to alias_contact() function itself. but (1) is not enough, since alias_contact() definitely needs to be called also when request arrives over tcp.
If proxy B receives a TCP request from proxy A, why should proxy B call alias_contact()?
True. We do not have keep-alive mechanisms between proxies, thus it might happen that the TCP connection will be closed and the port in the alias is not useable anymore.
That's also a reason why IMO there should it should be possible to use the alias function without auto-magic, and implement the usage rules in the script. And once we have found the proper usage rules, implement them and activate them using a certain flag/parameter.
regards klaus
Note that in-dialog request from proxy B to proxy A would be sent using route set mechanism.
Iñaki Baz Castillo writes:
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
- The IP in Contact is private.
- There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
inaki,
the rule is: do not call alias_contact(), when request or reply comes from a proxy. so even if there is no ;alias in contact, alias_contact() must not be called when request or reply comes from a proxy.
the question is, is it possible to somehow detect it. for initial requests, proxy can be detected based on existence of an rr header.
regarding in-dialog requests, perhaps that could be detected if proxy adds into rr header an param telling that request came from a proxy. it might then be possible to test that param in in-dialog requests.
lets think it more.
-- juha
Juha Heinanen schrieb:
Iñaki Baz Castillo writes:
What about calling alias_contact() just in case nat_test() detects the following two requeriments:
- The IP in Contact is private.
- There is no ";alias" param in Contact URI.
Of course a new nat_test flag would be needed for point 2.
inaki,
the rule is: do not call alias_contact(), when request or reply comes from a proxy. so even if there is no ;alias in contact, alias_contact() must not be called when request or reply comes from a proxy.
It is not possible to detect if a reply comes from a proxy or not. You could add the alias anyway and handle the problem in "handle_alias": If alias parameter is removed from RURI (in-dialog request), set $du only if it was not already set by loose_route().
Further, alias_contact() must also be called on in-dialog requests/responses.
I think the functions are great to have, but would like different naming (either have "alias" always at the beginning or at the end of the function name).
e.g: add_alias(), handle_alias()
regards klaus
the question is, is it possible to somehow detect it. for initial requests, proxy can be detected based on existence of an rr header.
regarding in-dialog requests, perhaps that could be detected if proxy adds into rr header an param telling that request came from a proxy. it might then be possible to test that param in in-dialog requests.
lets think it more.
-- juha
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Klaus Darilion writes:
It is not possible to detect if a reply comes from a proxy or not.
klaus,
yes, but the two via test tells that ua is not taking directly to this sr instance and i thus don't need to care about it.
could add the alias anyway and handle the problem in "handle_alias": If alias parameter is removed from RURI (in-dialog request), set $du only if it was not already set by loose_route().
i first thought to add the $du test, but looks like the via test makes it unnecessary. however, loose_route() may be key to solving the reply problem: if loose_route() sets $du, it means that next hop is another proxy. then it is possible to set TO_PROXY flag and test it onreply_route. right?
I think the functions are great to have, but would like different naming (either have "alias" always at the beginning or at the end of the function name).
e.g: add_alias(), handle_alias()
i can change the names. thanks for helping out on this.
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
It is not possible to detect if a reply comes from a proxy or not.
klaus,
yes, but the two via test tells that ua is not taking directly to this sr instance and i thus don't need to care about it.
I think the "reply" problem needs to be solved using the registrar NAT bflag. If NAT flag is set for callee, activate a reply-route with add_alias() (can be done per branch).
klaus
could add the alias anyway and handle the problem in "handle_alias": If alias parameter is removed from RURI (in-dialog request), set $du only if it was not already set by loose_route().
i first thought to add the $du test, but looks like the via test makes it unnecessary. however, loose_route() may be key to solving the reply problem: if loose_route() sets $du, it means that next hop is another proxy. then it is possible to set TO_PROXY flag and test it onreply_route. right?
I think the functions are great to have, but would like different naming (either have "alias" always at the beginning or at the end of the function name).
e.g: add_alias(), handle_alias()
i can change the names. thanks for helping out on this.
-- juha
Klaus Darilion writes:
I think the "reply" problem needs to be solved using the registrar NAT bflag. If NAT flag is set for callee, activate a reply-route with add_alias() (can be done per branch).
that is not correct, because add_alias() needs to be called even when reply comes from a tcp ua that is not behind nat.
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
I think the "reply" problem needs to be solved using the registrar NAT bflag. If NAT flag is set for callee, activate a reply-route with add_alias() (can be done per branch).
that is not correct, because add_alias() needs to be called even when reply comes from a tcp ua that is not behind nat.
ok. depends in your NAT-traversal approach. In my pragmatic approach I do NAT traversal anyway for all local users, thus it would work for me.
If you have a more advanced NAT traversal approach, probably you need a second bflag which will is activated either by NAT or TCP.
regards klaus
Klaus Darilion writes:
ok. depends in your NAT-traversal approach. In my pragmatic approach I do NAT traversal anyway for all local users, thus it would work for me.
If you have a more advanced NAT traversal approach, probably you need a second bflag which will is activated either by NAT or TCP.
klaus,
i don't use mediaproxy if is not needed. the example implementation already takes care of what you suggest:
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location");
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
ok. depends in your NAT-traversal approach. In my pragmatic approach I do NAT traversal anyway for all local users, thus it would work for me.
If you have a more advanced NAT traversal approach, probably you need a second bflag which will is activated either by NAT or TCP.
klaus,
i don't use mediaproxy if is not needed. the example implementation already takes care of what you suggest:
but shouldn't that be extended to detect of contact of response needs to be converted?
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); };
if (proto == TCP) { setbflag("TO_TCP"); };
}; save("location");
and after lookup() in branch route:
if (isbflagset(TO_TCP) || isbflagset(TO_NATED)) { t_on_reply(REWRITE_RESPONSE_CONTACT); };
regards klaus
Klaus Darilion writes:
but shouldn't that be extended to detect of contact of response needs to be converted?
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); };
if (proto == TCP) { setbflag("TO_TCP"); };
}; save("location");
it is already taken care of because alias_contact() is called in onreply_route.
-- juha
and after lookup() in branch route:
if (isbflagset(TO_TCP) || isbflagset(TO_NATED)) { t_on_reply(REWRITE_RESPONSE_CONTACT); };
not needed anymore. as i mentioned, config gets lot simpler with these functions.
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
It is not possible to detect if a reply comes from a proxy or not.
klaus,
yes, but the two via test tells that ua is not taking directly to this sr instance and i thus don't need to care about it.
could add the alias anyway and handle the problem in "handle_alias": If alias parameter is removed from RURI (in-dialog request), set $du only if it was not already set by loose_route().
i first thought to add the $du test, but looks like the via test makes it unnecessary. however, loose_route() may be key to solving the reply problem: if loose_route() sets $du, it means that next hop is another proxy. then it is possible to set TO_PROXY flag and test it onreply_route. right?
yes, but only in in-dialog requests.
In my setups currently I do the NAT decision in first request processing and store the result in a RR-cookie. in-dialog NAT handling is purely done on RR-cookie. RR-cookie defines if NAT handling is done for caller, callee or both.
Regarding NAT-detection my decision algorithm is simple and pragmatic: if request comes from a local account (is_from_local()), then the caller will be marked for NAT traversal (regardless if behind NAT or not. Further, target will be analysed and calls to local users will be NAT-handled.
regards klaus
I think the functions are great to have, but would like different naming (either have "alias" always at the beginning or at the end of the function name).
e.g: add_alias(), handle_alias()
i can change the names. thanks for helping out on this.
-- juha
Klaus Darilion writes:
i first thought to add the $du test, but looks like the via test makes it unnecessary. however, loose_route() may be key to solving the reply problem: if loose_route() sets $du, it means that next hop is another proxy. then it is possible to set TO_PROXY flag and test it onreply_route. right?
yes, but only in in-dialog requests.
that is what i meant.
In my setups currently I do the NAT decision in first request processing and store the result in a RR-cookie. in-dialog NAT handling is purely done on RR-cookie. RR-cookie defines if NAT handling is done for caller, callee or both.
Regarding NAT-detection my decision algorithm is simple and pragmatic: if request comes from a local account (is_from_local()), then the caller will be marked for NAT traversal (regardless if behind NAT or not. Further, target will be analysed and calls to local users will be NAT-handled.
klaus, you keep on mentioning nat. these functions have nothing to do with nat detection.
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
i first thought to add the $du test, but looks like the via test makes it unnecessary. however, loose_route() may be key to solving the reply problem: if loose_route() sets $du, it means that next hop is another proxy. then it is possible to set TO_PROXY flag and test it onreply_route. right?
yes, but only in in-dialog requests.
that is what i meant.
In my setups currently I do the NAT decision in first request processing and store the result in a RR-cookie. in-dialog NAT handling is purely done on RR-cookie. RR-cookie defines if NAT handling is done for caller, callee or both.
Regarding NAT-detection my decision algorithm is simple and pragmatic: if request comes from a local account (is_from_local()), then the caller will be marked for NAT traversal (regardless if behind NAT or not. Further, target will be analysed and calls to local users will be NAT-handled.
klaus, you keep on mentioning nat. these functions have nothing to do with nat detection.
Yes, TCP is another problem. But the solution is more or less the same.
klaus
i think i got it:
- call alias_contact() only if there is only one via header in request
that applies to both initial and in-dialog requests.
if no show stoppers show up, i can add that test into alias_contact() itself.
still need to think about replies.
-- juha
Juha Heinanen schrieb:
i think i got it:
- call alias_contact() only if there is only one via header in request
If this logic is inside, it would be good to have a parameter/flag to turn the "auto-magic" off.
regards klaus
that applies to both initial and in-dialog requests.
if no show stoppers show up, i can add that test into alias_contact() itself.
still need to think about replies.
-- juha
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Juha Heinanen schrieb:
Klaus Darilion writes:
- call alias_contact() only if there is only one via header in request
If this logic is inside, it would be good to have a parameter/flag to turn the "auto-magic" off.
klaus,
do you have in mind a scenario, where you don't want the build-in test?
Not really, just want to be flexible. Of course there might be strange scenarios, e.g. user with sipX (proxy) behind NAT: then the RR header of the proxy has an private IP and in-dialog requests will fail - but using your functions we could use to handle the case
klaus
El Lunes, 9 de Noviembre de 2009, Juha Heinanen escribió:
i think i got it:
- call alias_contact() only if there is only one via header in request
that applies to both initial and in-dialog requests.
if no show stoppers show up, i can add that test into alias_contact() itself.
still need to think about replies.
I think it's a good approach. However please read my question about TCP in other mail.
here is my current example config. it works for both initial and in-dial requests and replies from proxies or UAs with one catch:
if initial request goes to a proxy, the example does not detect it and alias_contact() gets called on reply from the proxy. it might be possible to detect it as follows:
store in an avp the number of rr headers the request has when it is sent out. when reply comes back, count rr headers again. if there is more than what was stored, don't call alias_contact(). by looking at the messages of example
3.2. Session Establishment Through Two Proxies
of rfc3665, i think that this is the only possible way to figure this thing out.
this example does not introduce any changes to the current implementation of the functions and gives klaus the flexibility he wants.
-- juha
--------------------------------------------------------
simple scenario usage instructions:
- call alias_contact() for all non-register initial requests, which don't come from another proxy, for example:
route [NON_REGISTER_INITIAL_REQUESTS] { if (!is_present_hf("Record-Route") && !alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; }; ... t_on_reply("REPLY"); if (!t_relay()) ...
- call fix_nated_register() on register requests, if registering ua is behind nat OR is using tcp, for example:
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location"); ...
- call handle_alias() for all in-dialog requests before t_relaying them, provided that loose_route() didn't set $du, which it does if next hop is another proxy. in the latter case set TO_PROXY fags to be tested in onreply_route. for example:
route [IN_DIALOG_REQUESTS] { loose_route(); ... if ($du == "") { handle_alias(); switch ($rc) { case -1: xlog("L_ERR", "Failed to handle alias of R-URI <$ru>\n"); send_reply("400", "Bad request"); exit; case 1: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$du>\n"); break; case 2: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$ru>\n"); break; }; } else { setflag(TO_PROXY); } t_on_reply("REPLY"); if (!t_relay()) { ...
- call alias_contact() on all replies except the ones that come from another proxy:
onreply_route [REPLY] { if (!isflagset(TO_PROXY) && !alias_contact()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad reply"); exit; }; ...
- do NOT call fix_nated_contact() on anything.
"final" versions of alias functions are now ready for testing in in this sr_3.0 based nathelper.c:
http://box.tutpro.com/tmp/nathelper.c
i changed the names to more descriptive ones: add_contact_alias() and handle_ruri_alias(). also helper function rr_count(pvar) is included that assigns into the pvar the number of rr headers in incoming message (request or reply).
usage example is below. i believe (until otherwise shown) that it works correctly.
if you are interested, please try with different UAs and different transports with or without nat.
-- juha
add_contact_alias()/handle_ruri_alias() usage example -----------------------------------------------------
supports re-use of tcp sessions between proxy and UAs. supports routing of requests to UAs behind NATs so that r-uri is always what UAs expect. proxying of media is not shown, but can be easily added.
NON_REGISTER_INITIAL_REQUESTS -----------------------------
- call alias_contact() for all non-register initial requests, which don't come from another proxy (which takes care of its own UAs).
- if you know that non-register initial request is going to another proxy, set TO_PROXY flag before relaying the request.
- in cases, where initial request may go to another proxy, but you are not sure about it, store the number of record-route headers in incoming request in an AVP that you can then later test in onreply route and find out, if next hop was a proxy.
route [NON_REGISTER_INITIAL_REQUESTS] {
if (!is_present_hf("Record-Route")) { route(ADD_CONTACT_ALIAS); }; ... if (I_KNOW_FOR_SURE_THAT_NEXT_HOP_IS_ANOTHER_PROXY) { setbflag("TO_PROXY"); };
if (NEXT_HOP_MAY_BE_ANOTHER_PROXY_BUT_I_DONT_KNOW_FOR_SURE) { if (!rr_count($avp("rr_count"))) { send_reply("400", "Bad request"); exit; }; }; t_on_reply("REPLY"); if (!t_relay()) ...
route [ADD_CONTACT_ALIAS] { if (!add_contact_alias()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; }; }
REGISTER_REQUESTS -----------------
- call fix_nated_register() on register requests, if registering ua is behind nat OR is using tcp.
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location"); ...
IN_DIALOG_REQUESTS ------------------
- call handle_ruri_alias() for all in-dialog requests before t_relaying them, provided that loose_route() didn't set $du, which it does if next hop is another proxy. in the latter case set TO_PROXY fag.
route [IN_DIALOG_REQUESTS] {
loose_route(); ... if ($du == "") { handle_ruri_alias(); switch ($rc) { case -1: xlog("L_ERR", "Failed to handle alias of R-URI <$ru>\n"); send_reply("400", "Bad request"); exit; case 1: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$du>\n"); break; case 2: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$ru>\n"); break; }; } else { setbflag("TO_PROXY"); } t_on_reply("REPLY"); if (!t_relay()) { ...
REPLIES -------
- call add_contact_alias() on all replies except the ones that come from another proxy.
onreply_route [REPLY] {
if (!isbflagset("TO_PROXY") { if (is_avp_set("rr_count")) { if (!rr_count("$(var(rr_count)"))) { xlog("L_NOTICE", "Bad R-R header in reply\n"); send_reply("400", "Bad reply"); exit; }; if ($var(rr_count) == $avp(rr_count) + 1) { route(ADD_CONTACT_ALIAS); }; } else { route(ADD_CONTACT_ALIAS); } } ...
NOTE ----
- do NOT call fix_nated_contact() on anything, because add_contact_alias() replaces it.
Juha Heinanen schrieb:
"final" versions of alias functions are now ready for testing in in this sr_3.0 based nathelper.c:
Great, thanks.
i changed the names to more descriptive ones: add_contact_alias() and handle_ruri_alias(). also helper function rr_count(pvar) is included that assigns into the pvar the number of rr headers in incoming message (request or reply).
I just wonder why "alias" is used, and not "received". Current similar features (fix_nated_register, Path) use the term "received" to refer to the socket from which the request was received, not alias. I know your mean purpose was TCP, but IMO this is proper method to handle both, NATed and TCP clients. Thus, I think by using add_contact_received and handle_uri_received it would be easier for people to understand what the function does.
But anyway, a name is just name :-)
thanks klaus
usage example is below. i believe (until otherwise shown) that it works correctly.
if you are interested, please try with different UAs and different transports with or without nat.
-- juha
add_contact_alias()/handle_ruri_alias() usage example
supports re-use of tcp sessions between proxy and UAs. supports routing of requests to UAs behind NATs so that r-uri is always what UAs expect. proxying of media is not shown, but can be easily added.
NON_REGISTER_INITIAL_REQUESTS
call alias_contact() for all non-register initial requests, which don't come from another proxy (which takes care of its own UAs).
if you know that non-register initial request is going to another proxy, set TO_PROXY flag before relaying the request.
in cases, where initial request may go to another proxy, but you are not sure about it, store the number of record-route headers in incoming request in an AVP that you can then later test in onreply route and find out, if next hop was a proxy.
route [NON_REGISTER_INITIAL_REQUESTS] {
if (!is_present_hf("Record-Route")) { route(ADD_CONTACT_ALIAS); }; ... if (I_KNOW_FOR_SURE_THAT_NEXT_HOP_IS_ANOTHER_PROXY) { setbflag("TO_PROXY"); }; if (NEXT_HOP_MAY_BE_ANOTHER_PROXY_BUT_I_DONT_KNOW_FOR_SURE) { if (!rr_count($avp("rr_count"))) { send_reply("400", "Bad request"); exit;
}; }; t_on_reply("REPLY"); if (!t_relay()) ...
route [ADD_CONTACT_ALIAS] { if (!add_contact_alias()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; }; }
REGISTER_REQUESTS
- call fix_nated_register() on register requests, if registering ua is behind nat OR is using tcp.
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location"); ...
IN_DIALOG_REQUESTS
- call handle_ruri_alias() for all in-dialog requests before t_relaying them, provided that loose_route() didn't set $du, which it does if next hop is another proxy. in the latter case set TO_PROXY fag.
route [IN_DIALOG_REQUESTS] {
loose_route(); ... if ($du == "") { handle_ruri_alias(); switch ($rc) { case -1: xlog("L_ERR", "Failed to handle alias of R-URI <$ru>\n"); send_reply("400", "Bad request"); exit; case 1: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$du>\n"); break; case 2: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$ru>\n"); break; }; } else { setbflag("TO_PROXY"); } t_on_reply("REPLY"); if (!t_relay()) { ...
REPLIES
- call add_contact_alias() on all replies except the ones that come from another proxy.
onreply_route [REPLY] {
if (!isbflagset("TO_PROXY") { if (is_avp_set("rr_count")) { if (!rr_count("$(var(rr_count)"))) { xlog("L_NOTICE", "Bad R-R header in reply\n"); send_reply("400", "Bad reply"); exit; }; if ($var(rr_count) == $avp(rr_count) + 1) { route(ADD_CONTACT_ALIAS); }; } else { route(ADD_CONTACT_ALIAS);
} } ...
NOTE
- do NOT call fix_nated_contact() on anything, because add_contact_alias() replaces it.
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
"final" version of alias functions was not final. daniel suggested to make rr_count a psedo variable $rr_count exported by nathalper module.
it turned out a very easy thing to do and i did it. new version of sr_3.0 based nathelper.c and the example are available as
http://box.tutpro.com/tmp/nathelper.c
and
http://box.tutpro.com/tmp/alias_example.txt
-- juha