0%

webtransport_http3_quic_format

webtransport和quic,http3的封装简单总结:

webTransport:

webtransport 是啥

This specification uses [WEB-TRANSPORT-HTTP3] to send data to and receive data from servers. It can be used like WebSockets but with support for multiple streams, unidirectional streams, out-of-order delivery, and reliable as well as unreliable transport.
(注意:本规范中提出的 API 代表了一个基于 IETF WEBTRANS WG 正在进行的工作的初步提案。由于 [WEB-TRANSPORT-HTTP3] 规范正在进行中,因此协议和 API 都可能在未来发生重大变化。)
根据这个描述,是使用这个web-transport-http3去发送数据到服务器或从服务器接收数据。 可以像webSocket但比较高级点。
所以是web<->server ,web端的话,基于chrome或浏览器就需要用js写,而且chrome自带了quic等。而server端就需要实现或使用webtransport框架?

WebTransport 会话是基于 HTTP/3 的 WebTransport 会话。启用池时,一个连接上可能有多个 WebTransport 会话。
A WebTransport session is a session of WebTransport over HTTP/3. There may be multiple WebTransport sessions on one connection, when pooling is enabled.
webTransport session有以下的能力:WebTransport session has the following capabilities defined in [WEB-TRANSPORT-HTTP3].
capability definition
send a datagram [WEB-TRANSPORT-HTTP3] section 4.4
receive a datagram [WEB-TRANSPORT-HTTP3] section 4.4
create an outgoing unidirectional stream [WEB-TRANSPORT-HTTP3] section 4.1
create a bidirectional stream [WEB-TRANSPORT-HTTP3] section 4.2
receive an incoming unidirectional stream [WEB-TRANSPORT-HTTP3] section 4.1
receive a bidirectional stream [WEB-TRANSPORT-HTTP3] section 4.2
https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3/#section-3.3

ref:https://www.w3.org/TR/webtransport/#introduction

3. Session Establishment
  • 3.1. Establishing a Transport-Capable HTTP/3 Connection

    In order to indicate support for WebTransport, both the client and
    the server MUST send a SETTINGS_ENABLE_WEBTRANSPORT value set to “1”
    in their SETTINGS frame. The SETTINGS_ENABLE_WEBTRANSPORT parameter
    value SHALL be either “0” or “1”, with “0” being the default; an
    endpoint that receives a value other than “0” or “1” MUST close the
    connection with the H3_SETTINGS_ERROR error code.
    为了提示支持webTransport, 包括client和server 必须发送一个SETTING frame包含了这个值SETTINGS_ENABLE_WEBTRANSPORT value set to “1”

0是默认的,节点收到的值如果不是0/1则需要关闭连接携带H3_SETTINGS_ERROR error code.
The client MUST NOT send a WebTransport request until it has received
the setting indicating WebTransport support from the server.
Similarly, the server MUST NOT process any incoming WebTransport
requests until the client settings have been received, as the client
may be using a version of WebTransport extension that is different
from the one used by the server.
client 必须不能发送一个webTransport请求直到它有接收到webtransport支持的设置从服务端。
相似的,server不能处理任何到来的webtransport的请求直到client设置被收到。因为client可能会使用和服务端的webtransport扩展不同的版本。

  • 3.2. Extended CONNECT in HTTP/3

  • 3.3. Creating a New Session 创建一个新的session

    As WebTransport sessions are established over HTTP/3, they are
    identified using the https URI scheme [RFC7230].
    使用http uri来标识。

    In order to create a new WebTransport session, a client can send an
    HTTP CONNECT request.
    The :protocol pseudo-header field ([RFC8441])
    MUST be set to webtransport. The :scheme field MUST be https. Both
    the :authority and the :path value MUST be set; those fields indicate
    the desired WebTransport server. An Origin header [RFC6454] MUST be
    provided within the request.
    要创建一个新的webtransport session,client㤇发送 http connect 请求。

请求的相关uri等:

Upon receiving an extended CONNECT request with a :protocol field set
to webtransport, the HTTP/3 server can check if it has a WebTransport
server associated with the specified :authority and :path values. If
it does not, it SHOULD reply with status code 404 (Section 6.5.4,
[RFC7231]). If it does, it MAY accept the session by replying with a
2xx series status code, as defined in Section 15.3 of [SEMANTICS].

The WebTransport server MUST verify the Origin header to ensure that
the specified origin is allowed to access the server in question.
服务端行为:接收到connect request后,要检查是否有管理的服务,路径,没有则返回404,有则返回2xx.
From the client’s perspective, a WebTransport session is established
when the client receives a 2xx response. 从客户端的角度看,一个webTransportsession被建立当client收到2xx恢复。
From the server’s
perspective, a session is established once it sends a 2xx response.
WebTransport over HTTP/3 does not support 0-RTT. 从服务端的角度看,一个session被建立了一旦它发送了2xx回复,webtransport不支持0-rtt

