PJSIP identify by match_header vs. match by ip

I’ve got the following pjsip.conf:

[transport-udp]
type=transport
bind=0.0.0.0:5060
protocol=udp
allow_reload=yes


[registrar]
type=identify
endpoint=registrar
match=172.31.9.202
match=172.31.10.12

[registrar]
type=aor
contact=sip:registrar-intmd.example.com

[registrar]
type=endpoint
transport=transport-udp
context=dial
disallow=all
allow=ulaw,alaw
aors=registrar
force_rport=yes
direct_media=no
rtp_symmetric=yes
rtp_timeout=120


[remote_atx]
type=identify
endpoint=remote_atx
match_header=X-Remote-Atx: true

[remote_atx]
type=endpoint
transport=transport-udp
context=remote_atx
disallow=all
allow=ulaw,alaw
aors=registrar
force_rport=yes
direct_media=no
rtp_symmetric=yes
refer_blind_progress=no
rtp_timeout=120
identify_by=header

What I’m trying to achieve is that normal invites from the IP addresses listed in the registrar identify must go to the registrar-context, and invites that contains a X-Remote-Atx: true header must go to the remote_atx.

The servers that sends these invites are Kamailio servers, and the purpose of it all is to handle Remote Attended Transfers, so whenever Kamailio sees an INVITE from an Asterisk server with a Replaces header, it’ll find out which server has the Call-ID referenced in this header, and forward that INVITE to the appropriate Asterisk server.

This works excellently, Asterisk magically performs a switch when it sees this invite with a Replaces-header:

    -- Channel PJSIP/registrar-00000000 left 'simple_bridge' basic-bridge <09141555-cb02-4efc-8a7f-50c995c49cc0>
    -- Channel PJSIP/registrar-00000002 swapped with PJSIP/registrar-00000000 into 'simple_bridge' basic-bridge <09141555-cb02-4efc-8a7f-50c995c49cc0>

However, I use AMI events from these servers for a ton of stuff, and I’d like the INVITE with the Replaces-header to be placed in the remote_atx context, instead of the registrar one.

This is what I’m trying to do with the [remote_atx] identify and endpoint, however it seems that PJSIP just sees that this is from one of the IP addresses in the [registrar] identify section, and just shoves this invite into the “dial” context.

Is there some method I can use that’ll make the match by match_header take precedence over identify by IP?

There isn’t a defined matching order for such a thing I’m afraid. It’s meant to be one or the other, not a combination of both usage from the same thing.

Ah that sucks! But I suspected it would’ve been like this.

The best way to go about it I guess would be to have a dedicated kamailio server to bounce these INVITEs around between the Asterisk boxes.

A clarification on how Asterisk reacts when receiving these INVITEs with a Replaces-header attached to them - if you know…

Does the call actually enter the Dialplan in the context associated with the PJSIP endpoint, or does the swap happen at an earlier stage? It looks like not a single line of dialplan code is executed, but I want to fully understand how Asterisk reacts to these.

If it’s for a dialog that is local then no dialplan occurs. If it’s for a dialog that is remote then it should execute dialplan. That being said, the remote functionality is rarely (if ever) used or exercised. The code is self contained[1]. I haven’t touched it or seen it used since it was probably originally written. Looking at the testsuite seems to show we have a test for it[2], so that may shine light on things.

[1] https://github.com/asterisk/asterisk/blob/master/res/res_pjsip_refer.c#L756
[2] https://github.com/asterisk/testsuite/tree/master/tests/channels/pjsip/transfers/attended_transfer/nominal/caller_remote

Ah I was more thinking on the Asterisk server that’s on the receiving end of the Remote Attended Transfer.

It seems, from Asterisk output, that the call is placed in a channel within whatever context gets matched by the identify/endpoint configuration. What I’m trying to understand is if any of the dialplan code associated with that endpoint code is ever executed. Is there any way to react to the incoming Remote Attended Transfer and potentially reject it?

It seems like Asterisk reacts to it and just does the bridging as soon as it sees a call in the Replaces header of the incoming INVITE, without offering any way to decide if I want to honor it.

It’s not an issue for me, as I DO want to honor it - it’s more in an effort to fully understand this feature. I’ve got my Kamailio servers in front of my Asterisk servers to handle the security part of it.

The only documentation I’ve found is this: https://wiki.asterisk.org/wiki/display/AST/res_pjsip+Remote+Attended+Transfers, which only really concerns itself with what happens on the Asterisk server that receives an REFER referencing a Call-ID the asterisk box doesn’t know, which triggers the external_replaces extension to be executed.

If it’s a known about call leg and a normal attended transfer then no, there is no ability that I’m aware of to reject such a thing. It happens automatically.

Excellent - I suspected as much!

Is this a feature that’s never really seeing any use, since it’s so scarcely documented? From what I can gauge it works just as described.

Is there another more preferred method of handling Attended Transfers within a cluster of Asterisk servers?

A deployment method like you’re referring to is not done by the majority of Asterisk users. Someone who has deployed such a thing may respond and provide further thoughts.