Can't get PJSIP reverse autopatch to work

I think I almost have reverse autopatch working with PJSIP and Flowroute. Using this as a guide ASL3 Autopatch & Reverse Autopatch · GitHub. I’m getting the call coming in, but it’s not routing right I think. The call comes in via pjsip and appears to be directed to the reverse-autopatch context in extensions.conf. It picks up the call before the first ring finishes, and then it sits idle just over 30 seconds before hangup. I see in the console that it’s trying to run rpt and connect the call to the node, but it never seems to get there. No audio is passed from phone to radio or back the other way and then it drops the call. I tried making a very simple dialplan for testing and same result. Here is what I have added to extensions.conf:

[reverse-autopatch]

; Connect the caller to the repeater using the “rpt” command.
; The “|P” option is used to specify “phone” mode in app_rpt.
exten => _X.,1,rpt(49555|Pv)

; Hang up the call after the connection is made.
exten => _X.,n,Hangup()

When the call comes in, I see this:

root@pi4allstar:~# asterisk -r -vvv
Asterisk 20.9.3+asl3-3.0.6-1.deb12, Copyright (C) 1999 - 2022, Sangoma Technologies Corporation and others.
Created by Mark Spencer markster@digium.com
Asterisk comes with ABSOLUTELY NO WARRANTY; type ‘core show warranty’ for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type ‘core show license’ for details.

Connected to Asterisk 20.9.3+asl3-3.0.6-1.deb12 currently running on pi4allstar (pid = 2738)
– Executing [14322031499@reverse-autopatch:1] Rpt(“PJSIP/flowroute-trunk-00000003”, “49555|Pv”) in new stack
– Hungup ‘DAHDI/pseudo-828692132’

I have also added an answer to the dial plan followed by saying connected for testing and I never hear it say anything. Not sure what I have done wrong.

You have to answer the call first:

[reverse-autopatch]
; Answer the incoming call.
exten => _X.,1,Answer()

; Wait for 1 second to ensure the line is stable.
exten => _X.,n,Wait(1)

; Connect the caller to the repeater using the "rpt" command.
exten => _X.,n,rpt(${NODE}|P)

; Hang up the call after the connection is made.
exten => _X.,n,Hangup()

I forgot to mention I did try that just in case. Docs say you should not answer the call if it’s going to be connected somewhere unless you need to play messages or anything else, at least asterisk docs. But, even with the answer and wait added, the call does not connect to the node. Slightly different error though:

Connected to Asterisk 20.9.3+asl3-3.0.6-1.deb12 currently running on pi4allstar (pid = 3403)
– Executing [14322031499@reverse-autopatch:1] Answer(“PJSIP/flowroute-trunk-00000000”, “”) in new stack
– Executing [14322031499@reverse-autopatch:2] Wait(“PJSIP/flowroute-trunk-00000000”, “1”) in new stack
– Auto fallthrough, channel ‘PJSIP/flowroute-trunk-00000000’ status is ‘UNKNOWN’
pi4allstar*CLI>

Ok, not sure on any of that. I am not very experienced with Asterisk or dialplans, I just happened to get far enough along to get my autopatch working and throw a guide together.

I’m loving that dialplan in your guide. Once I get the call to connect, I will be adding all that back. For reference, here is what I used for that last test in extensions.conf:

; REVERSE-AUTOPATCH - REPEATER RECEIVES INCOMING CALLS
[reverse-autopatch]
; Answer the incoming call.
exten => _X.,1,Answer()

; Wait for 1 second to ensure the line is stable before playing the prompt.
exten => _X.,n,Wait(1)

; “rpt/connected” could say something like: “You are now connected.”
;exten => _X.,n,Playback(rpt/connected)

; Connect the caller to the repeater using the “rpt” command.
; The “|P” option is used to specify “phone” mode in app_rpt.
exten => _X.,1,rpt(49555|Pv)

; Hang up the call after the connection is made.
exten => _X.,n,Hangup()

If you call your node while watching asterisk -r -vvv, what do you see for the rpt command in the output, like this part?:

-- Executing [14322031499@reverse-autopatch:1] Rpt("PJSIP/flowroute-trunk-00000003", "49555|Pv") in new stack

It bothers me that the R in Rpt is capitalized but it doesn’t seem to matter, I have zoiper setup on cellphone connecting to node as well. It connects successfully to the node and audio is passed both ways.

