Can I read the SIP INVITE Request-URI in a variable or from a function?

I have a case where a third-party phone switch sends a SIP INVITE to an Asterisk system I control in which the Request-URI in the SIP INVITE includes a crucial piece of information that I need in order to properly handle the call.

Is there a way to get the contents of the the Request URI from the initial SIP INVITE in some variable or a function call in a dial plan, or anywhere else during call processing, in Asterisk?

Following are two examples of the SIP INVITE message with varying information. The piece that is critical for this function is the “role=xxxx” portion of the Request-URI:

INVITE sip:7002015278@10.1.16.116:5060;transport=udp;role=orig SIP/2.0

INVITE sip:7002015277@10.1.16.116:5060;transport=udp;role=term SIP/2.0

That “role=orig” or “role=term” are critical for how I handle the call routing. Any way to access, read, or make a decision based on this information would give me what I need. Does anyone know of a way to act on that information?

Thank you!

The RURI is available in PJSIP using the CHANNEL(pjsip,target_uri) dialplan function[1] in the dialplan but I don’t believe chan_sip exposes the information. As it returns the URI you would need to parse/interpret it yourself.

[1] https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+Function_CHANNEL

1 Like

Excellent, thank you! I will likely switch to something using PJSIP then and try CHANNEL(pjsip,target_uri).

However, since you brought it up in:

I’m fine with parsing the RURI myself in an AGI script or something of that nature, but I haven’t found a way to get the info from the INVITE request itself via chan_sip - is there a way to get that info?

Looking in chan_sip quickly no, I don’t see a way.

OK, thank you very much!

I am now using Asterisk 13 and have implemented PJSIP. Unfortunately, CHANNEL(pjsip,target_uri) does not give me what I need. In fact, it seems to be incorrect, in addition to not being what I need. It appears to give me a portion of either the "From: " or "Contact: " SIP Header.

I would rather not publicly post the entire SIP packet, so I have sanitized my packet; I have replaced a local TN that is the caller id of the calling line with the characters “NPANXXXXXX” and I have changed two IP addresses with “aaa.bbb.ccc.ddd” and “eee.fff.ggg.hhh”, respectively. Here is the SIP packet:

<--- Received SIP request (1100 bytes) from UDP:aaa.bbb.ccc.ddd:5060 --->
INVITE sip:7002015278@10.1.16.117:5060;transport=udp;role=orig SIP/2.0
Via: SIP/2.0/UDP aaa.bbb.ccc.ddd:5060;rport;branch=z9hG4bK-c3fe5f0b107b3ef946ebfe0581a490021-aaa.bbb.ccc.ddd-1
Allow-Events: message-summary, refer, dialog, line-seize, presence, call-info, as-feature-event, calling-name
Call-ID: 0CD09489@aaa.bbb.ccc.ddd
From: <sip:NPANXXXXXX@aaa.bbb.ccc.ddd>;tag=aaa.bbb.ccc.ddd+1+11a9e2a+d0c25f9f;isup-oli=00
To: <sip:7002015278@aaa.bbb.ccc.ddd>
CSeq: 936584710 INVITE
Expires: 180
Organization: Full Service Network
Supported: resource-priority, siprec, 100rel
Content-Length: 140
Content-Type: application/sdp
Allow: INVITE, ACK, CANCEL, BYE, REGISTER, OPTIONS, PRACK, UPDATE, SUBSCRIBE, NOTIFY, REFER, INFO, PUBLISH
Max-Forwards: 69
Contact: <sip:NPANXXXXXX@aaa.bbb.ccc.ddd>;isup-oli=00
Alert-Info: normal
Route: <sip:30c515a@aaa.bbb.ccc.ddd;lr>
P-Charging-Vector: icid-value=30c755d
P-Asserted-Identity: <sip:7002015277@aaa.bbb.ccc.ddd>

v=0
o=- 2976361482 2976361482 IN IP4 eee.fff.ggg.hhh
s=-
c=IN IP4 eee.fff.ggg.hhh
t=0 0
m=audio 23640 RTP/AVP 0
a=ptime:20
a=sendrecv

