In Ermangelung einer CAPI-Implementierung für SOLARIS wurde für die Durchführung dieser Arbeit auf eine ISDN-Library von Zahl [czahl97:isdn] zurückgegriffen. Anstelle einer nachrichtenorientierten Kommunikation findet hier eine ereignisorientierte Kommunikation statt: Requests werden über normale Funktionsaufrufe an die Library gerichtet. Für die Behandlung von Indications registriert die Anwendung bei der Library Event-Handler-Funktionen, die bei Eintreten der entsprechenden Events von der Library aufgerufen werden. Dazu muß die Anwendung ähnlich wie beim X11-Window-System permanent in einer Main-Loop der ISDN-Library laufen. Die Behandlung von Events durch die Anwendung muß in so kurzer Zeit wie möglich erfolgen, damit die Library vom ISDN eingehende Indications schnell genug behandeln kann. Ansonsten würde das Q.931-Protokoll verletzt werden, falls Timeouts ablaufen und nicht rechtzeitig behandelt werden können.
Die Verbindung wird durch den Angerufenen beendet, was die Library mit einem ISDN_DISCONNECT_IND quittiert. Da der B-Kanal zwischen lokaler Vermittlungsstelle (VStO) und dem Anrufer immer noch aufgebaut ist, schickt die Library ein ISDN_PROGRESS_IND. In aller Regel wird jetzt von der VStO ein Besetzt-Zeichen auf dem B-Kanal gesendet. Die Anwendung beendet die Verbindung schließlich durch Aufruf der Library-Funktion IsdnReleaseReq() und erhält als finale Bestätigung ein ISDN_RELEASE_IND.
Wie man sieht, ist für die Initiierung eines Anrufes nur ein Funktionsaufruf erforderlich, von den eingehenden Indications brauchen lediglich ISDN_CHANNEL_IND und ISDN_RELEASE_IND behandelt zu werden. Ersteres deshalb, weil dort der Filedescriptor für den B-Kanal mitgeteilt wird und letzteres, weil damit das Ende der Verbindung erkannt wird. Ein ISDN_DISCONNECT_IND würde die Anwendung z.B. nicht erhalten, wenn sie die Verbindung selbst mit IsdnReleaseReq() beendet. Das ISDN_RELEASE_IND signalisiert in jedem Fall das Ende der Verbindung zwischen Anwendung und VStO.
Letztendlich spiegelt diese Dialogfolge den im Q.931 definierten Ablauf wieder, auch die dort verwendeten Namen finden sich in den Library-Funktionen und Namen der Indications wieder. Eine der wesentlichen Aufgaben der Library ist die Verwaltung der zahlreichen Timer, die im Q.931 definiert sind (allein 16 auf der Benutzerseite) sowie die Kommunikation mit dem darunterliegenden Q.921-Modul.
Während Requests per Funktionsaufrufe abgeschickt und Indications von Event-Handlern behandelt werden, erfolgt der Austausch der B-Kanal-Daten über direkten Zugriff auf das ISDN-Device. Mit einem ISDN_CHANNEL_IND teilt die Library der Anwendung einen Filedescriptor mit, auf dem der B-Kanal bereits geöffnet ist. Der Datenaustausch für den B-Kanal erfolgt also wie unter UNIX üblich per read() und write() System-Calls.
Der eingehende Anruf wird der Anwendung mit einem ISDN_CALL_IND signalisiert, durch welchen der Anwendung gleichzeitig eine eindeutige Verbindungs-Id mitgeteilt wird. Durch Aufruf von IsdnAlertingReq() wird der Gegenstelle die Signalisierung (also das Klingeln) angezeigt (der Anrufer erhält das Klingelzeichen). Anschließend stellt die Library den Filedescriptor für den B-Kanal zur Verfügung (ISDN_CHANNEL_IND). Schließlich nimmt die Anwendung mittels IsdnConnectReq() den Anruf entgegen; der B-Kanal zwischen beiden Sprechstellen gilt mit dem Eintreffen des ISDN_CONNECT_IND als aufgebaut. Der Angerufene beendet den Anruf durch Aufruf von IsdnReleaseReq(), was entsprechend mit ISDN_RELEASE_IND bestätigt wird.
Durch die Vergabe der Verbindungs-Ids kann eine Anwendung durchaus mehrere eingehende oder ausgehende Verbindungen gleichzeitig verwalten.
Um die in den letzten beiden Kapiteln beschriebenen Aufgaben möglichst flexibel realisieren zu können, lag der Gedanke nahe, die Behandlung von Anrufen durch Skripte, etwa wie UNIX-Shell-Skripte, ausführen zu lassen.
Ein entsprechender Skript-Befehl bewerkstelligt die Umleitung. Bei dieser Art der Umleitung, die man als passiv bezeichnen könnte, wird lediglich der Audiostrom umgeleitet, nicht aber der Anruf selbst. Es erfolgt also keine Rufsignalisierung ins Internet. Das Ende der Umleitung kann entweder durch das Skript (z.B. einem abgelaufenen Timer oder per ) oder aber durch den Anrufer (per Auflegen) aus dem ISDN erfolgen. Abbildung [pic-isdn-rtp-t] zeigt den Ablauf, bei dem das Verbindungsende durch das Skript eingeleitet wird.
Um den Anruf wie in Abbildung [pic-isdn-sip] gezeigt aus dem ISDN im Internet per SIP zu signalisieren, sieht die Skriptsprache den Befehl vor. Zusammen mit diesem werden die SIP-spezifischen Parameter übergeben, unter anderem die e-Mail-Adresse des Gerufenen. Es ist in jedem Fall Aufgabe des Skriptes, das Rufziel bzw. dessen e-Mail-Adresse zu ermitteln. Dies kann natürlich auch durch den Anrufer per Telefontastatur geschehen, wie in [e-mail-inp] beschrieben.
Die Ausführung der -Anweisung ist also erst nach Rufannahme durch den Angerufenen sinnvoll (Abbildung [pic-isdn-sip-t]).
Die Verbindung wird hier durch den Anrufer aus dem ISDN beendet (ISDN_RELEASE_IND). Eine u.a. kostensparende Variante wäre, die Verzögerung der ISDN-Rufannahme bis zu dem Zeitpunkt, an dem der positive Response Code (200) des SIP-Requests eintrifft. Lehnt der mit SIP gerufene Netzwerkbenutzer den Anruf nämlich ab, so wurde der ISDN-Ruf vergebens angenommen (außer für die Telefongesellschaft). Hierbei ist jedoch das ISDN-Timing zu beachten. ITU Q.931 sieht 120 s für die Rufsignalisierung vor, danach wird die Verbindung von der VStO beendet. Manche Telefonanlagen (z.B. die, die ich für die Entwicklung benutzt habe) tun dies scheinbar schon nach 90 s. Der SIP-Anruf muß also innerhalb dieser Zeit beantwortet werden, ansonsten wird die ISDN-Verbindung durch die VStO getrennt. Im allgemeinen wird ein Anrufer aus dem Telefonnetz, der nicht weiß, daß sein Anruf in ein völlig überlastetes Netzwerk umgeleitet wird, kaum länger als 20 bis 30 s warten. Daher scheint mir die sofortige Annahme des ISDN-Anrufes durchaus sinnvoll, um dann z.B. die Meldung "Bitte warten Sie, Ihr Anruf wird weitergeleitet"abzuspielen.
Für diese Form der Rufumleitung wird ein zweiter B-Kanal benötigt. Im Gegensatz zur Umleitung ins Internet erfolgt hier durch die -Anweisung gleichzeitig die Signalisierung des Anrufes. Die Benutzung von erübrigt sich somit. Abbildung [pic-isdn-isdn-t] zeigt den Ablauf. Zur Vereinfachung sind in der Abbildung die Indications ISDN_CHANNEL_IND und ISDN_ALERTING_IND weggelassen. Auch hier wird die Verbindung durch das Skript beendet.
Da das Ende eines RTP-Stromes quasi nur am dauerhaften Ausbleiben der RTCP-Pakete erkannt werden kann, bleibt die Beendigung einer solchen Umleitung dem gerufenen ISDN-Teilnehmer oder dem Skript überlassen. Eventuell könnte man ein RTCP BYE der Person, die den SIP-Anruf initiiert hat als Indikator für ein Verbindungsende nehmen, aber das scheint mir sehr vage. Der Anrufer könnte die Konferenz initiiert und sich zwischenzeitlich verabschiedet haben (daher das BYE-Paket). Jedoch könnten inzwischen andere Benutzer der Konferenz beigetreten sein, mit denen der ISDN-Teilnehmer noch in Verbindung bleiben will. Ein definitives Ende der Verbindung kann also nur durch den Telefonteilnehmer (durch Auflegen) oder durch das Skript (z.B. Timeout) herbeigeführt werden.
Bei dieser Form der Umleitung, die eigentlich nur in der Rückweisung des INVITE-Requests besteht, wird also kein Mediendatenstrom behandelt.
Wie man sieht, werden die vorgestellten Formen der Rufumleitung alle mit Hilfe von bewerkstelligt, das sich je nach Anrufquelle und Umleitungsziel anders verhält. Eigentlich sollte dies die Anrufbehandlung vereinheitlichen und somit auch vereinfachen. Mir ist nicht ganz klar, ob dies auch wirklich gelungen ist, zumal in dem Fall der Umleitung SIPSIP zuvor kein aufgerufen werden darf. Genau dieser Fall bleibt noch offen, wenn nämlich ein SIP-Request angenommen und anschließend mit ins Internet zurück umgeleitet wird. Man könnte sich hier durchaus eine Umleitung des RTP-Stroms vorstellen, die aber derzeit nicht realisiert ist.
Vor allem in Richtung Computer-Telephony-Integration (CTI) lassen sich beliebig weitere Beispiele ausdenken, von denen jedoch die meisten mit bereits existierenden Produkten realisierbar sind.
Bei leerer Konfigurationsdatei werden alle Anrufe ignoriert. Jede Zeile in dieser Datei definiert ein Tripel von rufender und gerufener MSN, einer Medien-Kennung sowie die dazugehörige Aktion, die der Server bei einem Anruf auslösen soll. Die einzelnen Einträge werden durch Leerzeichen getrennt. Rufende und gerufene MSN können mittels * rechtsmaskiert werden, d.h. es können Nummernbereiche mit gleichen Anfangsziffern bezeichnet werden (siehe Abbildung [cfg-ex]). Kommentarzeilen beginnen mit einem #.
# isdn.cfg -- isdn server configuration file
#
# calling called
# party no. party no. media action
* 41 audio iPhone
30314* 44 audio iPlay KeinAnschluss-8k.au loop
* 45 audio&video iScript foertel staff test.cpl
* 45 audio|video iScript foertel staff test1.cpl
<unknown> * audio iPlay NoServiceAvailable.au
Die Medienkennung legt die Medien fest, die behandelt werden können. Derzeit sind "audio"und "video" definiert. In den ersten beiden Zeilen des obigen Beispiel werden z.B. nur Anrufe mit Audiodatenstrom entgegengenommen. Ruft also jemand mit einem Fax die 41 an, so wird der genannte Service nicht ausgeführt. Die Medienangaben können mit und | UND- bzw. ODER-verknüpft werden, wie in der dritten und vierten Zeile.
Die erste Zeile definiert, daß alle Anrufe zur MSN 41 mit einem Service namens iPhone behandelt werden. Anrufern aus der TU-Berlin (30314*) wird unabhängig von der gewählten Nummer das angegebene Audiofile endlos (loop Option) vorgespielt (zweite Zeile). Die restlichen Zeilen aktivieren bei Anrufen die Ausführung des angegebenen Skriptes unter der User-Id foertel und der Group-Id staff. Während die erste Zeile für die MSN 45 das Skript test.cpl nur bei Anrufen mit Audio und Video ausführt wird, wird test1.cpl bei Anrufen mit Audio und/oder Video gestartet. Da die Zeilen der Konfigurationsdatei von oben nach unten interpretiert werden, wird bei einem Anruf der Dienst aufgerufen, bei der die drei Parameter als erstes passen. Bei einem Anruf mit Audio und Video auf der 45 wird also test.cpl ausgeführt.
Für den Fall, daß die Nummer des Anrufers/Gerufenen nicht bekannt ist, wie etwa bei Anrufen aus dem analogen Telefonnetz, sind die entsprechenden Felder mit <unknown> belegt. Folgende Dienste sind vorgesehen:
Wie sich später zeigen wird, können bis auf den iPhone-Dienst alle anderen auch durch Skripte realisiert werden. Dies hat sich jedoch erst im Laufe der Arbeit ergeben und so ist die Konfigurationsdatei isdn.cfg erhalten geblieben. Der iPhone-Dienst war ohnehin nur zum Testen gedacht, denn im Rahmen dieser Arbeit ging es nicht um die Neuerfindung des Telefons; auf ihn kann also verzichtet werden.
Somit könnte bei einen Anruf sofort ein bestimmtes Skript gestartet werden, z.B. icc.cpl für Incoming Call, in dem dann entschieden wird, ob der Anruf angenommen wird oder nicht. Für verschiedene Anrufer und Medien könnten dann von icc.cpl aus andere Skripte aufgerufen werden. Der Hauptteil eines solchen Skriptes könnte in Anlehnung an die im nächsten Kapitel entwickelte Sprache wie folgt aussehen:
...
if [string match 30314* $sysCallingParty ] {
accept
exec "iAuPlay KeinAnschluss.au"
exit
}
switch $sysCalledParty {
"44" { accept
enter AnsweringMachine
}
"45" { accept
source ~foertel/test.cpl
}
...
}
Die Variable sysCalledParty enthält die vom Anrufer gewählte Nummer, sysCallingParty enthält die Nummer des Anrufers, sofern vohanden. Der -Befehl liest und interpretiert das angegebene Skript.
Im Gegensatz zur tabellarischen Darstellung in isdn.cfg kann diese Lösung bei größeren Skripten schnell unübersichtlich und fehleranfällig werden, wie sich in dem Beispiel bereits andeutet. Außerdem ist unklar, unter welcher User-Id die Skripte ausgeführt werden. Derzeit läuft der Call-Server als Benutzer root, um auf das ISDN-Device zugreifen zu können. Aus Sicherheitsgründen ist dies problematisch, wenn Benutzer die mit gelesenen Skripte selbst erstellen dürfen. Zur Lösung dieses Problems könnte man jedoch einen -Befehl implementieren, der vor Ausführung des -Befehls aufgerufen wird.
Die Behandlung des ISDN-Protokolls (ISDN-Library), das Starten der Dienste bzw. Skripte sowie die Behandlung der RTP- und B-Kanal-Datenströme erfolgt also durch den Call-Server, der derzeit als einzelner Prozeß realisiert ist. In den folgenden Kapiteln wird sich zeigen, daß für bestimmte Aktivitäten des Servers weitere Prozesse gestartet werden müssen.