Connected to Asterisk 20.9.3+asl3-3.0.6-1.deb12 currently running on pi4allstar (pid = 3573)
– Executing [49555@sip-phones:1] Ringing(“PJSIP/1001-00000002”, “”) in new stack
– Executing [49555@sip-phones:2] Answer(“PJSIP/1001-00000002”, “3000”) in new stack
[2024-10-15 13:40:57.883] WARNING[3809][C-0000000d]: channel.c:1086 __ast_queue_frame: Exceptionally long voice queue length (97 voice / 97 total) queuing to PJSIP/1001-00000002
– Executing [49555@sip-phones:3] Set(“PJSIP/1001-00000002”, “NODENUM=1001”) in new stack
– Executing [49555@sip-phones:4] Rpt(“PJSIP/1001-00000002”, “49555|Pv”) in new stack
– Hungup ‘DAHDI/pseudo-2113427603’
pi4allstar*CLI>

Seems to be passing the call to rpt the same way but with the extension number instead of the trunk name.

From extensions.conf

[sip-phones]
exten => 1001,1,Dial(PJSIP/${EXTEN},60,rT)

exten => ${NODE},1,Ringing
exten => ${NODE},n,Answer()
exten => ${NODE},n,Set(NODENUM=${CALLERID(number)})

; exten => ${NODE},n,Playback(extension)
; exten => ${NODE},n,SayDigits(${NODENUM})
exten => ${NODE},n,Playback(connected)
; exten => ${NODE},n,Playback(rpt/node)
; exten => ${NODE},n,SayDigits(${EXTEN})
exten => ${NODE},n,rpt(${EXTEN}|Pv)
exten => ${NODE},n,Hangup

Dialplan:

; REVERSE-AUTOPATCH - REPEATER RECEIVES INCOMING CALLS
[reverse-autopatch]
; Show the incoming call in the console
exten => _X.,1,NoOp(Incoming reverse-autopatch from ${CALLERID(num)})

; Answer the incoming call.
exten => _X.,n,Answer()

; Wait for 1 second to ensure the line is stable before playing the prompt.
exten => _X.,n,Wait(1)

; Optional: Bypass PIN for trusted caller
; Uncomment the below line to enable this feature:
; exten => _X.,n,GotoIf($["${CALLERID(num)}" = "5551234567"]?connect,1)

; Initialize an attempt counter
exten => _X.,n,Set(ATTEMPTS=0)

; Play a message that asks the caller to enter their PIN followed by the pound/hash key.
exten => _X.,n(start),Playback(confbridge-pin)

; Wait for the caller to enter a 4-digit PIN.
exten => _X.,n,Read(PIN,beep,4,,,5)

; Check if the entered PIN is one of the valid PINs.
exten => _X.,n,GotoIf($["${PIN}" = "1234"]?wait-for-pound)

; Increment the attempt counter
exten => _X.,n,Set(ATTEMPTS=$[${ATTEMPTS}+1])

; If the PIN is invalid, play a message saying it was incorrect.
exten => _X.,n,Playback(confbridge-invalid)

; Check if the attempt counter has reached 3
exten => _X.,n,GotoIf($[${ATTEMPTS} >= 3]?too-many-failures)

; Go back to the start and ask the user to enter the PIN again.
exten => _X.,n,Goto(start)

; If the user fails to enter a valid PIN after 3 attempts, play a message saying they have entered too many invalid PINs.
exten => _X.,n(too-many-failures),Playback(confbridge-pin-bad)

; Hang up the call after the failure message.
exten => _X.,n,Hangup()

; After the valid PIN is entered, wait for the user to press the "#" key.
exten => _X.,n(wait-for-pound),WaitExten(5)

; If the user presses "#", go to the "connect" label.
exten => #,1,Goto(connect,1)

; If "#" is not pressed, go to the start label.
exten => _X.,99,Goto(start)

; If the correct PIN was entered and "#" was pressed, play a message confirming the connection.
exten => connect,1,Playback(rpt/welcome)

; Connect the caller to the repeater using the "rpt" command.
exten => connect,n,rpt(${NODE}|P)

; Hang up the call after the connection is made.
exten => connect,n,Hangup()

Console when accepting a reverse-autopatch call:

