Aller au contenu principal

6. Mappage et utilisation des flux (Stream Mapping and Usage)

Un flux QUIC fournit une livraison d'octets fiable et ordonnée, mais ne garantit pas l'ordre de livraison par rapport aux octets sur d'autres flux. Dans la version 1 de QUIC, les données de flux contenant des trames HTTP sont transportées par des trames QUIC STREAM, mais ce cadrage est invisible pour la couche de cadrage HTTP. La couche transport met en mémoire tampon et ordonne les données de flux reçues, exposant un flux d'octets fiable à l'application. Bien que QUIC permette la livraison désordonnée au sein d'un flux, HTTP/3 n'utilise pas cette fonctionnalité.

Les flux QUIC peuvent être soit unidirectionnels, transportant des données uniquement de l'initiateur vers le récepteur, soit bidirectionnels, transportant des données dans les deux directions. Les flux peuvent être initiés par le client ou le serveur. Pour plus de détails sur les flux QUIC, voir la section 2 de [QUIC-TRANSPORT].

Lorsque les champs et données HTTP sont envoyés sur QUIC, la couche QUIC gère la majeure partie de la gestion des flux. HTTP n'a pas besoin de faire de multiplexage séparé lors de l'utilisation de QUIC : les données envoyées sur un flux QUIC sont toujours mappées à une transaction HTTP particulière ou au contexte de connexion HTTP/3 entier.

6.1. Flux bidirectionnels (Bidirectional Streams)

Tous les flux bidirectionnels initiés par le client sont utilisés pour les requêtes et réponses HTTP. Un flux bidirectionnel garantit que la réponse peut être facilement corrélée avec la requête. Ces flux sont appelés flux de requête (Request Streams).

Cela signifie que la première requête du client se produit sur le flux QUIC 0, avec les requêtes suivantes sur les flux 4, 8, et ainsi de suite. Afin de permettre l'ouverture de ces flux, un serveur HTTP/3 DEVRAIT (SHOULD) configurer des valeurs minimales non nulles pour le nombre de flux autorisés et la fenêtre de contrôle de flux du flux initial. Afin de ne pas limiter inutilement le parallélisme, au moins 100 flux de requête DEVRAIENT (SHOULD) être autorisés à la fois.

HTTP/3 n'utilise pas de flux bidirectionnels initiés par le serveur, bien qu'une extension puisse définir une utilisation pour ces flux. Les clients DOIVENT (MUST) traiter la réception d'un flux bidirectionnel initié par le serveur comme une erreur de connexion de type H3_STREAM_CREATION_ERROR, sauf si une telle extension a été négociée.

6.2. Flux unidirectionnels (Unidirectional Streams)

Les flux unidirectionnels, dans les deux directions, sont utilisés à diverses fins. Le but est indiqué par un type de flux (Stream Type), qui est envoyé sous forme d'entier de longueur variable au début du flux. Le format et la structure des données qui suivent cet entier sont déterminés par le type de flux.

Unidirectional Stream Header {
Stream Type (i),
}

Figure 1 : En-tête de flux unidirectionnel

Deux types de flux sont définis dans ce document : les flux de contrôle (Control Streams) (section 6.2.1) et les flux de push (Push Streams) (section 6.2.2). [QPACK] définit deux types de flux supplémentaires. D'autres types de flux peuvent être définis par des extensions à HTTP/3 ; voir la section 9 pour plus de détails. Certains types de flux sont réservés (section 6.2.3).

Les performances des connexions HTTP/3 dans la phase précoce de leur durée de vie sont sensibles à la création et à l'échange de données sur les flux unidirectionnels. Les points de terminaison qui restreignent excessivement le nombre de flux ou la fenêtre de contrôle de flux de ces flux augmenteront les chances que le pair distant atteigne la limite tôt et soit bloqué. En particulier, les implémentations devraient considérer que les pairs distants peuvent souhaiter exercer le comportement de flux réservé (section 6.2.3) avec certains des flux unidirectionnels qu'ils sont autorisés à utiliser.

Chaque point de terminaison doit créer au moins un flux unidirectionnel pour le flux de contrôle HTTP. QPACK nécessite deux flux unidirectionnels supplémentaires, et d'autres extensions pourraient nécessiter d'autres flux. Par conséquent, les paramètres de transport envoyés par les clients et les serveurs DOIVENT (MUST) permettre au pair de créer au moins trois flux unidirectionnels. Ces paramètres de transport DEVRAIENT (SHOULD) également fournir au moins 1 024 octets de crédit de contrôle de flux à chaque flux unidirectionnel.

Notez qu'un point de terminaison n'est pas tenu d'accorder des crédits supplémentaires pour créer plus de flux unidirectionnels si son pair consomme tous les crédits initiaux avant de créer les flux unidirectionnels critiques. Les points de terminaison DEVRAIENT (SHOULD) créer le flux de contrôle HTTP ainsi que les flux unidirectionnels requis par les extensions obligatoires (tels que les flux d'encodeur et de décodeur QPACK) en premier, puis créer des flux supplémentaires comme autorisé par leur pair.

Si l'en-tête de flux indique un type de flux qui n'est pas pris en charge par le destinataire, le reste du flux ne peut pas être consommé car la sémantique est inconnue. Les destinataires de types de flux inconnus DOIVENT (MUST) soit abandonner la lecture du flux, soit rejeter les données entrantes sans traitement supplémentaire. Si la lecture est abandonnée, le destinataire DEVRAIT (SHOULD) utiliser le code d'erreur H3_STREAM_CREATION_ERROR ou un code d'erreur réservé (section 8.1). Le destinataire NE DOIT PAS (MUST NOT) considérer les types de flux inconnus comme une erreur de connexion de quelque nature que ce soit.

