PJSIP Re-Registration not happening when I expect it to happen


I’m running Asterisk 15.3.0 which registers to my SIP Provider. My provider requires an active registration (the expires header I sent must not be expired) in order to make calls. My provider responds with a Contact: …;expires=3600 header to my registration. I have set expiration = 10 in my pjsip configuration for testing but unfortunately I don’t have any attempt of re-registration.

Is it possible that PJSIP waits for the Contact header expires parameter to expire? I wasn’t patient enough yet to wait the 3600 seconds to see if it re-registers then. This behaviour currently results in incoming calls being possible while outgoing calls are failing as they are no longer authenticated. My temporary workaround is to set expiration = 3600 but I would expect that to be honored if I set it. I haven’t found any kind of issue reports about this, with chan_sip this used to work perfectly fine…

The Expires value in a REGISTER is a request for an expires, but it is just that - a request. The remote side is free to select a different value. The outbound registration code doesn’t wait until expiration, it re-registers before that occurs.

When I look at the SIP RFC and search for “expires”, I read that if a contact header has an expires-parameter, it defines how long that URI is valid. This defaults to 3600 if it’s not defined. So in my opinion this has absolutely nothing to do with how long the registration is valid, and shouldn’t affect my re-registration.

Of course a brief look at the RFC is not enough for completely understanding it, there might be relevant parts that I missed.

The only purpose of registration is to provide the Contact header value!

1 Like

As @david551 mentioned the sole purpose of a registration is to provide that Contact value, along with its expiration. That is what a registration is. The expiration time controls the life of that Contact, and thus the life of the registration.

In my case it’s used for some kind of “pre-authentication” aswell, I can’t make a call when I’m beyond the expires value I sent.

Looking at the RFC I also find this:

The registrar MAY choose an expiration less than the requested
expiration interval. If and only if the requested expiration
interval is greater than zero AND smaller than one hour AND
less than a registrar-configured minimum, the registrar MAY
reject the registration with a response of 423 (Interval Too
Brief). This response MUST contain a Min-Expires header field
that states the minimum expiration interval the registrar is
willing to honor. It then skips the remaining steps.

So my provider should never just raise the expiration time? Do I understand that correctly?

The specific phrasing uses MAY, so it may do as mentioned and behave that way. If you provided a SIP trace then we may be able to analyze what is actually happening with certainty.

It seems to me to say that if it doen’t exercise the MAY, it has to process it normally, which seems to involve using the value requested. The only exceptions seem to be if the time is zero or >= 3600.

The provider in use would also be useful. There’s at least one[1] that has specific requirements which go against the SIP RFCs for server resolution.

[1] PJSIP settings for two German Telekom products

The MAY refers to something less than the expiration Interval, I choose 120 so they can not go beyond that (at least to my understanding), which they do by sending a 3600 back.

What’s happening there is this:

<--- History Entry 36 Sent to xx.xxx.xxx.xxx:5060 at 1559610640 --->
REGISTER sip:xxx.xxxxxxxxx.xxxxxxxx.xx SIP/2.0
Via: SIP/2.0/UDP xx.xx.xxx.xx:5060;rport;branch=z9hG4bKPj16be6009-4ebd-4b71-8656-7da0fda7b9b2
From: <sip:xxxxxxxxxx@xxx.xxxxxxxxx.xxxxxxxx.xx>;tag=7b623796-18f1-411d-abed-cde1e5fb285b
To: <sip:xxxxxxxxxx@xxx.xxxxxxxxx.xxxxxxxx.xx>
Call-ID: 76e6c939-2517-431a-ad5c-6021112f0fac
Contact: <sip:xxxxxxx@x.x.x.x:5060>
Expires: 10
Max-Forwards: 70
User-Agent: Flole PBX
Authorization: Digest username="xxxxxx", realm="xxxxxxx.xxxxxxxxxxxx.xx", nonce="xxxxxxxxxxxxxxxxxx", uri="sip:xxx.xxxxxxxxxx.xxxxx.xxx", response="xxxxxxxxxxxxxxxxxxxxx", algorithm=MD5
Route: <sip:xxx.xxxxxxxxx.xxxxxxxx.xx>
Content-Length:  0

<--- History Entry 37 Received from xx.xxx.xxx.xxx:5060 at 1559610640 --->
SIP/2.0 200 OK
Via: SIP/2.0/UDP xx.xx.xxx.xx:5060;rport=62474;received=xx.xx.xxx.xx;branch=z9hG4bKPj16be6009-4ebd-4b71-8656-7da0fda7b9b2
From: <sip:xxxxxxxxxx@xxx.xxxxxxxxx.xxxxxxxx.xx>;tag=7b623796-18f1-411d-abed-cde1e5fb285b
To: <sip:xxxxxxxxxx@xxx.xxxxxxxxx.xxxxxxxx.xx>;tag=SDrokq999-rr5t6p5t
Call-ID: 76e6c939-2517-431a-ad5c-6021112f0fac
Contact: <sip:xxxxxxx@x.x.x.x:5060>;q=1;expires=3600
Content-Length: 0
Content-Length:  0

When I start a call after 10 seconds now, I receive a 403 Forbidden. When I start it within the 10 seconds I get a 407 Proxy auth required, authenticate and the call gets initiated.

My provider has in it’s endpoint description the following part (taken from the endpoint description)

A SIP INVITE message MUST only be sent out by SIP UE during an active registration and only to the SIP server on which the SIP UE is currently registered.

Which is probably what I am violating when I get the 403.

They responded back with an expiration of 3600 despite you requesting 10. The code does handle this.

It’s more likely you are getting hit by the “to the SIP server on which the SIP UE is currently registered”. The PJSIP resolver does not guarantee this. The chan_sip module can because it doesn’t re-resolve or do balancing/failover. Once the config is loaded it’s resolved, and that resolved IP is kept. It was mentioned in the post I linked that 16 behaves better, but I’m still not certain if it would behave as needed in all cases.

The buffer time on re-registration is 10 seconds by the way. So it would be “expiration from response - 10 seconds” at which time the re-register would occur.

They only have one server :wink:

They actually don’t keep the registration for 3600 seconds though, after 10 seconds I see the problem. If i set it to 120 the issue appears after 120 seconds (which was my original value).

But can we get back to this for a second:

Is this also how you understand the RFC? Or do I understand it wrong here?

If they aren’t keeping the registration for 3600 seconds then that would indeed be a bug on their side, and they should respond back as mentioned in the RFC. We’re tolerant of them not - though - provided they themselves consider the Contact valid for however long they state.

I think they see the registration as something seperate from the contact, as the contact does indeed stay valid for that time so I can get called and they forward it to the correct contact, just the registration as a requirement for calling out is no longer valid then.

Anyways, I am reporting this now, in about 1 month we will know more about this. Is there any way we can work around this by ignoring the response just like chan_sip was doing it?

If you hacked up the code yes… it’s all self contained in res/res_pjsip_outbound_registration.c

I’d prefer to not do that :wink: Considering that in handle_registration_response I do not have the request available yet, so I would have to add it into sip_outbound_registration_client_state, and set it at the time of registration. Also I would need another option like “honor_servers_expiration” which defaults to yes but could be set to no in case the server sends weird stuff back.

Would the changes described ever make it into master? Or would someone block it saying “we don’t want workarounds in the code just because one provider doesn’t get their servers right”?

It would not make it in. If you can’t trust what the server says for the expiration then something is fundamentally broken with the remote side. Ignoring what they say is just a workaround for extreme brokenness. Have you compared the traffic between chan_sip and chan_pjsip?

I agree that something is fundamentally broken with my provider (and also with their SIP Server :wink: ), I have just checked my logs and noticed that this issue has appeared recently and wasn’t there before… So this is not a bug in chan_sip (which does the same thing) but with my provider who messed with this recently according to my logs.

What if I make a change to never allow the expiry to go beyond the requested expiration? That would make sure the protocol is honored and even if someone is violating it, it would still work. I assume that would also not make it in, even though I think it would be a really nice change.

I still don’t think that would be a good idea. It’s best to be reasonable with the re-registration time and base it on the agreed upon expiration or else you end up sending more traffic to the provider, and depending on their own system they can see that as an attack or abuse of resources.