CLI> core set verbose 10
Console verbose was OFF and is now 10.
    -- Accepting AUTHENTICATED call from xxx.xxx.xxx.xxx:4569:
    --        > requested auth methods = (MD5),
    --        > actual auth method = MD5,
    --        > encrypted = no,
    --        > requested format = ulaw,
    --        > requested prefs = (ulaw|g729),
    --        > actual format = ulaw,
    --        > host prefs = (ulaw|g726aal2|gsm),
    --        > priority = mine
    -- Executing [1234567890@reverse-autopatch:1] NoOp("IAX2/voipms-2735", "Incoming reverse-autopatch from 0987654321") in new stack
    -- Executing [1234567890@reverse-autopatch:2] Answer("IAX2/voipms-2735", "") in new stack
    -- Executing [1234567890@reverse-autopatch:3] Wait("IAX2/voipms-2735", "1") in new stack
    -- Executing [1234567890@reverse-autopatch:4] Set("IAX2/voipms-2735", "ATTEMPTS=0") in new stack
    -- Executing [1234567890@reverse-autopatch:5] Playback("IAX2/voipms-2735", "confbridge-pin") in new stack
    -- <IAX2/voipms-2735> Playing 'confbridge-pin.ulaw' (language 'en')
    -- Executing [1234567890@reverse-autopatch:6] Read("IAX2/voipms-2735", "PIN,beep,4,,,5") in new stack
    -- Accepting a maximum of 4 digits.
    -- <IAX2/voipms-2735> Playing 'beep.ulaw' (language 'en')
[2024-10-15 13:37:29.469] DTMF[772936][C-000000d3]: channel.c:4008 __ast_read: DTMF begin '1' received on IAX2/voipms-2735
[2024-10-15 13:37:29.469] DTMF[772936][C-000000d3]: channel.c:4012 __ast_read: DTMF begin ignored '1' on IAX2/voipms-2735
[2024-10-15 13:37:29.549] DTMF[772936][C-000000d3]: channel.c:3894 __ast_read: DTMF end '1' received on IAX2/voipms-2735, duration 0 ms
[2024-10-15 13:37:29.549] DTMF[772936][C-000000d3]: channel.c:3963 __ast_read: DTMF end accepted without begin '1' on IAX2/voipms-2735
[2024-10-15 13:37:29.549] DTMF[772936][C-000000d3]: channel.c:3983 __ast_read: DTMF end passthrough '1' on IAX2/voipms-2735
[2024-10-15 13:37:29.989] DTMF[772936][C-000000d3]: channel.c:4008 __ast_read: DTMF begin '2' received on IAX2/voipms-2735
[2024-10-15 13:37:29.989] DTMF[772936][C-000000d3]: channel.c:4012 __ast_read: DTMF begin ignored '2' on IAX2/voipms-2735
[2024-10-15 13:37:30.069] DTMF[772936][C-000000d3]: channel.c:3894 __ast_read: DTMF end '2' received on IAX2/voipms-2735, duration 0 ms
[2024-10-15 13:37:30.069] DTMF[772936][C-000000d3]: channel.c:3963 __ast_read: DTMF end accepted without begin '2' on IAX2/voipms-2735
[2024-10-15 13:37:30.069] DTMF[772936][C-000000d3]: channel.c:3983 __ast_read: DTMF end passthrough '2' on IAX2/voipms-2735
[2024-10-15 13:37:30.569] DTMF[772936][C-000000d3]: channel.c:4008 __ast_read: DTMF begin '3' received on IAX2/voipms-2735
[2024-10-15 13:37:30.569] DTMF[772936][C-000000d3]: channel.c:4012 __ast_read: DTMF begin ignored '3' on IAX2/voipms-2735
[2024-10-15 13:37:30.648] DTMF[772936][C-000000d3]: channel.c:3894 __ast_read: DTMF end '3' received on IAX2/voipms-2735, duration 0 ms
[2024-10-15 13:37:30.649] DTMF[772936][C-000000d3]: channel.c:3963 __ast_read: DTMF end accepted without begin '3' on IAX2/voipms-2735
[2024-10-15 13:37:30.649] DTMF[772936][C-000000d3]: channel.c:3983 __ast_read: DTMF end passthrough '3' on IAX2/voipms-2735
[2024-10-15 13:37:31.168] DTMF[772936][C-000000d3]: channel.c:4008 __ast_read: DTMF begin '4' received on IAX2/voipms-2735
[2024-10-15 13:37:31.168] DTMF[772936][C-000000d3]: channel.c:4012 __ast_read: DTMF begin ignored '4' on IAX2/voipms-2735
[2024-10-15 13:37:31.229] DTMF[772936][C-000000d3]: channel.c:3894 __ast_read: DTMF end '4' received on IAX2/voipms-2735, duration 0 ms
[2024-10-15 13:37:31.229] DTMF[772936][C-000000d3]: channel.c:3963 __ast_read: DTMF end accepted without begin '4' on IAX2/voipms-2735
[2024-10-15 13:37:31.229] DTMF[772936][C-000000d3]: channel.c:3983 __ast_read: DTMF end passthrough '4' on IAX2/voipms-2735
    -- User entered '1234'
    -- Executing [1234567890@reverse-autopatch:7] GotoIf("IAX2/voipms-2735", "1?wait-for-pound") in new stack
    -- Goto (reverse-autopatch,1234567890,14)
    -- Executing [1234567890@reverse-autopatch:14] WaitExten("IAX2/voipms-2735", "5") in new stack
