ws

package
v1.2.5 Latest Latest
Warning

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

Go to latest
Published: Dec 28, 2022 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package ws implements websocket for advLayer.

Reference

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

Below is a real websocket handshake progress:

Request

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

Response

HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    Sec-WebSocket-Protocol: chat

websocket packages comparison: https://yalantis.com/blog/how-to-build-websockets-in-go/

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

All in all gobwas/ws is the best package. We use gobwas/ws.

gobwas包只支持http1.1, 所以如果使用nginx前置,确保 proxy_http_version 1.1;

Index

Constants

View Source
const MaxEarlyDataLen = 2048
View Source
const MaxEarlyDataLen_Base64 = 2732

2048 /3 = 682.6666... (682 又 三分之二), 683 * 4 = 2732, 你若不信,运行 we_test.go中的 TestBase64Len

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	Creator

	UseEarlyData bool
	// contains filtered or unexported fields
}

implements advLayer.SingleClient

func NewClient

func NewClient(hostAddr, path string, headers *httpLayer.HeaderPreset, isEarly bool) (*Client, error)

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

func (*Client) GetCreator added in v1.2.0

func (*Client) GetCreator() advLayer.Creator

func (*Client) GetPath

func (c *Client) GetPath() string

func (*Client) Handshake

func (c *Client) Handshake(underlay net.Conn, firstPayloadLen int) (net.Conn, error)

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

func (*Client) IsEarly

func (c *Client) IsEarly() 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函数 来读写 二进制数据。因为我们这里是代理,

func (*Conn) CanSpliceWrite added in v1.2.5

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

func (*Conn) EverPossibleToSpliceWrite added in v1.2.5

func (c *Conn) EverPossibleToSpliceWrite() 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) RemoteAddr added in v1.2.4

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

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) CanHandleHeaders added in v1.2.0

func (Creator) CanHandleHeaders() bool

func (Creator) GetDefaultAlpn

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

func (Creator) IsMux added in v1.2.0

func (Creator) IsMux() bool

func (Creator) IsSuper added in v1.2.0

func (Creator) IsSuper() 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

func (Creator) ProtocolName added in v1.2.0

func (Creator) ProtocolName() 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 {
	Creator
	UseEarlyData   bool
	Thepath        string
	RequestHeaders map[string][]string
	// contains filtered or unexported fields
}

implements advLayer.SingleServer

func NewServer

func NewServer(path string, headers *httpLayer.HeaderPreset, UseEarlyData bool) *Server

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

func (*Server) GetCreator added in v1.2.0

func (*Server) GetCreator() advLayer.Creator

func (*Server) GetPath

func (s *Server) GetPath() string

func (*Server) Handshake

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

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

返回可直接用于读写 websocket 二进制数据的 net.Conn. 如果遇到不符合的http1.1请求,会返回 httpLayer.FallbackMeta 和 httpLayer.ErrShouldFallback

func (*Server) Stop

func (*Server) Stop()

Jump to

Keyboard shortcuts

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