The webtransport HTTP Upgrade Token uses the Capsule Protocol as
defined in [HTTP-DATAGRAM]. webtransport http更新token使用 Capsule Protocol 定义在。。

session建立后;
WebTransport Features:
WebTransport over HTTP/3 provides the following features described in
[OVERVIEW]: unidirectional streams, bidirectional streams and
datagrams, initiated by either endpoint.
Session IDs are used to demultiplex streams and datagrams belonging
to different WebTransport sessions. On the wire, session IDs are
encoded using the QUIC variable length integer scheme described in
[RFC9000].
If at any point a session ID is received that cannot a valid ID for a
client-initiated bidirectional stream, the recepient MUST close the
connection with an H3_ID_ERROR error code.

发送/接收数据报:

4.4. Datagrams

Datagrams can be sent using HTTP Datagrams, using the WEB_TRANSPORT
HTTP Datagram Format Type (see value in Section 8.6). When using the
WEB_TRANSPORT HTTP Datagram Format Type, the WebTransport datagram
payload is sent unmodified in the “HTTP Datagram Payload” field of an
HTTP Datagram. When sending a registration capsule using the
“Datagram Format Type” set to WEB_TRANSPORT, the “Datagram Format
Additional Data” field SHALL be empty.

In QUIC, a datagram frame can span at most one packet. Because of
that, the applications have to know the maximum size of the datagram
they can send. However, when proxying the datagrams, the hop-by-hop
MTUs can vary. TODO: Describe how the path MTU can be computed,
specifically propagation across HTTP proxies.
可以使用 HTTP 数据报发送数据报,使用 WEB_TRANSPORT
HTTP 数据报格式类型(参见第 8.6 节中的值)。使用时
WEB_TRANSPORT HTTP 数据报格式类型,WebTransport 数据报
负载在“HTTP 数据报负载”字段中未经修改地发送
HTTP 数据报。当使用
“Datagram Format Type”设置为WEB_TRANSPORT,即“Datagram Format
附加数据”字段应为空。

在 QUIC 中,一个数据报帧最多可以跨越一个数据包。因为
也就是说,应用程序必须知道数据报他们可以发送的最大大小
。然而,当代理数据报时,逐跳
MTU 可能会有所不同。 TODO:描述如何计算路径 MTU,
特别是跨 HTTP 代理的传播。

创建一个传出的单向流/接收一个传入的单向流:

4.1. Unidirectional streams

Once established, both endpoints can open unidirectional streams.
The HTTP/3 unidirectional stream type SHALL be 0x54. The body of the
stream SHALL be the stream type, followed by the session ID, encoded
as a variable-length integer, followed by the user-specified stream
data (Figure 1).

1
2
3
4
5
6
7
8
9
10
11
12
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x54 (i) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Session ID (i) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream Body ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 1: Unidirectional WebTransport stream format

创建一个双向流/接收一个双向流。

4.2:

WebTransport endpoints can initiate bidirectional streams by opening
an HTTP/3 bidirectional stream and sending an HTTP/3 frame with type
WEBTRANSPORT_STREAM (type=0x41). The format of the frame SHALL be
the frame type, followed by the session ID, encoded as a variable-
length integer, followed by the user-specified stream data
(Figure 2). The frame SHALL last until the end of the stream.

1
2
3
4
5
6
7
8
9
10
11

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x41 (i) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Session ID (i) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream Body ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 2: WEBTRANSPORT_STREAM frame format

HTTP/3 does not by itself define any semantics for server-initiated
bidirectional streams. If WebTransport setting is negotiated by both
endpoints, the syntax of the server-initiated bidirectional streams
SHALL be the same as the syntax of client-initated bidirectional
streams, that is, a sequence of HTTP/3 frames. The only frame
defined by this document for use within server-initiated
bidirectional streams is WEBTRANSPORT_STREAM.

TODO: move the paragraph above into a separate draft; define what
happens with already existing HTTP/3 frames on server-initiated
bidirectional streams

4.3. Resetting Data Streams
4.5.缓冲传入的流和数据报 Buffering Incoming Streams and Datagrams

