fastws

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jan 2, 2020 License: MIT Imports: 18 Imported by: 3

README

Fastws

Websocket library for fasthttp.

See examples to see how to use it.

Why another websocket package?

Other websocket packages does not allow concurrent Read/Write operations and does not provide low level access to websocket packet crafting.

Following the fasthttp philosophy this library tries to avoid extra-allocations while providing concurrent access to Read/Write operations and stable API to be used in production allowing low level access to the websocket frames.

How it works? (Server)

Okay. It's easy. You have an Upgrader which is used to upgrade your connection. You must specify the Handler to handle the request.

If you just want a websocket connection and don't want to be a websocket expert you can just use Upgrade function parsing the handler.

func main() {
  fasthttp.ListenAndServe(":8080", fastws.Upgrade(wsHandler))
}

func wsHandler(conn *Conn) {
  fmt.Fprintf(conn, "Hello world")
}

After this point you can handle your awesome websocket connection. The connection is automatically closed by fastws when you exit your handler but you can close your connection if you wanna send close message to the peer.

If you want low level usage of the library your can use Frame structure to handle frame by frame in a websocket connection. Also you can use Conn.ReadFrame or Conn.NextFrame to read frame by frame from your connection peer.

func main() {
  fasthttp.ListenAndServe(":8080", fastws.Upgrade(wsHandler))
}

func wsHandler(conn *Conn) {
  fmt.Fprintf(conn, "Hello world")

  fr, err := conn.NextFrame()
  if err != nil {
    panic(err)
  }

  fmt.Printf("Received: %s\n", fr.Payload())

  ReleaseFrame(fr)
}

All of this functions are safe-concurrent. Ready to be used from different goroutines.

How it works? (Client)

Just call Dial.

conn, err := fastws.Dial("ws://localhost:8080/ws")
if err != nil {
  fmt.Println(err)
}
conn.WriteString("Hello")

fastws vs gorilla.

Features fastws Gorilla
Concurrent R/W Yes No
Passes Autobahn Test Suite On development Yes
Receive fragmented message Yes Yes
Send close message Yes Yes
Send pings and receive pongs Yes Yes
Get the type of a received data message Yes Yes
Compression Extensions On development Experimental
Read message using io.Reader Non planned Yes
Write message using io.WriteCloser Non planned Yes

Benchmarks

Fastws:

$ go test -v -bench=Fast -benchmem -benchtime=10s
Benchmark1000FastClientsPer10Messages-2         50000000               317 ns/op               0 B/op          0 allocs/op
Benchmark1000FastClientsPer100Messages-2        500000000               36.7 ns/op             0 B/op          0 allocs/op
Benchmark1000FastClientsPer1000Messages-2       5000000000               3.63 ns/op            0 B/op          0 allocs/op
Benchmark100FastMsgsPerConn-2                   500000000               38.2 ns/op             0 B/op          0 allocs/op
Benchmark1000FastMsgsPerConn-2                  5000000000               3.67 ns/op            0 B/op          0 allocs/op
Benchmark10000FastMsgsPerConn-2                 10000000000              0.47 ns/op            0 B/op          0 allocs/op
Benchmark100000FastMsgsPerConn-2                10000000000              0.03 ns/op            0 B/op          0 allocs/op

Gorilla:

$ go test -v -bench=Gorilla -benchmem -benchtime=10s
Benchmark1000GorillaClientsPer10Messages-2      20000000               813 ns/op              86 B/op          1 allocs/op
Benchmark1000GorillaClientsPer100Messages-2     200000000               75.4 ns/op             8 B/op          0 allocs/op
Benchmark1000GorillaClientsPer1000Messages-2    2000000000               7.54 ns/op            0 B/op          0 allocs/op
Benchmark100GorillaMsgsPerConn-2                200000000               85.0 ns/op             8 B/op          0 allocs/op
Benchmark1000GorillaMsgsPerConn-2               2000000000               8.12 ns/op            0 B/op          0 allocs/op
Benchmark10000GorillaMsgsPerConn-2              10000000000              0.84 ns/op            0 B/op          0 allocs/op
Benchmark100000GorillaMsgsPerConn-2             10000000000              0.08 ns/op            0 B/op          0 allocs/op

