[general]
static=yes
writeprotect=no
clearglobalvars=no
autofallthrough=yes

[globals]
IP=178.21.248.172
Hostname=tdc-mvno-VoLTE-1.uni-tel.dk
TDC=KHSBG1-tcp-172,ALBSBG1-tcp-173,ALBSBG1-tcp-174,ALBSBG1-tcp-175
UniTel=sip-core-1-172,sip-core-1-173,sip-core-1-174,sip-core-1-175
MaxCallTime=28800	; 8h
DialTimeout=180		; 3m
NoFailoverCause=1,16,17,18,19,20,21,22,28,127
				; 1	UNALLOCATED
				; 16	NORMAL_CLEARING
				; 17	USER_BUSY
				; 18	NO_USER_RESPONSE
				; 19	NO_ANSWER
				; 20	SUBSCRIBER_ABSENT
				; 21	CALL_REJECTED
				; 22	NUMBER_CHANGED
				; 28	INVALID_NUMBER_FORMAT
				; 127	INTERWORKING

;The prefix +03 WILL be maintained in the VoLTE solution for Mobile Terminating calls. The SBG WILL add prefix +03 to the call sent toward the SIP MVNO in case of a Mobile Terminating call. The SIP MVNO MUST return the call to TDC maintaining the prefix +03 when the call shall be delivered to the called mobile terminal on the radio/Wi-Fi access, e.g. SIP: +0320109999@host....

;The prefix +01 MUST be used in the VoLTE solution for ONNET calls, which means for calls between two customers at the same SIP MVNO. However, there will not be any check for ONNET calls on the TDC side anymore and prefix +01 WILL NOT be set by the SBG for the call toward the SIP MVNO. The SIP MVNO MUST add the prefix +01 for the call returned to TDC if both the calling- and called subscriber belongs to the SIP MVNO and the called number is a TDC mobile number.

;The reason for having prefix +01/+03 set for these calls is to suppress re-triggering of the call (and thus prevent looping of the call back to SIP MVNO operator) when the call shall be delivered to the called mobile terminal on the terminating radio/Wi-Fi access. In case the MVNO does not apply +01 for ONNET calls there will be one extra round trip. In case the operator removes +03 there will be an infinite loop between MVNO and SBG.

[default]
exten => s,1,Hangup(34)		; 34	NORMAL_CIRCUIT_CONGESTION

[History_To_E164]
exten => _[*#a-zA-Z]!,1,Return(INVALID)
exten => _00!,1,Goto(+${EXTEN:2},1)
exten => _X!,1,Goto(+45${EXTEN},1)
exten => _+!,1,Set(CALLERID(rdnis)=${EXTEN})
same => n,Set(REDIRECTING(from-num,i)=${EXTEN})
same => n,Set(_History=${EXTEN})
same => n,Return(OK)

[Diversion_To_E164]
exten => _[*#a-zA-Z]!,1,Return(INVALID)
exten => _00!,1,Goto(+${EXTEN:2},1)
exten => _X!,1,Goto(+45${EXTEN},1)
exten => _+!,1,Set(CALLERID(rdnis)=${EXTEN})
same => n,Set(REDIRECTING(from-num,i)=${EXTEN})
same => n,Set(_Diversion=${EXTEN})
same => n,Return(OK)

[PAI_To_E164]
exten => _[*#a-zA-Z]!,1,Return(INVALID)
exten => _00!,1,Goto(+${EXTEN:2},1)
exten => _X!,1,Goto(+45${EXTEN},1)
exten => _+!,1,Set(_P-Asserted-Identity=${EXTEN})
same => n,Return(OK)

[PAI_To_DK]
exten => _[*#a-zA-Z]!,1,Return(INVALID)
exten => _+45!,1,Goto(${EXTEN:3},1)
exten => _+!,1,Goto(00${EXTEN:1},1)
exten => _0045!,1,Goto(${EXTEN:4},1)
exten => _X!,1,Set(_P-Asserted-Identity=${EXTEN})
same => n,Return(OK)

[Dial_Handler]
exten => _[+0-9*#s]!,1,Set(PJSIP_HEADER(add,P-Early-Media)=supported) 
same => n,Set(PJSIP_HEADER(add,Max-Forwards)=${DEC(Max-Forwards)})
same => n,ExecIf(${EXISTS(${Resource-Priority})}?Set(PJSIP_HEADER(add,Resource-Priority)=${Resource-Priority}))	; rfc4412
same => n,ExecIf(${EXISTS(${Session-ID})}?Set(PJSIP_HEADER(add,Session-ID)=${Session-ID}))			; rfc7329
same => n,ExecIf(${EXISTS(${Number_pres})}?Set(PJSIP_HEADER(add,Privacy)="id"))
same => n,ExecIf(${EXISTS(${X-Unitel-origin})}?Set(PJSIP_HEADER(add,X-Unitel-origin)=${X-Unitel-origin}))
same => n,ExecIf(${EXISTS(${X-Unitel-TDC-Prefix})}?Set(PJSIP_HEADER(add,X-Unitel-TDC-Prefix)=${X-Unitel-TDC-Prefix}))
same => n,ExecIf(${EXISTS(${P-Asserted-Identity})}?Set(PJSIP_HEADER(add,P-Asserted-Identity)=<sip:${P-Asserted-Identity}@${GLOBAL(Hostname)}\;user=phone>))
same => n,While(${EXISTS(${SET(XCID=${SHIFT(X-Call-ID)})})})
same => n,Set(PJSIP_HEADER(add,X-Call-ID)=${XCID})								; sngrep F4 extended dialog
same => n,EndWhile()
same => n,Return()

[Hangup_Handler]
exten => _[+0-9*#s]!,1,Set(HANGUPCAUSE_STRING=${HANGUPCAUSE_KEYS()})
same => n,While(${EXISTS(${SET(Channel=${POP(HANGUPCAUSE_STRING)})})})
same => n,Verbose(0, Channel:"${CHANNEL(name)}" ToChannel:${Channel} CauseCode:"${HANGUPCAUSE(${Channel},tech)}", Asterisk:"${HANGUPCAUSE(${Channel},ast)}")
same => n,EndWhile()
same => n,Return()


[X-Call-ID]
exten => _[+0-9*#s]!,1,Set(i=0)
same => n,While(${EXISTS(${PJSIP_HEADER(read,X-Call-ID,${INC(i)})})})
same => n,Set(_X-Call-ID=${X-Call-ID},${PJSIP_HEADER(read,X-Call-ID,${i})})
same => n,ContinueWhile()
same => n,EndWhile()
same => n,Return()


[UniTel]	;calls from sip-core
exten => _00Z!,1,Goto(${FILTER(+1234567890#*,+${EXTEN:2})},1)						; International
exten => _X!,1,Goto(${FILTER(+1234567890#*,+45${EXTEN})},1)						; National

exten => _[+0-9*#s]!/_+!,1,Set(CALLERID(num)=${FILTER(+1234567890*#ABCD,${CALLERID(num)})})		; E164
exten => _[+0-9*#s]!/_00!,1,Set(CALLERID(num)=${FILTER(+1234567890*#ABCD,+${CALLERID(num):2})})		; International
exten => _[+0-9*#s]!/_XXXXXXXX,1,Set(CALLERID(num)=${FILTER(+1234567890*#ABCD,+45${CALLERID(num)})})	; National
exten => _[+0-9*#s]!/_X!,1,Set(CALLERID(num)=${FILTER(+1234567890*#ABCD,${CALLERID(num)})})		; Local
exten => _[+0-9*#s]!,1,Set(_Number_pres="prohib")							; Anonymous/INVALID
same => n,Set(_Max-Forwards=${PJSIP_HEADER(read,Max-Forwards)})
same => n,Set(_Resource-Priority=${PJSIP_HEADER(read,Resource-Priority)})				; rfc4412
same => n,Set(_Session-ID=${PJSIP_HEADER(read,Session-ID)})						; rfc7329
same => n,Set(_X-Call-ID=${PJSIP_HEADER(read,Call-ID)})							; sngrep F4 extended dialog
same => n,GoSubIf(${EXISTS(${PJSIP_HEADER(read,X-Call-ID)})}?X-Call-ID,${EXTEN},1)
same => n,ExecIf($[${EXISTS(${PJSIP_HEADER(read,Privacy)})} & "${PJSIP_HEADER(read,Privacy)}" != "none"]?Set(_Number_pres="prohib")	; Privacy: id;user;header
same => n,ExecIf(${EXISTS(${PJSIP_HEADER(read,X-Unitel-ReplaceFrom)})}?Set(CALLERID(num)=${PJSIP_HEADER(read,X-Unitel-ReplaceFrom):4:8}))
same => n,Set(CALLERID(number)=${REPLACE(REPLACE(CALLERID(num),#,C),*,B)})	; skal testes om det virker med TDCs nye platform
same => n,GoSubIf(${EXISTS(${CALLERID(rdnis)})}?,Diversion_To_E164,${CALLERID(rdnis)},1)			; change Diversion to E164
same => n,Set(_P-Asserted-Identity=${CUT(CUT(CUT(PJSIP_HEADER(read,P-Asserted-Identity),:,2),@,1),>,1)})	; P-Asserted-Identity: <sip:+4561484861@MSS.TDCTECH.DK;user=phone> || P-Asserted-Identity: <tel:+4593639134>
same => n,Set(XCLIP=${CUT(CUT(PJSIP_HEADER(read,X-clip),:,2),@,1)})
same => n,ExecIf($[${EXISTS(${XCLIP})}|${EXISTS(${P-Asserted-Identity})}]?GoSub(PAI_To_E164,${IF(${EXISTS(${XCLIP})}?${XCLIP}:${P-Asserted-Identity})},1))
same => n,ExecIf($["${PJSIP_HEADER(read,X-trunktype)}" = "MVNO"]?Set(X-Unitel-TDC-Prefix=01))
same => n,ExecIf($["${PJSIP_HEADER(read,X-Unitel-TDC-Prefix)}" = "03"]?Set(X-Unitel-TDC-Prefix=03))
same => n,Verbose(1,From Channel:"${CHANNEL(name)}" Prefix: ${X-Unitel-TDC-Prefix}, To: ${EXTEN}, From: ${CALLERID(num)}, PAI: ${P-Asserted-Identity})
same => n,Set(CHANNEL(hangup_handler_push)=Hangup_Handler,${FILTER(+1234567890#*,${EXTEN})},1)

same => n,GotoIf(${EXISTS(${Trunk})}?SIPP,${EXTEN},Trunk)				; *********** TEST ***************

same => n,Set(Trunk=${GLOBAL(TDC)})
same => n,Goto(Trunk,${FILTER(+1234567890#*,+${X-Unitel-TDC-Prefix}${EXTEN:1})},1)

[TDC]	;call from TD
exten => _+0XZ!,1,Set(_X-Unitel-TDC-Prefix=${FILTER(+1234567890#*,${EXTEN:1:2})})
same => n,Goto(${FILTER(+1234567890#*,+${EXTEN:3})},1)

exten => _+45Z!,1,Goto(${FILTER(+1234567890#*,${EXTEN:3})},1)						; National
exten => _+Z!,1,Goto(${FILTER(+1234567890#*,00${EXTEN:1})},1)						; International

exten => _[0-9*#s]!/_+45!,1,Set(CALLERID(number)=${FILTER(+1234567890#*,${CALLERID(number):3})})	; National
exten => _[0-9*#s]!/_+!,1,Set(CALLERID(number)=${FILTER(+1234567890#*,00${CALLERID(number):1})})	; International
exten => _[0-9*#s]!/_0045!,1,Set(CALLERID(number)=${FILTER(+1234567890#*,${CALLERID(number):4})})	; National
exten => _[0-9*#s]!/_X!,1,Set(CALLERID(number)=${FILTER(+1234567890#*,${CALLERID(number)})})		; Local
exten => _[0-9*#s]!,1,Set(_Number_pres="prohib")							; Anonymous/INVALID
same => n,Set(_Max-Forwards=${PJSIP_HEADER(read,Max-Forwards)})
same => n,Set(_Session-ID=${PJSIP_HEADER(read,Session-ID)})						; rfc7329
same => n,Set(_Resource-Priority=${PJSIP_HEADER(read,Resource-Priority)})				; rfc4412
same => n,Set(_X-Call-ID=${PJSIP_HEADER(read,Call-ID)})							; sngrep F4 extended dialog
same => n,GoSubIf(${EXISTS(${PJSIP_HEADER(read,X-Call-ID)})}?X-Call-ID,${EXTEN},1)
same => n,ExecIf($[${EXISTS(${PJSIP_HEADER(read,Privacy)})} & "${PJSIP_HEADER(read,Privacy)}" != "none"]?Set(_Number_pres="prohib")	; Privacy: id;user;header
same => n,GoSubIf(${EXISTS(${CALLERID(rdnis)})}?,Diversion_To_E164,${CALLERID(rdnis)},1)
same => n,Set(_P-Asserted-Identity=${CUT(CUT(CUT(PJSIP_HEADER(read,P-Asserted-Identity),:,2),@,1),>,1)})	; P-Asserted-Identity: <sip:+4561484861@MSS.TDCTECH.DK;user=phone> || P-Asserted-Identity: <tel:+4593639134>
same => n,GoSubIf(${EXISTS(${P-Asserted-Identity})}?PAI_To_DK,${P-Asserted-Identity},1)
same => n,Verbose(1,Channel:"${CHANNEL(name)}" To: ${EXTEN}, From: ${CALLERID(num)}, PAI: ${P-Asserted-Identity})
same => n,Set(CHANNEL(hangup_handler_push)=Hangup_Handler,${EXTEN},1)

same => n,GotoIf(${EXISTS(${Trunk})}?SIPP,${EXTEN},Trunk)				; *********** TEST ***************
;same => n,Answer()									; *********** TEST ***************
same => n,ExecIf(${ISNULL(${X-Unitel-TDC-Prefix})}?Set(_X-Unitel-TDC-Prefix=02))	; *********** TEST ***************
;same => n,Goto(UniTel,${EXTEN},1)


same => n,Set(Trunk=${GLOBAL(UniTel)})
same => n,Goto(Trunk,${EXTEN},1)

[Trunk]	;loadbalacing and failover
exten => _[+0-9*#s]!,1,Set(Num=${FIELDQTY(Trunk,\,)})
same => n,Set(Count=0)
same => n,Set(Current=${RAND(1,${Num})})
same => n,While($[${INC(Count)} <= ${Num}])
same => n,NoOp(Count=${Count})
same => n,Set(Current=$[${MATH(${Current}%${Num},i)}+1])
same => n,NoOp(["${DEVICE_STATE(PJSIP/${CUT(Trunk,\,,${Current})})}"="UNAVAILABLE"]?ContinueWhile())
same => n,ExecIf($["${DEVICE_STATE(PJSIP/${CUT(Trunk,\,,${Current})})}"="UNAVAILABLE"]?ContinueWhile())
same => n,ExecIf($["${DEVICE_STATE(PJSIP/${CUT(Trunk,\,,${Current})})}"="INVALID"]?ContinueWhile())
same => n,Dial(PJSIP/${EXTEN}@${CUT(Trunk,\,,${Current})},${DialTimeout},iS(${MaxCallTime})b(Dial_Handler^${EXTEN}^1))
same => n,ExecIf($["${NoFailoverCause}"!="${LISTFILTER(NoFailoverCause,",",${HANGUPCAUSE})}"]?ExitWhile())
same => n,EndWhile()
same => n,DumpChan()
same => n,ExecIF(${EXISTS(${HANGUPCAUSE})}?Hangup(${HANGUPCAUSE}):Hangup(38))	# 38	NETWORK_OUT_OF_ORDER
