6. Frame Definitions (Definizioni dei Frame)
Questa specifica definisce un certo numero di tipi di frame, ciascuno identificato da un codice di tipo unico a 8 bit. Ogni tipo di frame serve a uno scopo distinto nell'instaurazione e nella gestione della connessione nel suo complesso o dei singoli stream.
La trasmissione di tipi di frame specifici può alterare lo stato di una connessione. Se gli endpoint non riescono a mantenere una vista sincronizzata dello stato della connessione, la comunicazione riuscita all'interno della connessione non sarà più possibile. Pertanto, è importante che gli endpoint abbiano una comprensione condivisa di come lo stato sia influenzato dall'uso di un dato frame.
6.1. DATA
I frame DATA (type=0x00) trasportano sequenze di ottetti arbitrarie di lunghezza variabile associate a uno stream. Uno o più frame DATA vengono utilizzati, ad esempio, per trasportare il contenuto di messaggi di richiesta o risposta HTTP.
I frame DATA possono anche contenere padding. Il padding può essere aggiunto ai frame DATA per oscurare la dimensione dei messaggi. Il padding è una funzionalità di sicurezza; vedere la Sezione 10.7.
DATA Frame {
Length (24),
Type (8) = 0x00,
Unused Flags (4),
PADDED Flag (1),
Unused Flags (2),
END_STREAM Flag (1),
Reserved (1),
Stream Identifier (31),
[Pad Length (8)],
Data (..),
Padding (..2040),
}
Figura 3: Formato del Frame DATA
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il frame DATA contiene i seguenti campi aggiuntivi:
Pad Length (Lunghezza del padding): Un campo a 8 bit che contiene la lunghezza del padding del frame in unità di ottetti. Questo campo è condizionale ed è presente solo se il flag PADDED è impostato.
Data (Dati): Dati dell'applicazione. La quantità di dati è il resto del payload del frame dopo aver sottratto la lunghezza degli altri campi presenti.
Padding (Padding): Ottetti di padding che non contengono alcun valore semantico dell'applicazione. Gli ottetti di padding DEVONO essere impostati a zero durante l'invio. Un ricevitore non è obbligato a verificare il padding ma PUÒ trattare un padding non zero come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame DATA definisce i seguenti flag:
PADDED (0x08): Quando impostato, il flag PADDED indica che il campo Pad Length e qualsiasi padding che descrive sono presenti.
END_STREAM (0x01): Quando impostato, il flag END_STREAM indica che questo frame è l'ultimo che l'endpoint invierà per lo stream identificato. L'impostazione di questo flag fa entrare lo stream in uno degli stati "half-closed" o nello stato "closed" (Sezione 5.1).
| Nota: Un endpoint che viene a conoscenza della chiusura dello stream dopo aver inviato | tutti i dati può chiudere uno stream inviando un frame STREAM con un campo Data di | lunghezza zero e il flag END_STREAM impostato. Ciò è possibile solo se l'endpoint non | invia trailer, poiché il flag END_STREAM appare su un frame HEADERS in quel caso; vedere | la Sezione 8.1.
I frame DATA DEVONO essere associati a uno stream. Se viene ricevuto un frame DATA il cui campo Stream Identifier è 0x00, il destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
I frame DATA sono soggetti al controllo di flusso e possono essere inviati solo quando uno stream è nello stato "open" o "half-closed (remote)". L'intero payload del frame DATA è incluso nel controllo di flusso, compresi i campi Pad Length e Padding se presenti. Se viene ricevuto un frame DATA il cui stream non è nello stato "open" o "half-closed (local)", il destinatario DEVE rispondere con un errore di stream (Sezione 5.4.2) di tipo STREAM_CLOSED.
Il numero totale di ottetti di padding è determinato dal valore del campo Pad Length. Se la lunghezza del padding è pari o superiore alla lunghezza del payload del frame, il destinatario DEVE trattare questo come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
| Nota: Un frame può essere aumentato di dimensione di un ottetto includendo un campo | Pad Length con valore zero.
6.2. HEADERS
Il frame HEADERS (type=0x01) viene utilizzato per aprire uno stream (Sezione 5.1) e trasporta inoltre un frammento di blocco di campi. Nonostante il nome, un frame HEADERS può trasportare una sezione di intestazione o una sezione di trailer. I frame HEADERS possono essere inviati su uno stream negli stati "idle", "reserved (local)", "open" o "half-closed (remote)".
HEADERS Frame {
Length (24),
Type (8) = 0x01,
Unused Flags (2),
PRIORITY Flag (1),
Unused Flag (1),
PADDED Flag (1),
END_HEADERS Flag (1),
Unused Flag (1),
END_STREAM Flag (1),
Reserved (1),
Stream Identifier (31),
[Pad Length (8)],
[Exclusive (1)],
[Stream Dependency (31)],
[Weight (8)],
Field Block Fragment (..),
Padding (..2040),
}
Figura 4: Formato del Frame HEADERS
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload del frame HEADERS ha i seguenti campi aggiuntivi:
Pad Length (Lunghezza del padding): Un campo a 8 bit che contiene la lunghezza del padding del frame in unità di ottetti. Questo campo è presente solo se il flag PADDED è impostato.
Exclusive (Esclusivo): Un flag a singolo bit. Questo campo è presente solo se il flag PRIORITY è impostato. I segnali di priorità nei frame HEADERS sono deprecati; vedere la Sezione 5.3.2.
Stream Dependency (Dipendenza dello stream): Un identificatore di stream a 31 bit. Questo campo è presente solo se il flag PRIORITY è impostato.
Weight (Peso): Un intero senza segno a 8 bit. Questo campo è presente solo se il flag PRIORITY è impostato.
Field Block Fragment (Frammento di blocco di campi): Un frammento di blocco di campi (Sezione 4.3).
Padding (Padding): Ottetti di padding che non contengono alcun valore semantico dell'applicazione. Gli ottetti di padding DEVONO essere impostati a zero durante l'invio. Un ricevitore non è obbligato a verificare il padding ma PUÒ trattare un padding non zero come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame HEADERS definisce i seguenti flag:
PRIORITY (0x20): Quando impostato, il flag PRIORITY indica che i campi Exclusive, Stream Dependency e Weight sono presenti.
PADDED (0x08): Quando impostato, il flag PADDED indica che il campo Pad Length e qualsiasi padding che descrive sono presenti.
END_HEADERS (0x04): Quando impostato, il flag END_HEADERS indica che questo frame contiene un intero blocco di campi (Sezione 4.3) e non è seguito da frame CONTINUATION.
Un frame HEADERS senza il flag END_HEADERS impostato DEVE essere seguito da un frame CONTINUATION per lo stesso stream. Un ricevitore DEVE trattare la ricezione di qualsiasi altro tipo di frame o di un frame su uno stream diverso come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
END_STREAM (0x01): Quando impostato, il flag END_STREAM indica che il blocco di campi (Sezione 4.3) è l'ultimo che l'endpoint invierà per lo stream identificato.
Un frame HEADERS con il flag END_STREAM impostato segnala la fine di uno stream. Tuttavia, un frame HEADERS con il flag END_STREAM impostato può essere seguito da frame CONTINUATION sullo stesso stream. Logicamente, i frame CONTINUATION fanno parte del frame HEADERS.
Il payload del frame HEADERS contiene un frammento di blocco di campi (Sezione 4.3). Un blocco di campi che non si adatta in un frame HEADERS viene continuato in un frame CONTINUATION (Sezione 6.10).
I frame HEADERS DEVONO essere associati a uno stream. Se viene ricevuto un frame HEADERS il cui campo Stream Identifier è 0x00, il destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame HEADERS cambia lo stato della connessione come descritto nella Sezione 4.3.
Il numero totale di ottetti di padding è determinato dal valore del campo Pad Length. Se la lunghezza del padding è pari o superiore alla lunghezza del payload del frame, il destinatario DEVE trattare questo come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
| Nota: Un frame può essere aumentato di dimensione di un ottetto includendo un campo | Pad Length con valore zero.
6.3. PRIORITY
Il frame PRIORITY (type=0x02) è deprecato; vedere la Sezione 5.3.2. Un frame PRIORITY può essere inviato in qualsiasi stato dello stream, inclusi gli stream idle o closed.
PRIORITY Frame {
Length (24) = 0x05,
Type (8) = 0x02,
Unused Flags (8),
Reserved (1),
Stream Identifier (31),
Exclusive (1),
Stream Dependency (31),
Weight (8),
}
Figura 5: Formato del Frame PRIORITY
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload del frame PRIORITY contiene i seguenti campi aggiuntivi:
Exclusive (Esclusivo): Un flag a singolo bit.
Stream Dependency (Dipendenza dello stream): Un identificatore di stream a 31 bit.
Weight (Peso): Un intero senza segno a 8 bit.
Il frame PRIORITY non definisce alcun flag.
Il frame PRIORITY identifica sempre uno stream. Se viene ricevuto un frame PRIORITY con un identificatore di stream di 0x00, il destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
L'invio o la ricezione di un frame PRIORITY non influisce sullo stato di alcuno stream (Sezione 5.1). Il frame PRIORITY può essere inviato su uno stream in qualsiasi stato, incluso "idle" o "closed". Un frame PRIORITY non può essere inviato tra frame consecutivi che compongono un singolo blocco di campi (Sezione 4.3).
Un frame PRIORITY con una lunghezza diversa da 5 ottetti DEVE essere trattato come un errore di stream (Sezione 5.4.2) di tipo FRAME_SIZE_ERROR.
6.4. RST_STREAM
Il frame RST_STREAM (type=0x03) consente la terminazione immediata di uno stream. RST_STREAM viene inviato per richiedere la cancellazione di uno stream o per indicare che si è verificata una condizione di errore.
RST_STREAM Frame {
Length (24) = 0x04,
Type (8) = 0x03,
Unused Flags (8),
Reserved (1),
Stream Identifier (31),
Error Code (32),
}
Figura 6: Formato del Frame RST_STREAM
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Inoltre, il frame RST_STREAM contiene un singolo intero senza segno a 32 bit che identifica il codice di errore (Sezione 7). Il codice di errore indica perché lo stream viene terminato.
Il frame RST_STREAM non definisce alcun flag.
Il frame RST_STREAM termina completamente lo stream referenziato e lo fa entrare nello stato "closed". Dopo aver ricevuto un RST_STREAM su uno stream, il ricevitore NON DEVE inviare frame aggiuntivi per quello stream, ad eccezione di PRIORITY. Tuttavia, dopo aver inviato il RST_STREAM, l'endpoint mittente DEVE essere preparato a ricevere ed elaborare frame aggiuntivi inviati sullo stream che potrebbero essere stati inviati dal peer prima dell'arrivo del RST_STREAM.
I frame RST_STREAM DEVONO essere associati a uno stream. Se viene ricevuto un frame RST_STREAM con un identificatore di stream di 0x00, il destinatario DEVE trattare questo come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
I frame RST_STREAM NON DEVONO essere inviati per uno stream nello stato "idle". Se viene ricevuto un frame RST_STREAM che identifica uno stream idle, il destinatario DEVE trattare questo come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Un frame RST_STREAM con una lunghezza diversa da 4 ottetti DEVE essere trattato come un errore di connessione (Sezione 5.4.1) di tipo FRAME_SIZE_ERROR.
6.5. SETTINGS
Il frame SETTINGS (type=0x04) trasmette parametri di configurazione che influenzano il modo in cui gli endpoint comunicano, come le preferenze e i vincoli sul comportamento del peer. Il frame SETTINGS viene utilizzato anche per confermare la ricezione di tali impostazioni. Individualmente, un parametro di configurazione da un frame SETTINGS è chiamato "impostazione".
Le impostazioni non vengono negoziate; descrivono le caratteristiche del peer mittente, che vengono utilizzate dal peer ricevente. Valori diversi per la stessa impostazione possono essere pubblicizzati da ciascun peer. Ad esempio, un client potrebbe impostare una finestra di controllo di flusso iniziale elevata, mentre un server potrebbe impostare un valore inferiore per conservare le risorse.
Un frame SETTINGS DEVE essere inviato da entrambi gli endpoint all'inizio di una connessione e PUÒ essere inviato in qualsiasi altro momento da uno dei due endpoint durante la durata della connessione. Le implementazioni DEVONO supportare tutte le impostazioni definite da questa specifica.
Ogni parametro in un frame SETTINGS sostituisce qualsiasi valore esistente per quel parametro. Le impostazioni vengono elaborate nell'ordine in cui appaiono e un ricevitore di un frame SETTINGS non ha bisogno di mantenere alcuno stato diverso dal valore corrente di ciascuna impostazione. Pertanto, il valore di un parametro SETTINGS è l'ultimo valore visto da un ricevitore.
I frame SETTINGS vengono confermati dal peer ricevente. Per abilitare questo, il frame SETTINGS definisce il flag ACK:
ACK (0x01): Quando impostato, il flag ACK indica che questo frame conferma la ricezione e l'applicazione del frame SETTINGS del peer. Quando questo bit è impostato, il payload del frame SETTINGS DEVE essere vuoto. La ricezione di un frame SETTINGS con il flag ACK impostato e un valore del campo di lunghezza diverso da 0 DEVE essere trattata come un errore di connessione (Sezione 5.4.1) di tipo FRAME_SIZE_ERROR. Per ulteriori informazioni, vedere la Sezione 6.5.3 ("Sincronizzazione delle impostazioni").
I frame SETTINGS si applicano sempre a una connessione, mai a un singolo stream. L'identificatore di stream per un frame SETTINGS DEVE essere zero (0x00). Se un endpoint riceve un frame SETTINGS il cui campo Stream Identifier è diverso da 0x00, l'endpoint DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame SETTINGS influisce sullo stato della connessione. Un frame SETTINGS malformato o incompleto DEVE essere trattato come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Un frame SETTINGS con una lunghezza diversa da un multiplo di 6 ottetti DEVE essere trattato come un errore di connessione (Sezione 5.4.1) di tipo FRAME_SIZE_ERROR.
6.5.1. SETTINGS Format (Formato SETTINGS)
Il payload di un frame SETTINGS consiste di zero o più impostazioni, ciascuna costituita da un identificatore di impostazione senza segno a 16 bit e un valore senza segno a 32 bit.
SETTINGS Frame {
Length (24),
Type (8) = 0x04,
Unused Flags (7),
ACK Flag (1),
Reserved (1),
Stream Identifier (31) = 0,
Setting (48) ...,
}
Setting {
Identifier (16),
Value (32),
}
Figura 7: Formato del Frame SETTINGS
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload di un frame SETTINGS contiene un numero qualsiasi di campi Setting, ciascuno dei quali consiste di:
Identifier (Identificatore): Un identificatore di impostazione a 16 bit; vedere la Sezione 6.5.2.
Value (Valore): Un valore a 32 bit per l'impostazione.
6.5.2. Defined Settings (Impostazioni Definite)
Le seguenti impostazioni sono definite:
SETTINGS_HEADER_TABLE_SIZE (0x01): Questa impostazione consente al mittente di informare l'endpoint remoto della dimensione massima della tabella di compressione utilizzata per decodificare i blocchi di campi, in unità di ottetti. L'encoder può selezionare qualsiasi dimensione uguale o inferiore a questo valore utilizzando una segnalazione specifica del formato di compressione all'interno di un blocco di campi (vedere [COMPRESSION]). Il valore iniziale è 4.096 ottetti.
SETTINGS_ENABLE_PUSH (0x02): Questa impostazione può essere utilizzata per abilitare o disabilitare il push del server. Un server NON DEVE inviare un frame PUSH_PROMISE se riceve questo parametro impostato a un valore di 0; vedere la Sezione 8.4. Un client che ha impostato questo parametro a 0 e l'ha fatto confermare DEVE trattare la ricezione di un frame PUSH_PROMISE come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il valore iniziale di SETTINGS_ENABLE_PUSH è 1. Per un client, questo valore indica che è disposto a ricevere frame PUSH_PROMISE. Per un server, questo valore iniziale non ha effetto ed è equivalente al valore 0. Qualsiasi valore diverso da 0 o 1 DEVE essere trattato come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Un server NON DEVE impostare esplicitamente questo valore su 1. Un server PUÒ scegliere di omettere questa impostazione quando invia un frame SETTINGS, ma se un server include un valore, DEVE essere 0. Un client DEVE trattare la ricezione di un frame SETTINGS con SETTINGS_ENABLE_PUSH impostato a 1 come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
SETTINGS_MAX_CONCURRENT_STREAMS (0x03): Questa impostazione indica il numero massimo di stream simultanei che il mittente consentirà. Questo limite è direzionale: si applica al numero di stream che il mittente consente al ricevitore di creare. Inizialmente, non c'è limite a questo valore. Si raccomanda che questo valore non sia inferiore a 100, in modo da non limitare inutilmente il parallelismo.
Un valore di 0 per SETTINGS_MAX_CONCURRENT_STREAMS NON DOVREBBE essere trattato come speciale dagli endpoint. Un valore zero impedisce la creazione di nuovi stream; tuttavia, questo può accadere anche per qualsiasi limite esaurito con stream attivi. I server DOVREBBERO impostare un valore zero solo per brevi periodi; se un server non desidera accettare richieste, chiudere la connessione è più appropriato.
SETTINGS_INITIAL_WINDOW_SIZE (0x04): Questa impostazione indica la dimensione della finestra iniziale del mittente (in unità di ottetti) per il controllo di flusso a livello di stream. Il valore iniziale è 2^16-1 (65.535) ottetti.
Questa impostazione influisce sulla dimensione della finestra di tutti gli stream (vedere la Sezione 6.9.2).
I valori superiori alla dimensione massima della finestra di controllo di flusso di 2^31-1 DEVONO essere trattati come un errore di connessione (Sezione 5.4.1) di tipo FLOW_CONTROL_ERROR.
SETTINGS_MAX_FRAME_SIZE (0x05): Questa impostazione indica la dimensione del payload del frame più grande che il mittente è disposto a ricevere, in unità di ottetti.
Il valore iniziale è 2^14 (16.384) ottetti. Il valore pubblicizzato da un endpoint DEVE essere compreso tra questo valore iniziale e la dimensione massima consentita del frame (2^24-1 o 16.777.215 ottetti), inclusi. I valori al di fuori di questo intervallo DEVONO essere trattati come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
SETTINGS_MAX_HEADER_LIST_SIZE (0x06): Questa impostazione consultiva informa un peer della dimensione massima della sezione di campi che il mittente è preparato ad accettare, in unità di ottetti. Il valore si basa sulla dimensione non compressa delle righe di campi, inclusa la lunghezza del nome e del valore in unità di ottetti più un overhead di 32 ottetti per ogni riga di campo.
Per qualsiasi richiesta data, PUÒ essere applicato un limite inferiore a quello pubblicizzato. Il valore iniziale di questa impostazione è illimitato.
Un endpoint che riceve un frame SETTINGS con un identificatore sconosciuto o non supportato DEVE ignorare tale impostazione.
6.5.3. Settings Synchronization (Sincronizzazione delle Impostazioni)
La maggior parte dei valori in SETTINGS beneficia o richiede una comprensione di quando il peer ha ricevuto e applicato i valori dei parametri modificati. Per fornire tali punti di sincronizzazione, il destinatario di un frame SETTINGS in cui il flag ACK non è impostato DEVE applicare le impostazioni aggiornate il prima possibile alla ricezione. I frame SETTINGS vengono confermati nell'ordine in cui vengono ricevuti.
I valori nel frame SETTINGS DEVONO essere elaborati nell'ordine in cui appaiono, senza altra elaborazione di frame tra i valori. Le impostazioni non supportate DEVONO essere ignorate. Una volta elaborati tutti i valori, il destinatario DEVE emettere immediatamente un frame SETTINGS con il flag ACK impostato. Alla ricezione di un frame SETTINGS con il flag ACK impostato, il mittente delle impostazioni modificate può fare affidamento sui valori del frame SETTINGS non confermato più vecchio che sono stati applicati.
Se il mittente di un frame SETTINGS non riceve una conferma entro un periodo di tempo ragionevole, PUÒ emettere un errore di connessione (Sezione 5.4.1) di tipo SETTINGS_TIMEOUT. Nell'impostare un timeout, è necessario consentire un certo margine per i ritardi di elaborazione presso il peer; un timeout basato esclusivamente sul tempo di andata e ritorno tra gli endpoint potrebbe causare errori spuri.
6.6. PUSH_PROMISE
Il frame PUSH_PROMISE (type=0x05) viene utilizzato per notificare l'endpoint peer in anticipo degli stream che il mittente intende avviare. Il frame PUSH_PROMISE include l'identificatore senza segno a 31 bit dello stream che l'endpoint prevede di creare insieme a una sezione di campi che fornisce un contesto aggiuntivo per lo stream. La Sezione 8.4 contiene una descrizione approfondita dell'uso dei frame PUSH_PROMISE.
PUSH_PROMISE Frame {
Length (24),
Type (8) = 0x05,
Unused Flags (4),
PADDED Flag (1),
END_HEADERS Flag (1),
Unused Flags (2),
Reserved (1),
Stream Identifier (31),
[Pad Length (8)],
Reserved (1),
Promised Stream ID (31),
Field Block Fragment (..),
Padding (..2040),
}
Figura 8: Formato del Frame PUSH_PROMISE
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload del frame PUSH_PROMISE ha i seguenti campi aggiuntivi:
Pad Length (Lunghezza del padding): Un campo a 8 bit che contiene la lunghezza del padding del frame in unità di ottetti. Questo campo è presente solo se il flag PADDED è impostato.
Promised Stream ID (ID dello stream promesso): Un intero senza segno a 31 bit che identifica lo stream riservato dal PUSH_PROMISE. L'identificatore dello stream promesso DEVE essere una scelta valida per il prossimo stream inviato dal mittente (vedere "nuovo identificatore di stream" nella Sezione 5.1.1).
Field Block Fragment (Frammento di blocco di campi): Un frammento di blocco di campi (Sezione 4.3) contenente i dati di controllo della richiesta e una sezione di intestazione.
Padding (Padding): Ottetti di padding che non contengono alcun valore semantico dell'applicazione. Gli ottetti di padding DEVONO essere impostati a zero durante l'invio. Un ricevitore non è obbligato a verificare il padding ma PUÒ trattare un padding non zero come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame PUSH_PROMISE definisce i seguenti flag:
PADDED (0x08): Quando impostato, il flag PADDED indica che il campo Pad Length e qualsiasi padding che descrive sono presenti.
END_HEADERS (0x04): Quando impostato, il flag END_HEADERS indica che questo frame contiene un intero blocco di campi (Sezione 4.3) e non è seguito da frame CONTINUATION.
Un frame PUSH_PROMISE senza il flag END_HEADERS impostato DEVE essere seguito da un frame CONTINUATION per lo stesso stream. Un ricevitore DEVE trattare la ricezione di qualsiasi altro tipo di frame o di un frame su uno stream diverso come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
I frame PUSH_PROMISE DEVONO essere inviati solo su uno stream avviato dal peer che è nello stato "open" o "half-closed (remote)". L'identificatore di stream di un frame PUSH_PROMISE indica lo stream a cui è associato. Se il campo Stream Identifier specifica il valore 0x00, un destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Gli stream promessi non sono tenuti a essere utilizzati nell'ordine in cui sono promessi. Il PUSH_PROMISE riserva solo gli identificatori di stream per un uso successivo.
PUSH_PROMISE NON DEVE essere inviato se l'impostazione SETTINGS_ENABLE_PUSH dell'endpoint peer è impostata a 0. Un endpoint che ha impostato questa impostazione e ha ricevuto una conferma DEVE trattare la ricezione di un frame PUSH_PROMISE come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
I destinatari dei frame PUSH_PROMISE possono scegliere di rifiutare gli stream promessi restituendo un RST_STREAM che fa riferimento all'identificatore dello stream promesso al mittente del PUSH_PROMISE.
Un frame PUSH_PROMISE modifica lo stato della connessione in due modi. Primo, l'inclusione di un blocco di campi (Sezione 4.3) modifica potenzialmente lo stato mantenuto per la compressione della sezione di campi. Secondo, PUSH_PROMISE riserva anche uno stream per un uso successivo, facendo entrare lo stream promesso nello stato "reserved (local)" o "reserved (remote)". Un mittente NON DEVE inviare un PUSH_PROMISE su uno stream a meno che quello stream non sia "open" o "half-closed (remote)"; il mittente DEVE assicurarsi che lo stream promesso sia una scelta valida per un nuovo identificatore di stream (Sezione 5.1.1) (cioè, lo stream promesso DEVE essere nello stato "idle").
Poiché PUSH_PROMISE riserva uno stream, ignorare un frame PUSH_PROMISE fa sì che lo stato dello stream diventi indeterminato. Un ricevitore DEVE trattare la ricezione di un PUSH_PROMISE su uno stream che non è né "open" né "half-closed (local)" come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR. Tuttavia, un endpoint che ha inviato RST_STREAM sullo stream associato DEVE gestire i frame PUSH_PROMISE che potrebbero essere stati creati prima che il frame RST_STREAM fosse ricevuto ed elaborato.
Un ricevitore DEVE trattare la ricezione di un PUSH_PROMISE che promette un identificatore di stream illegale (Sezione 5.1.1) come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR. Si noti che un identificatore di stream illegale è un identificatore per uno stream che attualmente non è nello stato "idle".
Il numero totale di ottetti di padding è determinato dal valore del campo Pad Length. Se la lunghezza del padding è pari o superiore alla lunghezza del payload del frame, il destinatario DEVE trattare questo come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
| Nota: Un frame può essere aumentato di dimensione di un ottetto includendo un campo | Pad Length con valore zero.
6.7. PING
Il frame PING (type=0x06) è un meccanismo per misurare un tempo di andata e ritorno minimo dal mittente, nonché per determinare se una connessione inattiva è ancora funzionale. I frame PING possono essere inviati da qualsiasi endpoint.
PING Frame {
Length (24) = 0x08,
Type (8) = 0x06,
Unused Flags (7),
ACK Flag (1),
Reserved (1),
Stream Identifier (31) = 0,
Opaque Data (64),
}
Figura 9: Formato del Frame PING
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4.
Oltre all'intestazione del frame, i frame PING DEVONO contenere 8 ottetti di dati opachi nel payload del frame. Un mittente può includere qualsiasi valore scelga e utilizzare quegli ottetti in qualsiasi modo.
I ricevitori di un frame PING che non include un flag ACK DEVONO inviare un frame PING con il flag ACK impostato in risposta, con un payload del frame identico. Le risposte PING DOVREBBERO ricevere una priorità più alta rispetto a qualsiasi altro frame.
Il frame PING definisce il seguente flag:
ACK (0x01): Quando impostato, il flag ACK indica che questo frame PING è una risposta PING. Un endpoint DEVE impostare questo flag nelle risposte PING. Un endpoint NON DEVE rispondere a frame PING che contengono questo flag.
I frame PING non sono associati a nessuno stream individuale. Se viene ricevuto un frame PING con un valore del campo Stream Identifier diverso da 0x00, il destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
La ricezione di un frame PING con un valore del campo di lunghezza diverso da 8 DEVE essere trattata come un errore di connessione (Sezione 5.4.1) di tipo FRAME_SIZE_ERROR.
6.8. GOAWAY
Il frame GOAWAY (type=0x07) viene utilizzato per avviare l'arresto di una connessione o per segnalare condizioni di errore gravi. GOAWAY consente a un endpoint di smettere di accettare nuovi stream in modo corretto mentre continua a elaborare gli stream precedentemente stabiliti. Ciò consente azioni amministrative, come la manutenzione del server.
Esiste una race condition intrinseca tra un endpoint che avvia nuovi stream e il peer remoto che invia un frame GOAWAY. Per gestire questo caso, il GOAWAY contiene l'identificatore di stream dell'ultimo stream avviato dal peer che è stato o potrebbe essere elaborato sull'endpoint mittente in questa connessione. Ad esempio, se il server invia un frame GOAWAY, lo stream identificato è quello con il numero più alto avviato dal client.
Una volta inviato il GOAWAY, il mittente ignorerà i frame inviati su stream avviati dal ricevitore se lo stream ha un identificatore superiore all'ultimo identificatore di stream incluso. I ricevitori di un frame GOAWAY NON DEVONO aprire stream aggiuntivi sulla connessione, sebbene possa essere stabilita una nuova connessione per nuovi stream.
Se il ricevitore del GOAWAY ha inviato dati su stream con un identificatore di stream più alto di quello indicato nel frame GOAWAY, quegli stream non sono o non saranno elaborati. Il ricevitore del frame GOAWAY può trattare gli stream come se non fossero mai stati creati, consentendo così a quegli stream di essere ritentati successivamente su una nuova connessione.
Gli endpoint DOVREBBERO sempre inviare un frame GOAWAY prima di chiudere una connessione in modo che il peer remoto possa sapere se uno stream è stato elaborato parzialmente o meno. Ad esempio, se un client HTTP invia un POST nello stesso momento in cui un server chiude una connessione, il client non può sapere se il server ha iniziato a elaborare quella richiesta POST se il server non invia un frame GOAWAY per indicare su quali stream potrebbe aver agito.
Un endpoint può scegliere di chiudere una connessione senza inviare un GOAWAY per peer che si comportano male.
Un frame GOAWAY potrebbe non precedere immediatamente la chiusura della connessione; un ricevitore di un GOAWAY che non ha più uso per la connessione DOVREBBE comunque inviare un frame GOAWAY prima di terminare la connessione.
GOAWAY Frame {
Length (24),
Type (8) = 0x07,
Unused Flags (8),
Reserved (1),
Stream Identifier (31) = 0,
Reserved (1),
Last-Stream-ID (31),
Error Code (32),
Additional Debug Data (..),
}
Figura 10: Formato del Frame GOAWAY
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4.
Il frame GOAWAY non definisce alcun flag.
Il frame GOAWAY si applica alla connessione, non a uno stream specifico. Un endpoint DEVE trattare un frame GOAWAY con un identificatore di stream diverso da 0x00 come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
L'ultimo identificatore di stream nel frame GOAWAY contiene l'identificatore di stream con il numero più alto per il quale il mittente del frame GOAWAY potrebbe aver intrapreso qualche azione o potrebbe ancora intraprendere un'azione. Tutti gli stream fino a e incluso lo stream identificato potrebbero essere stati elaborati in qualche modo. L'ultimo identificatore di stream può essere impostato a 0 se non sono stati elaborati stream.
| Nota: In questo contesto, "elaborato" significa che alcuni dati dallo stream sono stati | passati a un livello superiore del software che potrebbe aver intrapreso qualche azione di | conseguenza.
Se una connessione termina senza un frame GOAWAY, l'ultimo identificatore di stream è effettivamente l'identificatore di stream più alto possibile.
Su stream con identificatori con numero inferiore o uguale che non sono stati chiusi completamente prima della chiusura della connessione, non è possibile ritentare richieste, transazioni o qualsiasi attività di protocollo, tranne per azioni idempotenti come HTTP GET, PUT o DELETE. Qualsiasi attività di protocollo che utilizza stream con numero superiore può essere ritentata in sicurezza utilizzando una nuova connessione.
L'attività su stream numerati inferiormente o ugualmente all'ultimo identificatore di stream potrebbe ancora completarsi con successo. Il mittente di un frame GOAWAY può arrestare correttamente una connessione inviando un frame GOAWAY, mantenendo la connessione in uno stato "open" fino al completamento di tutti gli stream in corso.
Un endpoint PUÒ inviare più frame GOAWAY se le circostanze cambiano. Ad esempio, un endpoint che invia GOAWAY con NO_ERROR durante un arresto corretto potrebbe successivamente incontrare una condizione che richiede la terminazione immediata della connessione. L'ultimo identificatore di stream dall'ultimo frame GOAWAY ricevuto indica quali stream potrebbero essere stati elaborati. Gli endpoint NON DEVONO aumentare il valore che inviano nell'ultimo identificatore di stream, poiché i peer potrebbero aver già ritentato le richieste non elaborate su un'altra connessione.
Un client che non può ritentare le richieste perde tutte le richieste in transito quando il server chiude la connessione. Ciò è particolarmente vero per gli intermediari che potrebbero non servire i client utilizzando HTTP/2. Un server che sta tentando di arrestare correttamente una connessione DOVREBBE inviare un frame GOAWAY iniziale con l'ultimo identificatore di stream impostato a 2^31-1 e un codice NO_ERROR. Questo segnala al client che un arresto è imminente e che l'avvio di ulteriori richieste è vietato. Dopo aver consentito il tempo per qualsiasi creazione di stream in transito (almeno un tempo di andata e ritorno), il server PUÒ inviare un altro frame GOAWAY con un ultimo identificatore di stream aggiornato. Ciò garantisce che una connessione possa essere arrestata correttamente senza perdere richieste.
Dopo aver inviato un frame GOAWAY, il mittente può scartare i frame per gli stream avviati dal ricevitore con identificatori superiori all'ultimo stream identificato. Tuttavia, qualsiasi frame che alteri lo stato della connessione non può essere completamente ignorato. Ad esempio, i frame HEADERS, PUSH_PROMISE e CONTINUATION DEVONO essere elaborati minimamente per garantire che lo stato mantenuto per la compressione della sezione di campi sia coerente (vedere la Sezione 4.3); allo stesso modo, i frame DATA DEVONO essere conteggiati nella finestra di controllo di flusso della connessione. Il mancato elaborazione di questi frame può causare la desincronizzazione del controllo di flusso o dello stato di compressione della sezione di campi.
Il frame GOAWAY contiene anche un codice di errore a 32 bit (Sezione 7) che contiene il motivo della chiusura della connessione.
Gli endpoint POSSONO aggiungere dati opachi al payload di qualsiasi frame GOAWAY. Dati di debug aggiuntivi sono destinati solo a scopi diagnostici e non portano alcun valore semantico. I dati di debug potrebbero contenere dati sensibili alla sicurezza o alla privacy. I dati di debug registrati o altrimenti memorizzati in modo persistente DEVONO avere adeguate protezioni per prevenire l'accesso non autorizzato.
6.9. WINDOW_UPDATE
Il frame WINDOW_UPDATE (type=0x08) viene utilizzato per implementare il controllo di flusso; vedere la Sezione 5.2 per una panoramica.
Il controllo di flusso opera a due livelli: su ogni singolo stream e sull'intera connessione.
Entrambi i tipi di controllo di flusso sono hop by hop, cioè solo tra i due endpoint. Gli intermediari non inoltrano i frame WINDOW_UPDATE tra connessioni dipendenti. Tuttavia, la limitazione del trasferimento dei dati da parte di qualsiasi ricevitore può causare indirettamente la propagazione delle informazioni di controllo di flusso verso il mittente originale.
Il controllo di flusso si applica solo ai frame identificati come soggetti al controllo di flusso. Dei tipi di frame definiti in questo documento, ciò include solo i frame DATA. I frame che sono esenti dal controllo di flusso DEVONO essere accettati ed elaborati, a meno che il ricevitore non sia in grado di assegnare risorse per gestire il frame. Un ricevitore PUÒ rispondere con un errore di stream (Sezione 5.4.2) o un errore di connessione (Sezione 5.4.1) di tipo FLOW_CONTROL_ERROR se non è in grado di accettare un frame.
WINDOW_UPDATE Frame {
Length (24) = 0x04,
Type (8) = 0x08,
Unused Flags (8),
Reserved (1),
Stream Identifier (31),
Reserved (1),
Window Size Increment (31),
}
Figura 11: Formato del Frame WINDOW_UPDATE
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload di un frame WINDOW_UPDATE è un bit riservato più un intero senza segno a 31 bit che indica il numero di ottetti che il mittente può trasmettere in aggiunta alla finestra di controllo di flusso esistente. L'intervallo legale per l'incremento della finestra di controllo di flusso va da 1 a 2^31-1 (2.147.483.647) ottetti.
Il frame WINDOW_UPDATE non definisce alcun flag.
Il frame WINDOW_UPDATE può essere specifico per uno stream o per l'intera connessione. Nel primo caso, l'identificatore di stream del frame indica lo stream interessato; nel secondo caso, il valore "0" indica che l'intera connessione è il soggetto del frame.
Un ricevitore DEVE trattare la ricezione di un frame WINDOW_UPDATE con un incremento della finestra di controllo di flusso di 0 come un errore di stream (Sezione 5.4.2) di tipo PROTOCOL_ERROR; gli errori sulla finestra di controllo di flusso della connessione DEVONO essere trattati come un errore di connessione (Sezione 5.4.1).
WINDOW_UPDATE può essere inviato da un peer che ha inviato un frame con il flag END_STREAM impostato. Ciò significa che un ricevitore potrebbe ricevere un frame WINDOW_UPDATE su uno stream in uno stato "half-closed (remote)" o "closed". Un ricevitore NON DEVE trattare questo come un errore (vedere la Sezione 5.1).
Un ricevitore che riceve un frame controllato dal flusso DEVE sempre tenere conto del suo contributo alla finestra di controllo di flusso della connessione, a meno che il ricevitore non tratti questo come un errore di connessione (Sezione 5.4.1). Ciò è necessario anche se il frame è in errore. Il mittente conta il frame nella finestra di controllo di flusso, ma se il ricevitore non lo fa, la finestra di controllo di flusso presso il mittente e il ricevitore può diventare diversa.
Un frame WINDOW_UPDATE con una lunghezza diversa da 4 ottetti DEVE essere trattato come un errore di connessione (Sezione 5.4.1) di tipo FRAME_SIZE_ERROR.
6.9.1. The Flow-Control Window (La Finestra di Controllo di Flusso)
Il controllo di flusso in HTTP/2 è implementato utilizzando una finestra mantenuta da ogni mittente su ogni stream. La finestra di controllo di flusso è un semplice valore intero che indica quanti ottetti di dati il mittente è autorizzato a trasmettere; come tale, la sua dimensione è una misura della capacità di buffering del ricevitore.
Due finestre di controllo di flusso sono applicabili: la finestra di controllo di flusso dello stream e la finestra di controllo di flusso della connessione. Il mittente NON DEVE inviare un frame controllato dal flusso con una lunghezza che supera lo spazio disponibile in una qualsiasi delle finestre di controllo di flusso pubblicizzate dal ricevitore. I frame con lunghezza zero con il flag END_STREAM impostato (cioè, un frame DATA vuoto) POSSONO essere inviati se non c'è spazio disponibile in nessuna delle finestre di controllo di flusso.
Per i calcoli del controllo di flusso, l'intestazione del frame a 9 ottetti non viene conteggiata.
Dopo aver inviato un frame controllato dal flusso, il mittente riduce lo spazio disponibile in entrambe le finestre della lunghezza del frame trasmesso.
Il ricevitore di un frame invia un frame WINDOW_UPDATE mentre consuma dati e libera spazio nelle finestre di controllo di flusso. I frame WINDOW_UPDATE separati vengono inviati per le finestre di controllo di flusso a livello di stream e di connessione. Si consiglia ai ricevitori di avere meccanismi in atto per evitare di inviare frame WINDOW_UPDATE con incrementi molto piccoli; vedere la Sezione 4.2.3.3 di [RFC1122].
Un mittente che riceve un frame WINDOW_UPDATE aggiorna la finestra corrispondente dell'importo specificato nel frame.
Un mittente NON DEVE consentire a una finestra di controllo di flusso di superare 2^31-1 ottetti. Se un mittente riceve un WINDOW_UPDATE che fa sì che una finestra di controllo di flusso superi questo massimo, DEVE terminare lo stream o la connessione, a seconda dei casi. Per gli stream, il mittente invia un RST_STREAM con un codice di errore di FLOW_CONTROL_ERROR; per la connessione, viene inviato un frame GOAWAY con un codice di errore di FLOW_CONTROL_ERROR.
I frame controllati dal flusso dal mittente e i frame WINDOW_UPDATE dal ricevitore sono completamente asincroni l'uno rispetto all'altro. Questa proprietà consente a un ricevitore di aggiornare in modo aggressivo la dimensione della finestra mantenuta dal mittente per impedire agli stream di bloccarsi.
6.9.2. Initial Flow-Control Window Size (Dimensione Iniziale della Finestra di Controllo di Flusso)
Quando una connessione HTTP/2 viene stabilita per la prima volta, i nuovi stream vengono creati con una dimensione iniziale della finestra di controllo di flusso di 65.535 ottetti. Anche la finestra di controllo di flusso della connessione è di 65.535 ottetti. Entrambi gli endpoint possono regolare la dimensione iniziale della finestra per i nuovi stream includendo un valore per SETTINGS_INITIAL_WINDOW_SIZE nel frame SETTINGS. La finestra di controllo di flusso della connessione può essere modificata solo utilizzando i frame WINDOW_UPDATE.
Prima di ricevere un frame SETTINGS che imposta un valore per SETTINGS_INITIAL_WINDOW_SIZE, un endpoint può utilizzare solo la dimensione iniziale predefinita della finestra quando invia frame controllati dal flusso. Allo stesso modo, la finestra di controllo di flusso della connessione viene impostata in base alla dimensione iniziale predefinita della finestra fino a quando non viene ricevuto un frame WINDOW_UPDATE.
Oltre a modificare la finestra di controllo di flusso per gli stream che non sono ancora attivi, un frame SETTINGS può alterare la dimensione iniziale della finestra di controllo di flusso per gli stream con finestre di controllo di flusso attive (cioè, stream negli stati "open" o "half-closed (remote)"). Quando il valore di SETTINGS_INITIAL_WINDOW_SIZE cambia, un ricevitore DEVE regolare la dimensione di tutte le finestre di controllo di flusso dello stream che mantiene della differenza tra il nuovo valore e il vecchio valore.
Una modifica a SETTINGS_INITIAL_WINDOW_SIZE può far sì che lo spazio disponibile in una finestra di controllo di flusso diventi negativo. Un mittente DEVE tenere traccia della finestra di controllo di flusso negativa e NON DEVE inviare nuovi frame controllati dal flusso fino a quando non riceve frame WINDOW_UPDATE che rendono la finestra di controllo di flusso positiva.
Ad esempio, se il client invia 60 KB immediatamente all'instaurazione della connessione e il server imposta la dimensione iniziale della finestra a 16 KB, il client ricalcolerà la finestra di controllo di flusso disponibile a -44 KB alla ricezione del frame SETTINGS. Il client mantiene una finestra di controllo di flusso negativa fino a quando i frame WINDOW_UPDATE ripristinano la finestra rendendola positiva, dopodiché il client può riprendere l'invio.
Un frame SETTINGS non può alterare la finestra di controllo di flusso della connessione.
Un endpoint DEVE trattare una modifica a SETTINGS_INITIAL_WINDOW_SIZE che fa sì che una qualsiasi finestra di controllo di flusso superi la dimensione massima come un errore di connessione (Sezione 5.4.1) di tipo FLOW_CONTROL_ERROR.
6.9.3. Reducing the Stream Window Size (Riduzione della Dimensione della Finestra dello Stream)
Un ricevitore che desidera utilizzare una finestra di controllo di flusso più piccola della dimensione corrente può inviare un nuovo frame SETTINGS. Tuttavia, il ricevitore DEVE essere preparato a ricevere dati che superano questa dimensione della finestra, poiché il mittente potrebbe inviare dati che superano il limite inferiore prima di elaborare il frame SETTINGS.
Dopo aver inviato un frame SETTINGS che riduce la dimensione iniziale della finestra di controllo di flusso, un ricevitore PUÒ continuare a elaborare gli stream che superano i limiti di controllo di flusso. Consentire agli stream di continuare non consente al ricevitore di ridurre immediatamente lo spazio che riserva per le finestre di controllo di flusso. Il progresso su questi stream può anche bloccarsi, poiché sono necessari frame WINDOW_UPDATE per consentire al mittente di riprendere l'invio. Il ricevitore PUÒ invece inviare un RST_STREAM con un codice di errore di FLOW_CONTROL_ERROR per gli stream interessati.
6.10. CONTINUATION
Il frame CONTINUATION (type=0x09) viene utilizzato per continuare una sequenza di frammenti di blocco di campi (Sezione 4.3). Può essere inviato un numero qualsiasi di frame CONTINUATION, purché il frame precedente sia sullo stesso stream e sia un frame HEADERS, PUSH_PROMISE o CONTINUATION senza il flag END_HEADERS impostato.
CONTINUATION Frame {
Length (24),
Type (8) = 0x09,
Unused Flags (5),
END_HEADERS Flag (1),
Unused Flags (2),
Reserved (1),
Stream Identifier (31),
Field Block Fragment (..),
}
Figura 12: Formato del Frame CONTINUATION
I campi Length, Type, Unused Flag(s), Reserved e Stream Identifier sono descritti nella Sezione 4. Il payload del frame CONTINUATION contiene un frammento di blocco di campi (Sezione 4.3).
Il frame CONTINUATION definisce il seguente flag:
END_HEADERS (0x04): Quando impostato, il flag END_HEADERS indica che questo frame termina un blocco di campi (Sezione 4.3).
Se il flag END_HEADERS non è impostato, questo frame DEVE essere seguito da un altro frame CONTINUATION. Un ricevitore DEVE trattare la ricezione di qualsiasi altro tipo di frame o di un frame su uno stream diverso come un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Il frame CONTINUATION cambia lo stato della connessione come definito nella Sezione 4.3.
I frame CONTINUATION DEVONO essere associati a uno stream. Se viene ricevuto un frame CONTINUATION con un campo Stream Identifier di 0x00, il destinatario DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Un frame CONTINUATION DEVE essere preceduto da un frame HEADERS, PUSH_PROMISE o CONTINUATION senza il flag END_HEADERS impostato. Un destinatario che osserva la violazione di questa regola DEVE rispondere con un errore di connessione (Sezione 5.4.1) di tipo PROTOCOL_ERROR.
Capitolo 6 completato!