Documentation ¶
Index ¶
- Constants
- Variables
- func Cipher(payload []byte, mask [4]byte, offset int)
- func FrameToBytes(f *Frame) (ret []byte, err error)
- func NewCloseFrameBody(code StatusCode, reason string) []byte
- func PutCloseFrameBody(p []byte, code StatusCode, reason string)
- func RejectConnectionError(options ...RejectOption) error
- func WriteHeader(h *Header) ([]byte, error)
- type Frame
- type Handshake
- type HandshakeHeader
- type HandshakeHeaderBytes
- type HandshakeHeaderFunc
- type HandshakeHeaderHTTP
- type HandshakeHeaderString
- type Header
- type MessageType
- type OpCode
- type ProtocolError
- type RejectOption
- type StatusCode
- func (s StatusCode) Empty() bool
- func (s StatusCode) In(r StatusCodeRange) bool
- func (s StatusCode) IsApplicationSpec() bool
- func (s StatusCode) IsNotUsed() bool
- func (s StatusCode) IsPrivateSpec() bool
- func (s StatusCode) IsProtocolDefined() bool
- func (s StatusCode) IsProtocolReserved() bool
- func (s StatusCode) IsProtocolSpec() bool
- type StatusCodeRange
- type Upgrader
Constants ¶
const (
// All control frames MUST have a payload length of 125 bytes or less and MUST NOT be fragmented.
MaxControlFramePayloadSize = 125
)
Constants defined by specification.
const (
MaxHeaderSize = 14
)
Header size length bounds in bytes.
Variables ¶
var ( ErrProtocolStatusCodeNotInUse = ProtocolError("status code is not in use") ErrProtocolStatusCodeApplicationLevel = ProtocolError("status code is only application level") ErrProtocolStatusCodeNoMeaning = ProtocolError("status code has no meaning yet") ErrProtocolStatusCodeUnknown = ProtocolError("status code is not defined in spec") ErrProtocolInvalidUTF8 = ProtocolError("invalid utf8 sequence in close reason") )
Errors used by the protocol checkers.
var ( ErrHandshakeBadProtocol = RejectConnectionError( RejectionStatus(http.StatusHTTPVersionNotSupported), RejectionReason("handshake error: bad HTTP protocol version"), ) ErrHandshakeBadMethod = RejectConnectionError( RejectionStatus(http.StatusMethodNotAllowed), RejectionReason("handshake error: bad HTTP request method"), ) ErrHandshakeBadHost = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerHost)), ) ErrHandshakeBadUpgrade = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerUpgrade)), ) ErrHandshakeBadConnection = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerConnection)), ) ErrHandshakeBadSecAccept = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerSecAccept)), ) ErrHandshakeBadSecKey = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerSecKey)), ) ErrHandshakeBadSecVersion = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerSecVersion)), ) )
Errors used by both client and server when preparing WebSocket handshake.
var ( StatusRangeNotInUse = StatusCodeRange{0, 999} StatusRangeProtocol = StatusCodeRange{1000, 2999} StatusRangeApplication = StatusCodeRange{3000, 3999} StatusRangePrivate = StatusCodeRange{4000, 4999} )
Status code ranges defined by specification. See https://tools.ietf.org/html/rfc6455#section-7.4.2
var ( ErrHeaderLengthMSB = fmt.Errorf("header error: the most significant bit must be 0") ErrHeaderLengthUnexpected = fmt.Errorf("header error: unexpected payload length bits") ErrHeaderNotReady = fmt.Errorf("header error: not enough") )
Errors used by frame reader.
var ErrHandshakeUpgradeRequired = RejectConnectionError( RejectionStatus(http.StatusUpgradeRequired), RejectionHeader(HandshakeHeaderString(headerSecVersion+": 13\r\n")), RejectionReason(fmt.Sprintf("handshake error: bad %q header", headerSecVersion)), )
ErrHandshakeUpgradeRequired is returned by Upgrader to indicate that connection is rejected because given WebSocket version is malformed.
According to RFC6455: If this version does not match a version understood by the server, the server MUST abort the WebSocket handshake described in this section and instead send an appropriate HTTP error code (such as 426 Upgrade Required) and a |Sec-WebSocket-Version| header field indicating the version(s) the server is capable of understanding.
var ErrMalformedRequest = RejectConnectionError( RejectionStatus(http.StatusBadRequest), RejectionReason("malformed HTTP request"), )
ErrMalformedRequest is returned when HTTP request can not be parsed.
Functions ¶
func Cipher ¶
Cipher applies XOR cipher to the payload using mask. Offset is used to cipher chunked data (e.g. in io.Reader implementations).
To convert masked data into unmasked data, or vice versa, the following algorithm is applied. The same algorithm applies regardless of the direction of the translation, e.g., the same steps are applied to mask the data as to unmask the data.
func NewCloseFrameBody ¶
func NewCloseFrameBody(code StatusCode, reason string) []byte
NewCloseFrameBody encodes a closure code and a reason into a binary representation.
It returns slice which is at most MaxControlFramePayloadSize bytes length. If the reason is too big it will be cropped to fit the limit defined by the spec.
func PutCloseFrameBody ¶
func PutCloseFrameBody(p []byte, code StatusCode, reason string)
PutCloseFrameBody encodes code and reason into buf.
It will panic if the buffer is too small to accommodate a code or a reason.
PutCloseFrameBody does not check buffer to be RFC compliant, but note that by RFC it must be at most MaxControlFramePayloadSize.
func RejectConnectionError ¶
func RejectConnectionError(options ...RejectOption) error
RejectConnectionError constructs an error that could be used to control the way handshake is rejected by Upgrader.
func WriteHeader ¶
WriteHeader writes header binary representation into w.
Types ¶
type Frame ¶
Frame represents websocket frame. See https://tools.ietf.org/html/rfc6455#section-5.2
func NewBinaryFrame ¶
NewBinaryFrame creates binary frame with p as payload. Note that p is not copied.
func NewCloseFrame ¶
NewCloseFrame creates close frame with given close body. Note that p is not copied. Note that p must have length of MaxControlFramePayloadSize bytes or less due to RFC.
func NewFrame ¶
NewFrame creates frame with given operation code, flag of completeness and payload bytes.
func NewPingFrame ¶
NewPingFrame creates ping frame with p as payload. Note that p is not copied. Note that p must have length of MaxControlFramePayloadSize bytes or less due to RFC.
func NewPongFrame ¶
NewPongFrame creates pong frame with p as payload. Note that p is not copied. Note that p must have length of MaxControlFramePayloadSize bytes or less due to RFC.
func NewTextFrame ¶
NewTextFrame creates text frame with p as payload. Note that p is not copied.
type Handshake ¶
type Handshake struct { // Protocol is the subprotocol selected during handshake. Protocol string // Extensions is the list of negotiated extensions. Extensions []httphead.Option }
Handshake represents handshake result.
type HandshakeHeader ¶
HandshakeHeader is the interface that writes both upgrade request or response headers into a given io.Writer.
type HandshakeHeaderBytes ¶
type HandshakeHeaderBytes []byte
HandshakeHeaderBytes is an adapter to allow the use of headers represented by ordinary slice of bytes as HandshakeHeader.
type HandshakeHeaderFunc ¶
HandshakeHeaderFunc is an adapter to allow the use of headers represented by ordinary function as HandshakeHeader.
type HandshakeHeaderHTTP ¶
HandshakeHeaderHTTP is an adapter to allow the use of http.Header as HandshakeHeader.
type HandshakeHeaderString ¶
type HandshakeHeaderString string
HandshakeHeaderString is an adapter to allow the use of headers represented by ordinary string as HandshakeHeader.
type Header ¶
Header represents websocket frame header. See https://tools.ietf.org/html/rfc6455#section-5.2
func VirtualReadHeader ¶
func VirtualReadHeader(bts []byte, in *ringbuffer.RingBuffer) (h Header, err error)
VirtualReadHeader reads a frame header from r.
type MessageType ¶
type MessageType int
MessageType represents the type of a WebSocket message. See https://tools.ietf.org/html/rfc6455#section-5.6
const ( // MessageText Text MessageText MessageType = iota + 1 // MessageBinary Binary MessageBinary )
type OpCode ¶
type OpCode byte
OpCode represents operation code.
const ( OpContinuation OpCode = 0x0 OpText OpCode = 0x1 OpBinary OpCode = 0x2 OpClose OpCode = 0x8 OpPing OpCode = 0x9 OpPong OpCode = 0xa )
Operation codes defined by specification. See https://tools.ietf.org/html/rfc6455#section-5.2
func (OpCode) IsControl ¶
IsControl checks whether the c is control operation code. See https://tools.ietf.org/html/rfc6455#section-5.5
func (OpCode) IsData ¶
IsData checks whether the c is data operation code. See https://tools.ietf.org/html/rfc6455#section-5.6
func (OpCode) IsReserved ¶
IsReserved checks whether the c is reserved operation code. See https://tools.ietf.org/html/rfc6455#section-5.2
type ProtocolError ¶
type ProtocolError string
ProtocolError describes error during checking/parsing websocket frames or headers.
func (ProtocolError) Error ¶
func (p ProtocolError) Error() string
Error implements error interface.
type RejectOption ¶
type RejectOption func(*rejectConnectionError)
RejectOption represents an option used to control the way connection is rejected.
func RejectionHeader ¶
func RejectionHeader(h HandshakeHeader) RejectOption
RejectionHeader returns an option that makes connection to be rejected with given HTTP headers.
func RejectionReason ¶
func RejectionReason(reason string) RejectOption
RejectionReason returns an option that makes connection to be rejected with given reason.
func RejectionStatus ¶
func RejectionStatus(code int) RejectOption
RejectionStatus returns an option that makes connection to be rejected with given HTTP status code.
type StatusCode ¶
type StatusCode uint16
StatusCode represents the encoded reason for closure of websocket connection.
There are few helper methods on StatusCode that helps to define a range in which given code is lay in. accordingly to ranges defined in specification.
See https://tools.ietf.org/html/rfc6455#section-7.4
const ( StatusNormalClosure StatusCode = 1000 StatusGoingAway StatusCode = 1001 StatusProtocolError StatusCode = 1002 StatusUnsupportedData StatusCode = 1003 StatusNoMeaningYet StatusCode = 1004 StatusInvalidFramePayloadData StatusCode = 1007 StatusPolicyViolation StatusCode = 1008 StatusMessageTooBig StatusCode = 1009 StatusMandatoryExt StatusCode = 1010 StatusInternalServerError StatusCode = 1011 StatusTLSHandshake StatusCode = 1015 // StatusAbnormalClosure is a special code designated for use in // applications. StatusAbnormalClosure StatusCode = 1006 // StatusNoStatusRcvd is a special code designated for use in applications. StatusNoStatusRcvd StatusCode = 1005 )
Status codes defined by specification. See https://tools.ietf.org/html/rfc6455#section-7.4.1
func ParseCloseFrameData ¶
func ParseCloseFrameData(payload []byte) (code StatusCode, reason string)
ParseCloseFrameData parses close frame status code and closure reason if any provided. If there is no status code in the payload the empty status code is returned (code.Empty()) with empty string as a reason.
func (StatusCode) Empty ¶
func (s StatusCode) Empty() bool
Empty reports whether the code is empty. Empty code has no any meaning neither app level codes nor other. This method is useful just to check that code is golang default value 0.
func (StatusCode) In ¶
func (s StatusCode) In(r StatusCodeRange) bool
In reports whether the code is defined in given range.
func (StatusCode) IsApplicationSpec ¶
func (s StatusCode) IsApplicationSpec() bool
IsApplicationSpec reports whether the code should be defined by application, framework or libraries specification.
func (StatusCode) IsNotUsed ¶
func (s StatusCode) IsNotUsed() bool
IsNotUsed reports whether the code is predefined in not used range.
func (StatusCode) IsPrivateSpec ¶
func (s StatusCode) IsPrivateSpec() bool
IsPrivateSpec reports whether the code should be defined privately.
func (StatusCode) IsProtocolDefined ¶
func (s StatusCode) IsProtocolDefined() bool
IsProtocolDefined reports whether the code is already defined by protocol specification.
func (StatusCode) IsProtocolReserved ¶
func (s StatusCode) IsProtocolReserved() bool
IsProtocolReserved reports whether the code is defined by protocol specification to be reserved only for application usage purpose.
func (StatusCode) IsProtocolSpec ¶
func (s StatusCode) IsProtocolSpec() bool
IsProtocolSpec reports whether the code should be defined by protocol specification.
type StatusCodeRange ¶
type StatusCodeRange struct {
Min, Max StatusCode
}
StatusCodeRange describes range of StatusCode values.
type Upgrader ¶
type Upgrader struct { // Protocol is a select function that is used to select subprotocol // from list requested by client. If this field is set, then the first matched // protocol is sent to a client as negotiated. // // The argument is only valid until the callback returns. Protocol func([]byte) bool // ProtocolCustrom allow user to parse Sec-WebSocket-Protocol header manually. // Note that returned bytes must be valid until Upgrade returns. // If ProtocolCustom is set, it used instead of Protocol function. ProtocolCustom func(*gev.Connection, []byte) (string, bool) // Extension is a select function that is used to select extensions // from list requested by client. If this field is set, then the all matched // extensions are sent to a client as negotiated. // // The argument is only valid until the callback returns. // // According to the RFC6455 order of extensions passed by a client is // significant. That is, returning true from this function means that no // other extension with the same name should be checked because server // accepted the most preferable extension right now: // "Note that the order of extensions is significant. Any interactions between // multiple extensions MAY be defined in the documents defining the extensions. // In the absence of such definitions, the interpretation is that the header // fields listed by the client in its request represent a preference of the // header fields it wishes to use, with the first options listed being most // preferable." Extension func(httphead.Option) bool // ExtensionCustorm allow user to parse Sec-WebSocket-Extensions header manually. // Note that returned options should be valid until Upgrade returns. // If ExtensionCustom is set, it used instead of Extension function. ExtensionCustom func(*gev.Connection, []byte, []httphead.Option) ([]httphead.Option, bool) // Header is an optional HandshakeHeader instance that could be used to // write additional headers to the handshake response. // // It used instead of any key-value mappings to avoid allocations in user // land. // // Note that if present, it will be written in any result of handshake. Header HandshakeHeader // OnRequest is a callback that will be called after request line // successful parsing. // // The arguments are only valid until the callback returns. // // If returned error is non-nil then connection is rejected and response is // sent with appropriate HTTP error code and body set to error message. // // RejectConnectionError could be used to get more control on response. OnRequest func(c *gev.Connection, uri []byte) error // OnHost is a callback that will be called after "Host" header successful // parsing. // // It is separated from OnHeader callback because the Host header must be // present in each request since HTTP/1.1. Thus Host header is non-optional // and required for every WebSocket handshake. // // The arguments are only valid until the callback returns. // // If returned error is non-nil then connection is rejected and response is // sent with appropriate HTTP error code and body set to error message. // // RejectConnectionError could be used to get more control on response. OnHost func(c *gev.Connection, host []byte) error // OnHeader is a callback that will be called after successful parsing of // header, that is not used during WebSocket handshake procedure. That is, // it will be called with non-websocket headers, which could be relevant // for application-level logic. // // The arguments are only valid until the callback returns. // // If returned error is non-nil then connection is rejected and response is // sent with appropriate HTTP error code and body set to error message. // // RejectConnectionError could be used to get more control on response. OnHeader func(c *gev.Connection, key, value []byte) error // OnBeforeUpgrade is a callback that will be called before sending // successful upgrade response. // // Setting OnBeforeUpgrade allows user to make final application-level // checks and decide whether this connection is allowed to successfully // upgrade to WebSocket. // // It must return non-nil either HandshakeHeader or error and never both. // // If returned error is non-nil then connection is rejected and response is // sent with appropriate HTTP error code and body set to error message. // // RejectConnectionError could be used to get more control on response. OnBeforeUpgrade func(c *gev.Connection) (header HandshakeHeader, err error) }
Upgrader contains options for upgrading connection to websocket.
func (*Upgrader) Upgrade ¶
func (u *Upgrader) Upgrade(c *gev.Connection, in *ringbuffer.RingBuffer) (out []byte, hs Handshake, err error)
Upgrade zero-copy upgrades connection to WebSocket. It interprets given conn as connection with incoming HTTP Upgrade request.
It is a caller responsibility to manage i/o timeouts on conn.
Non-nil error means that request for the WebSocket upgrade is invalid or malformed and usually connection should be closed. Even when error is non-nil Upgrade will write appropriate response into connection in compliance with RFC.