[Home]

Summary:ASTERISK-29704: res_pjsip_pubsub: Treats SUBSCRIBE with Expires 0 as invalid when it is valid
Reporter:Niksa Baldun (niksa)Labels:
Date Opened:2021-10-25 02:54:29Date Closed:
Priority:MinorRegression?No
Status:Open/NewComponents:Resources/res_pjsip_pubsub
Versions:18.7.1 Frequency of
Occurrence
Constant
Related
Issues:
Environment:Debian Linux 10Attachments:
Description:When res_pjsip receives SUBSCRIBE request with Expires=0, it responds with with 400 Bad request. Excerpt from res_pjsip_pubsub.c:

{code}
       if (expires_header->ivalue == 0) {
           ast_debug(1, "Subscription request from endpoint %s rejected. Expiration of 0 is invalid\n",
               ast_sorcery_object_get_id(endpoint));
           pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
               return PJ_TRUE;
       }
{code}

However, Expires of 0 is perfectly valid. Relevant text from RFC 3265, section 3.1.1:

{quote}
  A natural consequence of this scheme is that a SUBSCRIBE with an
  "Expires" of 0 constitutes a request to unsubscribe from an event.

     In addition to being a request to unsubscribe, a SUBSCRIBE message
     with "Expires" of 0 also causes a fetch of state; see section
     3.3.6.
{quote}

Therefore, a SUBSCRIBE with Expires=0 should cause one NOTIFY to be sent, and remove the subscription if it exists.
Comments:By: Asterisk Team (asteriskteam) 2021-10-25 02:54:31.311-0500

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution. Please note that log messages and other files should not be sent to the Sangoma Asterisk Team unless explicitly asked for. All files should be placed on this issue in a sanitized fashion as needed.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

Please note that once your issue enters an open state it has been accepted. As Asterisk is an open source project there is no guarantee or timeframe on when your issue will be looked into. If you need expedient resolution you will need to find and pay a suitable developer. Asking for an update on your issue will not yield any progress on it and will not result in a response. All updates are posted to the issue when they occur.

