Wie kann man die Rufnummer bei Telefonaten zwischen Sipgate Teilnehmern und Asterisk anzeigen (anstatt interne Sipgate-ID)?

AsteriskAnrufe zwischen Sipgate Teilnehmern werden automatisch als SIP-Anrufe geroutet, selbst wenn man die „externe“ Telefonnummer anruft. Das hat den Vorteil, dass die Anrufe zwischen den Sipgate Teilnehmern nichts kosten, da die Telefonate über Internet abgewickelt werden. Schön wäre es aber auch zu wissen, wer mich anruft 😉

Problem:
In der From-Header steht dann nicht die Telefonnummer des Anrufers sondern die SIP-URL (z.B. <sip:12345e0@sipgate.de>). Die von Asterisk gesetzte Variable CALLERID(num) beinhaltet dann nur noch die Sipgate SIP-UserID wie z.B. 12345e0. Die an Asterisk angeschlossenen Telefone können meistens damit nichts anfangen. Wenn die ID einen Buchstaben enthält (hier im Beispiel ‚e‚), führt es dazu, dass manch ältere Telefone gar keine Rufnummer anzeigen. Besonders ärgerlich ist es, wenn man einen Anruf verpasst hat und die Rufnummer nicht mehr zuordnen kann, wer tatsächtlich angerufen hat.

Lösungsweg:
Schaut man sich die SIP Header an, stellt man fest, dass die gewünschte Information in dem Headerelement „P-Asserted-Identity“ enthalten ist:

INVITE sip:5000@10.0.0.33 SIP/2.0
...
From: <sip:12345e0@sipgate.de>;tag=CAFEBABE
To: <sip:072198765432@sipgate.de>
Contact: <sip:12345e0@12.34.56.78;uniq=CAFEAFFE23>
...
P-Asserted-Identity: <sip:072112345678@sipgate.de>

Bei anderen Anbietern kann das Format abweichen. Mehr dazu in http://www.ietf.org/rfc/rfc3325.txt.

Zwecks Demonstration habe ich einen kleinen Dialplan für Asterisk geschrieben:

; debug
exten => 5000,1,NoOp(Caller-ID: ${CALLERID(all)})
exten => 5000,2,NoOp(SIP From: ${SIP_HEADER(From)})
exten => 5000,3,NoOp(SIP To  : ${SIP_HEADER(TO)})
exten => 5000,4,NoOp(SIP PAI : ${SIP_HEADER(P-Asserted-Identity)})

; try to extract phone number from sip header P-Asserted-Identity
exten => 5000,5,Set(FON=$["${SIP_HEADER(P-Asserted-Identity)}" : "<sip:([0-9]+)"])
exten => 5000,6,ExecIf($[${ISNULL(${FON})}=0]?Set(CALLERID(num)=${FON}))

; debug
exten => 5000,7,NoOp(Caller-ID: ${CALLERID(all)})
...

Erläuterung:
5: Wir extrahieren die Nummer mit RegExp und speichern das Ergebnis in die Variable FON.
6: Falls FON nicht null ist, ersetzen wir die CALLERID(num) mit dem Wert von FON.

Hier zwei UseCases und Ausgabe von Asterisk:
Teinehmer für das Beispiel (Telefonnummer, IPs sowie alle TAGs sind verschleiert).
Angerufene (Asterisk mit Sipgate-Account):
– Telefonnumber = 072198765432
Anrufer 1 (Fritzbox mit Sipgate-Account):
– Sipgate ID = 12345e0
– Telefonnumber = 072112345678
Anrufer 2 (Mobil):
– Telefonnumber = 017112345678

Case 1: Anrufer 1 (sipgate -> sipgate):

-- Exec...1] NoOp("SIP/sipgate.de-000000b6", "Caller-ID: "" <12345e0>") in new stack
-- Exec...2] NoOp("S..b6", "SIP From: <sip:12345e0@sipgate.de>;tag=CAFEBABE") in new stack
-- Exec...3] NoOp("S..b6", "SIP To  : <sip:072198765432@sipgate.de>") in new stack
-- Exec...4] NoOp("S..b6", "SIP PAI : <sip:072112345678@sipgate.de>") in new stack
-- Exec...5] Set("S..b6", "FON=072112345678") in new stack
-- Exec...6] ExecIf("S..b6", "1?Set(CALLERID(num)=072112345678)") in new stack
-- Exec...7] NoOp("S..b6", "Caller-ID: "" <072112345678>") in new stack
-- Exec...8] ...

Exec…5: Die externe Rufnummer des Anrufers wurde in FON reingeschrieben
Exec…6: 1? => Kondition erfüllt => ersetze CALLERID(num)
Exec…7: Verifizierung, dass die Nummer ersetzt wurde (vgl. Exec…1)

Case 2: Anrufer 2 (mobil -> sipgate):

-- Exec...1] NoOp("S..b8", "Caller-ID: "017112345678" <017112345678>") in new stack
-- Exec...2] NoOp("S..b8", "SIP From: "017112345678" <sip:017112345678@sipgate.de>;tag=cafebabe") in new stack
-- Exec...3] NoOp("S..b8", "SIP To  : <sip:004972198765432@sipgate.de>") in new stack
-- Exec...4] NoOp("S..b8", "SIP PAI : ") in new stack
-- Exec...5] Set("S..b8", "FON=") in new stack
-- Exec...6] ExecIf("S..b8", "0?Set(CALLERID(num)=)") in new stack
-- Exec...7] NoOp("S..b8", "Caller-ID: "017112345678" <017112345678>") in new stack
-- Exec...8] ...

Exec…5: Patternmatching schlägt fehl, da der Header nicht gesetzt ist, somit is die Variable FON null.
Exec…6: 0? => Kondition nicht erfüllt => nichts tun
Exec…7: Verifizierung, dass die Nummer unverändert geblieben ist (vgl. Exec…1)

Die Endgräte zeigen nun immer die externe Rufnummer des Anrufers an. Somit kann der Anrufer bei einem verpassten Anruf auch zurückgerufen werden.

Viel Spass,

= C. | SaaS Web Techniklabor =

P.S.: Lustig ist, dass die App von Sipgate auch nur die interne ID anzeigt („Anruf von 12345e0“) und man verwirrt ist, wer nun wirklich anruft…