Alma Mater Studiorum - Universita' di Bologna Sede di Cesena II Facolta' di Ingegneria Reti di Calcolatori Esercitazione 6 httpSockets Copyright © 2009-2011 by Claudio Salati. 1 Internet vs. WWW .1 • Confusione tra Internet e WWW: • Il WWW, in quanto accesso a pagine multimediali, e’ l’applicazione piu’ diffusa di Internet. • L’architettura WWW distingue nettamente gli ES tra client e server. Anche se un server puo’ anche assumere il ruolo di client. • La rete non e’ piatta, ma e’ organizzata come un insieme di intranet connesse da un backbone. All’interno di ogni intranet si utilizzano solo indirizzi IP privati. Solo i nodi che interagiscono direttamente con l’esterno come server, proxy, router, … hanno un indirizzo IP pubblico. • Per ragioni di sicurezza l’accesso a Internet da molte intranet aziendali e’ consentito in uscita solo in direzione di porte HTTP/HTTPS e in entrata solo verso ES esplicitamente autorizzati. (Anche le interazioni SMTP sono consentite solo da/verso un server ben definito) 2 Internet vs. WWW: modello della rete backbone IS sottorete sottorete intranet IS sottorete IS sottorete Sottorete client server server client Sottorete intranet IS 3 Internet vs. WWW .2 • Quando un client HTTP (che e’ dotato solo di indirizzo IP privato) apre una connessione con un server il suo indirizzo privato viene mappato dal NAT. • Ma anche l’utilizzo di NAT contribuisce a rendere difficile l’utilizzo delle tradizionali applicazioni di rete basate su TCP/UDP. (in gergo WWW: applicazioni di tipo peer-to-peer, cioe’ tra due macchine che normalmente operano come client HTTP) Una macchina client HTTP, dotata solo di indirizzo IP privato, non e’ indirizzabile come server dall’esterno dell’intranet. • Tutte le altre applicazioni convenzionali diverse dal Web, basate sull’utilizzo del servizio di Trasporto TCP/UDP tra intranet diverse, sono praticamente inutilizzabili. • Ma HTTP stesso e’ utilizzato/abile come un servizio di trasporto. • Possiamo incanalare le connessioni TCP sull’infrastruttura di trasporto WWW-HTTP. 4 Tunnel HTTP Applicazione Cliet TCP Applicazione Server TCP Connessione TCP Tunnel TCP/HTTP Stub TCP su HTTP Web server Web Application Relay Sessione well known Connessione TCP TCP su HTTP Tunnel TCP/HTTP Proxy • Il tunnel, come illustrato nella figura, puo’ supportare qualunque applicazione tradizionale basata su comunicazioni attraverso un’unica connessione TCP, e.g. VNC. • Per semplicita’ assumiamo di avere a che fare con un servizio end-to-end sequenziale. • Il servizio e’ accessibile, anziche’ su una porta TCP well known su una “sessione well known” sul web server: l’end point del tunnel HTTP su web server lato server. 5 Tunnel HTTP: architettura .1 • Il tunnel e’ realizzato come una applicazione web divisa in 3 parti: • Il tunnel proxy. • Il tunnel stub. • Il tunnel switch. • Il tunnel proxy: • E’ allocato sulla stessa macchina del server applicativo. • E’ un client web. • Esporta sul server web il punto d’accesso al servizio del server applicativo. • Il tunnel stub: • E’ allocato sulla stessa macchina del client applicativo. • E’ un client web. • Consente al client applicativo di connettersi al punto d’accesso al servizio del server applicativo sul web server. 6 Tunnel HTTP: architettura .2 • Il tunnel switch: • E’ allocato sul web server. • E’ un server web, composto ad esempio da un insieme di (anche una sola) servlet. • Implementa il punto d’accesso web al servizio del server applicativo. • Consente al client applicativo di connettersi a questo servizio. • Una volta instaurata la sessione tra client e server applicativi effettua lo scambio dati (switch dati) tra le due parti del tunnel web, quella verso client applicativo e quella verso server applicativo. • Come fanno tunnel stub e tunnel proxy a conoscere l’URL del tunnel switch? 7 Il tunnel proxy 1. Richiede l’apertura di una sessione well known (con quale identificatore?) sul tunnel switch. 2. Si mette in attesa della connessione di sessione da parte di un tunnel stub. 3. Quando riceve dal tunnel switch l’informazione che un tunnel stub si e’ connesso alla sessione, apre la connessione TCP con il server applicativo. 4. Se vede chiudere/cadere la connessione TCP con il server applicativo chiude la sessione corrente sul tunnel switch e ritorna in attesa di una nuova connessione alla sessione sullo switch (passo 2). 5. Se riceve dal tunnel switch l’informazione di chiusura/abort della sessione corrente chiude la connessione TCP con il server applicativo e ritorna in attesa di una nuova connessione alla sessione well known sullo switch (passo 2). 6. Durante lo stato di connessione della sessione esegue lo switch dei dati tra la connessione TCP verso il server applicativo e il 8 tunnel HTTP verso il tunnel switch. Il tunnel stub 1. Attende la indicazione di connessione TCP da parte del client applicativo (almeno in linea di principio: perche’ questo caveat?). 2. Quando il client applicativo effettua la connessione TCP chiede al tunnel switch sul web server di essere connesso alla sessione well known di interesse (come fa a sapere quale e’?). 3. Se vede chiudere/cadere la connessione TCP con il client applicativo chiude la sessione corrente sul tunnel switch e termina. 4. Se riceve dal tunnel switch l’informazione di rifiuto/chiusura/abort della sessione corrente chiude la connessione TCP con il client applicativo e termina. 5. Durante lo stato di connessione della sessione esegue lo switch dei dati tra la connessione TCP verso il client applicativo e il tunnel HTTP verso il tunnel switch. 9 Il tunnel switch sul web server 1. Rimane in attesa di tunnel proxy che chiedano la apertura di una sessione well known o di tunnel stub che chiedano la connessione ad una sessione well known . 2. Quando riceve da un tunnel proxy una richiesta di apertura di una sessione well known la registra. 3. Quando riceve da un tunnel stub una richiesta di connessione ad una sessione well known registrata, verifica se questa e’ gia’ in stato di connessione: • Se si’ rifiuta la richiesta. • Se no effettua la connessione e ne informa tunnel stub e tunnel proxy. 4. Quando riceve dal tunnel proxy o dal tunnel stub il comando di disconnessione della sessione corrente, effettua la chiusura e ne informa l’altra parte. 5. Una volta instaurata la sessione tra client e server applicativi effettua lo scambio dati (switch dati) tra le due parti del tunnel web, quella verso tunnel stub e quella verso tunnel proxy. 10 Il protocollo di tunnel HTTP • Il protocollo puo’ basarsi sull’utilizzo dell’operazione POST di HTTP. • Nel corpo del PDU di richiesta HTTP viene indicata l’operazione di tunnel che il client HTTP (il proxy o lo stub) richiede al server HTTP (lo switch), piu’ i parametri di questa operazione. Ad esempio: • OpenSession(nome della sessione) • ConnectSession(nome della sessione) • AcceptConnection(nome della sessione) • DisconnectSession(nome della sessione) • PutData(nome della sessione, stubXORproxy, dati) • GetData(nome della sessione, stubXORproxy) • Anche i parametri di ritorno sono contenuti nel corpo del PDU di risposta HTTP. Ad esempio, supponendo che non ci sia stato nessun errore di protocollo HTTP, l’operazione GetData potra’ avere come risposta: • DataAvailable(dati) • DisconnectionEvent(ragione) 11 • NoDataAvailable() Problemi di Presentazione • Richieste e risposte possono essere codificate come un normale testo o come un testo XML (e.g. un valore secondo una sintassi descritta da uno schema XML). • In realta’ per scambiare informazioni con un web server e’ di norma comunque necessario: • Codificare i byte binari come Base64 per poter operare solo a caratteri. • URLencodificarla (nella direzione client server). (altrimenti la piattafoprma server considera certi caratteri, come lo spazio, come caratteri speciali e li tratta come tali) 12 Transport Mapping .1 • Ma di quante connessioni TCP-HTTP c’e’ bisogno tra ciascun client HTTP e il server HTTP per supportare il tunnel? E che vincoli di utilizzo hanno? • HTTP e’ un protocollo request-reply, ma il tunnel switch ha bisogno di poter inviare spontaneamente dati e eventi di dis/connessione a ciascuno dei client durante la vita del tunnel. • Le operazioni HTTP non possono durare un tempo infinito: un client HTTP, se non vede arrivare in un tempo ragionevole la reply alla sua request, considera abortita l’operazione (non si aspetta di ricevere piu’ nessuna risposta). Questo significa in particolare che l’operazione di tunnel GetData deve terminare anche se non ci sono ne’ dati ne’ altri eventi che lo switch debba comunicare al client. • Ciascun client deve comunque inviare periodicamente delle request HTTP verso il web server, anche se non ha in realta’ niente da comunicare, altrimenti il web server chiuderebbe la connessione TCP di colloquio con il client. 13 Transport Mapping • .2 Questi problemi possono essere risolti se ciascun client web utilizza 2 connessioni TCP-HTTP per comunicare con il server web. • Sulla prima connessione il client invia dati (quando la sessione e’ in stato connesso) e comandi che possono avere risposta immediata (ad esempio ConnectSession e DisconnectSession). Su questa connessione il client deve comunque inviare periodicamente delle richieste, eventualmente nulle, per evitare che il web server chiuda la connessione stessa. • La seconda connessione consente ai client di ricevere dal web server dati ed eventi di variazione di stato della sessione (tramite le operazioni AcceptConnection e GetData). Queste operazioni non e’ detto che abbiano una risposta immediata. Ad un certo punto il web server deve comunque inviare una risposta, ma questa deve poter avere anche valore NoEvent . A fronte di una risposta di questo genere il web client tornera’ immediatamente ad inviare la stessa richiesta (una operativita’ a polling!) in modo che appena il web server si trovi nella situazione di poter inviare una risposta significativa lo possa fare (senza 14 ritardi). Problemi della soluzione tunnel: tecnici • Un tunnel ha un comportamento specializzato: • Tutte le applicazioni distribuite sono basate sull’uso di una sola connessione? No! Quante connessioni TCP deve tunnelare? • Ci sono servizi offerti su porte effimere, come quelli basati su RPC Sun. • Sulle connessioni TCP l’algoritmo di Nagle deve essere attivo o no? • E se vogliamo tunnelare un servizio concorrente? • E se il servizio fa uso di connessioni secondarie basate su porte effimere (il cui numero deve essere acquisito tramite getsockname() e comunicato al pari perche’ ci si possa connetere), come fa FTP? Come posso comunicare al mio pari il numero di porta effimera se questo puo’ essere modificato da NAT? Si e’ dovuto modificare FTP per aggirare il problema! 15 Problemi della soluzione tunnel: gestionali • Un tunnel ha bisogno di un web server che operi come relay: se il tunnel e’ specializzato l’applicazione web che opera come relay deve essere specializzata. • Il servizio di tunneling non e’ reso disponibile per se’, ma solo come parte di una applicazione web distribuita, e.g. TeamViewer. • Non esistono tunnel neutri, che si limitano a fornire un servizio di trasporto dati full-duplex, bidirezionale come una overlay network su HTTP. E ci sarebbero significativi problemi tecnici nel realizzarli. 16 WebSockets di Google • http://en.wikipedia.org/wiki/WebSockets • WebSocket is a technology providing for bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket. • It is designed to be implemented in web browsers and web servers but it can be used by any client or server application. • The handshake looks like HTTP but actually isn't. It allows the server to interpret part of the handshake request as HTTP and then switch to WebSocket. • Once established, WebSocket data frames can be sent back and forth between the client and the server in full-duplex mode. • Text frames can be sent full-duplex, in either direction at the same time. The data is minimally framed with 2 bytes: a frame starts with a 0x00 byte, ends with a 0xFF byte, and contains UTF-8 data in between. • Binary frames are not supported yet in the API. 17 Cosa vorremmo • Una internet piatta, senza problemi di firewall e di NAT. • Per poter scambiare dati, anche binari, tra due ES qualunque, non solo tra un browser e un web server. • Senza bisogno di tunnel specializzati. • Dove potessero essere utilizzate, come nel dominio internet, anche porte effimere. • Che consentisse di riutilizzare facilmente tutte le applicazioni sviluppate su TCP e UDP senza doverle modificare. ES ES ES ES ES 18 httpSocket • Un dominio di comunicazione diverso da quello internet: – SocketDomainT.WEB vs. SocketDomainT.INET – Un insieme di servizi di trasporto in questo dominio. • Un’API che consente di utilizzare i socket sia per interfacciare il dominio di comunicazione internet che quello WEB. • Socket estesi (generici) per poter rappresentare TSAP di diversi domini di comunicazione. • E’ mantenuta la completa compatibilita’ di interfaccia nell’uso dei socket INET. • Si opera sui socket WEB nella stessa maniera con cui si opera sui socket INET. • Sono introdotte nuove classi per la gestione degli indirizzi nel nuovo dominio di comunicazione. • Sono introdotti nuovi metodi che consentono di creare dei socket nel dominio WEB. 19 httpSocket: communication domain • Il dominio di comunicazione e’ implementato da un insieme di web server che funzionano da relay e sui quali e’ attiva l’applicazione web httpSocket. • Due possibilita’ di comunicazione: • Locale • Globale 20 httpSocket: communication domain • Il protocollo sulla sezione di accesso consente ad una applicazione allocata su un web client di operare su un TSAP allocato su un web server. • L’applicazione client interfaccia il TSAP sul web server tramite un socket. • socket stub, sul client • socket proxy, sul webserver, e’ l’implementazione del TSAP 21 httpSocket: genericita’ .1 public enum SocketDomainT { INET, WEB } public class Socket implements ProtocolInterface { // socket generico private java.net.Socket s; // usato come tale solo per i socket di tipo INET. // usato solo per denominazione univoca per socket // di tipo WEB private SocketDomainT . . . } socketType; 22 httpSocket: genericita’ .2 public Socket(SocketDomainT pf) { socketType=pf; if (pf==SocketDomainT.INET) { socketType = SocketDomainT.INET; s = new java.net.Socket(); } else { // un socket WEB e’ implementato // direttamente (cialtroneria) socketType = SocketDomainT.WEB; socketState = SocketStateT.LOCAL_CREATED; s = null; } } 23 httpSocket: bacward compatibility • Se un socket e’ del dominio INET viene mappato su un socket standard di Java (che puo’ appartenere solo al dominio internet), e le operazioni sul socket generico si ribaltano nelle corrispondenti operazioni sul socket Java. • I costruttori che non specificano in qualche modo il dominio del socket costruiscono un socket INET. public Socket() { socketType=SocketDomainT.INET; s = new java.net.Socket(); } public void bind(java.net.SocketAddress bindpoint) throws IOException { try { if (socketType==SocketDomainT.INET && bindpoint.getClass() .getName().equals("java.net.InetSocketAddress")) { s.bind(bindpoint); } else if (socketType==SocketDomainT.WEB && ... 24 httpSocket: implementazione • Il package genericsocketstub sostituisce nei programmi dell’utente il package java.net. • La classe HttpSocketAddress deriva (come la classe standard InetSocketAddress) dalla classe standard SocketAddress. La classe HttpSocketAddress e’ definita nel package genericsocketutility e quindi il programma utente deve importare anche questo package. • Prima di iniziare l’interazione con una web application httpSocket un programma client deve invocare il metodo (statico) WSStartup() della classe Socket. String WSStartup(String serverUrl, boolean getHost) • serverUrl e’ l’URL della web application con cui si vuole interagire . • getHost indica alla web application se deve (true) o no (false) ritornare al cliente un identificatore univoco di sessione. • L’identificatore univoco potra’ poi essere utilizzato per costruire l’indirizzo dei socket WEB creati da questa applicazione client su questo web server (vedi parametro hostname di un indirizzo di TSAP WEB). 25 httpSocket: indirizzo di un TSAP WEB L’indirizzo di un TSAP WEB e’ composto di 3 coordinate: • String serverUrl; serverUrl identifica l’URL della web application httpSocket su cui e’ stato creato il socket di cui si sta dando l’indirizzo, ad es.: http://httpsocket.smart.it/HttpSocketProxy/httpSocketServletProxy • String hostname; hostname e’ un identificatore univoco della macchina client (e.g. il suo nome dns) o comunque un identificatore univoco all’interno della web application httpSockets di indirizzo serverUrl, ad es.: Puo’ essere generato dinamicamente o assere assegnato dal gestore del web server. • int port; port e’ il numero di porta, univoco rispetto a hostname, del socket che si vuole indirizzare. 26 httpSocket: lato web server • public class httpSocketServletProxy extends HttpServlet e’ la classe che implementa la servlet che e’ l’applicazione web httpSocket. • A parte i metodi init() e destroy() definisce soltanto l’operazione doPost(). public void doPost(HttpServletRequest request, HttpServletResponse response) • request e’ il corpo del PDU HTTP POST che attiva il metodo. • response e’ il corpo del PDU HTTP di risposta che verra’ inviato al client. • Per come e’ definita la servlet, l’unico PDU HTTP utilizzato nell’interazione web client-server httpSocket e’ POST. • Il PDU HTTP POST e’ utilizzato per trasportare i PDU del protocollo httpSockets. • La servlet e’ installata all’URL: http://httpsocket.smart.it/HttpSocketProxy/httpSocketServletProxy 27 httpSocket: ASE HTTP di Java • Lato server l’ASE HTTP (lato server) e’ parte del framework del web server (e.g. Tomcat, GlassFish, ...). • Lato client l’ASE httpSocket non e’ implementato utilizzando direttamente l’API di trasporto. • Lato client l’ASE httpSocket e’ implementato utilizzando un insieme di classi standard dell’ambiente Java che implementano l’ASE HTTP lato client. • Classe URL, che rappresenta un indirizzo di un servizio/risorsa web. • Classe HttpURLConnection, che • Rappresenta una connessione con un servizio/risorsa web specifico (con indirizzo l’URL tramite cui e’ stato creato l’oggetto HttpURLConnection). • Consente la preparazione del PDU HTTP da spedire. • Classe OutputStream e InputStream della connessione HTTP, per inviare e ricevere PDU su di essa. 28 Classe HttpURLConnection • Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. • Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. • Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time. 29 httpSocket: ASE HTTP client di Java, TX public static HttpURLConnection sendHTTPPostRequest(byte [] msg, URL url) throws Exception { // apre una connessione con il web server di indirizzo url HttpURLConnection httpUc = (HttpURLConnection)url.openConnection(); // crea un PDU di POST httpUc.setRequestMethod("POST"); // setta i field dell'header httpUc.setRequestProperty("Content-Length", Integer.toString(urlEnc.length)); httpUc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); httpUc.setRequestProperty("Host", url.getHost()); httpUc.setRequestProperty("Connection", "Keep-Alive"); httpUc.setDoInput(true); httpUc.setDoOutput(true); // encodifica il corpo del PDU msg in BASE-64 + URL-encode byte [] urlEnc = URLEncoder.encode(Base64.encodeBytes(msg), "UTF-8").getBytes(); // si garantisce che la connessione con il web server sia effettivamente aperta httpUc.connect(); // acquisisce l’output stream di questa connessione OutputStream os = httpUc.getOutputStream(); // spedisce il PDU HTTP preparato, con corpo di PDU = urlEnc os.write(urlEnc); os.flush(); os.close(); // ritorna l’oggetto connessione per poter poi acquisire la risposta return httpUc; 30 } httpSocket: ASE HTTP client di Java, RX public static byte [] receiveHTTPPostResponse(HttpURLConnection httpUc) throws Exception { // procedura bloccante: aspetta la risposta del web server int code = httpUc.getResponseCode(); InputStream is = null; if (code>=200 && code<=299) { //range codice di risposta OK is = httpUc.getInputStream(); int len = httpUc.getContentLength(), nb=0; int offset = 0; byte [] res = new byte[len]; while(true) { nb=is.read(res, offset, len); if (nb==-1) throw new IOException(“ricezione fallita dal web server”); len -= nb; offset += nb; } // res = Base64.decode(URLDecoder.decode(new String(res, 0, res.length), "UTF-8")); res = Base64.decode(res); is.close(); return res; } else { // il server ha restituito un PDU di errore String errorMsg = "HTTP Response Error: " + code + httpUc.getResponseMessage(); System.out.println(errorMsg); throw new Exception(errorMsg); } 31 } httpSocket: security • Rendere accessibili servizi sulla rete tramite httpSockets non significa rinunciare alla sicurezza di rete, ma basarsi su strumenti piu’ flessibili. • Consideriamo l’architettura globale e che i web server siano allocati sulla frontiera tra intranet e internet. • Il metodo WSStartup() puo’ fornire al web server le credenziali che dimostrano i diritti d’accesso dell’utente (uscire come client, e di chi, offrire servizi, …). intranet internet intranet 32 Esempio di come e' evoluto il WWW • httpSockets e’ una infrastruttura client-server • distribuita su Internet • in cui un sistema di trasporto e i suoi TSAP, residenti sui server e controllabili tramite applicazioni web residenti sui server, • possono essere riferiti (e indirizzati) e possono riferirirsi tra loro • tramite URL (e.g. http://httpsocket.smart.it/HttpSocketProxy/httpSocketServletProxy) • e possono accedersi tra loro e essere acceduti da applicazioni residenti sui client • tramite le operazioni messe a disposizione dalla interfaccia httpSockets • l'interfaccia puo' essere definita come una API Java o C • e utilizza HTTP solo come protocollo di trasporto 33