18. Trasporto (Transport)
Il livello di trasporto è responsabile della trasmissione effettiva di richieste e risposte sugli strati di trasporto di rete. Ciò include la determinazione della connessione da utilizzare per una richiesta o una risposta nel caso di trasporti orientati alla connessione.
Il livello di trasporto è responsabile della gestione delle connessioni persistenti per protocolli di trasporto come TCP e SCTP, o TLS su di essi, incluse quelle aperte verso il livello di trasporto. Ciò include le connessioni aperte dai trasporti client o server, in modo che le connessioni siano condivise tra le funzioni di trasporto client e server. Queste connessioni sono indicizzate dalla tupla formata da indirizzo, porta e protocollo di trasporto all'estremità remota della connessione. Quando una connessione viene aperta dal livello di trasporto, questo indice è impostato sull'IP di destinazione, sulla porta e sul trasporto. Quando la connessione viene accettata dal livello di trasporto, questo indice è impostato sull'indirizzo IP sorgente, sul numero di porta e sul trasporto. Si noti che, poiché la porta sorgente è spesso effimera, ma non può essere noto se sia effimera o selezionata tramite le procedure in [4], le connessioni accettate dal livello di trasporto spesso non verranno riutilizzate. Il risultato è che due proxy in una relazione di "peering" che utilizzano un trasporto orientato alla connessione avranno spesso due connessioni in uso, una per le transazioni iniziate in ciascuna direzione.
È RACCOMANDATO che le connessioni siano mantenute aperte per una durata definita dall'implementazione dopo l'ultimo messaggio inviato o ricevuto su tale connessione. Questa durata DOVREBBE almeno essere pari alla quantità di tempo più lunga di cui l'elemento avrebbe bisogno per portare una transazione dalla sua istanziazione allo stato terminato. Ciò per rendere probabile che le transazioni siano completate sulla stessa connessione su cui sono iniziate (ad esempio, richiesta, risposta e, nel caso di un INVITE, l'ACK per risposte non-2xx). Ciò significa solitamente almeno 64*T1 (vedere la sezione 17.1.1.1 per una definizione di T1). Tuttavia, potrebbe essere maggiore in un elemento il cui TU utilizza un valore elevato per il timer C (punto 11 della sezione 16.6), ad esempio.
Tutti gli elementi SIP DEVONO implementare UDP e TCP. Gli elementi SIP POSSONO implementare altri protocolli.
Rendersi TCP obbligatorio per lo UA è un cambiamento sostanziale rispetto alla RFC 2543. È nato dalla necessità di gestire messaggi più grandi, che DEVONO utilizzare TCP, come discusso di seguito. Pertanto, anche se un elemento non invia mai messaggi di grandi dimensioni, potrebbe riceverne uno e deve essere in grado di gestirli.
18.1 Client (Clients)
18.1.1 Invio di richieste (Sending Requests)
Il lato client del livello di trasporto è responsabile dell'invio della richiesta e della ricezione delle risposte. L'utente del livello di trasporto passa al trasporto client la richiesta, un indirizzo IP, una porta, un trasporto e possibilmente un TTL per le destinazioni multicast.
Se una richiesta è entro 200 byte dal MTU del percorso, o se è più grande di 1300 byte e l'MTU del percorso è sconosciuto, la richiesta DEVE essere inviata utilizzando un protocollo di trasporto con controllo della congestione RFC 2914 [43], come TCP. Se ciò causa un cambiamento nel protocollo di trasporto rispetto a quello indicato nel Via superiore, il valore nel Via superiore DEVE essere modificato. Ciò previene la frammentazione dei messaggi su UDP e fornisce controllo della congestione per messaggi più grandi. Tuttavia, le implementazioni DEVONO essere in grado di gestire messaggi fino alla dimensione massima del pacchetto datagramma. Per UDP, tale dimensione è di 65.535 byte, incluse le intestazioni IP e UDP.
Il "buffer" di 200 byte tra la dimensione del messaggio e l'MTU tiene conto del fatto che la risposta in SIP può essere più grande della richiesta. Ciò avviene a causa dell'aggiunta di valori di campo dell'intestazione Record-Route alle risposte agli INVITE, ad esempio. Con il buffer aggiuntivo, la risposta può essere circa 170 byte più grande della richiesta e non essere comunque frammentata in IPv4 (circa 30 byte sono consumati da IP/UDP, supponendo nessun IPSec). 1300 è scelto quando l'MTU del percorso non è noto, sulla base dell'assunzione di un MTU Ethernet di 1500 byte.
Se un elemento invia una richiesta su TCP a causa di questi vincoli di dimensione del messaggio, e tale richiesta sarebbe altrimenti stata inviata su UDP, se il tentativo di stabilire la connessione genera sia un ICMP Protocol Not Supported, sia comporta un reset TCP, l'elemento DOVREBBE ritentare la richiesta utilizzando UDP. Ciò è solo per fornire compatibilità con le implementazioni conformi alla RFC 2543 che non supportano TCP. Si prevede che questo comportamento sarà deprecato in una futura revisione di questa specifica.
Un client che invia una richiesta a un indirizzo multicast DEVE aggiungere il parametro "maddr" al valore del proprio campo di intestazione Via contenente l'indirizzo multicast di destinazione e, per IPv4, DOVREBBE aggiungere il parametro "ttl" con valore 1. L'uso del multicast IPv6 non è definito in questa specifica e sarà oggetto di futura standardizzazione quando sorgerà la necessità.
Queste regole comportano una limitazione deliberata del multicast in SIP. La sua funzione principale è fornire un servizio di tipo "single-hop-discovery", recapitando una richiesta a un gruppo di server omogenei, dove è richiesto di elaborare la risposta da uno qualsiasi di essi. Questa funzionalità è particolarmente utile per le registrazioni. Infatti, in base alle regole di elaborazione delle transazioni della sezione 17.1.3, la transazione client accetterà la prima risposta e considererà le altre come ritrasmissioni poiché contengono tutte lo stesso identificatore di diramazione Via.
Prima che una richiesta sia inviata, il trasporto client DEVE inserire un valore del campo "sent-by" nel campo di intestazione Via. Questo campo contiene un indirizzo IP o un nome host e una porta. L'uso di un FQDN è RACCOMANDATO. Questo campo è utilizzato per inviare risposte in certe condizioni, descritte di seguito. Se la porta è assente, il valore predefinito dipende dal trasporto. È 5060 per UDP, TCP e SCTP, 5061 per TLS.
Per i trasporti affidabili, la risposta è normalmente inviata sulla connessione su cui la richiesta è stata ricevuta. Pertanto, il trasporto client DEVE essere preparato a ricevere la risposta sulla stessa connessione utilizzata per inviare la richiesta. In condizioni di errore, il server può tentare di aprire una nuova connessione per inviare la risposta. Per gestire questo caso, il livello di trasporto DEVE essere altresì preparato a ricevere una connessione in arrivo sull'indirizzo IP sorgente da cui la richiesta è stata inviata e sul numero di porta nel campo "sent-by". DEVE inoltre essere preparato a ricevere connessioni in arrivo su qualsiasi indirizzo e porta che sarebbero selezionati da un server in base alle procedure descritte nella sezione 5 di [4].
Per i trasporti unicast non affidabili, il trasporto client DEVE essere preparato a ricevere risposte sull'indirizzo IP sorgente da cui la richiesta è inviata (poiché le risposte sono rispedite all'indirizzo sorgente) e sul numero di porta nel campo "sent-by". Inoltre, come per i trasporti affidabili, in alcuni casi la risposta sarà inviata altrove. Il client DEVE essere preparato a ricevere risposte su qualsiasi indirizzo e porta che sarebbero selezionati da un server in base alle procedure descritte nella sezione 5 di [4].
Per il multicast, il trasporto client DEVE essere preparato a ricevere risposte sullo stesso gruppo multicast e porta verso cui la richiesta è inviata (ovvero, deve essere membro del gruppo multicast a cui ha inviato la richiesta).
Se una richiesta è destinata a un indirizzo IP, a una porta e a un trasporto per i quali una connessione esistente è aperta, è RACCOMANDATO utilizzare questa connessione per inviare la richiesta, ma un'altra connessione PUÒ essere aperta e utilizzata.
Se una richiesta è inviata utilizzando il multicast, è inviata al gruppo di indirizzi, alla porta e al TTL forniti dall'utente del trasporto. Se una richiesta è inviata utilizzando trasporti unicast non affidabili, è inviata all'indirizzo IP e alla porta forniti dall'utente del trasporto.
18.1.2 Ricezione di risposte (Receiving Responses)
Quando una risposta viene ricevuta, il trasporto client esamina il valore del campo di intestazione Via superiore. Se il valore del parametro "sent-by" in quel valore di campo di intestazione non corrisponde a un valore che il trasporto client è configurato per inserire nelle richieste, la risposta DEVE essere scartata silenziosamente.
Se esistono transazioni client, il trasporto client utilizza le procedure di corrispondenza della sezione 17.1.3 per tentare di abbinare la risposta a una transazione esistente. Se c'è corrispondenza, la risposta DEVE essere passata a tale transazione. Altrimenti, la risposta DEVE essere passata al core (che sia un proxy senza stato, un proxy con stato o un UA) per un'ulteriore elaborazione. La gestione di queste risposte "smarrite" dipende dal core (un proxy le inoltrerà, mentre un UA le scarterà, ad esempio).
18.2 Server (Servers)
18.2.1 Ricezione di richieste (Receiving Requests)
Un server DOVREBBE essere preparato a ricevere richieste su qualsiasi combinazione di indirizzo IP, porta e trasporto che possa essere il risultato di una ricerca DNS su un URI SIP o SIPS [4] fornito allo scopo di comunicare con tale server. In questo contesto, "fornire" include il posizionamento di un URI in un campo di intestazione Contact in una richiesta REGISTER o in una risposta di reindirizzamento, o in un campo di intestazione Record-Route in una richiesta o risposta. Un URI può anche essere "fornito" posizionandolo su una pagina web o su un biglietto da visita. È inoltre RACCOMANDATO che un server ascolti le richieste sulle porte SIP predefinite (5060 per TCP e UDP, 5061 per TLS su TCP) su tutte le interfacce pubbliche. L'eccezione tipica sarebbero le reti private o quando più istanze di server sono in esecuzione sullo stesso host. Per qualsiasi porta e interfaccia su cui un server ascolta per UDP, DEVE ascoltare su quella stessa porta e interfaccia per TCP. Ciò perché un messaggio potrebbe dover essere inviato utilizzando TCP anziché UDP se è troppo grande. Di conseguenza, il contrario non è vero. Un server non deve ascoltare per UDP su un determinato indirizzo e porta solo perché sta ascoltando su quello stesso indirizzo e porta per TCP. Ci possono, naturalmente, essere altri motivi per cui un server ha bisogno di ascoltare per UDP su un determinato indirizzo e porta.
Quando il trasporto server riceve una richiesta su qualsiasi trasporto, DEVE esaminare il valore del parametro "sent-by" nel valore del campo di intestazione Via superiore. Se la parte host del parametro "sent-by" contiene un nome di dominio, o se contiene un indirizzo IP che differisce dall'indirizzo sorgente del pacchetto, il server DEVE aggiungere un parametro "received" a quel valore di campo di intestazione Via. Questo parametro DEVE contenere l'indirizzo sorgente da cui il pacchetto è stato ricevuto. Ciò per assistere il livello di trasporto server nell'invio della risposta, poiché essa deve essere inviata all'indirizzo IP sorgente da cui è arrivata la richiesta.
Si consideri una richiesta ricevuta dal trasporto server che appare, in parte, così:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060
La richiesta è ricevuta con un indirizzo IP sorgente di 192.0.2.4. Prima di passare la richiesta verso l'alto, il trasporto aggiunge un parametro "received", in modo che la richiesta apparirebbe, in parte, così:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4
Successivamente, il trasporto server tenta di abbinare la richiesta a una transazione server. Lo fa utilizzando le regole di corrispondenza descritte nella sezione 17.2.3. Se viene trovata una transazione server corrispondente, la richiesta viene passata a tale transazione per l'elaborazione. Se non viene trovata alcuna corrispondenza, la richiesta viene passata al core, che può decidere di costruire una nuova transazione server per quella richiesta. Si noti che quando un core UAS invia una risposta 2xx a un INVITE, la transazione server viene distrutta. Ciò significa che quando arriva l'ACK, non ci sarà alcuna transazione server corrispondente e, in base a questa regola, l'ACK viene passato al core UAS, dove viene elaborato.
18.2.2 Invio di risposte (Sending Responses)
Il trasporto server utilizza il valore del campo di intestazione Via superiore per determinare dove inviare una risposta. DEVE seguire il seguente processo:
o Se il "sent-protocol" è un protocollo di trasporto affidabile come TCP o SCTP, o TLS su di essi, la risposta DEVE essere inviata utilizzando la connessione esistente verso la fonte della richiesta originale che ha creato la transazione, se tale connessione è ancora aperta. Ciò richiede che il trasporto server mantenga un'associazione tra transazioni server e connessioni di trasporto. Se tale connessione non è più aperta, il server DOVREBBE aprire una connessione verso l'indirizzo IP nel parametro "received", se presente, utilizzando la porta nel valore "sent-by", o la porta predefinita per quel trasporto se non è specificata alcuna porta. Se tale tentativo di connessione fallisce, il server DOVREBBE utilizzare le procedure in [4] per i server per determinare l'indirizzo IP e la porta su cui aprire la connessione e inviare la risposta.
o Altrimenti, se il valore del campo di intestazione Via contiene un parametro "maddr", la risposta DEVE essere inoltrata all'indirizzo ivi elencato, utilizzando la porta indicata in "sent-by", o la porta 5060 se non è presente. Se l'indirizzo è un indirizzo multicast, la risposta DOVREBBE essere inviata utilizzando il TTL indicato nel parametro "ttl", o con un TTL di 1 se tale parametro non è presente.
o Altrimenti (per i trasporti unicast non affidabili), se il Via superiore ha un parametro "received", la risposta DEVE essere inviata all'indirizzo nel parametro "received", utilizzando la porta indicata nel valore "sent-by", o utilizzando la porta 5060 se non è specificata esplicitamente. Se ciò fallisce, ad esempio generando una risposta ICMP "port unreachable", le procedure della sezione 5 di [4] DOVREBBERO essere utilizzate per determinare dove inviare la risposta.
o Altrimenti, se non è contrassegnata dal ricevitore, la risposta DEVE essere inviata all'indirizzo indicato dal valore "sent-by", utilizzando le procedure della sezione 5 di [4].
18.3 Incorniciatura (Framing)
Nel caso di trasporti orientati ai messaggi (come UDP), se il messaggio ha un campo di intestazione Content-Length, si presume che il corpo del messaggio contenga tale numero di byte. Se ci sono byte aggiuntivi nel pacchetto di trasporto oltre la fine del corpo, DEVONO essere scartati. Se il pacchetto di trasporto termina prima della fine del corpo del messaggio, ciò è considerato un errore. Se il messaggio è una risposta, DEVE essere scartato. Se il messaggio è una richiesta, l'elemento DOVREBBE generare una risposta 400 (Bad Request). Se il messaggio non ha un campo di intestazione Content-Length, si presume che il corpo del messaggio termini alla fine del pacchetto di trasporto.
Nel caso di trasporti orientati al flusso come TCP, il campo di intestazione Content-Length indica la dimensione del corpo. Il campo di intestazione Content-Length DEVE essere utilizzato con i trasporti orientati al flusso.
18.4 Gestione degli errori (Error Handling)
La gestione degli errori è indipendente dal fatto che il messaggio fosse una richiesta o una risposta.
Se l'utente del trasporto richiede l'invio di un messaggio su un trasporto non affidabile e il risultato è un errore ICMP, il comportamento dipende dal tipo di errore ICMP. Errori host, network, port o protocol unreachable, o errori parameter problem DOVREBBERO indurre il livello di trasporto a informare l'utente del trasporto di un fallimento nell'invio. Errori ICMP source quench e TTL exceeded DOVREBBERO essere ignorati.
Se l'utente del trasporto richiede l'invio di una richiesta su un trasporto affidabile e il risultato è un fallimento della connessione, il livello di trasporto DOVREBBE informare l'utente del trasporto di un fallimento nell'invio.