wsadapters

package
v0.0.0-...-335aeae Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2023 License: Apache-2.0 Imports: 5 Imported by: 2

Documentation

Overview

The package defines an interface to adapt 3rd parties websocket libraries to websocket engine.

The package defines an interface to adapt 3rd parties websocket libraries to websocket engine.

The package defines an interface to adapt 3rd parties websocket libraries to websocket engine.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MessageType

type MessageType int

Websocket message types which can be received.

Codes mimics RFC6455 frame opcodes. Control frames like continuation, close, ping, pong and others are excluded as the library focuses on message level and not frame level. Furthermore, the underlying websocket library used by the engine is expected to seamlessly handle message fragmentation and control frames like close, ping & pong.

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

const (
	// Denotes a text message
	Text MessageType = iota + 1
	// Denotes a binary message
	Binary
)

type StatusCode

type StatusCode int

Constants for RFC6455 defined close status codes

RFC: https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1

Code names are inspired by: https://www.iana.org/assignments/websocket/websocket.xhtml

const (
	// 1000 indicates a normal closure, meaning that the purpose for
	// which the connection was established has been fulfilled.
	NormalClosure StatusCode = iota + 1000
	// 1001 indicates that an endpoint is "going away", such as a server
	// going down or a browser having navigated away from a page.
	GoingAway
	// 1002 indicates that an endpoint is terminating the connection due
	// to a protocol error.
	ProtocolError
	// 1003 indicates that an endpoint is terminating the connection
	// because it has received a type of data it cannot accept (e.g., an
	// endpoint that understands only text data MAY send this if it
	// receives a binary message).
	UnsupportedData
	// 1005 is a reserved value and MUST NOT be set as a status code in a
	// Close control frame by an endpoint.  It is designated for use in
	// applications expecting a status code to indicate that no status
	// code was actually present.
	NoStatusReceived StatusCode = iota + 1000 + 1 // Skip 1003
	// 1006 is a reserved value and MUST NOT be set as a status code in a
	// Close control frame by an endpoint.  It is designated for use in
	// applications expecting a status code to indicate that the
	// connection was closed abnormally, e.g., without sending or
	// receiving a Close control frame.
	AbnormalClosure
	// 1007 indicates that an endpoint is terminating the connection
	// because it has received data within a message that was not
	// consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
	// data within a text message).
	InvalidFramePayloadData
	// 1008 indicates that an endpoint is terminating the connection
	// because it has received a message that violates its policy.  This
	// is a generic status code that can be returned when there is no
	// other more suitable status code (e.g., 1003 or 1009) or if there
	// is a need to hide specific details about the policy.
	PolicyViolation
	// 1009 indicates that an endpoint is terminating the connection
	// because it has received a message that is too big for it to
	// process.
	MessageTooBig
	// 1010 indicates that an endpoint (client) is terminating the
	// connection because it has expected the server to negotiate one or
	// more extension, but the server didn't return them in the response
	// message of the WebSocket handshake.  The list of extensions that
	// are needed SHOULD appear in the /reason/ part of the Close frame.
	// Note that this status code is not used by the server, because it
	// can fail the WebSocket handshake instead.
	MandatoryExtension
	// 1011 indicates that a server is terminating the connection because
	// it encountered an unexpected condition that prevented it from
	// fulfilling the request.
	InternalError
	// 1015 is a reserved value and MUST NOT be set as a status code in a
	// Close control frame by an endpoint.  It is designated for use in
	// applications expecting a status code to indicate that the
	// connection was closed due to a failure to perform a TLS handshake
	// (e.g., the server certificate can't be verified).
	TLSHandshake StatusCode = iota + 1000 + 3 // Skip 1012 to 1014
)

type WebsocketCloseError

type WebsocketCloseError struct {
	// Status code used or received when connection has been closed. If websocket connection has
	// been closed and no close message has been received, 1006 should be used.
	//
	// https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5
	Code StatusCode
	// Optional close reason used/received when connection has been closed.
	//
	// https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6
	Reason string
	// Embedded error if any. Can be the error returned by the underlying websocket library by Read
	// method when websocket is closed.
	Err error
}

Error used by websocket connection to signal connection has been closed

func (WebsocketCloseError) Error

func (err WebsocketCloseError) Error() string

func (WebsocketCloseError) Unwrap

func (err WebsocketCloseError) Unwrap() error

type WebsocketConnectionAdapterInterface

