wsflate

package
v1.3.2 Latest Latest
Warning

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

Go to latest
Published: Jan 8, 2024 License: MIT Imports: 7 Imported by: 15

Documentation

Index

Constants

View Source
const (
	ExtensionName = "permessage-deflate"
)
View Source
const (
	MaxLZ77WindowSize = 32768 // 2^15
)

Variables

View Source
var DefaultHelper = Helper{
	Compressor: func(w io.Writer) Compressor {

		f, _ := flate.NewWriter(w, 9)
		return f
	},
	Decompressor: func(r io.Reader) Decompressor {
		return flate.NewReader(r)
	},
}

DefaultHelper is a default helper instance holding standard library's `compress/flate` compressor and decompressor under the hood.

Note that use of DefaultHelper methods assumes that DefaultParameters were used for extension negotiation during WebSocket handshake.

View Source
var DefaultParameters = Parameters{
	ServerNoContextTakeover: true,
	ClientNoContextTakeover: true,
}

DefaultParameters holds deflate extension parameters which are assumed by DefaultHelper to be used during WebSocket handshake.

View Source
var ErrUnexpectedCompressionBit = ws.ProtocolError(
	"control frame or non-first fragment of data contains compression bit set",
)
View Source
var (
	ExtensionNameBytes = []byte(ExtensionName)
)

Functions

func CompressFrame

func CompressFrame(f ws.Frame) (ws.Frame, error)

CompressFrame is a shortcut for DefaultHelper.CompressFrame().

Note that use of DefaultHelper methods assumes that DefaultParameters were used for extension negotiation during WebSocket handshake.

func CompressFrameBuffer

func CompressFrameBuffer(buf Buffer, f ws.Frame) (ws.Frame, error)

CompressFrameBuffer is a shortcut for DefaultHelper.CompressFrameBuffer().

Note that use of DefaultHelper methods assumes that DefaultParameters were used for extension negotiation during WebSocket handshake.

func DecompressFrame

func DecompressFrame(f ws.Frame) (ws.Frame, error)

DecompressFrame is a shortcut for DefaultHelper.DecompressFrame().

Note that use of DefaultHelper methods assumes that DefaultParameters were used for extension negotiation during WebSocket handshake.

func DecompressFrameBuffer

func DecompressFrameBuffer(buf Buffer, f ws.Frame) (ws.Frame, error)

DecompressFrameBuffer is a shortcut for DefaultHelper.DecompressFrameBuffer().

Note that use of DefaultHelper methods assumes that DefaultParameters were used for extension negotiation during WebSocket handshake.

func IsCompressed

func IsCompressed(h ws.Header) (bool, error)

IsCompressed reports whether the Per-Message Compression bit is set in header h. It returns non-nil error if compression bit has unexpected value.

If you need to be fully compatible with Compression Extensions for WebSocket RFC and work with chains of extensions, take a look at the UnsetBit() instead. That is, IsCompressed() is a shortcut for UnsetBit() with reduced number of return values.

func SetBit

func SetBit(h ws.Header) (_ ws.Header, err error)

SetBit sets the Per-Message Compression bit in header h and returns its modified copy. It returns non-nil error if compression bit has unexpected value.

func UnsetBit

func UnsetBit(h ws.Header) (_ ws.Header, wasSet bool, err error)

UnsetBit clears the Per-Message Compression bit in header h and returns its modified copy. It reports whether compression bit was set in header h. It returns non-nil error if compression bit has unexpected value.

This function's main purpose is to be compatible with "Framing" section of the Compression Extensions for WebSocket RFC. If you don't need to work with chains of extensions then IsCompressed() could be enough to check if message is compressed. See https://tools.ietf.org/html/rfc7692#section-6.2

Types

type Buffer

type Buffer interface {
	io.Writer
	Bytes() []byte
}

Buffer is an interface representing some bytes buffering object.

type Compressor

type Compressor interface {
	io.Writer
	Flush() error
}

Compressor is an interface holding deflate compression implementation.

type Decompressor

type Decompressor interface {
	io.Reader
}

