[pjsip] Parsing expires from REGISTER reply

Benny Prijono bennylp at pjsip.org
Fri May 9 06:05:20 EDT 2008

On Fri, May 9, 2008 at 3:53 AM, Alan J. Bond <alan.bond at wintology.com> wrote:
> Benny,
>  >> funny and desperate at the same time
>  lol
>  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
>          else
>              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
>      else
>          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?


>  Alan.

More information about the pjsip mailing list