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 | 0 1 2 3 |
创建一个双向流/接收一个双向流。
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 |
|
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,
- a CLOSE_WEBTRANSPORT_SESSION capsule is either sent or received.
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 封装:
- 一个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
53quic 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 | /*关于 0x08-0x0f是Stream Frame的解释) |
而Stream Data (..) 放的是什么? 看下http3的rfc:
先看看双向流和单向流的不同:
双向流不变,单向流要支持更多的功能,所以:在Stream Data前多了一个字段:
1 | Unidirectional Stream Header { Stream Type (i), } |
详细见rfc 6.1,6.2.
接下来是StreamData的内容:
1 | 7.1. Frame Layout |