In-dialog SIP INFO messages causing connections to be dropped

Hi Everybody,

This is my first post on this forum.

After 3 minutes our VOIP provider is sending out SIP INFOpackets and then drops the connection. When watching the debug logs I see three INFO messages coming it followed by a BYE message.

A ticket with the provider replay came back as:

We have checked the affected call using a SIP trace.

The call itself is established correctly and remains active for around three minutes. After approximately 180 seconds, our platform sends a SIP INFO request as part of the dead-call detection mechanism.

On the carrier side, this request is answered correctly with 200 OK. On the customer side, however, the INFO request is not answered. The request is retransmitted several times and, after the timeout, the call is terminated.

What is particularly noticeable is that the subsequent BYE is immediately answered with 200 OK. This means the Asterisk system is still reachable at SIP level, but the INFO request itself is apparently not being processed or answered.

We therefore recommend checking the SIP configuration on the Asterisk side, in particular whether in-dialog SIP INFO requests are accepted and answered correctly. Based on the trace, this does not currently look like a general connectivity, codec or RTP issue.

We are using PJSIP included in Asterisk 20.20.1 and INFO packets are allowed. The log shows:

Allow: OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, INFO, MESSAGE, REFER

My question is: What needs to be configured to respond to these INFO messages?

Many thanks in advance.

There’s the res_pjsip_empty_info module, but otherwise you haven’t shown a SIP trace to show what the actual INFO packet is like so I can’t say if that is applicable.

This doesn’t make sense. If they are getting a 200 OK, that’s all they need. They can only get one 2xx response for a request. The only interim responses would be 1xx ones.

The Allow: header is a red herring here — it advertises the methods the stack will accept, not that anything will answer a given INFO. I think your carrier’s description is accurate and Asterisk is answering nothing at all, and the reason is worth knowing.

In PJSIP an in-dialog INFO is answered only if a session supplement claims it. Two modules register one:

  • res_pjsip_dtmf_info — claims application/dtmf, application/dtmf-relay and application/hook-flash. For any other content type its handler returns “not handled”.
  • res_pjsip_empty_info — claims an INFO with no Content-Type and answers 200 OK. Its comment says it exists precisely because some SBCs send empty INFOs as keepalives.

The catch is in res_pjsip_session.c. session_on_rx_request() decides whether to claim the request with has_supplement(), which returns true if any supplement is registered for the method — and res_pjsip_dtmf_info is autoloaded, so every INFO is claimed. handle_incoming_request() then walks the supplements, each returns 0 because the content type is not theirs, and the function falls off the end without sending anything. Because the request was already claimed at the module level, pjproject’s dialog layer never gets to apply its own fallback (it would otherwise answer 500 Unhandled by dialog usages). Net result: the INFO is swallowed silently — retransmissions, timeout, BYE, and the BYE answered 200 OK immediately because BYE is handled by the invite session itself. That is exactly the shape of what the carrier traced.

So, in order:

  1. module show like info on the CLI. If res_pjsip_empty_info.so is not loaded — a noload, or autoload=no in modules.conf — and the dead-call-detection INFO is bodyless, that single module is your answer.
  2. If it is loaded and you still get no response, the INFO carries a body of a type nothing claims. Post the INFO exactly as it arrives from pjsip set logger on, with the Content-Type and the body — that decides whether res_pjsip_empty_info applies at all or you need a small supplement of your own.

Either way the trace @jcolp asked for is the thing that settles it, and the Content-Type line is the one that matters.

Worth adding: dead-call detection over in-dialog INFO every 180 s is an odd choice by your provider. If they also support RFC 4028 session timers, timers=yes with sensible timers_min_se / timers_sess_expires on the endpoint gives them the same liveness check through a mechanism Asterisk implements fully, and takes the whole question away.

@keshavdutt Are you replying to posts here using LLM output? If so, disclose it and also be aware that some individuals don’t like being responded to with the copy/paste of an LLM.

Thank you everyone.

The line:

load = res_pjsip_empty_info.so

was not in /etc/asterisk/modules.conf.

After adding it and restarting Asterisk the INFO messages are being replied to with an OK message.

I checked using tcpdump -i eth0 -w /tmp/sip2.pcap port 5060and could see the OK messages being sent after the INFO message. Let the call continue for 9 minutes and the connection did not drop.

Thanks for the help and the very quick responses.

Shouldn’t this be raised as an issue, as a UAS should never ignore requests, even if it doesn’t know what to do with them.

I raised a ticket in the pjsip project and it was rejected.

Asterisk was built from source and the res_pjsip_empty_info.so module was built. However, it was not included in the modules.conf.

Maybe this has been fixed in a later version; I didn’t was to build the latest version without SIP, just in case.