; phreaknet.conf - Main PhreakNet dialplan file ; v 1.0.11 (2022/08/01) ; ********************************************** INCOMING ROUTING ********************************************** ; ** Incoming calls to this node ** [from-phreaknet] exten => _12[6-9]NNXXXXX,1,ExecIf(${EXISTS(${IAXVAR(clidverif)})}?Hangup(21)) same => n,Gosub(phreaknet-verify,s,1(${EXTEN},0)) ; hard coded verify against the number 0. This prevents any call except the network operator tandem from checking out as OK. same => n,Goto(phreaknet-inward,${EXTEN},1) exten => _[0-9*#A-Zms]!,1,Gosub(phreaknet-verify,s,1(${EXTEN})) same => n,Goto(phreaknet-in,${EXTEN},1) [from-stepnet] ; StepNet disabled by default, since not everyone wants calls tandeming through their nodes. To enable: 1) uncomment x2 context = from-stepnet in iax.conf 2) Call the Business Office to have StepNet routing for your node enabled. StepNet Nodes must support MF and SF for outgoing trunk calls. exten => _[0-9*#A-Ds]!,1,Gosub(phreaknet-verify,s,1(${EXTEN})) same => n,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${EXTEN},1)}]?phreaknet-in,${EXTEN},1) ; if number is on this switch, that's the end of the route for this call. We made it! same => n,Goto(phreaknet-stepnet,${EXTEN},1) ; *** StepNet *** [phreaknet-stepnet] exten => _[0-9*#A-Ds]!,1,NoOp() ; add StepNet sounds here... same => n,Wait(1) ; add any additional custom outpulsing sounds here. Look in the Docs and add MF or SF or StepNet sounds, etc. Make sure any audio does *NOT* supervise... ; MFing/SFing is not needed, you could just add a simple random click from the StepNet sounds collection. Don't overdo it, whatever is done here. same => n,Gosub(dialphreaknet,s,1(${EXTEN},ms)) same => n,Hangup() [phreaknet-inward-semipublic] ; any network inward may access these exten => s,1,Progress() same => n,Playback(beep,noanswer) ; ACK to go ahead same => n,Read(code) ; read a #-terminated code. same => n,GotoIf($[${DIALPLAN_EXISTS(${CONTEXT},${code},1)}]?${code},1:i,1) exten => i,1,PlayTones(congestion) same => n,Wait(4) same => n,Goto(s,1) exten => _*.,1,GotoIf($[${DIALPLAN_EXISTS(${CONTEXT},${EXTEN:1},1)}]?${EXTEN:1},1:i,1) ; additional reference: https://telephoneworld.org/long-distance-companies/att-long-distance-network/old-att-operator-routing-codes/ exten => 102,1,Progress() same => n,Milliwatt(m) same => n,Hangup() ; 112 = network operator calls (0-, 0+, TSPS, etc.), 113 = network directory assistance calls, 114 = network repair service calls, 115 = ONI (operator number identification). 116 = Business Office. 117 = TRS. 118 = CoinZone. 119 = Emergency. The remaining 11X codes here may be utilized in the future and are reserved. ; Each node owner may individually handle these by prepending a tag to the CNAM for identification, setting up distinctive ring, etc. This also makes it possible to route different kinds of calls to different places, e.g. operator calls to a 3CL cordboard, directory assistance calls to a computer terminal, etc. ; By default, send these all to the same place. Feel free to customize or break this down further. These codes exist separately so that routing can be separate, but you could also send 112/121, 113/131, 114/141 to the same place locally. exten => _11X,1,Goto(5551211,1) ; for public network operator calls. Not used if you are not a network operator. THIS MUST NEVER SUPERVISE unless an ACTUAL human operator answers. exten => _1[2-68]1,1,Goto(5551211,1) ; if operators key 121 (inward operator), 131 (information), or 141 (rate and route), or 151 (international assistance), 161 (trunk trouble reporting), or 181 (Toll Station) route these to this node's operator position. Most smaller exchanges will likely send these all to the same "station", but you don't have to.... ; Operator Thru-Route (out) - if you "keyed" your NNX + 121, that would probably come back into your from-phreaknet and ring your inward station. exten => _NNX!,1,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${EXTEN},1)}]?phreaknet-exchange,${EXTEN},1:phreaknet-inward-out,${EXTEN},1) ; basically, anything at least 3 digits not starting with 1 is not for this server, it's for somewhere else... Also terminate calls to 7D #s on this switch. exten => _0XX!,1,Goto(phreaknet-inward-out,${EXTEN},1) ;exten => 046,1,Goto(5550000,1) ; if you had a hosted operator on this switch whose routing code was (one of your NNX's) + 046, you could send that directly to a trunk on that person's PBX, assuming 5550000 was a trunk that answered. ;exten => 046121,1,Dial(5550000@${CONTEXT}/n,,D(::${EXTEN:3})) ; ...more realistically, you might pick up a trunk to his PBX and send forward the digits 121. Slightly hacky workaround but probably the best way. Or you could send him the digits dialed another way, up to you. ; same => n,Hangup() ; exten => 046121,1,Goto(5550121,1) ; if you were hosting a user who wanted an inward routing, that could be managed using a routing code in front. If *you* yourself are reachable via a routing code, that doesn't get sent. This is really just a note, and you can leave this commented out and ignore it. ; if you don't have an operator position, you can put an intercept here, but it's best to have these route to a station *somewhere*, even if it's not attended some/most of the time. [phreaknet-in] ; Route different kinds of calls more specifically exten => _NXXXXXX,1,NoOp() ; global incoming inpulsing could go here (e.g. fake MF tones) same => n,GotoIf(${DIALPLAN_EXISTS(phreaknet-local,${EXTEN},1)}?phreaknet-local,${EXTEN},1:invalidincoming,${EXTEN},1) exten => _*66NXXXXXX,1,Goto(phreaknet-class,${EXTEN},1) ; "Busy Callback" / "Repeat Dialing" integration *between* nodes (pretty cool, right?) If other people use *66 against your node frequently, you may want to move this line to from-phreaknet. This means such calls will not be verified, but since this is only used for signaling, there's less risk. Nodes using MD5/RSA authentication shouldn't need to worry about external spam as it is. ; In-Band Trunking - needs to be enabled in the user portal ; if you need multiple different MF receivers, e.g. to cut through to different electromechanical, add an extension with the specific CLLI(s), e.g. exten => mfHSTNTXMOCG0,1,NoOp(To the #5 Crossbar), etc. Each receiver is independent of the others. exten => _mf.,1,Set(TONE_DETECT(2600,500,g(2))=) ; 2600 Hz detector: from now on, if 2600 is received, it will "reset this trunk" ; if you are routing calls to an electromechanical switch, cut through directly to it right here. Rest is if you are receiving digits in Asterisk. same => n,SendFrame(WINK) ; wink start by default. You can replace this with Progress() for progress start. same => n,ReceiveMF(digits,7,kos) same => n,GotoIf($["${RECEIVEMFSTATUS}"="START"]?:signalfail,1) same => n,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${digits},1)}]?phreaknet-local,${digits},1) ; ensure there is no fake MF afterwards same => n,Goto(phreaknet-route,${digits},1) exten => _sf.,1,Set(TONE_DETECT(2600,500,g(2))=) ; 2600 Hz detector: from now on, if 2600 is received, it will "reset this trunk" same => n,SendFrame(WINK) same => n,ReceiveSF(digits,7,13,2600) ; if you only use SF for one NNX, you could just receive 4 inpulse digits and route to that NNX (quicker) same => n,GotoIf($["${RECEIVESFSTATUS}"="START"]?:signalfail,1) same => n,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${digits},1)}]?phreaknet-local,${digits},1) ; ensure there is no fake MF afterwards same => n,Goto(phreaknet-route,${digits},1) exten => signalfail,1,PlayTones(congestion) same => n,Wait(60) same => n,Hangup() [phreaknet-local] ; the only calls that actually go into this context (as opposed to checking if an extension exists here) are incoming external ones ; inpulsing sounds (e.g. revertive / dial pulsing, etc.) should go in this context ;exten => 5551111,Goto(phreaknet-exchange,${EXTEN},1) ; if you didn't want a specific extension to inpulse, you can add an exception exten => _555[19]XXX,1,NoOp() ; optional exchange-specific inpulsing sounds here... (e.g. revertive pulsing) same => n,Goto(phreaknet-exchange,${EXTEN},1) ; route calls to all your thousand blocks, e.g. 555-1XXX and 555-9XXX in this example ; ^ this is an example of a pattern match. Patterns must begin with an underscore (_). ; For calls within the office, to either the same "exchange" or a different one... [phreaknet-intraoffice] ; the idea is that inpulsing may be desired *between* exchanges on the same system, but not *within* them. We use the dtlocation var to help us. exten => _NXXXXXX,1,GotoIf(${ISNULL(${dtlocation})}?phreaknet-local,${EXTEN},1) ; in this case, always inpulse (assuming there is some in phreaknet-local) same => n,GotoIf($["${EVAL_EXTEN(phreaknet-intraoffice-lookup,${dtlocation},1)}"="${EVAL_EXTEN(phreaknet-intraoffice-lookup,${EXTEN},1)}"]?phreaknet-exchange,${EXTEN},1:phreaknet-local,${EXTEN},1) ; if they're in the same office, no inpulsing. Otherwise, inpulsing. ; ********************************************** EXTENSION TERMINATION ********************************************** [phreaknet-intraoffice-lookup] ; RETURN: 0 for no inpulsing, otherwise the same value if these "locations" are in the same switch (no pulsing within the same switch) exten => _[0-9*#A-D]!,1,Return() ; catch all exten => _555XXXX,1,Return(5XB) [phreaknet-exchange] ; Numbers associated with this exchange. ; if you have multiple exchanges, you may wish to separate them into separate exchanges, and then include them, e.g: ; include => KLondike5 ; Standard numbers (at least the last 3/4 digits) exten => 5551111,1,Goto(phreaknet-dialtone,${EXTEN},1) ; main DISA exten => 5559901,1,SayAlpha(${clli}) ; "Switch Verification" same => n,Hangup() exten => 5559931,1,Progress() ; test numbers should NEVER provide answer supervision, so use Progress so that audio can pass without answering same => n,Echo() ; Echo test same => n,Hangup() exten => 5559932,1,Progress() same => n,Wait(7200) ; Silent Termination same => n,Hangup() exten => 5559958,1,Progress() same => n,SayDigits(${CALLERID(num)}) ; a primitive ANAC same => n,Hangup() exten => 5559960,1,Progress() same => n,Milliwatt(m) ; 1004 Hz milliwatt test line same => n,Hangup() exten => 5559970,1,Gosub(phreaknet-ring,local-BUSY,1) ; Always busy same => n,Hangup() exten => 5559971,1,Gosub(phreaknet-ring,local-CHANUNAVAIL,1) ; Always reorder same => n,Hangup() exten => 5559990,1,Progress() same => n,MusicOnHold(ringback) ; number that always rings "forever". same => n,Hangup() ; Switch specific stuff: exten => 5552366,1,Gosub(phreaknet-peer,s,1(SIP/DeskPhone1,1)) ; And voila. Here is an example of a simple hunt group with 2 lines. same => n,GosubIf($["${GOSUB_RETVAL}"!="ANSWER"]?phreaknet-peer,s,1(SIP/DeskPhone2,1)) same => n,Hangup() include => phreaknet-subscriber-lines ; the reason this is included as a separate context is that if you include other contexts (e.g. KLondike5), those other contexts with specific extension patterns will match before the broad _NXXXXXX. If the latter were present in this context directly, that would always match before any includes, which is likely not the desired behavior. ; ** Call intercepts ** [phreaknet-intercept] ; ************ REPLACE the audio file below with a "number dialed not in service or disconnected" intercept message. If you have the Pat Fleet prompts, this should play, though. exten => permsig,1,Gosub(dialphreaknet,s,1()) ; if you have your own perm. sig. recording ("If you'd like to make a call, please hang up..."), put it here. Otherwise, use the network-wide perm. sig. (calling dialphreaknet with no #) same => n,Hangup() exten => _NXXXXXX,1,Playback(discon-or-out-of-service,noanswer) ; *** <-- notice that we use noanswer so the call does not supervise. This is important! same => n,Hangup() exten => mlppfail,1,PlayTones(congestion) ; replace with an appropriate intercept if you use MLPP same => n,Wait(30) same => n,Hangup(21) [invalidincoming] exten => _[0-9*#A-Zs]!,1,PlayTones(congestion) same => n,Wait(30) same => n,Hangup(21) [phreaknet-subscriber-lines] ; Catch all so that numbers corresponding to lines ring the right phone(s). exten => _NXXXXXX,1,NoOp() ;same => n,ExecIf($[${LEN(${CALLERID(num)})}=7]?Set(CALLERID(name)=${CURL(https://api.phreaknet.org/v1/cnam?key=${interlinkedkey}&number=${CALLERID(num)})})) ; uncomment this if you want to use the PhreakNet CNAM API to perform CNAM dips on incoming network calls. This may improve the usefulness of the Caller ID name that you see. same => n,Gosub(phreaknet-peer,${EXTEN},1) ; check if the number dialed goes to a peer same => n,GotoIf(${ISNULL(${GOSUB_RETVAL})}?phreaknet-intercept,${EXTEN},1) ; if number not in service, go to intercept. If it is, ring the line. same => n,ExecIf(${EXISTS(${mlppdigit})}?Set(cadence=8)) same => n,Gosub(phreaknet-ring,s,1(${GOSUB_RETVAL},,${cadence})) ; ring the peer same => n,Hangup() ; ** Ringing local lines ** ; This is where you map numbers to peers that Asterisk can dial. Do *NOT* use numeric peer names. Instead, map them all to alphanumeric names that have a logical meaning to you (see examples) ; Hints are primarily used for Busy Lamp Fields in Asterisk. However, it's also the best way to define peer translations. ; If you're just getting started with Asterisk, you should use PJSIP instead of SIP, because SIP is deprecated and will be removed soon. If you're already using SIP and not ready to migrate, that's up to you. [phreaknet-hints] ; Of everything, you'll likely be updating phreaknet-hints and phreaknet-exchange the most exten => 5552368,hint,SIP/DeskPhone1 exten => 5552369,hint,SIP/DeskPhone2 exten => 5552370,hint,PJSIP/NewDeskPhone exten => 5552371,hint,SIP/Basement1&SIP/Basement2 ; hey, let's ring two phones at once when this number is called... [phreaknet-peer] ; Translates number to peer name. This exists as a subroutine so we have an agnostic wrapper regardless of how the translation is done. Don't remove this. exten => _NXXXXXX,1,Return(${HINT(${EXTEN}@phreaknet-hints)}) ;exten => _NXXXXXX,1,Return(${NUM2DEVICE(${EXTEN})}) ; ...please, please do not blindly use a catch all solution to convert numbers to peers ; we've included this for compatability with people who may have been using SIPxNumToPeer, but please use phreaknet-hints instead ; This means you *WILL* need to manually add all peers as hints in phreaknet-hints, but you should do this because it's more powerful. [phreaknet-ring] ; Rings a local peer, ARG1 = peer name, ARG2 = return immediately if not reachable, ARG3 = ringing cadence # (docs.phreaknet.org/#cadences) exten => s,1,ExecIf(${ISNULL(${FILTER(\x26,${ARG1})})}?Set(DB(lastcaller/${ARG1})=${IF($["${CALLERID(pres):0:5}"="allow"]?${CALLERID(num)})})) ; as written, doesn't work with ring groups same => n,Dial(${ARG1},,gm(ringback)b(phreaknet-predial^s^1(${ARG3}))) ; <-- ringback is the name of the music on hold class defined in musiconhold.conf. Change this to a city ringback tone, unique to your switch! ; Distinctive ringing cadences for PJSIP same => n,ExecIf($["${ARG2}"="1"]?Return(${DIALSTATUS})) same => n,Goto(local-${DIALSTATUS},1) exten => local-ANSWER,1,Return() ; *********** YOU *SHOULD* replace these with something "personal" to this switch, like a city busy signal or reorder tone. exten => local-BUSY,1,PlayTones(busy) ; Remember to use the ,noanswer flag to NOT provide answer supervision if the call doesn't get answered! same => n,Wait(60) same => n,Return() exten => local-CONGESTION,1,PlayTones(congestion) same => n,Wait(60) same => n,Return() exten => local-CHANUNAVAIL,1,Goto(local-CONGESTION,1) exten => local-BLOCKED,1,Goto(local-CONGESTION,1) exten => local-NOANSWER,1,Return() exten => local-.,1,Return() ; ********************************************** OUTGOING CALLS ********************************************** ; ** Originating calls from local lines [from-internal] exten => _[0-9*#A-Ds]!,1,Set(CDR_PROP(disable)=1) ; you don't want CDR records just for going off hook, do you? same => n,Answer() ; answer so audio passes, many ATAs need to see supervision. same => n,Set(__fullpeername=${CUT(CHANNEL,-,1)}) ; set this variable to the actual peer name, e.g. SIP/DeskPhone1. CHANNEL will give you something like SIP/DeskPhone1-0000012, unique per call, so cut that off. same => n,Goto(phreaknet-dialtone,${CALLERID(num)},1) ; Also note that the dial tone itself in the dt context does not Answer, so that's why we answer here. This means incoming DISA calls via IAX2 won't be answered. ; *** Dial tone sounds *** [phreaknet-cdpr-dialtone] ; Optional Playback(,noanswer) of pre-dial tone sound + return the dial tone exten => _NXXXXXX,1,NoOp() ; any line noise before dial tone is returned same => n,Return(custom/signal/dialtone) ;;;;;;;;;;;;;; update this to your dial tone audio file in /var/lib/asterisk/sounds/en/custom. Optimal audio length is 1-3 minutes. [phreaknet-cdpr-dialsounds] ; Return dialing sound for intermediate digits exten => _X!,1,Return(silence/10) ;exten => _NXXXXXX,1,Return(custom/dialsounds/dialsound${RAND(1,3)}) ; ;;;;;;;;;;;;;; Depending on what file(s) you have (and how many), adjust this. Optimal audio length is ~ 20 seconds to 1-2 mins, esp. for "electromechanical" switches. [phreaknet-cdpr-dialcomplete] ; Return dialing complete sound (NOT outpulsing). Return nothing (e.g. Return()) for no sound. ;exten => _NXXXXXX,1,Return(custom/dialcomplete/complete${RAND(1,1)}) exten => _X!,1,Return() ; *** Routing once a call is dialed *** ; Local lines will end up here when done dialing. Everything else will end up directly at phreaknet-route [phreaknet-internal-dest] ; anything in here specifically is internal only exten => ##,1,GotoIf(${EXISTS(${SET(lastnum=${DB(lastnumberdialed/${fullpeername})})})}?${lastnum},1:invalidincoming,${EXTEN},1) ; if we have a number saved, call it exten => *12,1,GotoIf($["${CALLERID(num)}"="5551211"|"${CALLERID(num)}"="5551210"]?phreaknet-inward,s,1:invalidincoming,s,1) ; allow the local inward to access local inward stuff. Feel free to change the code - this just happens to be a code not assigned for anything (PSTN or PhreakNet), and not something an external user can dial anyways. exten => *66,1,GotoIf(${EXISTS(${SET(lastnum=${DB(lastnumberdialed/${fullpeername})})})}?:invalidincoming,${EXTEN},1) ; only works if we have a number saved same => n,Goto(phreaknet-busy-callback,${lastnum},1) ; check out phreaknet-busy-callback in phreaknet.conf if this interests you... exten => *67,1,Set(CALLERID(pres)=prohib_not_screened) ; per call block Caller ID (set privacy bit) same => n,Goto(phreaknet-dialtone,s,1) exten => *69,1,GotoIf(${EXISTS(${SET(lastcaller=${DB(lastcaller/${fullpeername})})})}?:invalidincoming,${EXTEN},1) same => n,Playback(that-number) same => n,SayDigits(${lastcaller}) same => n,WaitDigit(10,1) ; wait up to 10s for digit "1" to be entered same => n,Goto(${lastcaller},1) ; call back the caller exten => *82,1,Set(CALLERID(pres)=allowed_not_screened) ; per call show Caller ID (no privacy bit) same => n,Goto(phreaknet-dialtone,s,1) exten => _*8[69],1,CancelCallback() same => n,Playback(thank-you) same => n,Goto(phreaknet-dialtone,s,1) ; exten => *98,1,Goto(voicemail,${CALLERID(num)},1) ; e.g. voicemail. Note that [voicemail] is not provided here, but this is an example of what you could do if you were using it... post to the list if you need guidance on voicemail configuration. If you don't know what you're doing, you could introduce security vulnerabilities! ; exten => _11XX,1,Goto(*${EXTEN:-2},1) ; vertical service codes for rotary / pulse dial phones. If you uncomment this, uncomment the matching pattern in phreaknet-digit-map. ; exten => _3XXX,1,Goto(555${EXTEN},1) ; if you wanted, you could set up intercom dialing so that you only need to dial the last M number of digits (e.g. 4) for calls within the same block. You'd need to modify the digit map above appropriately. exten => _[0-9*#A-D]!,1,NoOp() ;same => n,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${EXTEN},1)}]?local) ; if you didn't want to ticket "local" calls, you could uncommented this. By default, a hook is used to trigger ticketing for all calls. If the call is answered, a ticket will be submitted to the "toll tandem" and non-free calls will then appear on your "bill". Ticketing local calls is like charging message rates and will appear on your "bill". If you wanted "flat rate" unlimited "free" local calling, you could uncomment this and bypass ticketing for local calls made by local stations. same => n(all),Dial(Local/${EXTEN}@phreaknet-dest/n,,g) ; public numbers same => n,Goto(phreaknet-dialtone,s,1) ; drop back to dial tone when the called party hangs up. same => n(local),Dial(Local/${EXTEN}@phreaknet-route/n,,g) same => n,Goto(phreaknet-dialtone,s,1) [phreaknet-dest] ; intermediary context between phreaknet-route, so that CDR works properly for the billing record include => phreaknet-pseudo-dialable include => phreaknet-dialable [phreaknet-pseudo-dialable] ; tie lines go here ;exten => 50,1,Goto(phreaknet-exchange,5551111,1) ; short dialing code to access a dial tone/DISA. If you have multiple exchanges, these can be handy. ; if you use these, add a matching extension/pattern to the cdpr digit map in phreaknet-aux.conf [phreaknet-dialable] exten => _[0-9*#A-D]!,1,Set(chargenum=${IF($[${ISNULL(${clidverif})}&${EXISTS(${CALLERID(RDNIS)})}]?${CALLERID(RDNIS)}:${CALLERID(num)})}) ; the charge # is generally the same as the calling #, unless a local station just forwarded a call. same => n,GotoIf(${IFMODULE(res_phreaknet.so)}?:old) ; this should really use If(), Else(), and EndIf(). However this was only recently merged, so hold off on that a while. same => n,Set(PHREAKNET(CDR)=${EXTEN},${CALLERID(num)},${chargenum}) same => n,Goto(dial) same => n(old),Set(CHANNEL(hangup_handler_push)=phreaknet-ticket,${EXTEN},1(${STRFTIME(${EPOCH},,%s)},${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)},${chargenum},${CALLERID(num)})) same => n(dial),Dial(Local/${EXTEN}@phreaknet-route/n) ; the /n is SUPER important! It prevents local channel optimization. It's the whole reason we're doing this. same => n,Hangup() [phreaknet-route] ; Don't simply include => phreaknet-in, because *66 calls and operator routings shouldn't be publicly dialable! exten => _[A-D]!,1,Set(CDR_PROP(disable)=1) same => n,GotoIf($[${ISNULL(${clidverif})}|"${clidverif}"="70"]?:phreaknet-intercept,mlppfail,1) ; unauthorized. By default, only local and verified network callers can use MLPP at all. same => n,GotoIf($[$["${EXTEN:0:1}"="A"|"${EXTEN:0:1}"="B"]&${EXISTS(${clidverif})}]?phreaknet-intercept,mlppfail,1) ; don't allow anyone external to use Flash or Flash Override. ; feel free to adjust or add rules... same => n,Set(__mlppdigit=${EXTEN:0:1}) same => n,Goto(${EXTEN:1},1) exten => _[0-9*#]!,1,Set(CDR_PROP(disable)=1) ; CDR is done in phreaknet-ticket, we don't need duplicates so disable for this channel same => n,GotoIf($[${DIALPLAN_EXISTS(phreaknet-local,${EXTEN},1)}]?phreaknet-intraoffice,${EXTEN},1) ; route calls to all your thousand blocks, e.g. 555-1XXX and 555-9XXX in this example ; if you want to add basic "AUTOVON"/MLPP functionality, do that here. https://docs.phreaknet.org/#mlpp ; below is a multi-line comment, beginning with semicolon, double dash, ending with double dash, semicolon ;-- same => n,GotoIf($[${SYSINFO(numcalls)}<25]?proceed) same => n,Gosub(autovonpreempt,s,1) ; Attempt to preempt a call same => n,Wait(3.2) ; may need to adjust to all group count to fall when preempted call clears same => n,GotoIf($[${SYSINFO(numcalls)}<25]?proceed) same => n,GotoIf(${ISNULL(${mlppdigit})}?allcircuitsbusy) same => n,Playback(custom/mlpp/insufficientprecedence,noanswer) ; for priority callers with insufficient precedence to preempt same => n,PlayTones(congestion) same => n,Wait(30) same => n,Hangup() same => n(allcircuitsbusy),Playback(custom/allcircuitsbusy,noanswer) ; for non-priority callers same => n,Hangup() same => n(proceed),Gosub(autovoninit,${autovonprioritydigit},1) --; ; if you wanted to add some outpulsing sounds for "long distance" calls leaving your switch, this might be a natural place to do that... ;same => n,GosubIf(${EXISTS(${dtlocation})}?phreaknet-outpulse,${dtlocation},1(${EXTEN})) same => n,Goto(to-phreaknet,${EXTEN},1) ; if the number dialed isn't on this switch, go "out" to the rest of PhreakNet... [phreaknet-outpulse] ; EXTEN = outpulsing switch location, ARG1 = called number (being outpulsed) exten => _[A-D0-9*#]!,1,ExecIf($[${LEN(${ARG1})}!=7|"${ARG1:-7:3:}"="101"]?Return) ; no outpulsing same => n,Return() ; ** Outbound calling leaving this node ** [to-phreaknet] ; send calls outbound to PhreakNet here, and it'll take care of the rest. Past this point, make sure local Caller IDs are 7-digit network Caller IDs, regardless of what they are locally. exten => _X!,1,ExecIf(${IFMODULE(res_phreaknet.so)}?PhreakNetDial(${EXTEN},ms):Gosub(dialphreaknet,s,1(${EXTEN},ms))) ; ms = support MF and SF signalling for outbound calls. same => n,Hangup() [dialphreaknet] ; ARG1 = #, ARG2 = trunk flags (optional) exten => s,1,Gosub(dialphreaknet-helper,s,1(${ARG1},${ARG2})) ; ARG1 = #, ARG2 = trunking flags (if any), ARG3 = specific context (if any) same => n,GosubIf($[$["${DIALSTATUS}"="CONGESTION"]&${ISNULL(${clidverif})}]?dialphreaknet-helper,s,1(${ARG1},${ARG2}t)) ; if call failed 1st time, retry with alt. rtg. using StepNet, automatically, but only if originating locally, to prevent infinite loops. same => n,GotoIf($["${GOSUB_RETVAL}"="2"]?phreaknet-BLOCKED,1:phreaknet-${DIALSTATUS},1) exten => phreaknet-ANSWER,1,Return() ; feel free to replace precise busy/reorder with old city tones or intercepts, but keep in mind these are ; trunk conditions, not line conditions, so they won't get triggered very often. The tones you really should replace are those in phreaknet-ring exten => phreaknet-BUSY,1,PlayTones(busy) same => n,Wait(60) same => n,Return() exten => phreaknet-CONGESTION,1,PlayTones(congestion) same => n,Wait(60) same => n,Return() exten => phreaknet-CHANUNAVAIL,1,Goto(phreaknet-CONGESTION,1) exten => phreaknet-BLOCKED,1,Goto(phreaknet-CONGESTION,1) exten => phreaknet-NOANSWER,1,Return() exten => phreaknet-.,1,Return()