webtransport

package module
v1.2.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2024 License: MIT Imports: 28 Imported by: 0

README

WebTransport

WebTransport 是什么?

WebTransport 是一个协议框架,该协议使客户端与远程服务器在安全模型下通信,并且采用安全多路复用传输技术。最新版的WebTransport草案中,该协议是基于HTTP3的,即WebTransport可天然复用QUIC和HTTP3的特性。

它有以下几种机制交换数据:

  • Client 创建一个由特殊的不限制长度的 HTTP3 frame 组成的双向流(bidirectional stream),然后转移该流的所有权给 WebTransport;
  • Server 创建一个 bidirectional stream,因为 HTTP3 没有为 Server 端创建 bidirectional stream 定义任何语义;
  • Client 和 Server 都可以创建单向流类型(unidirectional stream);
  • 通过 QUIC DATAGRAM 帧发送数据包 datagram。

QUIC 特性

  • 用户态构建: QUIC是在用户层构建的,所以不需要每次协议升级时进行内核修改。同时由于用户态可构建,QUIC的开源项目十分之多(具体可参见QUIC 开源实现列表 - 知乎 | https://zhuanlan.zhihu.com/p/270628018)。

  • 流复用和流控: QUIC引入了连接上的多路流复用的概念。QUIC通过设计实现了单独的、针对每个流的流控,解决了整个连接的队头阻塞问题。

  • 灵活的拥塞控制机制: TCP的拥塞控制机制是刚性的。该协议每次检测到拥塞时,都会将拥塞窗口大小减少一半。相比之下,QUIC的拥塞控制设计得更加灵活,可以更有效地利用可用的网络带宽,从而获得更好的吞吐量。

  • 链接迁移: 当客户端IP或端口发生变化时(这在移动端比较常见),TCP连接基于两端的ip:port四元组标示,因此会重新握手,而UDP不面向连接,不用握手。其上层的QUIC链路由于使用了64位Connection id作为唯一标识,四元组变化不影响链路的标示,也不用重新握手。

  • 更好的错误处理能力: QUIC使用增强的丢失恢复机制和转发纠错功能,以更好地处理错误数据包。该功能对于那些只能通过缓慢的无线网络访问互联网的用户来说是一个福音,因为这些网络用户在传输过程中经常出现高错误率。

  • 更快的握手: QUIC使用相同的TLS模块进行安全连接。然而,与TCP不同的是,QUIC的握手机制经过优化,避免了每次两个已知的对等者之间建立通信时的冗余协议交换,甚至可以做到0RTT握手。

  • 更灵活的传输方式: QUIC具有重传功能,可以提供可靠传输(stream),又因为基于UDP,也可提供非可靠传输(datagram)

WebTransport 特性

Webtransport 基于 QUIC 协议,其底层是 UDP。虽然是 UDP 是不可靠的传输协议,但是 QUIC 在 UDP 的基础上融合了 TCP、TLS、HTTP/2 等协议的特性,使得 QUIC 成为一种低时延、安全可靠的传输协议。可以简单理解 QUIC 把 TCP+TLS 的功能基于 UDP 重新实现了一遍。

WebTransport 提供了如下功能特性:

  • 传输可靠数据流 (类似 TCP)
  • 传输不可靠数据流(类似 UDP)
  • 数据加密和拥塞控制(congestion control)
  • 基于 Origin 的安全模型(校验请求方是否在白名单内,类似于 CORS 的Access-Control-Allow-Origin)
  • 支持多路复用(类似于 HTTP2 的 Stream)

WebTransport 与 WebSocket 的区别

WebTransport 与 WebSocket最直接的区别就是一个是基于UDP,一个是基于TCP。WebSocket基于TCP,从而也自带TCP协议本身的缺陷,比如队头阻塞。

WebSocket 是基于消息的协议,所以你不需要考虑数据分包,封装的问题。WebTransport 是基于流式的协议,在传递消息的时候需要自己再增加一层数据的封装格式,使用起来会比WebSocket略麻烦。

另外WebTransport 支持不可靠的UDP发送,这个扩宽了新的场景,这个是WebSocket所不能对比的。 相信WebTransport在成熟之后会抢占WebSocket的一部分使用场景。

WebTransport 功能列表

WebTransport over HTTP3 提供了以下功能特性:

  • 单向流 unidirectional streams
  • 双向流 bidirectional streams
  • 数据包 datagrams

以上功能均可由任意一端发起。Session ID 可用于解复用 Streams 和 Datagrams 以判断属于不同的 WebTransport session,在网络中,session IDs 使用的是 QUIC 可变长度整数方案编码的 QUIC-TRANSPORT。

浏览器WebTransport API

WebTransport 主要提供三种类型的 API

  • datagramReadabledatagramWritable,不可靠数据传输。可用于不需要保证数据发送先后顺序的场景;
  • createBidirectionalStream,双向数据流可靠传输。可用于需要保证数据发送顺序且关心返回结果的场景;
  • createUnidirectionalStream,单向数据流可靠传输。可用于需要保证数据发送顺序,但是不关心返回值的场景。

感谢

代码基于https://github.com/marten-seemann/webtransport-go改造而来。

参考资料

Documentation

Index

Constants

View Source
const WebTransportBufferedStreamRejectedErrorCode quic.StreamErrorCode = 0x3994bd84

WebTransportBufferedStreamRejectedErrorCode is the error code of the H3_WEBTRANSPORT_BUFFERED_STREAM_REJECTED error.

Variables

This section is empty.

Functions

func NewCertPool

func NewCertPool(caFile string) (*x509.CertPool, error)

func NewTlsConfig

func NewTlsConfig(keyFile, certFile, caFile string) *tls.Config

Types

type Any

type Any interface{}

type Binder

type Binder func() Any

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(opts ...ClientOption) *Client

func (*Client) Connect

func (c *Client) Connect() error

func (*Client) DeregisterMessageHandler

func (c *Client) DeregisterMessageHandler(messageType MessageType)

func (*Client) Disconnect

func (c *Client) Disconnect() error

func (*Client) RegisterMessageHandler

func (c *Client) RegisterMessageHandler(messageType MessageType, handler ClientMessageHandler, binder Binder)

func (*Client) SendMessage

func (c *Client) SendMessage(messageType int, message interface{}) error

func (*Client) SendRawData

func (c *Client) SendRawData(data []byte) error

type ClientHandlerData

type ClientHandlerData struct {
	Handler ClientMessageHandler
	Binder  Binder
}

type ClientMessageHandler

type ClientMessageHandler func(MessagePayload) error

type ClientMessageHandlerMap

type ClientMessageHandlerMap map[MessageType]ClientHandlerData

type ClientOption

type ClientOption func(*Client)

func WithClientCodec

func WithClientCodec(c string) ClientOption

func WithClientKeepAlivePeriod

func WithClientKeepAlivePeriod(timeout time.Duration) ClientOption

func WithClientMaxIdleTimeout

func WithClientMaxIdleTimeout(timeout time.Duration) ClientOption

func WithClientTLSConfig

func WithClientTLSConfig(c *tls.Config) ClientOption

func WithEndpoint

func WithEndpoint(url string) ClientOption

type ConnectHandler

type ConnectHandler func(SessionID, bool)

type ConnectionError

type ConnectionError struct {
	Remote  bool
	Message string
}

ConnectionError is a WebTransport connection error.

func (*ConnectionError) Error

func (e *ConnectionError) Error() string

type ErrorCode

type ErrorCode uint8

type HandlerData

type HandlerData struct {
	Handler MessageHandler
	Binder  Binder
}

type Message

type Message struct {
	Type MessageType
	Body []byte
}

func (*Message) Marshal

func (m *Message) Marshal() ([]byte, error)

func (*Message) Unmarshal

func (m *Message) Unmarshal(buf []byte) error

type MessageHandler

type MessageHandler func(SessionID, MessagePayload) error

type MessageHandlerMap

type MessageHandlerMap map[MessageType]HandlerData

type MessagePayload

type MessagePayload Any

type MessageType

type MessageType uint32

type ReceiveStream

type ReceiveStream interface {
	io.Reader
	CancelRead(ErrorCode)

	SetReadDeadline(time.Time) error
}

type SendStream

type SendStream interface {
	io.Writer
	io.Closer

	CancelWrite(ErrorCode)

	SetWriteDeadline(time.Time) error
}

type Server

type Server struct {
	*http3.Server
	// contains filtered or unexported fields
}

func NewServer

func NewServer(opts ...ServerOption) *Server

func (*Server) DeregisterMessageHandler

func (s *Server) DeregisterMessageHandler(messageType MessageType)

func (*Server) Endpoint

func (s *Server) Endpoint() (*url.URL, error)

func (*Server) RegisterMessageHandler

func (s *Server) RegisterMessageHandler(messageType MessageType, handler MessageHandler, binder Binder)

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

type ServerOption

type ServerOption func(*Server)

func WithAddress

func WithAddress(addr string) ServerOption

func WithCodec

func WithCodec(c string) ServerOption

func WithConnectHandle

func WithConnectHandle(h ConnectHandler) ServerOption

func WithKeepAlivePeriod

func WithKeepAlivePeriod(timeout time.Duration) ServerOption

func WithMaxIdleTimeout

func WithMaxIdleTimeout(timeout time.Duration) ServerOption

func WithPath

func WithPath(path string) ServerOption

func WithTLSConfig

func WithTLSConfig(c *tls.Config) ServerOption

func WithTimeout

func WithTimeout(timeout time.Duration) ServerOption

type Session

type Session struct {
	// contains filtered or unexported fields
}

func (*Session) AcceptStream

func (c *Session) AcceptStream(ctx context.Context) (Stream, error)

func (*Session) AcceptUniStream

func (c *Session) AcceptUniStream(ctx context.Context) (ReceiveStream, error)

func (*Session) Close

func (c *Session) Close() error

func (*Session) Context

func (c *Session) Context() context.Context

Context returns a context that is closed when the session is closed.

func (*Session) LocalAddr

func (c *Session) LocalAddr() net.Addr

func (*Session) OpenStream

func (c *Session) OpenStream() (Stream, error)

func (*Session) OpenStreamSync

func (c *Session) OpenStreamSync(ctx context.Context) (stream Stream, err error)

func (*Session) OpenUniStream

func (c *Session) OpenUniStream() (SendStream, error)

func (*Session) OpenUniStreamSync

func (c *Session) OpenUniStreamSync(ctx context.Context) (stream SendStream, err error)

func (*Session) RemoteAddr

func (c *Session) RemoteAddr() net.Addr

func (*Session) SessionID

func (c *Session) SessionID() SessionID

type SessionID

type SessionID uint64

SessionID is the WebTransport Session ID

type Stream

type Stream interface {
	SendStream
	ReceiveStream

	SetDeadline(time.Time) error
}

type StreamError

type StreamError struct {
	ErrorCode ErrorCode
}

StreamError is the error that is returned from qStream operations (Read, Write) when the qStream is canceled.

func (*StreamError) Error

func (e *StreamError) Error() string

func (*StreamError) Is

func (e *StreamError) Is(target error) bool

type Upgrader

type Upgrader struct {
	CheckOrigin func(r *http.Request) bool
}

func (*Upgrader) Upgrade

func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (http3.HTTPStreamer, error)

Directories

Path Synopsis
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL