nix/modules/voip/asterisk.nix

140 lines
3.9 KiB
Nix

{ lib, cfg, models, intercomEntries }:
let
# Phones that have voicemail enabled
vmPhones = lib.filterAttrs (_: phone: phone.voicemailTimeout != null) cfg.phones;
hasVoicemail = vmPhones != {};
pjsip = ''
[transport-tcp]
type = transport
protocol = tcp
bind = 0.0.0.0:${toString cfg.sipPort}
[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0:${toString cfg.sipPort}
; --- templates ---
[endpoint-cisco-8961](!)
type = endpoint
context = internal
transport = transport-tcp
disallow = all
allow = ulaw
allow = alaw
allow = g722
allow = g726
allow = ilbc
allow = gsm
direct_media = no
trust_id_inbound = yes
[endpoint-generic](!)
type = endpoint
context = internal
transport = transport-tcp
disallow = all
allow = ulaw
allow = alaw
allow = g722
direct_media = no
[auth-userpass](!)
type = auth
auth_type = userpass
; --- phones ---
'' + lib.concatStringsSep "\n" (lib.mapAttrsToList (key: phone:
let m = models.${phone.model}; in ''
[${key}](${m.endpointTemplate})
auth = auth-${key}
aors = ${key}
${lib.optionalString (phone.voicemailTimeout != null) "mailboxes = ${phone.extension}@voicemail\n set_var=VOICEMAIL_MAILBOX=${phone.extension}"}
[auth-${key}](auth-userpass)
username = ${key}
password = ${phone.password}
[${key}]
type = aor
max_contacts = ${toString m.maxContacts}
remove_existing = yes
'') cfg.phones)
+ lib.concatMapStringsSep "\n" (ic: ''
[${ic.endpoint}](${ic.endpointTemplate})
auth = auth-${ic.endpoint}
aors = ${ic.endpoint}
[auth-${ic.endpoint}](auth-userpass)
username = ${ic.endpoint}
password = ${ic.password}
[${ic.endpoint}]
type = aor
max_contacts = ${toString ic.maxContacts}
remove_existing = yes
'') intercomEntries;
# Reverse map: extension number -> pjsip endpoint key
extensionToEndpoint = lib.foldlAttrs (acc: key: phone:
acc // { ${phone.extension} = key; }
) {} cfg.phones;
# All page endpoints: intercom line for provisioned phones, regular for others
allPageEndpoints = lib.concatStringsSep "&" (lib.mapAttrsToList (key: phone:
let m = models.${phone.model}; in
if m.hasProvisioning && cfg.intercomPrefix != null
then "PJSIP/${key}-intercom"
else "PJSIP/${key}"
) cfg.phones);
extensions = ''
[internal]
'' + lib.concatStringsSep "\n" (lib.mapAttrsToList (ext: extCfg:
if extCfg.mode == "app"
then "exten => ${ext},1,${extCfg.app}"
else if extCfg.mode == "page"
then "exten => ${ext},1,Page(${allPageEndpoints},i,120)"
else if lib.hasAttr ext extensionToEndpoint
then
let
phoneKey = extensionToEndpoint.${ext};
phone = cfg.phones.${phoneKey};
in if phone.voicemailTimeout != null
then ''exten => ${ext},1,Dial(PJSIP/${phoneKey},${toString phone.voicemailTimeout})
same => n,VoiceMail(${ext}@voicemail,u)''
else "exten => ${ext},1,Dial(PJSIP/${phoneKey})"
else "exten => ${ext},1,Hangup() ; WARNING: no endpoint assigned to extension ${ext}"
) cfg.extensions)
+ "\n" + lib.concatMapStringsSep "\n" (ic:
"exten => ${ic.extension},1,Dial(PJSIP/${ic.endpoint},30)"
) intercomEntries
+ lib.optionalString hasVoicemail "\nexten => *97,1,VoiceMailMain(\${VOICEMAIL_MAILBOX}@voicemail,sa(0))";
rtp = ''
[general]
rtpstart = ${toString cfg.rtpStart}
rtpend = ${toString cfg.rtpEnd}
'';
voicemail = ''
[general]
format = ulaw
[voicemail]
'' + lib.concatStringsSep "\n" (lib.mapAttrsToList (_: phone:
let displayName = cfg.extensions.${phone.extension}.displayName; in
" ${phone.extension} => ,${displayName},,attach=no"
) vmPhones);
in {
"pjsip.conf" = pjsip;
"extensions.conf" = extensions;
"rtp.conf" = rtp;
} // lib.optionalAttrs hasVoicemail {
"voicemail.conf" = voicemail;
}