Documentation

Index

Constants

View Source
const (
	StatusNone              StatusCode = 1000
	StatusGoAway                       = 1001
	StatusProtocolError                = 1002
	StatusNotAcceptable                = 1003
	StatusReserved                     = 1004
	StatusNotConsistent                = 1007
	StatusViolation                    = 1008
	StatusTooBig                       = 1009
	StatuseExtensionsNeeded            = 1010
	StatusUnexpected                   = 1011
)

Variables

View Source
var (
	EOF = io.EOF
)
View Source
var (
	ErrCannotUpgrade = errors.New("cannot upgrade connection")
)

Functions

func ReleaseFrame

func ReleaseFrame(fr *Frame)

ReleaseFrame puts fr Frame into the pool.

func Upgrade

func Upgrade(handler RequestHandler) func(ctx *fasthttp.RequestCtx)

Upgrade returns a RequestHandler for fasthttp resuming upgrading process.

Types

type Code

type Code uint8

Code to send.

const (
	CodeContinuation Code = 0x0
	CodeText         Code = 0x1
	CodeBinary       Code = 0x2
	CodeClose        Code = 0x8
	CodePing         Code = 0x9
	CodePong         Code = 0xA
)

type Conn

type Conn struct {

	// Mode indicates Write default mode.
	Mode Mode

	// MaxPayloadSize prevents huge memory allocation.
	//
	// By default MaxPayloadSize is 4096.
	MaxPayloadSize uint64
	// contains filtered or unexported fields
}

Conn represents websocket connection handler.

This handler is compatible with io.Reader, io.ReaderFrom, io.Writer, io.WriterTo

func Client

func Client(c net.Conn, url string) (*Conn, error)

Client returns Conn using existing connection.

url must be complete URL format i.e. http://localhost:8080/ws

func ClientWithHeaders

func ClientWithHeaders(c net.Conn, url string, req *fasthttp.Request) (*Conn, error)

ClientWithHeaders returns a Conn using existing connection and sending personalized headers.

func Dial

func Dial(url string) (*Conn, error)

Dial performs establishes websocket connection as client.

url parameter must follow WebSocket url format i.e. ws://host:port/path

func DialWithHeaders

func DialWithHeaders(url string, req *fasthttp.Request) (*Conn, error)

DialWithHeaders establishes websocket connection as client sending personalized request.

func (*Conn) Close

func (conn *Conn) Close() error

Close closes the websocket connection.

func (*Conn) CloseString

func (conn *Conn) CloseString(b string) error

CloseString sends b as close reason and closes the descriptor.

When connection is handled by server the connection is closed automatically.

func (*Conn) LocalAddr

func (conn *Conn) LocalAddr() net.Addr

LocalAddr returns local address.

func (*Conn) NextFrame

func (conn *Conn) NextFrame() (fr *Frame, err error)

NextFrame reads next connection frame and returns if there were no error.

If NextFrame fr is not nil do not forget to ReleaseFrame(fr) This function responds automatically to PING and PONG messages.

func (*Conn) ReadFrame

func (conn *Conn) ReadFrame(fr *Frame) (nn int, err error)

ReadFrame fills fr with the next connection frame.

This function responds automatically to PING and PONG messages.

func (*Conn) ReadMessage

func (conn *Conn) ReadMessage(b []byte) (Mode, []byte, error)

ReadMessage reads next message from conn and returns the mode, b and/or error.

b is used to avoid extra allocations and can be nil.

func (*Conn) RemoteAddr

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

RemoteAddr returns peer remote address.

func (*Conn) ReplyClose

func (conn *Conn) ReplyClose(fr *Frame) (err error)