因为报文的无序性,所以可能数据先到,到的时候还没建立session,此时需要缓存起来等session resp,当然,缓存大小也是有限制大小的。
session终止:
To terminate a WebTransport session session with an optional integer code and an optional byte sequence reason, follow [WEB-TRANSPORT-HTTP3] section 5. 以下两个情况会关session:

  • the CONNECT stream is closed, either cleanly or abruptly, on
    either side; or

    • a CLOSE_WEBTRANSPORT_SESSION capsule is either sent or received.
      A WebTransport session session is terminated, with optionally an integer code and a byte sequence reason,

when the HTTP/3 stream associated with the CONNECT request that initiated session is closed by the server,
as described at [WEB-TRANSPORT-HTTP3] section 5.

webTransport流的概念:

WebTransport stream is a concept for HTTP/3 stream on a WebTransport session. 流是基于session的

A WebTransport stream is one of incoming unidirectional, outgoing unidirectional or bidirectional. 流有这些类型。

WebTransport stream has the following capabilities:
capability definition incoming unidirectional outgoing unidirectional bidirectional
send bytes (potentially with FIN) [QUIC] section 2.2 No Yes Yes
receive bytes (potentially with FIN) [QUIC] section 2.2 Yes No Yes
send STOP_SENDING [QUIC] section 3.5 Yes No Yes
reset a WebTransport stream [QUIC] section 19.4 No Yes Yes

WebTransport stream has the following signals:

event definition incoming unidirectional outgoing unidirectional bidirectional
STOP_SENDING [QUIC] section 3.5 No Yes Yes
reset [QUIC] section 19.4 Yes No Yes

相关接口:

1) WebTransportDatagramDuplexStream(网络传输数据报双工流) 接口
5.1. Internal slots
A WebTransportDatagramDuplexStream object has the following internal slots.
2) webTransport Interface

http3,quic 封装:

ref: https://www.taohui.tech/2021/02/04/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/%E6%B7%B1%E5%85%A5%E5%89%96%E6%9E%90HTTP3%E5%8D%8F%E8%AE%AE/

  • 一个udp连接:
  • 一个udp载荷:可以放多个quic pkt。 一个quic pkt可以放多个FRAME(多种FRAME),对于一个http_conn来说,可以等同于一个quic conn==一个udp conn
  • quic的以下类型的pkt不能带帧(frame)其他可以:
    这几个类型的,不能携带帧。其他可以
    Version Negotiation, Stateless Reset, and Retry packets do not contain frames.
  • 关系:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    quic pkt : long header pkt / short header pkt (long header pkt:Initial/0-RTT/Handshake/Retry, short header pkt:1-RTT)
    quic frame (type ...) : ACK Frame / Crypto Frame/ Stream Frame / PING Frame.. (0x08 – 0x0f范围是Stream Frame)
    http3: 基于quic frame中的Stream Frame: 其中streamid代表 流id,data字段为http frame的载荷,载荷中的type字段表明这种frame下面的载荷类型:
    streamid可以用来识别是单向还是双向;
    这里的stream frame即是放流的。
    type字段:
    0x00:DATA帧,用于传输HTTP Body包体;
    0x01:HEADERS帧,通过QPACK 编码,传输HTTP Header头部;
    0x03:CANCEL_PUSH控制帧,用于取消1次服务器推送消息,通常客户端在收到PUSH_PROMISE帧后,通过它告知服务器不需要这次推送;
    0x04:SETTINGS控制帧,设置各类通讯参数;
    0x05:PUSH_PROMISE帧,用于服务器推送HTTP Body前,先将HTTP Header头部发给客户端,流程与HTTP2相似;
    0x07:GOAWAY控制帧,用于关闭连接(注意,不是关闭Stream);
    0x0d:MAX_PUSH_ID,客户端用来限制服务器推送消息数量的控制帧。
    0x41/0x54用于webtransport

    例如webrtc中的webtransport:
    net/third_party/quiche/src/quiche/quic/core/http/http_frames.h
    enum class HttpFrameType {
    DATA = 0x0,
    HEADERS = 0x1,
    CANCEL_PUSH = 0X3,
    SETTINGS = 0x4,
    PUSH_PROMISE = 0x5,
    GOAWAY = 0x7,
    MAX_PUSH_ID = 0xD,
    // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02
    ACCEPT_CH = 0x89,
    // https://tools.ietf.org/html/draft-ietf-httpbis-priority-03
    PRIORITY_UPDATE_REQUEST_STREAM = 0xF0700,
    // https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html
    WEBTRANSPORT_STREAM = 0x41,
    };
    net/third_party/quiche/src/quiche/quic/core/http/http_encoder.cc
    QuicByteCount HttpEncoder::SerializeWebTransportStreamFrameHeader(
    WebTransportSessionId session_id, std::unique_ptr<char[]>* output) {
    uint64_t stream_type =
    static_cast<uint64_t>(HttpFrameType::WEBTRANSPORT_STREAM);
    QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(stream_type) +
    QuicDataWriter::GetVarInt62Len(session_id);

    *output = std::make_unique<char[]>(header_length);
    QuicDataWriter writer(header_length, output->get());
    bool success =
    writer.WriteVarInt62(stream_type) && writer.WriteVarInt62(session_id);
    if (success && writer.remaining() == 0) {
    return header_length;
    }

    QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
    "WEBTRANSPORT_STREAM frame header.";
    return 0;
    }

