ws

package
v1.2.0-alpha.1 Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2022 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package ws implements websocket handshake.

Reference

websocket rfc: https://datatracker.ietf.org/doc/html/rfc6455/

下面把一个握手放在这里作为参考

请求 GET /chat HTTP/1.1

Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

响应 HTTP/1.1 101 Switching Protocols

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

总之,一个websocket的请求头直接就是一个 合法的http请求头,所以也没必要额外包一个http连接, 直接使用tcp/tls 连接即可。

websocket 库比较 https://yalantis.com/blog/how-to-build-websockets-in-go/

中文翻译: https://tonybai.com/2019/09/28/how-to-build-websockets-in-go/

总之 gobwas/ws 是最好的库. 本包使用 gobwas/ws

Index

Constants

View Source
const MaxEarlyDataLen_Base64 = 2732

2048 /3 = 682.6666 , 683 * 4 = 2732, 若你不信,运行 we_test.go中的 TestBase64Len

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

implements advLayer.Client

func NewClient

func NewClient(hostAddr, path string, headers map[string][]string, isEarly bool) (*Client, error)

这里默认,传入的path必须 以 "/" 为前缀. 本函数 不对此进行任何检查

func (*Client) GetPath

func (c *Client) GetPath() string

func (*Client) Handshake

func (c *Client) Handshake(underlay net.Conn, ed []byte) (net.Conn, error)

与服务端进行 websocket握手,并返回可直接用于读写 websocket 二进制数据的 net.Conn

func (*Client) IsEarly

func (c *Client) IsEarly() bool

func (*Client) IsMux

func (c *Client) IsMux() bool

func (*Client) IsSuper

func (c *Client) IsSuper() bool

type Conn

type Conn struct {
	net.Conn
	// contains filtered or unexported fields
}

实现 net.Conn, io.ReaderFrom, utils.MultiWriter, netLayer.Splicer 因为 gobwas/ws 不包装conn,在写入和读取二进制时需要使用 较为底层的函数才行,并未被提供标准的Read和Write 因此我们包装一下,统一使用Read和Write函数 来读写 二进制数据。因为我们这里是代理, 所以我们默认 抛弃 websocket的 数据帧 长度。 如果以后考虑与 vless v1的 udp 相结合的话,则数据包长度 不能丢弃,需要使用另外的实现。

func (*Conn) CanSplice

func (c *Conn) CanSplice() (r bool, conn net.Conn)

func (*Conn) EverPossibleToSplice

func (c *Conn) EverPossibleToSplice() bool

func (*Conn) Read

func (c *Conn) Read(p []byte) (int, error)

Read websocket binary frames

func (*Conn) ReadFrom

func (c *Conn) ReadFrom(r io.Reader) (written int64, err error)

func (*Conn) Write

func (c *Conn) Write(p []byte) (n int, e error)

Write websocket binary frames

func (*Conn) WriteBuffers

func (c *Conn) WriteBuffers(buffers [][]byte) (int64, error)

实现 utils.MultiWriter 主要是针对一串数据的情况,如果底层连接可以用writev, 此时我们不要每一小段都包包头 然后写N次, 而是只在最前面包数据头,然后即可用writev 一次发送出去 比如从 socks5 读数据,写入 tcp +ws + vless 协议, 就是这种情况 若底层是tls,那我们也合并再发出,这样能少些很多头部,也能减少Write次数

type Creator

type Creator struct{}

func (Creator) GetDefaultAlpn

func (Creator) GetDefaultAlpn() (alpn string, mustUse bool)

func (Creator) NewClientFromConf

func (Creator) NewClientFromConf(conf *advLayer.Conf) (advLayer.Client, error)

func (Creator) NewServerFromConf

func (Creator) NewServerFromConf(conf *advLayer.Conf) (advLayer.Server, error)

func (Creator) PackageID

func (Creator) PackageID() string

type EarlyDataConn

type EarlyDataConn struct {
	net.Conn
	// contains filtered or unexported fields
}

func (*EarlyDataConn) Read

func (edc *EarlyDataConn) Read(p []byte) (int, error)

func (*EarlyDataConn) Write

func (edc *EarlyDataConn) Write(p []byte) (int, error)

第一次会获取到 内部的包头, 然后我们在这里才开始执行ws的握手 这是verysimple的架构造成的. ws层后面跟着的应该就是代理层 的 Handshake调用,它会写入一次包头 我们就是利用这个特征, 把vless包头 和 之前给出的earlydata绑在一起,进行base64编码然后进行ws握手

type Server

type Server struct {
	//upgrader     *ws.Upgrader
	UseEarlyData bool
	Thepath      string
	// contains filtered or unexported fields
}

func NewServer

func NewServer(path string, headers map[string][]string, UseEarlyData bool) *Server

这里默认: 传入的path必须 以 "/" 为前缀. 本函数 不对此进行任何检查.

func (*Server) GetPath

func (s *Server) GetPath() string

func (*Server) Handshake

func (s *Server) Handshake(optionalFirstBuffer *bytes.Buffer, underlay net.Conn) (net.Conn, error)

Handshake 用于 websocket的 Server 监听端,建立握手. 用到了 gobwas/ws.Upgrader.

返回可直接用于读写 websocket 二进制数据的 net.Conn

func (*Server) IsMux

func (*Server) IsMux() bool

func (*Server) IsSuper

func (*Server) IsSuper() bool

func (*Server) Stop

func (*Server) Stop()

Jump to

Keyboard shortcuts

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