[pjsip] Parsing expires from REGISTER reply
Alan J. Bond
alan.bond at wintology.com
Mon May 12 14:13:19 EDT 2008
> But actually I have another idea which make the algorithm works
> better. The idea is to add a unique parameter in the Contact (e.g.
> "x-ua-id=GUID"). The registrar is required to return all parameters in
> the Contact, so if we fail to find matching URI Contact header in the
> response, we could try to match this parameter only. This makes the
> matching algorithm less brittle IMO. But of course it can only work if
> the registrar returns all parameters intact, and since we're talking
> about non-compliant registrars, who knows what will happen.
I like this idea. If the registrar has not returned it (which it should, even if pre-RFC 3261) we can still fall back as before. Where in the code do you propose creating this extension attribute and do you intend keeping it for all other requests that carry the Contact: header?
> This has been solved by refreshing the registration sooner than the
> actual expiration time. We refresh the registration 5 seconds before
> expiration time (see DELAY_BEFORE_REFRESH constant in sip_reg.c),
> although unfortunately this value adjustment is not reported back to
> the application (i.e. application still sees the original expiration
In that case we don't need to adjust for response latency.
So I guess the algorithm should therefore be:
if we're registering:
if the answer is 200/OK:
if matched Contact by everything except expires= attribute is found
get expiration from Contact
else if matched Contact by extension-attribute x-ua-id=GUID=
get expiration from Contact
else if Expires is found:
get expiration from Expires header
get expiration from the request
else if the answer is 3xx-6xx:
the registration has failed
if we're unregistering:
if the answer is 200/OK:
the unregistration has been successful
it doesn't matter, we're unregistering no matter
Did a quick scan of RFC 2543 for anything we should worry about when handing older registrar implementations. Here are the bits I picked up on:
Para 6.13 Page 48
REGISTER 2xx responses: A REGISTER response MAY return all locations at which the user is currently reachable. An optional "expires" parameter indicates the expiration time of the registration. If a Contact entry does not have an "expires" parameter, the value of the Expires header field indicates the expiration time. If
neither mechanism is used, the expiration time specified in the request, explicitly or by default, is used.
We're fine with that I think.
Para 6.20 Page 55/56 regarding Expires Header:
This header field is currently defined only for the REGISTER and INVITE methods. For REGISTER, it is a request and response-header field. In a REGISTER request, the client indicates how long it wishes the registration to be valid. In the response, the server indicates the earliest expiration time of all registrations. The server MAY choose a shorter time interval than that requested by the client, but SHOULD NOT choose a longer one.
I guess we're fine with that too. "In the response, the server indicates the earliest expiration time of all registrations." makes it unlikely that a registrar would but a default value in here.
So, are we all happy to go with this?
From: pjsip-bounces at lists.pjsip.org [mailto:pjsip-bounces at lists.pjsip.org] On Behalf Of Benny Prijono
Sent: 09 May 2008 11:05
To: pjsip list
Subject: Re: [pjsip] Parsing expires from REGISTER reply
On Fri, May 9, 2008 at 3:53 AM, Alan J. Bond <alan.bond at wintology.com> wrote:
> >> funny and desperate at the same time
> Thoughts on your algorithm:
> 1. If there is no matched Contact but there is an Expires header, that should take precedence over picking an 'arbitrary' value by whatever means otherwise you break compliance. RFC3261 10.2.4: "The UA compares each contact address to see if it created the contact address, using comparison rules in Section 19.1.4. If so, it updates the expiration
> time interval according to the expires parameter or, if absent, the Expires field value." (The capital E says to me this is talking about the Expires header, the word 'field' in this context is spurious and can have no other meaning, yes?).
Yes I suppose field means header field there.
I didn't prefer to use the Expires because I was thinking that the
registrar may put a default Expires header in every 200 response,
probably hoping that the UA will use the value in the expires
parameter instead. But that's just a guess, I don't know what
registrars normally do.
> 2. The value of the expires parameter in Contact headers for any other UACs returned by the registrar is not that originally registered, it's the remaining time until that registration expires (at least from SER anyway). If you have two UACs each picking the lowest from the returned Contact headers at each re-registration you'll induce a 'race' condition where they both speed up and eventually get a 423 error (especially if they initially registered different values). I tried that approach till I saw what was happening.
I thought the speed up will occur only once, when the newly registered
UA sees expires value from other UA which is almost expired. And after
that, the worst that can happen is all UAs will register at
approximately the same time, picking up the lowest expiration. And I
thought that should be fine, since that lowest expiration value has
been accepted by the registrar in the first place.
> 3. Using the value from the request as a last resort to simplify things will be OK most of the time. The response latency bit may seem daft but we have customers on the other side of the planet, the latency is often in excess of 500mS. Over satellite links and some cellular infrastructures its > 800mS. A heavy download going on at the client end can jack it up further. Adding this twist is a tad safer and there's little overhead in doing it.
> RFC3261 says very little about how the server is supposed to construct a reply to a REGISTER command. Section 10.3 says nothing about the value to be returned in the expires parameter of Contact headers or requirement for and value in an Expires header. There is nothing at 20.10. 20.19 tells us the value in Expires header (if any) is the time until the response itself expires measured from when the request was received by the server but what does that mean in this context? The largest of the expires parameters in the contained Contact headers perhaps or the one specific to the request? Rather-Fuzzy-Concept again.
> There is nothing about tolerance to be applied by a registrar when flushing stale registrations, hence IMHO the need to compensate for request/response latency.
This has been solved by refreshing the registration sooner than the
actual expiration time. We refresh the registration 5 seconds before
expiration time (see DELAY_BEFORE_REFRESH constant in sip_reg.c),
although unfortunately this value adjustment is not reported back to
the application (i.e. application still sees the original expiration
I guess most reliable value for DELAY_BEFORE_REFRESH is probably 32
seconds, to match the SIP transaction timeout. But it's just that the
current refresh timer adjustment is lazy and doesn't take into account
the case when the expiration time is lower than DELAY_BEFORE_REFRESH,
hence I chose a low value for it. (some registrar responds with low
expiration time to make client refreshes NAT bindings. I've seen value
as low as 15 seconds).
> There is this at 10.3 point 7 on page 65 "The registrar MAY choose an expiration less than the requested expiration interval." This makes using the requested time as a last resort open to failure but:
> 1. We are in non-compliant lala land anyway.
> 2. As I already said to Electrocut, that's easily sorted by changing the client configuration to be within the servers configured maximum.
Yep. But this problem could be solved if only the "use the lower
expiration time" approach works.
> So... IMHO the algorithm should be:
> if we're registering:
> if the answer is 200/OK:
> if matched Contact is found:
> get expiration from Contact
> else if Expires is found:
> get expiration from Expires header
> get expiration from the request (adjusted for response latency)
> else if the answer is 3xx-6xx:
> the registration has failed
> if we're unregistering:
> if the answer is 200/OK:
> the unregistration has been successful
> it doesn't matter, we're unregistering no matter
> Thoughts back?
I think I agree with that.
But actually I have another idea which make the algorithm works
better. The idea is to add a unique parameter in the Contact (e.g.
"x-ua-id=GUID"). The registrar is required to return all parameters in
the Contact, so if we fail to find matching URI Contact header in the
response, we could try to match this parameter only. This makes the
matching algorithm less brittle IMO. But of course it can only work if
the registrar returns all parameters in tact, and since we're talking
about non-compliant registrars, who knows what will happen.
What do you think?
Visit our blog: http://blog.pjsip.org
pjsip mailing list
pjsip at lists.pjsip.org
More information about the pjsip