Please note that by submitting data, code, or documentation to Sangoma through JIRA, you accept the Terms of Use present at [https://www.asterisk.org/terms-of-use/|https://www.asterisk.org/terms-of-use/].

By: George Joseph (gjoseph) 2021-10-25 11:07:38.931-0500

Just FYI...  The code snippet quoted is in pubsub_on_rx_subscribe_request() which only gets called on new dialogs.  We do erroneously treat the expires=0 as a failure when we should send a NOTIFY but not create a persistent subscription.   We handle expires=0 on *in-dialog* SUBSCRIBE termination requests correctly in  pubsub_on_rx_refresh().


By: Niksa Baldun (niksa) 2021-10-25 11:20:32.640-0500

The reason I've noticed this is that I've tried to unsubscribe with Expires=0 and got a 400 response. There might be a problem in my code, I'll re-test.

By: Niksa Baldun (niksa) 2021-10-26 03:04:15.205-0500

There was a problem with my code, but now that I've corrected it I am getting a new error: 500 Unhandled by dialog usages. That would imply that re-subscribe or unsubscribe is invalid within same dialog. However, RFC states:

{quote}
  In order to keep subscriptions effective beyond the duration
  communicated in the "Expires" header, subscribers need to refresh
  subscriptions on a periodic basis using a new SUBSCRIBE message on
  the same dialog as defined in SIP.
{quote}

{panel:bgColor=yellow}
SUBSCRIBE sip:888@127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:5070;branch=z9hG4bKBkIIVXmQY3
Accept: application/dialog-info+xml
Accept-Encoding: zlib+base64
CSeq: 1 SUBSCRIBE
Call-ID: 5c2a4364-35a4-4ddc-941c-9961bdd819ec
Contact: <sip:999@127.0.0.1:5070>
Content-Length: 0
Event: dialog
Expires: 3600
From: <sip:999@127.0.0.1>;tag=fb7e68040562b05a
Max-Forwards: 70
To: <sip:888@127.0.0.1>
User-Agent: CS


SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 127.0.0.1:5070;received=127.0.0.1;branch=z9hG4bKBkIIVXmQY3
Call-ID: 5c2a4364-35a4-4ddc-941c-9961bdd819ec
From: <sip:999@127.0.0.1>;tag=fb7e68040562b05a
To: <sip:888@127.0.0.1>;tag=z9hG4bKBkIIVXmQY3
CSeq: 1 SUBSCRIBE
WWW-Authenticate: Digest realm="asterisk",nonce="1635232984/49c720a890c5b681325e891ed0db9015",opaque="7144850e016c1658",algorithm=md5,qop="auth"
Server: Asterisk PBX 18.6.0
Content-Length:  0


SUBSCRIBE sip:888@127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:5070;branch=z9hG4bKM2U0JloZuM
Accept: application/dialog-info+xml
Accept-Encoding: zlib+base64
Authorization: Digest uri="sip:888@127.0.0.1", username="999", response="02a42a41ffec8025b3a4dfc829ba12a5", method="SUBSCRIBE", realm="asterisk", nonce="1635232984/49c720a890c5b681325e891ed0db9015", opaque="7144850e016c1658", algorithm=md5, qop="auth", nc="1", cnonce="kqwPWoKqKH"
CSeq: 2 SUBSCRIBE
Call-ID: 5c2a4364-35a4-4ddc-941c-9961bdd819ec
Contact: <sip:999@127.0.0.1:5070>
Content-Length: 0
Event: dialog
Expires: 3600
From: <sip:999@127.0.0.1>;tag=fb7e68040562b05a
Max-Forwards: 70
To: <sip:888@127.0.0.1>
User-Agent: CS


SUBSCRIBE sip:888@127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:5070;branch=z9hG4bKBkIIVXmQY3
Accept: application/dialog-info+xml
Accept-Encoding: zlib+base64
CSeq: 3 SUBSCRIBE
Call-ID: 5c2a4364-35a4-4ddc-941c-9961bdd819ec
Contact: <sip:999@127.0.0.1:5070>
Content-Length: 0
Event: dialog
Expires: 0
From: <sip:999@127.0.0.1>;tag=fb7e68040562b05a
Max-Forwards: 70
To: <sip:888@127.0.0.1>;tag=fe34b375-d09d-479b-a4f5-8745451763eb
User-Agent: CS


SIP/2.0 500 Unhandled by dialog usages
Via: SIP/2.0/UDP 127.0.0.1:5070;received=127.0.0.1;branch=z9hG4bKBkIIVXmQY3
Call-ID: 5c2a4364-35a4-4ddc-941c-9961bdd819ec
From: <sip:999@127.0.0.1>;tag=fb7e68040562b05a
To: <sip:888@127.0.0.1>;tag=fe34b375-d09d-479b-a4f5-8745451763eb
CSeq: 3 SUBSCRIBE
Server: Asterisk PBX 18.6.0
Content-Length:  0
{panel}

By: Joshua C. Colp (jcolp) 2021-10-26 04:15:53.440-0500

Unsubscribe and re-subscribe are properly handled within PJSIP, we know this for a fact. We have test coverage for both and they are so widely used and done that if there were a problem we'd quickly find out.

The issue is with your implementation. I don't know off the top of my head, plus you didn't provide a full trace.

Are you implementing your own SIP stack or something?

By: Niksa Baldun (niksa) 2021-10-26 06:08:46.447-0500

Yes, partial SIP implementation. Anyway, I was running the service on the same machine as Asterisk, and Asterisk wouldn't send a NOTIFY in that case. Why, I couldn't begin to guess. That's what caused "Unhandled by dialog usages" - Asterisk thought it sent a NOTIFY and didn't receive a response. When I tried subscribing from another host, everything was fine.

So, the only problem is Expires=0 in a new dialog. Obviously, a very minor issue.