Der SIP-Proxy OpenSIPS verfügt über mittlerweile über eine ziemlich beachtliche Anzahl an Modulen. Ein sehr interessantes davon ist das Perl-Modul: es erlaubt, eigenen Perl-Code in das Routing-Skript einzubetten.
Da ich gegenwärtig die Migration unserer Voice-Plattform auf die "nächste Generation" vorbereite, ist es mir immer wieder mal von großem Nutzen: zwar habe ich aktuell keine Perl-Funktion für den Produktivbetrieb vorgesehen, zum Testen und Experimentieren ist eingebetteter Perl-Code aber ein beeindruckend vielfältiges Instrument.
Wie man sich das vorstellen darf? Man schreibt seinen Perl-Code in eine dedizierte Perl-Datei, im Routing-Skript wird dann das Perl-Modul geladen, der entsprechende Dateiname wird vorkonfiguriert:
loadmodule "perl.so"
modparam("perl", "filename", "/etc/opensips/perlcode.pl")
Funktionen in dieser Datei können dann wie im folgenden Beispiel aufgerufen werden:
onreply_route[1]
{
...
if(t_check_status("183")) {
perl_exec("sendReplyAs180");
drop();
}
}
Na, habe ich euer Interesse geweckt? Ich habe vor ein paar Monaten ein entsprechendes Beispiel geschrieben, Ihr findet es in den OpenSIPS Tutorials unter dem Namen Replace 183 early media reply with 180 (Ringing). Und wer es besonders eilig hat, kann es auch gleich hier herunterladen: perlfunctions.pl
Wichtig ist im eigenen Code eigentlich bloß das Einbinden der entsprechenden OpenSIPS-Library, z.B. so:
use OpenSIPS qw ( log );
use OpenSIPS::Constants;
sub logtest {
my $m = shift;
my $method = $m->getMethod();
log(L_INFO, "Logged by Perl, method is $method\n");
return 1;
}
Der Code ist für folgendes Szenario gedacht: ein Gespräch soll beim Aufbau (INVITE) geforkt werden: ein Branch geht zum eigentlichen Ziel, der andere an einen Media-Server, welcher z.B. irgend eine Ansage ("Ihr Guthaben ist bald erschöpft...") als Early Media abspielt.
Das Problem ist jetzt folgendes: wenn vom PSTN Gateway kein 180 Ringing, sondern ein Klingelton als 183-Reply kommt, dann erhält der Client (UAC) zwei RTP-Streams - und das Ergebnis ist ziemlich unberechenbar. Einige Clients spielen bloß den ersten Stream ab, andere den letzten ab. Während das noch am ehesten Sinn machen würde (wenn auch inkonsistent), gibt es auch solche, die ein fürchterliches Geräusch produzieren - sie "mixen" wohl irgendwie die zwei Streams ineinander.
Wie kann man das lösen? Ganz einfach: aus dem 183er Reply vom PSTN-Gateway muss ein 180er werden. Und genau diese Aufgabe erfüllt das Perl-Skript. Da es nicht möglich ist, den Code eines Replies für OpenSIPS abzuändern, holen wir uns die vollständige SIP-Nachricht, routen sie selbst - und verwerfen sie im Routing-Skript von OpenSIPS (s.o.).
Das mit dem Routen muss dann natürlich streng nach RFC 3261 (SIP) geschehen: Top-most Via-Header entfernen (Vorsicht, es können auch mehrere in einer Zeile sein!), zum Routen nutzen, den rport-Parameter berücksichtigen - usw. Wichtig ist außerdem, dass der Port des Proxies verwendet wird (5060) - da er schon belegt ist, muss für IO::Socket::INET zwingend ReuseAddr auf '1' gesetzt werden.
Naja, das wär's dann eigentlich schon - viel Spaß beim Experimentieren!