Decompressor is an interface holding deflate decompression implementation.

type Extension

type Extension struct {
	// Parameters is specification of extension parameters server is going to
	// accept.
	Parameters Parameters
	// contains filtered or unexported fields
}

Extension contains logic of compression extension parameters negotiation made during HTTP WebSocket handshake. It might be reused between different upgrades (but not concurrently) with Reset() being called after each.

func (*Extension) Accepted

func (n *Extension) Accepted() (_ Parameters, accepted bool)

Accepted returns parameters parsed during last negotiation and a flag that reports whether they were accepted.

func (*Extension) Negotiate

func (n *Extension) Negotiate(opt httphead.Option) (accept httphead.Option, err error)

Negotiate parses given HTTP header option and returns (if any) header option which describes accepted parameters.

It may return zero option (i.e. one which Size() returns 0) alongside with nil error.

func (*Extension) Reset

func (n *Extension) Reset()

Reset resets extension for further reuse.

type Helper

type Helper struct {
	Compressor   func(w io.Writer) Compressor
	Decompressor func(r io.Reader) Decompressor
}

Helper is a helper struct that holds common code for compression and decompression bytes or WebSocket frames.

Its purpose is to reduce boilerplate code in WebSocket applications.

func (*Helper) Compress

func (h *Helper) Compress(p []byte) ([]byte, error)

Compress compresses given bytes. Note that it does memory allocations internally. To control those allocations consider using CompressTo().

func (*Helper) CompressFrame

func (h *Helper) CompressFrame(in ws.Frame) (f ws.Frame, err error)

CompressFrame returns compressed version of a frame. Note that it does memory allocations internally. To control those allocations consider using CompressFrameBuffer().

func (*Helper) CompressFrameBuffer

func (h *Helper) CompressFrameBuffer(buf Buffer, f ws.Frame) (ws.Frame, error)

CompressFrameBuffer compresses a frame using given buffer. Returned frame's payload holds bytes returned by buf.Bytes().

func (*Helper) CompressTo

func (h *Helper) CompressTo(w io.Writer, p []byte) (err error)

CompressTo compresses bytes into given buffer.

func (*Helper) Decompress

func (h *Helper) Decompress(p []byte) ([]byte, error)

Decompress decompresses given bytes. Note that it does memory allocations internally. To control those allocations consider using DecompressTo().

func (*Helper) DecompressFrame

func (h *Helper) DecompressFrame(in ws.Frame) (f ws.Frame, err error)

DecompressFrame returns decompressed version of a frame. Note that it does memory allocations internally. To control those allocations consider using DecompressFrameBuffer().

func (*Helper) DecompressFrameBuffer

func (h *Helper) DecompressFrameBuffer(buf Buffer, f ws.Frame) (ws.Frame, error)

DecompressFrameBuffer decompresses a frame using given buffer. Returned frame's payload holds bytes returned by buf.Bytes().

func (*Helper) DecompressTo

func (h *Helper) DecompressTo(w io.Writer, p []byte) (err error)

DecompressTo decompresses bytes into given buffer. Returned bytes are bytes returned by buf.Bytes().

type MessageState

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

MessageState holds message compression state.

It is consulted during SetBits(h) call to make a decision whether we must set the Per-Message Compression bit for given header h argument. It is updated during UnsetBits(h) to reflect compression state of a message represented by header h argument. It can also be consulted/updated directly by calling IsCompressed()/SetCompressed().

In general MessageState should be used when there is no direct access to connection to read frame from, but it is still needed to know if message being read is compressed. For other cases SetBit() and UnsetBit() should be used instead.

NOTE: the compression state is updated during UnsetBits(h) only when header h argument represents data (text or binary) frame.

func (*MessageState) IsCompressed

func (s *MessageState) IsCompressed() bool

IsCompressed reports whether message is "compressed". See https://tools.ietf.org/html/rfc7692#section-6

func (*MessageState) SetBits

func (s *MessageState) SetBits(h ws.Header) (ws.Header, error)

SetBits changes RSV bits of the frame header h which is being send as if compression extension was negotiated. It returns modified copy of h and error if header is malformed from the RFC perspective.