type WebsocketConnectionAdapterInterface interface {
	// # Description
	//
	// Dial open a connection to the websocket server, performs a WebSocket handshake on url and
	// keep internally the underlying websocket connection for further use.
	//
	// # Expected behaviour
	//
	//	- Dial MUST block until websocket handshake completes. Websocket handshake and TLS must be
	//    handled seamlessly either by the adapter implementation or by the underlying websocket
	//    library.
	//
	//	- Dial MUST NOT return the undelrying websocket connection. The undelrying websocket
	//    connection must be kept internally by the adapter implementation in order to be used
	//    later by Read, Write, ...
	//
	//	- Dial SHOULD close any previous opened connection if called again and MUST drop any
	//    previous connection. Connection closure must be seamless.
	//
	// # Inputs
	//
	//	- ctx: Context used for tracing/timeout purpose
	//	- target: Target server URL
	//
	// # Returns
	//
	//	- Server response to websocket handshake
	//	- error if any
	Dial(ctx context.Context, target *url.URL) (*http.Response, error)
	// # Description
	//
	// Send a close message with the provided status code and an optional close reason and close
	// the websocket connection.
	//
	// # Expected behaviour
	//
	//	- Close MUST be blocking until close message has been sent to the server.
	//	- Close MUST drop pending write/read messages.
	//	- Close MUST close the connection even if provided context is already canceled.
	//	- Close MUST return a (wrapped) net.ErrClosed error in case connection is already closed.
	//
	// # Inputs
	//
	//	- ctx: Context used for tracing purpose
	//	- code: Status code to use in close message
	//	- reason: Optional reason joined in clsoe message. Can be empty.
	//
	// # Returns
	//
	//	- nil in case of success
	//	- error: server unreachable, connection already closed, ...
	Close(ctx context.Context, code StatusCode, reason string) error
	// # Description
	//
	// Send a Ping message to the websocket server and blocks until a Pong response is received.
	//
	// # Expected behaviour
	//
	//	- Ping MUST be blocking either until an error or a context timeout or cancellation occurs
	//    or until Ping message is sent and a Pong response is somehow detected either by the
	//    adapter implementation or by the underlying websocket connection library.
	//
	//	- It CANNOT be assumed that there will be at least one concurrent goroutine which continuously
	//    call Read method. In case the underlying websocket library requires to have a concurrent
	//    goroutine continuously reading in order for Ping to complete, it is up to either the
	//    adapter or to the final user to ensure there is a concurrent goroutine reading.
	//
	//	- Ping MUST return an error if connection is closed, if server is unreachable or if context
	//    has expired (timeout or cancel). In this later case, Ping MUST return the context error.
	//
	// # Inputs
	//
	//	- ctx: context used for tracing/timeout purpose.
	//
	// # Returns
	//
	// - nil in case of success: if a Ping message is sent to the server and if a Pong is received.
	// - error: connection is closed, context timeout/cancellation, ...
	Ping(ctx context.Context) error
	// # Description
	//
	// Read a single message from the websocket server. Read blocks until a message is received
	// from the server, until connection closes or until a timeout or a cancel occurs.
	//
	// # Expected behaviour
	//
	//	- Read MUST handle seamlessly message defragmentation, decompression and TLS decryption.
	//    It is up to the adapter implementation or to the underlying websocket library to handle
	//    these features.
	//
	//	- Read MUST NOT return close, ping, pong and continuation frames as control frames MUST be
	//    handled seamlessly either by the adapter implementation or by the underlying websocket
	//    connection library.
	//
	//	- Read MUST return a WebsocketCloseError either if a close message is read or if connection
	//    is closed without a close message. In the later case, the 1006 status code MUST be used.
	//
	//	- Read MUST block until a message is read from the server or until an error occurs.
	//
	// # Inputs
	//
	//	- ctx: Context used for tracing/timeout purpose
	//
	// # Returns
	//
	//	- MessageType: received message type (Binary | Text)
	//	- []bytes: Message content
	//	- error: in case of connection closure, context timeout/cancellation or failure.
	Read(ctx context.Context) (MessageType, []byte, error)
	// # Description
	//
	// Write a single message to the websocket server. Write blocks until message is sent to the
	// server or until an error occurs: context timeout, cancellation, connection closed, ....
	//
	// # Expected behaviour
	//
	//	- Write MUST handle seamlessly message fragmentation, compression and TLS encryption. It is
	//    up to the adapter implementation or to the underlying websocket library to handle these.
	//
	//	- Write MUST NOT handle sending control frames like Close, Ping, etc...
	//
	//	- Write MUST be blocking until a message is sent to the server or until an error occurs.
	//
	// # Inputs
	//
	//	- ctx: Context used for tracing/timeout purpose
	//	- MessageType: received message type (Binary | Text)
	//	- []bytes: Message content
	//
	// # Returns
	//
	//	- error: in case of connection closure, context timeout/cancellation or failure.
	Write(ctx context.Context, msgType MessageType, msg []byte) error
	// # Description
	//
	// Return the underlying websocket connection if any. Returned value has to be type asserted.
	//
	// # Returns
	//
	// The underlying websocket connection if any. Returned value has to be type asserted.
	GetUnderlyingWebsocketConnection() any
}

Adapter which describes methods and behaviour expected by the websocket engine from the underlying websocket connection library.

Adapters are assumed to be tread-safe. Thread-safety must be ensured either by the adapter implementation or by the underlying websocket connection library. implementations or underlying websocket