Étant donné que certains types de flux peuvent affecter l'état de la connexion, un destinataire NE DEVRAIT PAS (SHOULD NOT) rejeter les données des flux unidirectionnels entrants avant de lire le type de flux.

Les implémentations PEUVENT (MAY) envoyer des types de flux avant de savoir si le pair les prend en charge. Cependant, les types de flux qui pourraient modifier l'état ou la sémantique des composants de protocole existants, y compris QPACK ou d'autres extensions, NE DOIVENT PAS (MUST NOT) être envoyés tant que le pair n'est pas connu pour les prendre en charge.

Un expéditeur peut fermer ou réinitialiser un flux unidirectionnel sauf indication contraire. Un récepteur DOIT (MUST) tolérer la fermeture ou la réinitialisation des flux unidirectionnels avant la réception de l'en-tête de flux unidirectionnel.

6.2.1. Flux de contrôle (Control Streams)

Un flux de contrôle est indiqué par un type de flux de 0x00. Les données sur ce flux consistent en des trames HTTP/3, comme défini dans la section 7.2.

Chaque côté DOIT (MUST) initier un seul flux de contrôle au début de la connexion et envoyer sa trame SETTINGS comme première trame sur ce flux. Si la première trame du flux de contrôle est tout autre type de trame, cela DOIT (MUST) être traité comme une erreur de connexion de type H3_MISSING_SETTINGS. Un seul flux de contrôle par pair est autorisé ; la réception d'un deuxième flux prétendant être un flux de contrôle DOIT (MUST) être traitée comme une erreur de connexion de type H3_STREAM_CREATION_ERROR. L'expéditeur NE DOIT PAS (MUST NOT) fermer le flux de contrôle, et le récepteur NE DOIT PAS (MUST NOT) demander que l'expéditeur ferme le flux de contrôle. Si l'un ou l'autre flux de contrôle est fermé à tout moment, cela DOIT (MUST) être traité comme une erreur de connexion de type H3_CLOSED_CRITICAL_STREAM. Les erreurs de connexion sont décrites dans la section 8.

Parce que le contenu du flux de contrôle est utilisé pour gérer le comportement d'autres flux, les points de terminaison DEVRAIENT (SHOULD) fournir suffisamment de crédit de contrôle de flux pour empêcher le flux de contrôle du pair de devenir bloqué.

Une paire de flux unidirectionnels est utilisée plutôt qu'un seul flux bidirectionnel. Cela permet à l'un ou l'autre pair d'envoyer des données dès qu'il le peut. Selon que 0-RTT est disponible sur la connexion QUIC, le client ou le serveur peut être capable d'envoyer des données de flux en premier.

6.2.2. Flux de push (Push Streams)

Le push serveur (Server Push) est une fonctionnalité facultative introduite dans HTTP/2 qui permet à un serveur d'initier une réponse avant qu'une requête ait été faite. Voir la section 4.6 pour plus de détails.

Un flux de push est indiqué par un type de flux de 0x01, suivi de l'ID de push (Push ID) de la promesse qu'il remplit, encodé sous forme d'entier de longueur variable. Les données restantes sur ce flux consistent en des trames HTTP/3, comme défini dans la section 7.2, et remplissent un push serveur promis par zéro ou plusieurs réponses HTTP intermédiaires suivies d'une seule réponse HTTP finale, comme défini dans la section 4.1. Le push serveur et les ID de push sont décrits dans la section 4.6.

Seuls les serveurs peuvent pousser ; si un serveur reçoit un flux de push initié par le client, cela DOIT (MUST) être traité comme une erreur de connexion de type H3_STREAM_CREATION_ERROR.

Push Stream Header {
Stream Type (i) = 0x01,
Push ID (i),
}

Figure 2 : En-tête de flux de push

Un client NE DEVRAIT PAS (SHOULD NOT) abandonner la lecture d'un flux de push avant de lire l'en-tête de flux de push, car cela pourrait entraîner un désaccord entre le client et le serveur sur les ID de push qui ont déjà été consommés.

Chaque ID de push NE DOIT (MUST) être utilisé qu'une seule fois dans un en-tête de flux de push. Si un client détecte qu'un en-tête de flux de push inclut un ID de push qui a été utilisé dans un autre en-tête de flux de push, le client DOIT (MUST) traiter cela comme une erreur de connexion de type H3_ID_ERROR.

6.2.3. Types de flux réservés (Reserved Stream Types)

Les types de flux du format 0x1f * N + 0x21 pour les valeurs entières non négatives de N sont réservés pour exercer l'exigence que les types inconnus soient ignorés. Ces flux n'ont pas de sémantique, et ils peuvent être envoyés lorsque le remplissage de la couche application est souhaité. Ils PEUVENT (MAY) également être envoyés sur des connexions où aucune donnée n'est actuellement transférée. Les points de terminaison NE DOIVENT PAS (MUST NOT) considérer que ces flux ont une signification quelconque à la réception.

La charge utile et la longueur du flux sont sélectionnées de la manière que l'implémentation d'envoi choisit. Lors de l'envoi d'un type de flux réservé, l'implémentation PEUT (MAY) soit terminer le flux proprement, soit le réinitialiser. Lors de la réinitialisation du flux, soit le code d'erreur H3_NO_ERROR, soit un code d'erreur réservé (section 8.1) DEVRAIT (SHOULD) être utilisé.