func (*MessageState) SetCompressed

func (s *MessageState) SetCompressed(v bool)

SetCompressed marks message as "compressed" or "uncompressed". See https://tools.ietf.org/html/rfc7692#section-6

func (*MessageState) UnsetBits

func (s *MessageState) UnsetBits(h ws.Header) (ws.Header, error)

UnsetBits changes RSV bits of the given frame header h as if compression extension was negotiated. It returns modified copy of h and error if header is malformed from the RFC perspective.

type Parameters

type Parameters struct {
	ServerNoContextTakeover bool
	ClientNoContextTakeover bool
	ServerMaxWindowBits     WindowBits
	ClientMaxWindowBits     WindowBits
}

Parameters contains compression extension options.

func (Parameters) Option

func (p Parameters) Option() httphead.Option

Option encodes parameters into HTTP header option.

func (*Parameters) Parse

func (p *Parameters) Parse(opt httphead.Option) (err error)

Parse reads parameters from given HTTP header option accordingly to RFC.

It returns non-nil error at least in these cases:

  • The negotiation offer contains an extension parameter not defined for use in an offer/response.
  • The negotiation offer/response contains an extension parameter with an invalid value.
  • The negotiation offer/response contains multiple extension parameters with the same name.

type ReadResetter

type ReadResetter interface {
	Reset(io.Reader)
}

ReadResetter is an optional interface that Decompressor can implement.

type Reader

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

Reader implements decompression from an io.Reader object using Decompressor. Essentially Reader is a thin wrapper around Decompressor interface to meet PMCE specs.

After all data has been written client should call Flush() method. If any error occurs after reading from Reader, all subsequent calls to Read() or Close() will return the error.

Reader might be reused for different io.Reader objects after its Reset() method has been called.

func NewReader

func NewReader(r io.Reader, ctor func(io.Reader) Decompressor) *Reader

NewReader returns a new Reader.

func (*Reader) Close

func (r *Reader) Close() error

Close closes Reader and a Decompressor instance used under the hood (if it implements io.Closer interface).

func (*Reader) Err

func (r *Reader) Err() error

Err returns an error happened during any operation.

func (*Reader) Read

func (r *Reader) Read(p []byte) (n int, err error)

Read implements io.Reader.

func (*Reader) Reset

func (r *Reader) Reset(src io.Reader)

Reset resets Reader to decompress data from src.

type WindowBits

type WindowBits byte

WindowBits specifies window size accordingly to RFC. Use its Bytes() method to obtain actual size of window in bytes.

func (WindowBits) Bytes

func (b WindowBits) Bytes() int

Bytes returns window size in number of bytes.

func (WindowBits) Defined

func (b WindowBits) Defined() bool

Defined reports whether window bits were specified.

type WriteResetter

type WriteResetter interface {
	Reset(io.Writer)
}

WriteResetter is an optional interface that Compressor can implement.

type Writer

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

Writer implements compression for an io.Writer object using Compressor. Essentially Writer is a thin wrapper around Compressor interface to meet PMCE specs.

After all data has been written client should call Flush() method. If any error occurs after writing to or flushing a Writer, all subsequent calls to Write(), Flush() or Close() will return the error.

Writer might be reused for different io.Writer objects after its Reset() method has been called.

func NewWriter

func NewWriter(w io.Writer, ctor func(io.Writer) Compressor) *Writer

NewWriter returns a new Writer.

func (*Writer) Close

func (w *Writer) Close() error

Close closes Writer and a Compressor instance used under the hood (if it implements io.Closer interface).

func (*Writer) Err

func (w *Writer) Err() error

Err returns an error happened during any operation.

func (*Writer) Flush

func (w *Writer) Flush() error

Flush writes any pending data into w.Dest.

func (*Writer) Reset

func (w *Writer) Reset(dest io.Writer)

Reset resets Writer to compress data into dest. Any not flushed data will be lost.

func (*Writer) Write

func (w *Writer) Write(p []byte) (n int, err error)

Write implements io.Writer.

Jump to

Keyboard shortcuts

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