[2024-10-15 13:37:34.069] DTMF[772936][C-000000d3]: channel.c:4008 __ast_read: DTMF begin '#' received on IAX2/voipms-2735
[2024-10-15 13:37:34.069] DTMF[772936][C-000000d3]: channel.c:4012 __ast_read: DTMF begin ignored '#' on IAX2/voipms-2735
[2024-10-15 13:37:34.219] DTMF[772936][C-000000d3]: channel.c:3894 __ast_read: DTMF end '#' received on IAX2/voipms-2735, duration 0 ms
[2024-10-15 13:37:34.219] DTMF[772936][C-000000d3]: channel.c:3963 __ast_read: DTMF end accepted without begin '#' on IAX2/voipms-2735
[2024-10-15 13:37:34.219] DTMF[772936][C-000000d3]: channel.c:3983 __ast_read: DTMF end passthrough '#' on IAX2/voipms-2735
    -- Executing [#@reverse-autopatch:1] Goto("IAX2/voipms-2735", "connect,1") in new stack
    -- Goto (reverse-autopatch,connect,1)
    -- Executing [connect@reverse-autopatch:1] Playback("IAX2/voipms-2735", "rpt/welcome") in new stack
    -- <IAX2/voipms-2735> Playing 'rpt/welcome.slin' (language 'en')
    -- Executing [connect@reverse-autopatch:2] Rpt("IAX2/voipms-2735", "1999|P") in new stack
    -- Hungup 'IAX2/voipms-2735'
    -- Hungup 'DAHDI/pseudo-761606412'

Looks like mine without all the addition stuff in the dial plan. I’m going to try and walk away for a while, I’ve been at this too long. But just to clarify for anyone listening, I have my SIP client Zoiper running on an old phone. It is connecting to asterisk on my node. When I dial my node number in Zoiper, it connects and works as expected. When I call in via my SIP trunk from Flowroute, the call never seems to connect to the node and no audio is passed. Asterisk does pick up the call and appears to try to connect it via rpt, but there is no audio.

Here is the console output, I tried calling in via reverse autopatch first. It shows the node saying ‘connected’ but I never hear that on the phone. Then it sits there silent until I hangup or 30 seconds until timeout and call is dropped. Then I connected the Zoiper and dialed the node and I heard it say ‘connected’ and then it works as expected:

Connected to Asterisk 20.9.3+asl3-3.0.6-1.deb12 currently running on pi4allstar (pid = 5075)
– Hungup ‘DAHDI/pseudo-675662053’
– Hungup ‘DAHDI/pseudo-385102324’
– Executing [14322031499@reverse-autopatch:1] Answer(“PJSIP/flowroute-trunk-00000000”, “”) in new stack
– Executing [14322031499@reverse-autopatch:2] Wait(“PJSIP/flowroute-trunk-00000000”, “1”) in new stack
– Executing [14322031499@reverse-autopatch:3] Playback(“PJSIP/flowroute-trunk-00000000”, “rpt/connected”) in new stack
– <PJSIP/flowroute-trunk-00000000> Playing ‘rpt/connected.gsm’ (language ‘en’)
– Executing [14322031499@reverse-autopatch:4] Rpt(“PJSIP/flowroute-trunk-00000000”, “49555|Pv”) in new stack
== Manager ‘admin’ logged on from 127.0.0.1
– Hungup ‘DAHDI/pseudo-529585729’
– Added contact ‘sip:1001@192.168.10.61:48461;transport=UDP;rinstance=8370fa8855576f74’ to AOR ‘1001’ with expiration of 60 seconds
== Endpoint 1001 is now Reachable
– Executing [49555@sip-phones:1] Ringing(“PJSIP/1001-00000001”, “”) in new stack
– Executing [49555@sip-phones:2] Answer(“PJSIP/1001-00000001”, “”) in new stack
– Executing [49555@sip-phones:3] Set(“PJSIP/1001-00000001”, “NODENUM=1001”) in new stack
– Executing [49555@sip-phones:4] Playback(“PJSIP/1001-00000001”, “rpt/connected”) in new stack
– <PJSIP/1001-00000001> Playing ‘rpt/connected.gsm’ (language ‘en’)
– Executing [49555@sip-phones:5] Rpt(“PJSIP/1001-00000001”, “49555|Pv”) in new stack

Both contexts in extensions.conf look similar:
[reverse-autopatch]
; Answer the incoming call.
exten => _X.,1,Answer()

; Wait for 1 second to ensure the line is stable before playing the prompt.
exten => _X.,n,Wait(1)

; “rpt/connected” could say something like: “You are now connected.”
exten => _X.,n,Playback(rpt/connected)

; Connect the caller to the repeater using the “rpt” command.
; The “|P” option is used to specify “phone” mode in app_rpt.
exten => _X.,n,rpt(49555|Pv)

; Hang up the call after the connection is made.
exten => _X.,n,Hangup()

[sip-phones]
exten => 1001,1,Dial(PJSIP/${EXTEN},60,rT)

exten => ${NODE},1,Ringing
exten => ${NODE},n,Answer()
exten => ${NODE},n,Set(NODENUM=${CALLERID(number)})

; exten => ${NODE},n,Playback(extension)
; exten => ${NODE},n,SayDigits(${NODENUM})
exten => ${NODE},n,Playback(rpt/connected)
; exten => ${NODE},n,Playback(rpt/node)
; exten => ${NODE},n,SayDigits(${EXTEN})
exten => ${NODE},n,rpt(${EXTEN}|Pv)
exten => ${NODE},n,Hangup

I see you’re still trying to use Pv in most places, I would try with just P at least until you get everything else working to remove another potential variable.

1 Like

Worth trying I guess. The vox is working on the zoiper client, and I just changed it for rev auto, same result. Also tried changing the endpoint name to remove the ‘-’ just in case but that was not it either. I wonder if I need different audio codecs enabled, but no errors indicating that. I have to be close, but still didn’t hear the connected message and never landed in rpt:

Connected to Asterisk 20.9.3+asl3-3.0.6-1.deb12 currently running on pi4allstar (pid = 5516)
– Hungup ‘DAHDI/pseudo-614387270’
== Contact 1001/sip:1001@192.168.10.61:48461;transport=UDP;rinstance=bc79720bfb1e2a22 has been deleted
== Endpoint 1001 is now Unreachable
– Added contact ‘sip:1001@192.168.10.61:48461;transport=UDP;rinstance=bc79720bfb1e2a22’ to AOR ‘1001’ with expiration of 60 seconds
== Endpoint 1001 is now Reachable
– Executing [14322031499@reverse-autopatch:1] Answer(“PJSIP/flowrouteendpoint-00000000”, “”) in new stack
– Executing [14322031499@reverse-autopatch:2] Wait(“PJSIP/flowrouteendpoint-00000000”, “1”) in new stack
– Executing [14322031499@reverse-autopatch:3] Playback(“PJSIP/flowrouteendpoint-00000000”, “rpt/connected”) in new stack
– <PJSIP/flowrouteendpoint-00000000> Playing ‘rpt/connected.gsm’ (language ‘en’)
– Executing [14322031499@reverse-autopatch:4] Rpt(“PJSIP/flowrouteendpoint-00000000”, “49555|P”) in new stack
== Manager ‘admin’ logged on from 127.0.0.1
– Hungup ‘DAHDI/pseudo-1525301139’

I fixed this. In pjsip.conf, I had the wrong external IP address in every place it was listed. No surprise that when I fixed that, it started working just fine. :thumbsup:

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.