type WebsocketConnectionAdapterInterfaceMock

type WebsocketConnectionAdapterInterfaceMock struct {
	mock.Mock
}

Mock for WebsocketConnectionAdapterInterface

func NewWebsocketConnectionAdapterInterfaceMock

func NewWebsocketConnectionAdapterInterfaceMock() *WebsocketConnectionAdapterInterfaceMock

Factory

func (*WebsocketConnectionAdapterInterfaceMock) Close

Description

Send a close message with the provided status code and an optional close reason and close the websocket connection.

Expected behaviour

  • Close MUST be blocking until close message has been sent to the server and until websocket connection closure.

  • There are no guidelines about dropping pending write/read messages when Close is called. Refer to the adapter or the underlying websocket library documentation for guidance.

Inputs

  • ctx: Context used for tracing purpose
  • code: Status code to use in close message
  • reason: Optional reason joined in clsoe message. Can be empty.

Returns

  • nil in case of success
  • error: server unreachable, connection already closed, ...

func (*WebsocketConnectionAdapterInterfaceMock) Dial

Description

Dial open a connection to the websocket server, performs a WebSocket handshake on url and keep internally the underlying websocket connection for further use.

Expected behaviour

  • Dial MUST block until websocket handshake completes. Websocket handshake and TLS must be handled seamlessly either by the adapter implementation or by the underlying websocket library.

  • Dial MUST NOT return the undelrying websocket connection. The undelrying websocket connection must be kept internally by the adapter implementation in order to be used later by Read, Write, ...

  • Dial SHOULD close any previous opened connection if called again and MUST drop any previous connection. Connection closure must be seamless.

Inputs

  • ctx: Context used for tracing/timeout purpose
  • target: Target server URL

Returns

  • Server response to websocket handshake
  • error if any

func (*WebsocketConnectionAdapterInterfaceMock) GetUnderlyingWebsocketConnection

func (mock *WebsocketConnectionAdapterInterfaceMock) GetUnderlyingWebsocketConnection() any

Description

Return the underlying websocket connection if any. Returned value has to be type asserted.

Returns

The underlying websocket connection if any. Returned value has to be type asserted.

func (*WebsocketConnectionAdapterInterfaceMock) Ping

Description

Send a Ping message to the websocket server and blocks until a Pong response is received.

Expected behaviour

  • Ping MUST be blocking either until an error or a context timeout or cancellation occurs or until Ping message is sent and a Pong response is somehow detected either by the adapter implementation or by the underlying websocket connection library.

  • It can be assumed that there will be at least one concurrent goroutine which continuously call Read method.

  • Ping MUST return an error if connection is closed, if server is unreachable or if context has expired (timeout or cancel). In this later case, Ping MUST return the context error.

Inputs

  • ctx: context used for tracing/timeout purpose.

Returns

- nil in case of success: if a Ping message is sent to the server and if a Pong is received. - error: connection is closed, context timeout/cancellation, ...

func (*WebsocketConnectionAdapterInterfaceMock) Read

Description

Read a single message from the websocket server. Read blocks until a message is received from the server, until connection closes or until a timeout or a cancel occurs.

Expected behaviour

  • Read MUST handle seamlessly message defragmentation, decompression and TLS decryption. It is up to the adapter implementation or to the underlying websocket library to handle these features.

  • Read MUST NOT return close, ping, pong and continuation frames as control frames MUST be handled seamlessly either by the adapter implementation or by the underlying websocket connection library.

  • Read MUST return a WebsocketCloseError either if a close message is read or if connection is closed without a close message. In the later case, the 1006 status code MUST be used.

  • Read MUST block until a message is read from the server or until an error occurs.

Inputs

  • ctx: Context used for tracing/timeout purpose

Returns

  • MessageType: received message type (Binary | Text)
  • []bytes: Message content
  • error: in case of connection closure, context timeout/cancellation or failure.

func (*WebsocketConnectionAdapterInterfaceMock) Write

Description

Write a single message to the websocket server. Write blocks until message is sent to the server or until an error occurs: context timeout, cancellation, connection closed, ....

Expected behaviour

  • Write MUST handle seamlessly message fragmentation, compression and TLS encryption. It is up to the adapter implementation or to the underlying websocket library to handle these.

  • Write MUST NOT handle sending control frames like Close, Ping, etc...

  • Write MUST be blocking until a message is sent to the server or until an error occurs.

Inputs

  • ctx: Context used for tracing/timeout purpose
  • MessageType: received message type (Binary | Text)
  • []bytes: Message content

Returns

  • error: in case of connection closure, context timeout/cancellation or failure.

Directories

Path Synopsis
Package which contains a WebsocketConnectionAdapterInterface implementation for nhooyr/websocket library (https://github.com/nhooyr/websocket).
Package which contains a WebsocketConnectionAdapterInterface implementation for nhooyr/websocket library (https://github.com/nhooyr/websocket).

Jump to

Keyboard shortcuts

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