因为是在Stream Frame上做更多的封装,所以解释下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*关于 0x08-0x0f是Stream Frame的解释)
STREAM Frame {
Type (i) = 0x08..0x0f,
Stream ID (i),
[Offset (i)],
[Length (i)],
Stream Data (..),
}
Figure 32: STREAM Frame Format
STREAM frames implicitly create a stream and carry stream data.
The Type field in the STREAM frame takes the form 0b00001XXX (or the set of values from 0x08 to 0x0f).
The three low-order bits of the frame type determine the fields that are present in the frame:
STREAM 帧隐式创建流并携带流数据。
STREAM 帧中的类型字段采用 0b00001XXX 的形式(或从 0x08 到 0x0f 的一组值)。
帧类型的三个低位确定帧中存在的字段:

* The OFF bit (0x04) in the frame type is set to indicate that there is an Offset field present.
When set to 1, the Offset field is present.
When set to 0, the Offset field is absent and the Stream Data starts at an offset of 0 (that is, the frame contains the first bytes of the stream, or the end of a stream that includes no data).
* 帧类型中的 OFF 位 (0x04) 设置为指示存在偏移字段。
设置为 1 时,存在偏移字段。
当设置为 0 时,偏移字段不存在并且流数据从偏移量 0 开始(即,帧包含流的第一个字节,或不包含数据的流的结尾)。

* The LEN bit (0x02) in the frame type is set to indicate that there is a Length field present.
If this bit is set to 0, the Length field is absent and the Stream Data field extends to the end of the packet.
If this bit is set to 1, the Length field is present.
* 帧类型中的 LEN 位 (0x02) 设置为指示存在长度字段。
如果该位设置为 0,则长度字段不存在,流数据字段延伸到数据包的末尾。
如果该位设置为 1,则存在长度字段。

* The FIN bit (0x01) indicates that the frame marks the end of the stream.
The final size of the stream is the sum of the offset and the length of this frame.
* FIN 位(0x01)表示该帧标志着流的结束。
流的最终大小是偏移量和该帧长度的总和。

An endpoint MUST terminate the connection with error STREAM_STATE_ERROR if it receives a STREAM frame for a locally initiated stream that has not yet been created, or for a send-only stream.
如果端点接收到一个尚未创建的本地启动流或仅发送流的 STREAM 帧,则端点必须以错误 STREAM_STATE_ERROR 终止连接。

而Stream Data (..) 放的是什么? 看下http3的rfc:
先看看双向流和单向流的不同:
双向流不变,单向流要支持更多的功能,所以:在Stream Data前多了一个字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Unidirectional Stream Header {     Stream Type (i),   }
Figure 1: Unidirectional Stream Header
Stream Type的取值:
https://datatracker.ietf.org/doc/html/draft-ietf-quic-http#section-6.2.1
0x00:控制Stream,传递各类Stream控制消息;
0x01:服务器推送消息;
0x02:用于编码QPACK动态表,比如面对不属于静态表的HTTP请求头部,客户端可以通过这个Stream发送动态表编码;
0x03:用于通知编码端QPACK动态表的更新结果。
其他:https://datatracker.ietf.org/doc/html/draft-ietf-quic-http#section-6.2
Two stream types are defined in this document: control streams
(Section 6.2.1) and push streams (Section 6.2.2). [QPACK] defines
two additional stream types. Other stream types can be defined by
extensions to HTTP/3; see Section 9 for more details. Some stream
types are reserved (Section 6.2.3).

详细见rfc 6.1,6.2.

接下来是StreamData的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
7.1.  Frame Layout

All frames have the following format:
HTTP/3 Frame Format {
Type (i),
Length (i),
Frame Payload (..),
}
Figure 3: HTTP/3 Frame Format
A frame includes the following fields:
Type: A variable-length integer that identifies the frame type.

Length: A variable-length integer that describes the length in bytes of the Frame Payload.

Frame Payload: A payload, the semantics of which are determined by the Type field.
一个帧包括以下字段:
类型:标识帧类型的可变长度整数。

长度:一个可变长度整数,描述帧有效负载的字节长度。

Frame Payload:有效载荷,其语义由 Type 字段确定。