Greetings,
I've got a small problem with how registration lookups work.
I have several concurrent registrations from one PBX that have multiple contact URIs that they declare that aren't the same; they contain the DIDs to route a call to. So, for instance, in Asterisk:
register => user:pass@registrar/DID1 register => user:pass@registrar/DID2
Of course, lookup() doesn't care what those contacts actually are. If it sees multiple contacts for one username, t_relay() will simply create branches for all of them and and ring them all. I can't actually have that happen.
I'm looking for suggestions on how to handle this most elegantly. The two options I've got in mind are:
1. Stop using lookup() and do my own URI rewrites and branch forking (if the contact URIs are identical) with attention to the contact.
2. Use BRANCH-ROUTEs to arrest the call leg if it is going to an RURI user part that does not match the user part of the contact URI, and... drop() the branches?
I also need to build in some other logic, such that for example if a user has only one contact registered and it does not match the DID, or none of the contacts match the DID, proceed as normal anyway.
Is it possible there is a better way? Recommendations welcome.
Cheers,
-- Alex
Hello Alex,
On 08/06/08 02:55, Alex Balashov wrote:
Greetings,
I've got a small problem with how registration lookups work.
I have several concurrent registrations from one PBX that have multiple contact URIs that they declare that aren't the same; they contain the DIDs to route a call to. So, for instance, in Asterisk:
register => user:pass@registrar/DID1 register => user:pass@registrar/DID2
Of course, lookup() doesn't care what those contacts actually are. If it sees multiple contacts for one username, t_relay() will simply create branches for all of them and and ring them all. I can't actually have that happen.
I'm looking for suggestions on how to handle this most elegantly. The two options I've got in mind are:
- Stop using lookup() and do my own URI rewrites and branch forking (if
the contact URIs are identical) with attention to the contact.
This is a bit more complex if you still want to use registrar to save location entries. Perhaps by using selects in the location table, you can achieve directly in the script. or using a shell/perl script.
- Use BRANCH-ROUTEs to arrest the call leg if it is going to an RURI
user part that does not match the user part of the contact URI, and... drop() the branches?
That is more elegant to be done in the configuration file.
I also need to build in some other logic, such that for example if a user has only one contact registered and it does not match the DID, or none of the contacts match the DID, proceed as normal anyway.
Here you get back in complexity. Perhaps if you play with $bR, transformations and script operations you will achieve that. As I understood it is about selecting the branches to be dropped. You can go through the addresses returned by $bR, test your conditions and accumulate what branches are to be dropped in AVP, checking again in branch route for actually dropping.
Just early morning opinion ...
Cheers, Daniel
Is it possible there is a better way? Recommendations welcome.
Cheers,
-- Alex
Daniel-Constantin,
Good morning. Thanks for the early morning opinion. How about some really late night followup? :)
Daniel-Constantin Mierla wrote:
- Stop using lookup() and do my own URI rewrites and branch forking
(if the contact URIs are identical) with attention to the contact.
This is a bit more complex if you still want to use registrar to save location entries. Perhaps by using selects in the location table, you can achieve directly in the script. or using a shell/perl script.
That was the idea. I already have extensive call logic outboarded to a Perl script, so I would just replace lookup() with my own intelligent, contact header-aware database dip.
I ultimately elected to go with the second option, not the first.
[ BTW, slightly unrelated: Whatever the cause of script methods being largely inaccessible from the Perl module API (i.e. OpenSER::rewrite_uri()) is (I was told a memory leak) it is a source of vexation and disappointment.
It means that I really can't do anything with my Perl scripts--of which there is a plethora--other than get and set AVPs and read custom pseudovariables and parse messages and URIs. I can't really move any of the logic I have from script to Perl at all, so instead I have to use countless AVPs as a message-passing mechanism and end up with big, nasty, ugly chunks of script that look like:
if($avp(S:translation_status) == "1") { # do a bunch of things
avp_delete("$avp(S:translation_status)"); }
My number one wish for the project is that someone would give some attention to the neglected Perl module and get it all fixed up so I can get a lot of logic out of the route plan. ]
I also need to build in some other logic, such that for example if a user has only one contact registered and it does not match the DID, or none of the contacts match the DID, proceed as normal anyway.
Here you get back in complexity. Perhaps if you play with $bR, transformations and script operations you will achieve that. As I understood it is about selecting the branches to be dropped. You can go through the addresses returned by $bR, test your conditions and accumulate what branches are to be dropped in AVP, checking again in branch route for actually dropping.
The route I decided to go is to check all the conditions in the branch route; it keeps things simple and prevents me from having to iterate over any AVP arrays.
The real headache I'm facing now has to do with call statekeeping. I keep call state in a database using custom logic in order to try -- as much as the reliability of SIP signaling can allow -- to enforce simultaneous session limits.
The problem is that none of this stuff is branch-aware, but now I'm getting into a situation where a branch that is cancelled triggers a reply (and therefore, for that call leg, an ONREPLY-ROUTE) like 487 Transaction Terminated that has to be handled in a branch-aware way. Previously, in unitary branch mode, I would just delete the call from the state table upon encountering a >= 300 cause code in the reply. Now I have to make sure I only delete that branch, and handle a bunch of other contingencies that come with that. Oof.
-- Alex
Alex Balashov schrieb:
Greetings,
I've got a small problem with how registration lookups work.
I have several concurrent registrations from one PBX that have multiple contact URIs that they declare that aren't the same; they contain the DIDs to route a call to. So, for instance, in Asterisk:
register => user:pass@registrar/DID1 register => user:pass@registrar/DID2
Of course, lookup() doesn't care what those contacts actually are. If it sees multiple contacts for one username, t_relay() will simply create branches for all of them and and ring them all. I can't actually have that happen.
Sorry - but I do not see the problem. If somebody registers multiple contacts for the same AoR this means it really wants to receive multiple INVITEs. If this is not wanted, then it should not register multiple times.
regards klaus
Klaus,
Klaus Darilion wrote:
Of course, lookup() doesn't care what those contacts actually are. If it sees multiple contacts for one username, t_relay() will simply create branches for all of them and and ring them all. I can't actually have that happen.
Sorry - but I do not see the problem. If somebody registers multiple contacts for the same AoR this means it really wants to receive multiple INVITEs. If this is not wanted, then it should not register multiple times.
I agree. The problem here is related to the provisioning systems of which the OpenSER-based registrar is a part.
Basically, every registering user has a username - this is just a username used for authentication, not related to contact. When a call comes in for a DID, I do a database dip and associate the DID with a user, and rewrite the RURI to have the username as the user part, since that is what the lookup() is keyed on in the location table.
Then, lookup() is called and it (under the hood) rewrites the RURI to contain the Contact URI provided by the end-user UA.
The problem here is that the Contact header can be many things. In the case of Asterisk, the default contact user part is 's', which is just a generic catch-all extension for the inbound context associated with that SIP peer. But what if I want -- in Asterisk, say -- to be able to apply different logic in my dial plan depending on what 'extension' the call came in on (AKA the user part of request URI of the INVITE)? I have to send the DID as the user part, but I can't do that if the contact it provided isn't the DID.
Asterisk lets you register like this:
register => user:password@registrar.ip.address:port/contact
So, I can override 's' with a DID for 'contact.' But if I do that, then I need to arrest call branches going to that user whose contact is not DID@their_IP.
I do that by comparing $tU and $rU in the BRANCH-ROUTE. But this leads to a whole lot of other headaches; one, I mentioned in my reply to Daniel-Constantin, is revising my call statekeeping logic to handle various things that can happen on one branch and not another (if the Contacts match up). The other is, what if the user doesn't actually want to register multiple times with multiple contacts?
The really best way to handle this is to stick with one contact and count on the UAC to use the To: header to determine how to handle the call, just like a traditional DNIS/CPN facility. But all of Asterisk's DNIS/DNID/RDNIS stuff seems to be broken right now, so there's no way to do this. And as for other UACs users might be using, forget it.
So, I need to come up with some logic where users that want all calls on all DIDs they have (which can potentially be a large number) can get them by specifying one magic "catch-all" contact user part, or register with DIDs as contacts specifically so the branch manipulation can do its work. It isn't easy for non-Asterisk clients; while I assume that most ATAs, IADs and VoIP PBXs that have a concept of a trunk "line" will provide the DID as the contact, others, like some soft phones, can put in the contact whatever they want, and it may have no imaginable correlation to the authentication username or the line name or whatever. That's where the mess comes in.
-- Alex
Alex Balashov schrieb:
Asterisk lets you register like this:
register => user:password@registrar.ip.address:port/contact
Can you specify user and auth-user separate?
Then you could register with the DID as userpart of the the AoR. The Asterisk still uses only one auth-user/password and there is no more need to rewrite the RURI in openser.
regards klaus
Klaus Darilion wrote:
Alex Balashov schrieb:
Asterisk lets you register like this:
register => user:password@registrar.ip.address:port/contact
Can you specify user and auth-user separate?
Then you could register with the DID as userpart of the the AoR. The Asterisk still uses only one auth-user/password and there is no more need to rewrite the RURI in openser.
It's not how the provider's provisioning is set up to handle it; they do not use DIDs as usernames. And in any case, many of the UAs are not going to be Asterisk.
Perhaps I can put the issue more succinctly:
Say I have a user that has two DIDs - the ones in my signature, 6789540670 and 6789540671.
If I actually have a user (evariste1, say) register from two pieces of CPE with a contact of 6789540670@IP, then, yes, I agree, there should be two branches generated.
The problem I have is with the scenario where endpoint A registers as evariste1@my_sip_domain with a contact of 6789540670 and endpoint B registers as evariste1@my_sip_domain with a contact of 6789540671.
When the registrar/usrloc lookup() evariste1, they're going to get both contacts, and branch the call to both contacts -- regardless of which number is the one that was actually dialed from the PSTN.
So, what I'm trying to do with my branch routes is have it look at the To URI user part ($tU) and compare it with the lookup()'d RURI user part. If they match up, send it on, otherwise drop() the branch.
The problem, as I mentioned, is that there are far too many possible registration and end-user UA scenarios. What if they only want to register once/their equipment only allows one registration? What if they want to receive some DIDs on one "line" and some DIDs on another "line?" What if, in the former scenario, they want one registration but need to do DNIS-based routing, which in Asterisk is currently entirely broken? The problem is that if I register with a contact of 6789540670 without any checks, I'm going to get calls for 6789540671 as well (as indicated in To:) with a RURI user part of 6789540670 as well, because, well, that's what the contact is. Can't have that happen.
-- Alex
Alex Balashov schrieb:
Perhaps I can put the issue more succinctly:
Say I have a user that has two DIDs - the ones in my signature, 6789540670 and 6789540671.
If I actually have a user (evariste1, say) register from two pieces of CPE with a contact of 6789540670@IP, then, yes, I agree, there should be two branches generated.
The problem I have is with the scenario where endpoint A registers as evariste1@my_sip_domain with a contact of 6789540670 and endpoint B registers as evariste1@my_sip_domain with a contact of 6789540671.
I wonder how you manage to do this without Asterisk. AFAIK Asterisk is the only SIP client which allows you to specify the userpart of the contact.
I think this is the design problem. If you do not want branching then you should not have multiple contacts for the same AoR.
IIRC there was an extension to SIP registration in the SIPConnect specification of the SIP forum how to register multiple DIDs. Maybe this can give you some more ideas how to solve the problem.
http://www.sipforum.org/component/option,com_docman/task,cat_view/gid,43/Ite...
regards klaus
When the registrar/usrloc lookup() evariste1, they're going to get both contacts, and branch the call to both contacts -- regardless of which number is the one that was actually dialed from the PSTN.
So, what I'm trying to do with my branch routes is have it look at the To URI user part ($tU) and compare it with the lookup()'d RURI user part. If they match up, send it on, otherwise drop() the branch.
The problem, as I mentioned, is that there are far too many possible registration and end-user UA scenarios. What if they only want to register once/their equipment only allows one registration? What if they want to receive some DIDs on one "line" and some DIDs on another "line?" What if, in the former scenario, they want one registration but need to do DNIS-based routing, which in Asterisk is currently entirely broken? The problem is that if I register with a contact of 6789540670 without any checks, I'm going to get calls for 6789540671 as well (as indicated in To:) with a RURI user part of 6789540670 as well, because, well, that's what the contact is. Can't have that happen.
-- Alex
Klaus Darilion wrote:
I wonder how you manage to do this without Asterisk. AFAIK Asterisk is the only SIP client which allows you to specify the userpart of the contact.
Not elegantly or consistently, that's for sure.
Various UAs have various configurable fields that relate to how they populate the contact. For instance, the Twinkle softphone turns out to use the 'Username' (as opposed to 'Authentication Username') for this. Regrettably, it also furnishes that 'Username' for the AOR itself, although it uses the 'Authentication Username' for the digestion portion.
Part of the intent is to build enough workarounds in the branch logic; if the username == the AoR, route it. If it's 's', route it, etc.
I think this is the design problem. If you do not want branching then you should not have multiple contacts for the same AoR.
Well, in principle, I concur! Sadly I am dealing here with some requirements not my own.
IIRC there was an extension to SIP registration in the SIPConnect specification of the SIP forum how to register multiple DIDs. Maybe this can give you some more ideas how to solve the problem.
Ah - thanks. Although, admittedly, it is a most abstruse read.
-- Alex
Hi Alex,
I don't know your complete architecture, but let me ask you why Asterisk is not a trusted gateway? The you can use rewritehost or LCR logic to route DIDs to Asterisk If you need to associate users with DIDs, you can use dbaliases.
Cheers,
Gustavo On Tue, Aug 5, 2008 at 8:55 PM, Alex Balashov abalashov@evaristesys.comwrote:
Greetings,
I've got a small problem with how registration lookups work.
I have several concurrent registrations from one PBX that have multiple contact URIs that they declare that aren't the same; they contain the DIDs to route a call to. So, for instance, in Asterisk:
register => user:pass@registrar/DID1 register => user:pass@registrar/DID2
Of course, lookup() doesn't care what those contacts actually are. If it sees multiple contacts for one username, t_relay() will simply create branches for all of them and and ring them all. I can't actually have that happen.
I'm looking for suggestions on how to handle this most elegantly. The two options I've got in mind are:
- Stop using lookup() and do my own URI rewrites and branch forking (if
the contact URIs are identical) with attention to the contact.
- Use BRANCH-ROUTEs to arrest the call leg if it is going to an RURI
user part that does not match the user part of the contact URI, and... drop() the branches?
I also need to build in some other logic, such that for example if a user has only one contact registered and it does not match the DID, or none of the contacts match the DID, proceed as normal anyway.
Is it possible there is a better way? Recommendations welcome.
Cheers,
-- Alex
-- Alex Balashov Evariste Systems Web : http://www.evaristesys.com/ Tel : (+1) (678) 954-0670 Direct : (+1) (678) 954-0671 Mobile : (+1) (706) 338-8599
Users mailing list Users@lists.kamailio.org http://lists.kamailio.org/cgi-bin/mailman/listinfo/users