And when I do the following in extensions.ael:

                NoOP(${CHANNEL(pjsip,target_uri)});
                NoOP(${CHANNEL(pjsip,local_uri)});
                NoOP(${CHANNEL(pjsip,remote_uri)});
                NoOP(${CHANNEL(pjsip,local_addr)});
                NoOP(${CHANNEL(pjsip,remote_uri)});

Then I get:

    -- Executing [7002015278@SOMECONTEXT:6] NoOp("PJSIP/server.domain.tld-0000000c", "sip:NPANXXXXXX@aaa.bbb.ccc.ddd") in new stack
    -- Executing [7002015278@SOMECONTEXT:7] NoOp("PJSIP/server.domain.tld-0000000c", "<sip:7002015278@aaa.bbb.ccc.ddd>") in new stack
    -- Executing [7002015278@SOMECONTEXT:8] NoOp("PJSIP/server.domain.tld-0000000c", "<sip:NPANXXXXXX@aaa.bbb.ccc.ddd>") in new stack
    -- Executing [7002015278@SOMECONTEXT:9] NoOp("PJSIP/server.domain.tld-0000000c", "") in new stack
    -- Executing [7002015278@SOMECONTEXT:10] NoOp("PJSIP/server.domain.tld-0000000c", "<sip:NPANXXXXXX@aaa.bbb.ccc.ddd>") in new stack

Whereas, the information I’m trying to get is the full RURI from the INVITE request:

sip:7002015278@10.1.16.117:5060;transport=udp;role=orig

Do you have any further suggestions on how I might retrieve this info?

I appreciate your help so far, and any help you can provide. Thanks!

Ah, it’s giving strictly the URI as user/host…

No, you’ll need to do code modifications if you need that information.

OK. Thanks for the help.

Note, that in the RURI, the user@host is: 7002015278@10.1.16.117, but I don’t find that in any of my output; the closest I get is from CHANNEL(pjsip,local_uri) which yields: 7002015278@aaa.bbb.ccc.ddd (where aaa.bbb.ccc.ddd is the originating server that sent the SIP packet to me.)

Sigh, onto Asterisk code modifications. (Which I haven’t done before, so it’ll be a learning curve…) – any recommendations for where to start if I intend to possibly send a patch back to the group? Should I grab the latest release/head/a specific branch/etc?

The actual process for contributing a patch is documented on the wiki[1]. As for where to start for a branch it’d be the oldest supported, 13, since it’d be a bug fix and the file which contains that functionality is channels/pjsip/dialplan_functions.c in the function channel_read_pjsip.

[1] https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process

Maybe this to be the required function?

--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -688,6 +688,11 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const
                ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject which does not have the required functionality to support the 'secure' argument. Please upgrade to version 2.3 or later.\n");
                return -1;
 #endif
+       } else if (!strcmp(type, "request_uri")) {
+               struct pjsip_request_line *req = channel->session->inv_session->inv_request->msg->line->req;
+               pjsip_uri_print(PJSIP_URI_IN_REQ_URI, req, buf, buflen);
+               buf_copy = ast_strdupa(buf);
+               ast_escape_quoted(buf_copy, buf, buflen);
        } else if (!strcmp(type, "target_uri")) {
                pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->target, buf, buflen);
                buf_copy = ast_strdupa(buf);

Who can try this?

FYI, this has been resolved in chan_sip per ASTERISK-27278 – it looks like the above reply by @schoberw may solve it for chan_pjsip, but I no longer have the appropriate systems setup to test pjsip for this, so I cannot verify that.

Build now, but patch above is wrong. Correct is:

+	} else if (!strcmp(type, "request_uri")) {
+		// inv_session is defined in /usr/include/pjsip-ua/sip_inv.h, msg in /usr/include/pjsip/sip_msg.h
+		pjsip_uri *req = channel->session->inv_session->invite_req->msg->line.req.uri;
+		pjsip_uri_print(PJSIP_URI_IN_REQ_URI, req, buf, buflen);
+		buf_copy = ast_strdupa(buf);
+		ast_escape_quoted(buf_copy, buf, buflen);

There is SIPDOMAIN variable in chan_sip, what about port? is there any way to get ruri port?