1 Überblick Multimedia Kommunikation Übung 3: Session Initiation Protocol () Besprechung der 2. Aufgabe (JAIN, NIST ) Client Server Neue Aufgabenstellung holger.schmidt@uni-ulm.de 2 Besprechung der 2. Aufgabe Socket: Eingehende Verbindungen Parser: Extraktion Informationen aus eintreffenden Nachrichten (Requests) Zustandsautomat: Logik für Informationsverarbeitung Nachrichtengenerator: Antworten (Responses) Zustandsautomat DESCRIBE INIT SETUP READY PAUSED PAUSE ING 3.1 main-methode, Socket-Kommunikation ServerSocket listensocket = new ServerSocket(serverPort); SimpleRTSPServer.rtspSocket = listensocket.accept(); // nur 1 Verbindung listensocket.close(); clientipaddr = rtspsocket.getinetaddress(); rtspbufferedreader = new BufferedReader(new InputStreamReader (SimpleRTSPServer.rtspSocket.getInputStream())); rtspbufferedwriter = new BufferedWriter(new OutputStreamWriter (SimpleRTSPServer.rtspSocket.getOutputStream())); [] 3.2
DESCRIBE Verarbeitung DESCRIBE INIT SETUP READY Verarbeitung eines Requests: parserequest() int request_type; boolean done = false; while(!done){ // Warten auf nächsten Request request_type = rtspserver.parserequest(); PAUSED if (request_type == DESCRIBE){ done = true; rtspserver.senddescriberesponse(); PAUSE ING 3.3 String request = rtspbufferedreader.readline(); StringTokenizer tokens = new StringTokenizer(request); String request_type = tokens.nexttoken(); if (request_type.compareto("describe") == 0) type = DESCRIBE; else if [] if (type == SETUP type == DESCRIBE) videoname = tokens.nexttoken(); // EOM: leere Zeile while ( ((!EOM) && (nextline = rtspbufferedreader.readline())!=null) ){ // extract CSeq // extract Transport // end of message => finish 3.4 Senden der Antwort: senddescriberesponse() SETUP Verarbeitung DESCRIBE INIT SETUP READY // Erzeugen der Nachricht als String String msg = rtspbufferedwriter.write(msg); rtspbufferedwriter.write(crlf); // CRLF = \r\n rtspbufferedwriter.flush(); done = false; while(!done){ // wait for next request request_type = rtspserver.parserequest(); if (request_type == SETUP){ PAUSED PAUSE ING Antwort auf DESCRIBE // init the videostream && rtp socket rtspserver.initrtp(); RTSP/1.0 200 OK CSeq: 224 Content-Base: rtsp://134.60.77.162/test/ Content-Type: application/sdp Content-Length: 302 [SDP Inhalt] 3.5 done = true; state = READY; rtspserver.sendsetupresponse(); 3.6
Initialisierung des Video Streams: initrtp(), PAUSE, TEARDOWN Verarbeitung DESCRIBE INIT SETUP READY Datei Data Source Processor Data Source Data Sink Netzwerk processor = Manager.createProcessor(ds); boolean result = waitforstate(processor, Processor.Configured); // Video-Output: JPEG/RTP, Content Descriptor RAW_RTP [] result = waitforstate(processor, Controller.Realized); dataoutput = processor.getdataoutput(); // rtpurl = rtp://clientipaddr:port/video MediaLocator outputlocator = new MediaLocator(rtpURL); rtptransmitter = Manager.createDataSink(dataOutput, outputlocator); rtptransmitter.open(); rtptransmitter.start(); dataoutput.start(); 3.7 while(true){ PAUSED PAUSE ING request_type = rtspserver.parserequest(); if ( (request_type == ) && (state == (READY PAUSED)) ){ rtspserver.playvideo(); state=ing; rtspserver.sendplayresponse(); else if ((request_type == PAUSE) && (state == ING)){ rtspserver.pausevideo(); state=paused; rtspserver.sendresponse(); else if (request_type == TEARDOWN){ rtspserver.stopvideo(); rtspserver.sendresponse(); System.exit(0); 3.8 4 Session Initiation Protocol () Abspielen Video: playvideo() processor.start(); Pausieren Video: pausevideo() processor.stop(); Signalisierungsprotokoll für beliebige Sitzungen (RTSP: VoD) Voice over IP, Instant Messaging, Gaming, etc. Konfigurieren, Starten, Modifizieren, Stoppen der Übertragung Textbasiertes Protokoll Client/Server (Request/Response) Sessionaufbau, -modifikation, -abbau Stoppen Video: stopvideo() Request processor.stop(); processor.close(); processor = null; rtptransmitter.close(); rtptransmitter = null; 3.9 Client Response Server Spezifikation bestimmter Netzwerkelemente Terminal: User Agent Infrastruktur: Registar, Location Server, Proxy Server, Redirect Server 3.10
4 Session Initiation Protocol () 4 Session Initiation Protocol () Sitzungsaufbau Location Service Location Service Location Service Location Service Registrar Proxy Proxy Registrar Registrar Proxy Proxy Registrar REGISTER OK REGISTER OK INVITE OK 3.11 3.12 5 JAIN 5 JAIN Standardisierte Java API für (RFC 3261) Schnittstelle zum Stack Schnittstelle für Nachrichten s und -Semantiken Erweiterungen, u.a. s (RFC 3265) Instant Messages (RFC 3428) Generische API: Verwendung in s, Proxies, etc. Vereinfachung der Anwendungsentwicklung Architektur Setup Function Stack Factory NIST Implementierung JAIN API: http://snad.ncsl.nist.gov/proj/iptel/ 3.13 Stack [in Anlehnung an JAIN Tutorial] Stack 3.14
5 JAIN 5 JAIN Stack Interface Verwaltet und Zugehörig zu einer IP-Adresse Mehrere möglich (Ports) Anwendung kann mehrere Stacks haben Eigenschaften als Properties, u.a. Name, IP Adresse, Ausgehender Proxy, Retransmission Einstellungen Interface Benachrichtigt registrierten über Ereignisse Methoden zur von Transaktionen Zustandsbehaftet bzw. zustandslos Initiiert Senden von Nachrichten Setup Function Factory Setup Function Factory Stack Stack Stack 3.15 Stack Stack Stack 3.16 5 JAIN 5 JAIN Interface Ein pro Stack Alle eines Stacks haben den selben Verarbeitet Requests und Responses Zustandsbehaftet bzw. zustandslos Verarbeitet Timeouts und Retransmits Aufgabe der Anwendung Registrieren um mit Stack zu interagieren Registrieren eines s zur Nachrichtenverarbeitung Erzeugen Transaktion (Request/Response zustandsbehaftet) Senden von zustandslosen Nachrichten Zugriff auf Stack Objekte Anwendung erhält Ereignisse durch das Interface Setup Function Factory Setup Function Factory Stack Stack Stack 3.17 Stack Stack Stack 3.18
5 JAIN 5 JAIN Erzeugen eines Stacks // Eigenschaften des Stacks definieren Properties properties = new Properties(); properties.setproperty("javax.sip.stack_name", "shootme"); properties.setproperty("gov.nist.javax.sip.trace_level", "32"); properties.setproperty("gov.nist.javax.sip.debug_log","debug"); properties.setproperty("gov.nist.javax.sip.server_log",srvlog"); // Erzeugen sipfactory = SipFactory.getInstance(); sipfactory.setpathname("gov.nist"); // SipStack: Pfad +".javax.sip.sipstackimpl" sipstack = sipfactory.createsipstack(properties); Nachricht JAIN Nachrichten Architektur Anwendung Listening Point Anwendung Nachricht Listening Point // ListeningPoint lp = sipstack.createlisteningpoint("127.0.0.1",5070, "udp"); Sip sip = sipstack.createsip(lp); sip.addsip(listener); Stack [in Anlehnung an JAIN Tutorial] Stack 3.19 3.20 5 JAIN 5 JAIN Unterstützte Nachrichtentypen REGISTER Registrieren der Kontaktinformationen am Registar INVITE Aufbau einer Session BYE Beenden der Session CANCEL Abbruch der Session OPTIONS Abfrage der Fähigkeiten eines Teilnehmers ACK 3-way Handshake (INVITE) INFO Kontroll-Informationen während einer Session PRACK Zuverlässige provisional responses UPDATE Aktualisieren der Session ohne Zustandsänderung SUBSCRIBE Registrieren bei Benachrichtigungsdienst NOTIFY Benachrichtigung MESSAGE Instant Message REFER Session Migration 3.21 Erzeugen von Nachrichten headerfactory = sipfactory.createheaderfactory(); addressfactory = sipfactory.createaddressfactory(); messagefactory = sipfactory.createmessagefactory(); SipURI uri = addressfactory.createsipuri( test, abc.com ); from = addressfactory.createaddress(fromaddress); from.setdisplayname( Mr. X ); fromheader = headerfactory.createfromheader(from, tag); // Erzeugen aller anderen Header // Request requesturi = addressfactory.createsipuri(touser,port); Request request = messagefactory.createrequest(requesturi, Request.INVITE, callidheader, cseqheader, fromheader, toheader, viaheaders, maxforwards); 3.22
5 JAIN 5 JAIN Erzeugen von Nachrichten // Restliche Header dem Request hinzufügen request.addheader(contactheader); // Attachments String sdpdata = "v=0\r\n" byte[] contents = sdpdata.getbytes(); request.setcontent(contents, contenttypeheader); Versenden von Nachrichten Zustandsbehaftet // Erzeugen einer Client Transaktion invitetid = sip.getnewclienttransaction(request); invitetid.sendrequest(); dialog = invitetid.getdialog(); Zustandslos sip.sendrequest(request); Client Request Response Server 3.23 3.24 5 JAIN 5 JAIN Empfangen von Nachrichten public class implements Sip{ public void processrequest(request e) { Empfangen eines Requests (hier: INVITE-Request) public void processrequest(request request) { request = request.getrequest(); st = request.getservertransaction(); public void processresponse(response e) { public void processtimeout(timeout e) { public void processioexception(ioexception e) { public void processtransactionterminated( TransactionTerminated e) { if (request.getmethod().equals(request.invite)) { sip = (Sip)request.getSource(); response = messagefactory.createresponse(response.trying,request); if (st == null) st = sip.getnewservertransaction(request); dialog = st.getdialog(); st.sendresponse(response); public void processdialogterminated(dialogterminated e) { Client Request Response Server 3.25 busyresponse = messagefactory.createresponse(response.busy_here,request); response.addheader(contactheader); st.sendresponse(busyresponse); 3.26
5 JAIN 5 JAIN Empfangen einer Response (hier: OK-Reponse) public void processresponse(response responsereceived ) { response = (Response) responsereceived.getresponse(); tid = responsereceived.getclienttransaction(); CSeqHeader cseq = (CSeqHeader)response.getHeader(CSeqHeader.NAME); if (tid == null) { //Fehler if (response.getstatuscode() == Response.OK) { if (cseq.getmethod().equals(request.invite)) { ackrequest = dialog.createrequest(request.ack); dialog.sendack(ackrequest); 3.27 Transaktionen Transaktion = Request und alle dazugehörigen Responses JAIN bietet standardisierte Schnittstelle ClientTransaction und ServerTransaction ClientTransaction Explizite beim Senden eines Requests Automatische Zuordung bei ankommender Response sip.getnewclienttransaction(request) ServerTransaction Implizite bei ankommender Nachricht 3.28 5 JAIN 5 JAIN Dialoge Assoziation der beteiligten Entitäten einer Transaktion Repräsentiert Kontext, in dem die Nachrichten interpretiert werden Keine explizite eines Dialogs, implizit durch Dialog-erzeugende Transaktionen, z.b. INVITE, SUBSCRIBE, Stack verwaltet Zuordnung: Transaktion <----> Dialog Verwendung: Halten wichtige Daten für Kommunikation, u.a. Sequenz- Nummern, URIs der beteiligten Entitäten 3.29 Instant Messages (IM) MESSAGE Request Spezifiziert in RFC 3428 IM-Beispiel (Request) MESSAGE sip:user2@domain.com /2.0 Via: /2.0/TCP user1pc.domain.com;branch=z9hg4bk776sgdkse Max-Forwards: 70 From: sip:user1@domain.com;tag=49583 To: sip:user2@domain.com Call-ID: asd88asd77a@1.2.3.4 CSeq: 1 MESSAGE Content-Type: text/plain Content-Length: 18 Watson, come here. MESSAGE 200 OK 3.30
5 JAIN 5 JAIN IM-Beispiel (Reponse) /2.0 200 OK Via: /2.0/TCP user1pc.domain.com;branch=z9hg4bk776sgdkse; received=1.2.3.4 From: sip:user1@domain.com;;tag=49394 To: sip:user2@domain.com;tag=ab8asdasd9 Call-ID: asd88asd77a@1.2.3.4 CSeq: 1 MESSAGE Content-Length: 0 Erweiterbarkeit Neue Methoden Neue Header Methoden Methoden-Feld bei createrequest() ist String (kann angepasst werden) -Stack Property EXTENSION_METHOD setzen! Unterstützung durch NIST Implementierung MESSAGE Request erzeugen Header ExtensionHeader Schnittstelle Request request = messagefactory.createrequest(requesturi, Request.MESSAGE, callidheader, cseqheader, fromheader, toheader, viaheaders, maxforwards); 3.31 3.32 5 JAIN 5 JAIN Beispiel-Anwendungen JAIN Presence Proxy Presence Unterstützung Einfacher Instant Messenger Communicator Audio/Video-Telefon, Instant Messenger Unterstützt bisher, Jabber, AIM/ICQ, MSN Aktuelle Version: 1.0-alpha2 http://sip-communicator.org/ NIST- Port to J2ME MIDP 2.0 Vor allem für Mobiltelefone 3.33 Debugging Grafische Darstellung duch Tool (tools.tracesviewer.tracesviewer) Verwendung der Log-Dateien Erzeugen von grafischen Nachrichtenflüssen <message from="127.0.0.1:5060" to="127.0.0.1:5080" time="1164898132984" issender="true" transactionid="z9hg4bk3e0027213f21a94fe7e12e1878137ea7" callid="e3bf47ddef1f2ea3896f04ebe0e88276@127.0.0.1" firstline="message sip:abc@127.0.0.1:5080 /2.0" debugline="72" > <![CDATA[MESSAGE sip:abc@127.0.0.1:5080 /2.0 Call-ID: e3bf47ddef1f2ea3896f04ebe0e88276@127.0.0.1 ]]> </message> 3.34
5 JAIN 6 Literatur Debugging RFC 3261 RFC 3428 (MESSAGE Request) NIST Projektseite http://snad.ncsl.nist.gov/proj/iptel/ Tutorial von 2003, Achtung: Nicht mehr zu 100% aktuell JAIN- mit NIST Referenzimplementierung http://jcp.org/en/jsr/detail?id=032 (JSR32) https://jain-sip.dev.java.net/ 3.35 Tutorial zu JAIN http://dev2dev.bea.com/pub/a/2007/10/introduction-jain-sip.html 3.36 7 Aufgabe Implementierung eines einfachen Instant-Messengers Keine GUI nötig: Eingabe/Ausgabe auf Konsole Versenden und Empfangen MESSAGE Kein Proxy (direktes Senden!) Optionale Aufgabe: Implementierung eines einfachen Softphones auf Basis der vorangegangenen Aufgaben INVITE Transaktion Java Media Framework zur Aufnahme / Übertragung 3.37