PJSIP extension with 2 contacts; parked call returns to wrong device after timeout

Hello,

I’ve received a report from a customer that when they park a call on their primary device it rings back to their secondary device once the timeout is reached. This is on 12.7.6-1904-1.sng7 with Asterisk 13.22

I’ve had a tech onsite to confirm this, and can’t see anything in the config that would impact this. Anyone encountered and/or solved this problem before?

Take care,

Nate

You have two devices using the same PJ-SIP extension, right?

Does the call always return to the “other” device, or do the calls always return to the same device?

I’d expect the latter. The other would be strange, but could be a bug.

Exactly right. I have two devices connected to the same extension, and if you park a call via device A, it returns to device B.

I think my expectation would be that both devices would ring, though I’d be happy with just the device that parked the call ringing.

I agree, I think it is a bug. But I figured I’d throw it out there to see if anyone had any suggestions. I’m going to try Asterisk 16 and see if the behavior is the same before I open a bug report.

Cheers,

Nate

Logs should tell you what’s up, AFAIK, before a parked call is returned the PBX checks if the extension in inuse, if so it won’t return the call.

Yep, logs show it is returning to the original extension, which is not in use. However it’s only ringing the device that did NOT park the call.

As far as I can tell, logs don’t show anything about specific contacts registered to a pjsip extension, just the extension itself.

Would you know if that device was free?

I’m sure there’s more digging/testing I can do, such as trying to place a call to the extension, checking device state via hints, etc., though we did have a tech out there confirm the device is being hung up after placing the call. So if the device is showing in use, then that would be an issue as well.

Was curious if anyone had encountered this before, and if anyone has a box with two devices connected to a single extension and could test this, that would be helpful. I’ve duplicated the issue on multiple systems. I’m not at the office right now but when I am I will test on Asterisk 16, and check a few more things.

@ngingras At this point you need to show this happening so we can see how the system is building the call back to the parker. We need to see some verbose log output.

In addition to actually providing logs and such, you need to be more precise in your description.

Does it always return to he opposite phone?
When you park a call with phone A does it always return to phone B?
When you park a call with phone B does it always return to phone A?

Look at the AOR list for the extension.
Does it always go to the contact listed first?

I’ve had an issue in the past with the dial pad in FOP2 only sending calls to the first AOR. It was a super low priority that I have never spent time looking into yet.

I noticed the same behavior as Nate.

Not in my case.

Yes, the first contact is always used, no matter from which device the call was parked.

So sounds like something needs updated to ring all AOR but is instead only ringing the first because the old chan_sip never had more functionality.

1 Like

I didn’t have much time to test this today, however one of the techs I work with did check and verify that the issue still exists in Asterisk v16 and that both phones ring if called immediately after parking a call. He didn’t have time to test if it was always the first contact that rings.

Confirmed it is the first Contact that rings every time.

Trying to determine the best way to report this; I don’t know enough about how this works to determine if this would be a FreePBX issue (seems less likely) or an Asterisk issue (seems more likely)

I don’t think there’s any dial plan associated with delivering calls to contacts of an AOR and that leads me to believe it’d be Asterisk related.

We need to look at the generated dial plan for parking and see what FreePBX is doing to the returned call.

You provide the information that was requested so we can review it. So a verbose debug of the call output.

FreePBX does nothing but generate configs and dialplan for this in Asterisk, so if it’s a FreePBX issue then it’s because something is being generated wrong. Everything else after that would be Asterisk because that is what is parking the call, dialing the call, etc.

There is dialplan, there are things that happen that you might not be aware of. Parking will generate it’s own dialplan on the fly as well based on the parking lot. In order to dial an extension you must issue a Dial() command. This is all 100% dialplan in that regards.

You’ve admitted you’re know sure how to determine any of this but instead of providing the output details from your testing so we could see hard evidence. You just did the test and told us what you think it meant. This is just not moving us forward and wasting time.

While a call log is going to be required, you could calm down and actually look at the code as I mentioned.

Now that I am at home, I did. It is very clear in the code what is happening. Here is the dial plan generated on my system.

[park-return-routing]
include => park-return-routing-custom
exten => 720,1,Set(PLOT=720)
exten => 720,n,ExecIf($[${LEN(${PREPARK_CID})} = 0]?Set(PREPARK_CID=${CALLERID(name)}))
exten => 720,n,Set(CALLERID(name)=${PARKINGSLOT}:${PREPARK_CID})
exten => 720,n,ExecIf($["${ALERT_INFO}"!=""]?Set(HASH(__SIPHEADERS,Alert-Info)=${ALERT_INFO}))
exten => 720,n,ExecIf($["${RVOL}"!=""]?Set(HASH(__SIPHEADERS,Alert-Info)=${ALERT_INFO}\;volume=${RVOL}))
exten => 720,n,Dial(${PARKCALLBACK},15,b(func-apply-sipheaders^s^1),tr)
exten => 720,n,Set(PARKCALLBACK=)
exten => 720,n,Goto(ext-local,vmi103,1)

exten => 721,1,Goto(720,1)

