Hi,
I'm making slow but steady progress with my Kamailio project.
My next task: I need to "relay" a registration to an upstream service. IE when one or more devices registers against my local registration service, I need to initiate a corresponding registration upstream. If all my local devices unregister, all all the registrations lapse, I want to drop the upstream registration.
There is an example a bit like this in the Asterisk integration example. However in that case the Asterisk doesn't challenge for authentication. My upstream does.
I can't find anything in the uac module docs about authenticating.
Is there any way to handle this.
One thing I did try was to create "uacreg" as a view, and use that as the source of upstream registrations:
CREATE VIEW `uacreg` AS select distinct `s`.`id` AS `id`,`l`.`username` AS `l_uuid`,`l`.`username` AS `l_username`,`s`.`domain` AS `l_domain`,`l`.`username` AS `r_username`,`s`.`domain` AS `r_domain`,`s`.`domain` AS `realm`,`l`.`username` AS `auth_username`,`s`.`password` AS `auth_password`,concat('sip:',`s`.`domain`,':5060') AS `auth_proxy`,timestampdiff(SECOND,now(),`l`.`expires`) AS `expires` from (`location` `l` join `subscriber` `s`) where (`l`.`username` = `s`.`username`)
This kinda worked - but didn't quite track the registration status. Do you think this idea has promise? Maybe something similar that works using triggers rather than a straight view might work better?
Thanks, Steve
16 sep 2013 kl. 18:08 skrev Steve Davies steve@connection-telecom.com:
Hi,
I'm making slow but steady progress with my Kamailio project.
My next task: I need to "relay" a registration to an upstream service. IE when one or more devices registers against my local registration service, I need to initiate a corresponding registration upstream. If all my local devices unregister, all all the registrations lapse, I want to drop the upstream registration.
Why not forward the registration from the endpoint and let them handle authentication?
/O
There is an example a bit like this in the Asterisk integration example. However in that case the Asterisk doesn't challenge for authentication. My upstream does.
I can't find anything in the uac module docs about authenticating.
Is there any way to handle this.
One thing I did try was to create "uacreg" as a view, and use that as the source of upstream registrations:
CREATE VIEW `uacreg` AS select distinct `s`.`id` AS `id`,`l`.`username` AS `l_uuid`,`l`.`username` AS `l_username`,`s`.`domain` AS `l_domain`,`l`.`username` AS `r_username`,`s`.`domain` AS `r_domain`,`s`.`domain` AS `realm`,`l`.`username` AS `auth_username`,`s`.`password` AS `auth_password`,concat('sip:',`s`.`domain`,':5060') AS `auth_proxy`,timestampdiff(SECOND,now(),`l`.`expires`) AS `expires` from (`location` `l` join `subscriber` `s`) where (`l`.`username` = `s`.`username`)
This kinda worked - but didn't quite track the registration status. Do you think this idea has promise? Maybe something similar that works using triggers rather than a straight view might work better?
Thanks, Steve
-- Steve Davies: Technical Director, Connection Telecom (Pty) Ltd
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
--- * Olle E Johansson - oej@edvina.net * Cell phone +46 70 593 68 51, Office +46 8 96 40 20, Sweden
Why not forward the registration from the endpoint and let them handle authentication?
I need to push the registration upstream. But I also need a local location record since I have an Asterisk on the side that also needs to send calls to the phones via the Kamailio instance.
The device on the side is Asterisk and will simply dial SIP/userpart@kamailio, so Kamailio needs to know a location for the device too.
I also need the registration from the phone to succeed even when the upstream link is down since the point is that in that case the local Asterisk will be used to handle both out and incoming calls.
Steve
16 sep 2013 kl. 19:11 skrev Steve Davies steve@connection-telecom.com:
Why not forward the registration from the endpoint and let them handle authentication?
I need to push the registration upstream. But I also need a local location record since I have an Asterisk on the side that also needs to send calls to the phones via the Kamailio instance.
save before t_relay...
Just forward the reg upstream. There's a parameter to save() to not respond.
/O
The device on the side is Asterisk and will simply dial SIP/userpart@kamailio, so Kamailio needs to know a location for the device too.
I also need the registration from the phone to succeed even when the upstream link is down since the point is that in that case the local Asterisk will be used to handle both out and incoming calls.
Steve
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
--- * Olle E Johansson - oej@edvina.net * Cell phone +46 70 593 68 51, Office +46 8 96 40 20, Sweden
On 16 September 2013 19:49, Olle E. Johansson oej@edvina.net wrote:
16 sep 2013 kl. 19:11 skrev Steve Davies steve@connection-telecom.com:
Why not forward the registration from the endpoint and let them handle authentication?
I need to push the registration upstream. But I also need a local location record since I have an Asterisk on the side that also needs to send calls to the phones via the Kamailio instance.
save before t_relay...
Just forward the reg upstream. There's a parameter to save() to not respond.
Thanks for the reply.
It doesn't matter if the upstream isn't reachable? I suppose not since if we just save the registration from the original REGISTER it doesn't matter what happens after that.
But I don't want the phone to show not-registered. So I need to return an OK to the phone if (and only if) there is no response from the upstream. Since If the registration actively fails upstream then I want the phone to show that, but if the registration fails because the upstream link is down then I want the registration to succeed from the pov of the phone since the phone is at least locally registered.
My reasoning is that I conceptually I have a local registration backed up by a corresponding upstream registration. But reading between the lines you are saying Kamailio can't easily do that if the upstream requires authentication?
Thanks, Steve
16 sep 2013 kl. 20:54 skrev Steve Davies steve-lists-srusers@connection-telecom.com:
On 16 September 2013 19:49, Olle E. Johansson oej@edvina.net wrote:
16 sep 2013 kl. 19:11 skrev Steve Davies steve@connection-telecom.com:
Why not forward the registration from the endpoint and let them handle authentication?
I need to push the registration upstream. But I also need a local location record since I have an Asterisk on the side that also needs to send calls to the phones via the Kamailio instance.
save before t_relay...
Just forward the reg upstream. There's a parameter to save() to not respond.
Thanks for the reply.
It doesn't matter if the upstream isn't reachable? I suppose not since if we just save the registration from the original REGISTER it doesn't matter what happens after that.
If so you can save and respond in the failure route.
But I don't want the phone to show not-registered. So I need to return an OK to the phone if (and only if) there is no response from the upstream. Since If the registration actively fails upstream then I want the phone to show that, but if the registration fails because the upstream link is down then I want the registration to succeed from the pov of the phone since the phone is at least locally registered.
Yep. You need to consider what happens when upstream comes back. From that pov the phon ewill be unregistred.
My reasoning is that I conceptually I have a local registration backed up by a corresponding upstream registration. But reading between the lines you are saying Kamailio can't easily do that if the upstream requires authentication?
I say you're making it too complex. Let the proxy be a proxy and force the client to behave properly.
/O
On 16 September 2013 21:03, Olle E. Johansson oej@edvina.net wrote:
I say you're making it too complex. Let the proxy be a proxy and force the client to behave properly.
The client is an ordinary SIP phone. I don't have any control over its behaviour. But I'm not sure in what way it is behaving improperly?
Steve
Hello,
you can call save() for 200ok received from downstream. In case you deal with nat or multiple local sockets, you need to call the functions for fixing the registration as well as storing the local socket.
The processing can be like: - forward register - if getting 200ok, call save() for it - if local timeout, call save in failure route -- you will have to call it via a sub-route, because save() is only allowed in request route and reply route, although failure_route should be safe for it - if other reply from downstram, let it go to the phone
Cheers, Daniel
On 9/16/13 9:08 PM, Steve Davies wrote:
On 16 September 2013 21:03, Olle E. Johansson <oej@edvina.net mailto:oej@edvina.net> wrote:
I say you're making it too complex. Let the proxy be a proxy and force the client to behave properly.
The client is an ordinary SIP phone. I don't have any control over its behaviour. But I'm not sure in what way it is behaving improperly?
Steve
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
On 16 September 2013 21:30, Daniel-Constantin Mierla miconda@gmail.comwrote:
you can call save() for 200ok received from downstream. In case you deal with nat or multiple local sockets, you need to call the functions for fixing the registration as well as storing the local socket.
The processing can be like:
- forward register
- if getting 200ok, call save() for it
- if local timeout, call save in failure route -- you will have to call it
via a sub-route, because save() is only allowed in request route and reply route, although failure_route should be safe for it
- if other reply from downstram, let it go to the phone
Cheers, Daniel
OK - thanks Daniel and Olle for the pointers, much appreciated.
Steve
Hi Daniel, Olle,
On 16 September 2013 21:30, Daniel-Constantin Mierla miconda@gmail.comwrote:
you can call save() for 200ok received from downstream. In case you deal with nat or multiple local sockets, you need to call the functions for fixing the registration as well as storing the local socket.
The processing can be like:
- forward register
- if getting 200ok, call save() for it
- if local timeout, call save in failure route -- you will have to call it
via a sub-route, because save() is only allowed in request route and reply route, although failure_route should be safe for it
- if other reply from downstram, let it go to the phone
I've made a start with this but need a little more help.
In route block [SIPOUT], in the case of a request going to a foreign domain I added:
# we need to track the reply to the REGISTER since we need to also save
locally if ( is_method("REGISTER") ) { t_on_reply("REGISTER_REPLY"); t_on_failure("REGISTER_FAILURE"); }
So this "captures" the reply or failure.
Then:
onreply_route[REGISTER_REPLY] {
# Got a reply to a register from upstream. Save locally if its an OK if (t_check_status("200")) { save("location", "0x02", "sip:$tU@local.domain.com"); append_hf("X-Runway-Trace: Runway saved registration as $ tU@local.domain.com\r\n"); } }
The problem I have is that the save operates based on the content of the 200 OK reply.
So what goes into my DB for a register is like so:
id: 31 ruid: uloc-52383743-20e9-2 username: 2686959 domain: NULL contact: sip:2686959@172.16.230.1:36574 ;rinstance=212220b8566c4337;transport=udp received: sip:10.64.5.16:5060 path: NULL expires: 2013-09-17 14:32:24 q: -1.00 callid: MDA1MzRmZDQzZmMxNzhlNWUwMGUzNmYwNGYwZTM1YTc cseq: 2 last_modified: 2013-09-17 13:32:24 flags: 0 cflags: 0 user_agent: n/a socket: udp:10.64.5.16:5060 methods: NULL instance: NULL reg_id: 0
So this is OK, but the received and socket are both wrong (they are the "outside" interface of my proxy, where the reply came in. The registering phone actually talks to Kamailio on the 172.16.230.128 interface).
More of a problem is what happens for an "unregister".
Here's the REGISTER as forwarded by Kamailio and the reply that comes back and is processed in the onreply_route:
U 2013/09/17 13:22:58.004730 10.64.5.16:5060 -> x.x.x.60:5060
REGISTER sip:vc2.connection-telecom.com SIP/2.0. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0. Via: SIP/2.0/UDP 172.16.230.1:50108 ;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. Max-Forwards: 16. Contact: sip:2686959@172.16.230.1:50108 ;rinstance=36d56481f191d185;transport=udp;expires=0. To: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com. From: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO. User-Agent: Bria 3 release 3.5.4 stamp 70878. Authorization: Digest username="2686959",realm=" xxxx.connection-telecom.com ",nonce="52383baf2e3b9efcb10180e2ad059ff0ae7fa675",uri="sip: vc2.connection-telecom.com ",response="bad296f5041c869c330f015c4dcb6351",algorithm=MD5. Content-Length: 0. P-hint: outbound.
.
U 2013/09/17 13:22:58.226378 x.x.x.60:5060 -> 10.64.5.16:5060
SIP/2.0 200 OK. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0;rport=5060. Via: SIP/2.0/UDP 172.16.230.1:50108 ;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. To: "vc2 2686959"<sip:2686959@xxxx.connection-telecom.com
;tag=4bb452afea88ea368a51bf5f3eee867d.8da4.
From: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Server: Telviva SIP proxy. Content-Length: 0.
So the 200 OK does not have the Contact header.
On the save Kamailio does not remove the existing registration from the location table, so the unregister isn't effective for the local location table.
Is there a way to get the save to find the original request? Can I pull the original request back via tm module somehow? Other ideas on getting this right?
Thanks, Steve
17 sep 2013 kl. 13:52 skrev Steve Davies steve-lists-srusers@connection-telecom.com:
Hi Daniel, Olle,
On 16 September 2013 21:30, Daniel-Constantin Mierla miconda@gmail.com wrote:
you can call save() for 200ok received from downstream. In case you deal with nat or multiple local sockets, you need to call the functions for fixing the registration as well as storing the local socket.
The processing can be like:
- forward register
- if getting 200ok, call save() for it
- if local timeout, call save in failure route -- you will have to call it via a sub-route, because save() is only allowed in request route and reply route, although failure_route should be safe for it
- if other reply from downstram, let it go to the phone
I've made a start with this but need a little more help.
In route block [SIPOUT], in the case of a request going to a foreign domain I added:
# we need to track the reply to the REGISTER since we need to also save locally if ( is_method("REGISTER") ) { t_on_reply("REGISTER_REPLY"); t_on_failure("REGISTER_FAILURE"); }
So this "captures" the reply or failure.
Then:
onreply_route[REGISTER_REPLY] { # Got a reply to a register from upstream. Save locally if its an OK if (t_check_status("200")) { save("location", "0x02", "sip:$tU@local.domain.com"); append_hf("X-Runway-Trace: Runway saved registration as $tU@local.domain.com\r\n"); } }
The problem I have is that the save operates based on the content of the 200 OK reply.
So what goes into my DB for a register is like so:
id: 31 ruid: uloc-52383743-20e9-2 username: 2686959 domain: NULL contact: sip:2686959@172.16.230.1:36574;rinstance=212220b8566c4337;transport=udp received: sip:10.64.5.16:5060 path: NULL expires: 2013-09-17 14:32:24 q: -1.00 callid: MDA1MzRmZDQzZmMxNzhlNWUwMGUzNmYwNGYwZTM1YTc cseq: 2
last_modified: 2013-09-17 13:32:24 flags: 0 cflags: 0 user_agent: n/a socket: udp:10.64.5.16:5060 methods: NULL instance: NULL reg_id: 0
So this is OK, but the received and socket are both wrong (they are the "outside" interface of my proxy, where the reply came in. The registering phone actually talks to Kamailio on the 172.16.230.128 interface).
More of a problem is what happens for an "unregister".
Here's the REGISTER as forwarded by Kamailio and the reply that comes back and is processed in the onreply_route:
U 2013/09/17 13:22:58.004730 10.64.5.16:5060 -> x.x.x.60:5060 REGISTER sip:vc2.connection-telecom.com SIP/2.0. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0. Via: SIP/2.0/UDP 172.16.230.1:50108;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. Max-Forwards: 16. Contact: sip:2686959@172.16.230.1:50108;rinstance=36d56481f191d185;transport=udp;expires=0. To: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com. From: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO. User-Agent: Bria 3 release 3.5.4 stamp 70878. Authorization: Digest username="2686959",realm="xxxx.connection-telecom.com",nonce="52383baf2e3b9efcb10180e2ad059ff0ae7fa675",uri="sip:vc2.connection-telecom.com",response="bad296f5041c869c330f015c4dcb6351",algorithm=MD5. Content-Length: 0. P-hint: outbound. .
U 2013/09/17 13:22:58.226378 x.x.x.60:5060 -> 10.64.5.16:5060 SIP/2.0 200 OK. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0;rport=5060. Via: SIP/2.0/UDP 172.16.230.1:50108;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. To: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com;tag=4bb452afea88ea368a51bf5f3eee867d.8da4. From: "vc2 2686959"sip:2686959@xxxx.connection-telecom.com;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Server: Telviva SIP proxy. Content-Length: 0.
So the 200 OK does not have the Contact header.
Because the REGISTER has expires=0 on the contact, so this is a DEREGISTRATION, and that's why you do not see any contacts in the 200 OK. You need to check that you have contact headers before saving based on the 200 OK. Or possibly read the response code from save().
/O
On the save Kamailio does not remove the existing registration from the location table, so the unregister isn't effective for the local location table.
Is there a way to get the save to find the original request? Can I pull the original request back via tm module somehow? Other ideas on getting this right?
Thanks, Steve
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
--- * Olle E Johansson - oej@edvina.net * Cell phone +46 70 593 68 51, Office +46 8 96 40 20, Sweden
On 17 September 2013 14:02, Olle E. Johansson oej@edvina.net wrote:
Because the REGISTER has expires=0 on the contact, so this is a DEREGISTRATION, and that's why you do not see any contacts in the 200 OK. You need to check that you have contact headers before saving based on the 200 OK. Or possibly read the response code from save().
I do understand that its a deregistration. I want my Kamailio to remove the local registration, but it is not.
The registrar module save() documentation says that "The function processes a REGISTER message. It can add, remove or modify usrloc records depending on Contact and Expires HFs in the REGISTER message.". So it seems it would do the right thing if it could see the actual REGISTER message. But since I'm in the in reply_route looks like it is working off the reply. In which case it can't "see" the Contact and especially not the ;expires=0. Is that right?
So is there a way to get at the original REGISTER request in onreply_route? Otherwise I guess I must use an avp to remember the request or something like that? Since in the 200 OK there isn't really enough information to tell that its a de-registration. Unless I can imply that from the missing Contact header? But I think not since if there were multiple registrations the returned OK IIRC will still report the remaining registrations?
If I can figure out that the returned 200 OK is in response to a deregistration I guess I can use unregister() to remove my local registration.
Steve
17 sep 2013 kl. 14:22 skrev Steve Davies steve-lists-srusers@connection-telecom.com:
On 17 September 2013 14:02, Olle E. Johansson oej@edvina.net wrote:
Because the REGISTER has expires=0 on the contact, so this is a DEREGISTRATION, and that's why you do not see any contacts in the 200 OK. You need to check that you have contact headers before saving based on the 200 OK. Or possibly read the response code from save().
I do understand that its a deregistration. I want my Kamailio to remove the local registration, but it is not.
The registrar module save() documentation says that "The function processes a REGISTER message. It can add, remove or modify usrloc records depending on Contact and Expires HFs in the REGISTER message.". So it seems it would do the right thing if it could see the actual REGISTER message. But since I'm in the in reply_route looks like it is working off the reply. In which case it can't "see" the Contact and especially not the ;expires=0. Is that right?
http://www.kamailio.org/wiki/cookbooks/4.0.x/pseudovariables#t_req_pv
Documentation is your best friend!
/O
Hello,
On 9/17/13 1:52 PM, Steve Davies wrote:
Hi Daniel, Olle,
On 16 September 2013 21:30, Daniel-Constantin Mierla <miconda@gmail.com mailto:miconda@gmail.com> wrote:
you can call save() for 200ok received from downstream. In case you deal with nat or multiple local sockets, you need to call the functions for fixing the registration as well as storing the local socket. The processing can be like: - forward register - if getting 200ok, call save() for it - if local timeout, call save in failure route -- you will have to call it via a sub-route, because save() is only allowed in request route and reply route, although failure_route should be safe for it - if other reply from downstram, let it go to the phone
I've made a start with this but need a little more help.
In route block [SIPOUT], in the case of a request going to a foreign domain I added:
# we need to track the reply to the REGISTER since we need to also save locally if ( is_method("REGISTER") ) { t_on_reply("REGISTER_REPLY"); t_on_failure("REGISTER_FAILURE"); }
So this "captures" the reply or failure.
Then:
onreply_route[REGISTER_REPLY] { # Got a reply to a register from upstream. Save locally if its an OK if (t_check_status("200")) { save("location", "0x02", "sip:$tU@local.domain.com <mailto:tU@local.domain.com>"); append_hf("X-Runway-Trace: Runway saved registration as $tU@local.domain.com <mailto:tU@local.domain.com>\r\n"); } }
The problem I have is that the save operates based on the content of the 200 OK reply.
So what goes into my DB for a register is like so:
id: 31 ruid: uloc-52383743-20e9-2 username: 2686959 domain: NULL contact:
sip:2686959@172.16.230.1:36574;rinstance=212220b8566c4337;transport=udp received: sip:10.64.5.16:5060 http://10.64.5.16:5060 path: NULL expires: 2013-09-17 14:32:24 q: -1.00 callid: MDA1MzRmZDQzZmMxNzhlNWUwMGUzNmYwNGYwZTM1YTc cseq: 2 last_modified: 2013-09-17 13:32:24 flags: 0 cflags: 0 user_agent: n/a socket: udp:10.64.5.16:5060 http://10.64.5.16:5060 methods: NULL instance: NULL reg_id: 0
So this is OK, but the received and socket are both wrong (they are the "outside" interface of my proxy, where the reply came in. The registering phone actually talks to Kamailio on the 172.16.230.128 interface).
For the received field, you should call fix_nated_register() when you get the REGISTER (not for the reply). Or build the value for received_avp (http://kamailio.org/docs/modules/stable/modules/registrar.html#idp84696) manually in config from source ip, source port and transport.
With the socket is a bit more complex in this case, with multiple network interfaces, it can be set via a header, but msg_apply_changes() works on reply only with development version. Practically is about using the two parameters of registrar module:
- http://kamailio.org/docs/modules/stable/modules/registrar.html#idp115832
It might me easier to make a patch to provide custom socket value via an avp (like for received value), instead of header (this with header was added long time ago for replicated registrations).
Is the subscriber having more than one phone? Or is restricted to have only one device? IIRC, with some (old?) versions of asterisk, only one phone was used. If it is only for one phone, you can try a different approach:
- use save() with no reply flag for REGISTER - forward the register downstream - in failure route, if it is a reply received from downstream, use unregister()
There will be a short time window that the phone is registered locally. You can optimize it to call save() only when Authorization header is present in REGISTER, as you know downstream is always authenticating.
The development version (to be 4.1.0 in aprox. 2months) works better with this approach, allowing even multiple phones for same subscriber. That because save() returns an unique id (ruid) for the contact, that can be passed as 3rd parameter to unregister() to remove only that specific contact.
More of a problem is what happens for an "unregister".
Here's the REGISTER as forwarded by Kamailio and the reply that comes back and is processed in the onreply_route:
U 2013/09/17 13:22:58.004730 10.64.5.16:5060 <http://10.64.5.16:5060> -> x.x.x.60:5060 REGISTER sip:vc2.connection-telecom.com <http://vc2.connection-telecom.com> SIP/2.0. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0. Via: SIP/2.0/UDP 172.16.230.1:50108;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. Max-Forwards: 16. Contact: <sip:2686959@172.16.230.1:50108;rinstance=36d56481f191d185;transport=udp>;expires=0. To: "vc2 2686959"<sip:2686959@xxxx.connection-telecom.com <mailto:sip%3A2686959@xxxx.connection-telecom.com>>. From: "vc2 2686959"<sip:2686959@xxxx.connection-telecom.com <mailto:sip%3A2686959@xxxx.connection-telecom.com>>;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO. User-Agent: Bria 3 release 3.5.4 stamp 70878. Authorization: Digest username="2686959",realm="xxxx.connection-telecom.com <http://xxxx.connection-telecom.com>",nonce="52383baf2e3b9efcb10180e2ad059ff0ae7fa675",uri="sip:vc2.connection-telecom.com <http://vc2.connection-telecom.com>",response="bad296f5041c869c330f015c4dcb6351",algorithm=MD5. Content-Length: 0. P-hint: outbound.
.
U 2013/09/17 13:22:58.226378 x.x.x.60:5060 -> 10.64.5.16:5060 <http://10.64.5.16:5060> SIP/2.0 200 OK. Via: SIP/2.0/UDP 10.64.5.16;branch=z9hG4bK66a6.f18d2a5.0;rport=5060. Via: SIP/2.0/UDP 172.16.230.1:50108;branch=z9hG4bK-d8754z-f3d2c8070cecc90e-1---d8754z-;rport=50108. To: "vc2 2686959"<sip:2686959@xxxx.connection-telecom.com <mailto:sip%3A2686959@xxxx.connection-telecom.com>>;tag=4bb452afea88ea368a51bf5f3eee867d.8da4. From: "vc2 2686959"<sip:2686959@xxxx.connection-telecom.com <mailto:sip%3A2686959@xxxx.connection-telecom.com>>;tag=114bde0a. Call-ID: ZmUyY2JiOWQzMWE3OTM3YTNjNTM1OGUxOTE5Njc2ZTk. CSeq: 4 REGISTER. Server: Telviva SIP proxy. Content-Length: 0.
So the 200 OK does not have the Contact header.
On the save Kamailio does not remove the existing registration from the location table, so the unregister isn't effective for the local location table.
Is there a way to get the save to find the original request? Can I pull the original request back via tm module somehow? Other ideas on getting this right?
You can call unregister() if the reply for REGISTER has no contacts.
Cheers, Daniel
Thanks, Steve
On 17 September 2013 14:23, Daniel-Constantin Mierla miconda@gmail.comwrote:
For the received field, you should call fix_nated_register() when you get the REGISTER (not for the reply). Or build the value for received_avp ( http://kamailio.org/docs/modules/stable/modules/registrar.html#idp84696) manually in config from source ip, source port and transport.
I already have and call this route block: (WITH_NAT is defined)
# Caller NAT detection route route[NATDETECT] { #!ifdef WITH_NAT force_rport(); if (nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { add_contact_alias(); } setflag(FLT_NATS); } #!ifdef WITH_RTPBRIDGING if (!is_method("BYE")) { setflag(FLT_NATS); } #!endif #!endif return; }
But there is no NAT between the phone and Kamailio, so fix_nated_register isn't called. And there is nothing to fix about the incoming register.
But the register goes out on a different interface with a different address. And the reply comes back on that interface.
So I presume the issue with the received/socket is that save() derived them off the reply.
With the socket is a bit more complex in this case, with multiple network interfaces, it can be set via a header, but msg_apply_changes() works on reply only with development version. Practically is about using the two parameters of registrar module:
It might me easier to make a patch to provide custom socket value via an avp (like for received value), instead of header (this with header was added long time ago for replicated registrations).
Is the subscriber having more than one phone? Or is restricted to have only one device? IIRC, with some (old?) versions of asterisk, only one phone was used. If it is only for one phone, you can try a different approach:
The subscriber is not restricted to only having one phone - they can register more than one. The downstream service supports that fine. Kamailio can support it and I don't want to introduce a restriction since customers often have a desk phone and also want to use a soft client on mobile phone or similar.
- use save() with no reply flag for REGISTER
- forward the register downstream
- in failure route, if it is a reply received from downstream, use
unregister()
There will be a short time window that the phone is registered locally. You can optimize it to call save() only when Authorization header is present in REGISTER, as you know downstream is always authenticating.
So apart from dealing with the multiple registrations this seems like a promising approach.
Another idea: can I do "append_branch" for a register? If so, can I turn a register to the downstream service into a register for both the downstream service and my local registrar?
Thanks, Steve
On 9/17/13 2:43 PM, Steve Davies wrote:
On 17 September 2013 14:23, Daniel-Constantin Mierla <miconda@gmail.com mailto:miconda@gmail.com> wrote:
For the received field, you should call fix_nated_register() when you get the REGISTER (not for the reply). Or build the value for received_avp (http://kamailio.org/docs/modules/stable/modules/registrar.html#idp84696) manually in config from source ip, source port and transport.
I already have and call this route block: (WITH_NAT is defined)
# Caller NAT detection route route[NATDETECT] { #!ifdef WITH_NAT force_rport(); if (nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { add_contact_alias(); } setflag(FLT_NATS); } #!ifdef WITH_RTPBRIDGING if (!is_method("BYE")) { setflag(FLT_NATS); } #!endif #!endif return; }
But there is no NAT between the phone and Kamailio, so fix_nated_register isn't called. And there is nothing to fix about the incoming register.
Just call the function, don't make it optional for natted traffic only.
But the register goes out on a different interface with a different address. And the reply comes back on that interface.
So I presume the issue with the received/socket is that save() derived them off the reply.
With the socket is a bit more complex in this case, with multiple network interfaces, it can be set via a header, but msg_apply_changes() works on reply only with development version. Practically is about using the two parameters of registrar module: - http://kamailio.org/docs/modules/stable/modules/registrar.html#idp115832 It might me easier to make a patch to provide custom socket value via an avp (like for received value), instead of header (this with header was added long time ago for replicated registrations). Is the subscriber having more than one phone? Or is restricted to have only one device? IIRC, with some (old?) versions of asterisk, only one phone was used. If it is only for one phone, you can try a different approach:
The subscriber is not restricted to only having one phone - they can register more than one. The downstream service supports that fine. Kamailio can support it and I don't want to introduce a restriction since customers often have a desk phone and also want to use a soft client on mobile phone or similar.
- use save() with no reply flag for REGISTER - forward the register downstream - in failure route, if it is a reply received from downstream, use unregister() There will be a short time window that the phone is registered locally. You can optimize it to call save() only when Authorization header is present in REGISTER, as you know downstream is always authenticating.
So apart from dealing with the multiple registrations this seems like a promising approach.
Another idea: can I do "append_branch" for a register? If so, can I turn a register to the downstream service into a register for both the downstream service and my local registrar?
append_branch() works, but I don't think helps here, it will be like calling save() for register with no reply. Why forward it again to same instance. Anyhow, even so, should be better to use t_replicate_to() instead of adding a new branch.
Cheers, Daniel