ReplyClose is used to reply to CodeClose.

func (*Conn) Reset

func (conn *Conn) Reset(c net.Conn)

Reset resets conn values setting c as default connection endpoint.

func (*Conn) SendCode

func (conn *Conn) SendCode(code Code, status StatusCode, b []byte) error

SendCode writes code, status and message to conn.

status is used by CodeClose to report any close status (as HTTP responses). Can be 0. b can be nil.

func (*Conn) SendCodeString

func (conn *Conn) SendCodeString(code Code, status StatusCode, b string) error

SendCodeString writes code, status and message to conn as SendCode does.

func (*Conn) SetDeadline

func (conn *Conn) SetDeadline(t time.Time) error

SetDeadline calls net.Conn.SetDeadline

func (*Conn) SetReadDeadline

func (conn *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline calls net.Conn.SetReadDeadline

func (*Conn) SetWriteDeadline

func (conn *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline calls net.Conn.SetWriteDeadline

func (*Conn) Write

func (conn *Conn) Write(b []byte) (int, error)

Write writes b using conn.Mode as default.

func (*Conn) WriteFrame

func (conn *Conn) WriteFrame(fr *Frame) (int, error)

WriteFrame writes fr to the connection endpoint.

func (*Conn) WriteMessage

func (conn *Conn) WriteMessage(mode Mode, b []byte) (int, error)

WriteMessage writes b to conn using mode.

func (*Conn) WriteString

func (conn *Conn) WriteString(b string) (int, error)

WriteString writes b to conn using conn.Mode as default.

type Frame

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

Frame is the unit used to transfer message between endpoints using websocket protocol.

Frame could not be used during message exchanging. This type can be used if you want low level access to websocket.

func AcquireFrame

func AcquireFrame() *Frame

AcquireFrame gets Frame from pool.

func (*Frame) Code

func (fr *Frame) Code() Code

Code returns the code set in fr.

func (*Frame) HasRSV1

func (fr *Frame) HasRSV1() bool

HasRSV1 checks if RSV1 bit is set.

func (*Frame) HasRSV2

func (fr *Frame) HasRSV2() bool

HasRSV2 checks if RSV2 bit is set.

func (*Frame) HasRSV3

func (fr *Frame) HasRSV3() bool

HasRSV3 checks if RSV3 bit is set.

func (*Frame) IsClose

func (fr *Frame) IsClose() bool

IsClose returns true if Code is CodeClose.

func (*Frame) IsContinuation

func (fr *Frame) IsContinuation() bool

func (*Frame) IsFin

func (fr *Frame) IsFin() bool

IsFin checks if FIN bit is set.

func (*Frame) IsMasked

func (fr *Frame) IsMasked() bool

IsMasked checks if Mask bit is set.

func (*Frame) IsPing

func (fr *Frame) IsPing() bool

IsPong returns true if Code is CodePing.

func (*Frame) IsPong

func (fr *Frame) IsPong() bool

IsPong returns true if Code is CodePong.

func (*Frame) Len

func (fr *Frame) Len() (length uint64)

Len returns payload length based on Frame field of length bytes.

func (*Frame) Mask

func (fr *Frame) Mask()

Mask masks Frame payload.

func (*Frame) MaskKey

func (fr *Frame) MaskKey() []byte

MaskKey returns mask key if exist.

func (*Frame) Mode

func (fr *Frame) Mode() (mode Mode)

Mode returns frame mode.

func (*Frame) Payload

func (fr *Frame) Payload() []byte

Payload returns Frame payload.

func (*Frame) PayloadSize

func (fr *Frame) PayloadSize() uint64

PayloadSize returns max payload size.

func (*Frame) ReadFrom

func (fr *Frame) ReadFrom(rd io.Reader) (nn uint64, err error)

ReadFrom fills fr reading from rd.

if rd == nil then ReadFrom returns EOF

func (*Frame) Reset

func (fr *Frame) Reset()

Reset resets all Frame values to be reused.

func (*Frame) SetBinary

func (fr *Frame) SetBinary()

SetText sets CodeText in Code field.

func (*Frame) SetClose

func (fr *Frame) SetClose()

SetClose sets CodeClose in Code field.

func (*Frame) SetCode

func (fr *Frame) SetCode(code Code)

SetCode sets code bits.

func (*Frame) SetContinuation

func (fr *Frame) SetContinuation()

SetContinuation sets CodeContinuation in Code field.

func (*Frame) SetFin

func (fr *Frame) SetFin()

SetFin sets FIN bit.

func (*Frame) SetMask

func (fr *Frame) SetMask(b []byte)

SetMask sets mask key to mask the frame and enabled mask bit.

func (*Frame) SetPayload

func (fr *Frame) SetPayload(b []byte)

SetPayload sets payload to fr.

func (*Frame) SetPayloadSize

func (fr *Frame) SetPayloadSize(size uint64)

SetPayloadSize sets max payload size.

func (*Frame) SetPing

func (fr *Frame) SetPing()

SetPing sets CodePing in Code field.

func (*Frame) SetPong

func (fr *Frame) SetPong()

SetPong sets CodePong in Code field.

func (*Frame) SetRSV1

func (fr *Frame) SetRSV1()

SetRSV1 sets RSV1 bit.

func (*Frame) SetRSV2

func (fr *Frame) SetRSV2()

SetRSV2 sets RSV2 bit.

func (*Frame) SetRSV3

func (fr *Frame) SetRSV3()

SetRSV3 sets RSV3 bit.

func (*Frame) SetStatus

func (fr *Frame) SetStatus(status StatusCode)

SetStatus sets status code to the request.

Status code is usually used in Close request.

func (*Frame) SetText

func (fr *Frame) SetText()

SetText sets CodeText in Code field.

func (*Frame) Status

func (fr *Frame) Status() (status StatusCode)

Status returns StatusCode from request payload.

func (*Frame) Unmask

func (fr *Frame) Unmask()

Unmask unmasks Frame payload.

func (*Frame) UnsetMask

func (fr *Frame) UnsetMask()

UnsetMask drops mask bit.

func (*Frame) Write

func (fr *Frame) Write(b []byte) (int, error)

Write writes b to the frame payload.

func (*Frame) WriteTo

func (fr *Frame) WriteTo(wr io.Writer) (n uint64, err error)

WriteTo flushes Frame data into wr.

type Mode

type Mode uint8

Mode is the mode in which the bytes are sended.

https://tools.ietf.org/html/rfc6455#section-5.6

const (
	ModeNone Mode = iota
	ModeText
	ModeBinary
)

type RequestHandler

type RequestHandler func(conn *Conn)

RequestHandler is the websocket handler.

type StatusCode

type StatusCode uint16

type UpgradeHandler

type UpgradeHandler func(*fasthttp.RequestCtx) bool

RequestHandler is the websocket handler.

type Upgrader

type Upgrader struct {
	// UpgradeHandler allows user to handle RequestCtx when upgrading.
	//
	// If UpgradeHandler returns false the connection won't be upgraded and
	// the parsed ctx will be used as a response.
	UpgradeHandler UpgradeHandler

	// Handler is the request handler for ws connections.
	Handler RequestHandler

	// Protocols are the supported protocols.
	Protocols []string

	// Origin ...
	Origin string

	// Compress ...
	Compress bool
}

Upgrader upgrades HTTP connection to a websocket connection if it's possible.

Upgrader executes Upgrader.Handler after successful websocket upgrading.

func (*Upgrader) Upgrade

func (upgr *Upgrader) Upgrade(ctx *fasthttp.RequestCtx)

Upgrader upgrades HTTP to websocket connection if possible.

If client does not request any websocket connection this function will execute ctx.NotFound()

When connection is successfully stablished this function calls s.Handler.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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