exten => 722,1,Goto(720,1)

exten => 723,1,Goto(720,1)

exten => 724,1,Goto(720,1)

exten => 725,1,Goto(720,1)

;--== end of [park-return-routing] ==--;

It is a Dial command exten => 720,n,Dial(${PARKCALLBACK},15,b(func-apply-sipheaders^s^1),tr)

PARKCALLBACK is set in [macro-park-call] to PARKER

exten => s,n,Noop(PARKRETURNTO: ${SHARED(PARKRETURNTO,${CHANNEL})})
exten => s,n,Park(${ARG2},sc(${CONTEXT},s,200))
exten => s,1+199(backtosender),Noop(Attempting to go back to sender)
exten => s,n,Set(PARKCALLBACK=${PARKER})
exten => s,n,Set(SHARED(PARKRETURNTO,${CHANNEL})=)
exten => s,n,Goto(park-return-routing,${PARKINGSLOT},1)

But I don’t know where PARKER comes from with a quick look, as that is the only reference.

[jbusch@pbx ~]$ sudo grep PARKER /etc/asterisk/*.conf
/etc/asterisk/extensions_additional.conf:exten => s,n,Set(PARKCALLBACK=${PARKER})
[jbusch@pbx ~]$ 

Here is a call log. I called in from my mobile, dialled my extension in the IVR, answered, direct parked to slot 1, let it time out, let that fail to abandoned, hung up my mobile.

https://pastebin.com/UMLzhmak

Relevant bits:

it decided the return dial string was PJSIP/103:

[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:28] Set("PJSIP/Bundy_Twilio-000004cb", "PARKINGEXTEN=721") in new stack
[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:29] ExecIf("PJSIP/Bundy_Twilio-000004cb", "1?Set(SHARED(PARKRETURNTO,PJSIP/Bundy_Twilio-000004cb)=PJSIP/103):Set(SHARED(PARKRETURNTO,PJSIP/Bundy_Twilio-000004cb)=)") in new stack
[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:30] NoOp("PJSIP/Bundy_Twilio-000004cb", "PARKRETURNTO: PJSIP/103") in new stack
[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:31] Park("PJSIP/Bundy_Twilio-000004cb", "default,sc(macro-parked-call,s,200)") in new stack
[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] parking/parking_applications.c: Setting Parker dial string to PJSIP/103 from BLINDTRANSFER value
[2019-09-19 00:20:25] VERBOSE[8406][C-000002ca] parking/parking_bridge.c: Parking 'PJSIP/Bundy_Twilio-000004cb' in 'default' at space 721

timer ran out.

[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] res_musiconhold.c: Stopped music on hold on PJSIP/Bundy_Twilio-000004cb
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:200] NoOp("PJSIP/Bundy_Twilio-000004cb", "Attempting to go back to sender") in new stack
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:201] Set("PJSIP/Bundy_Twilio-000004cb", "PARKCALLBACK=PJSIP/103") in new stack
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:202] Set("PJSIP/Bundy_Twilio-000004cb", "SHARED(PARKRETURNTO,PJSIP/Bundy_Twilio-000004cb)=") in new stack
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@macro-parked-call:203] Goto("PJSIP/Bundy_Twilio-000004cb", "park-return-routing,721,1") in new stack
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx_builtins.c: Goto (park-return-routing,721,1)

executing the dial line.

[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [720@park-return-routing:6] Dial("PJSIP/Bundy_Twilio-000004cb", "PJSIP/103,15,b(func-apply-sipheaders^s^1),tr") in new stack

sip headers applied, and dial happened.

[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] pbx.c: Executing [s@func-apply-sipheaders:13] Return("PJSIP/103-000004cf", "") in new stack
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] app_stack.c: Spawn extension (from-internal, 720, 1) exited non-zero on 'PJSIP/103-000004cf'
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] app_stack.c: PJSIP/103-000004cf Internal Gosub(func-apply-sipheaders,s,1) complete GOSUB_RETVAL=
[2019-09-19 00:22:25] VERBOSE[8406][C-000002ca] app_dial.c: Called PJSIP/103

So, the other two phones registered to my ext are not where I could know if they were ringing. My desk is the first contact listed in the AOR, and it was ringing. See the picture in the previous post

It is generated by res_parking when it is used. There are about 4 or 5 variables that are set when parking happens due to res_parking. If PJSIP/103 parked the call then ${PARKER} is set to the flatten version of that and becomes PJSIP_103 and then in the dialplan it does a replace of _ with / to make the dial string PJSIP/103 again to use in the Dial().

Dial(PJSIP/103) will dial all the contacts in the AOR. To help verify this, instead of just running a verbose output of the dialplan, you need to run a pjsip set logger to verify all the contacts are being dialed.

Currently the core isn’t capable of dialling a single endpoint resulting in multiple channels, thus why the PJSIP_DIAL_CONTACTS dialplan function exists. If the dialplan logic was extended to examine the parker and if PJSIP to get the endpoint and replace it with a PJSIP_DIAL_CONTACTS result then it would work.

3 Likes

Point.