WebsockexNova.Gun.FrameCodec (WebsockexNova v0.1.0)

View Source

Handles encoding and decoding of WebSocket frames.

This module provides functionality for working with WebSocket frames in Gun. It handles various frame types (text, binary, ping, pong, close) and provides utilities for validating frames and working with close codes.

The module uses a pluggable handler system that allows for custom frame handlers to be registered, supporting extensions like permessage-deflate and other WebSocket extensions.

Gun WebSocket frames are represented as:

  • {:text, binary()} - Text frames
  • {:binary, binary()} - Binary frames
  • :ping or {:ping, binary()} - Ping frames
  • :pong or {:pong, binary()} - Pong frames
  • :close or {:close, code()} or {:close, code(), binary()} - Close frames

Summary

Functions

Returns the meaning of a WebSocket close code.

Decodes a WebSocket frame received from Gun.

Encodes a WebSocket frame for sending via Gun.

Gets the handler module for a specific frame type.

Determines the frame type of a WebSocket frame.

Initializes the ETS table for frame handlers.

Registers a custom frame handler for a specific frame type.

Checks if a WebSocket close code is valid.

Validates a WebSocket close code.

Validates the size of a control frame payload.

Validates a WebSocket frame.

Types

decode_result()

@type decode_result() :: {:ok, frame()} | {:error, atom()}

frame()

@type frame() ::
  {:text, binary()}
  | {:binary, binary()}
  | :ping
  | {:ping, binary()}
  | :pong
  | {:pong, binary()}
  | :close
  | {:close, non_neg_integer()}
  | {:close, non_neg_integer(), binary()}

validate_result()

@type validate_result() :: :ok | {:error, atom()}

Functions

close_code_meaning(arg1)

@spec close_code_meaning(non_neg_integer()) :: String.t()

Returns the meaning of a WebSocket close code.

Examples

iex> WebsockexNova.Gun.FrameCodec.close_code_meaning(1000)
"Normal closure"

iex> WebsockexNova.Gun.FrameCodec.close_code_meaning(3000)
"Unknown close code"

decode_frame(frame)

@spec decode_frame(tuple() | atom()) :: decode_result()

Decodes a WebSocket frame received from Gun.

Takes a frame in the Gun format and converts it to the internal format. Uses the appropriate frame handler based on the frame type.

Examples

iex> WebsockexNova.Gun.FrameCodec.decode_frame({:text, "Hello"})
{:ok, {:text, "Hello"}}

iex> WebsockexNova.Gun.FrameCodec.decode_frame(:ping)
{:ok, :ping}

iex> WebsockexNova.Gun.FrameCodec.decode_frame({:close, 1000, "Normal closure"})
{:ok, {:close, 1000, "Normal closure"}}

encode_frame(frame)

@spec encode_frame(frame()) :: tuple() | atom()

Encodes a WebSocket frame for sending via Gun.

Takes a frame in the internal format and converts it to the format expected by Gun. Uses the appropriate frame handler based on the frame type.

Examples

iex> WebsockexNova.Gun.FrameCodec.encode_frame({:text, "Hello"})
{:text, "Hello"}

iex> WebsockexNova.Gun.FrameCodec.encode_frame(:ping)
:ping

iex> WebsockexNova.Gun.FrameCodec.encode_frame({:close, 1000, "Normal closure"})
{:close, 1000, "Normal closure"}

frame_handler_for(frame_type)

@spec frame_handler_for(atom()) :: module()

Gets the handler module for a specific frame type.

Uses the built-in handler registry, which can be extended at runtime with register_frame_handler/2.

Parameters

  • frame_type - The type of frame to get a handler for

Returns

The handler module for the specified frame type

frame_type(arg1)

@spec frame_type(frame()) :: atom()

Determines the frame type of a WebSocket frame.

Parameters

  • frame - The WebSocket frame

Returns

The frame type as an atom (:text, :binary, etc.)

init_handlers_table()

@spec init_handlers_table() :: :ok | {:error, :table_exists}

Initializes the ETS table for frame handlers.

This function creates the ETS table for storing frame handlers if it doesn't exist yet. It is called once at application startup to ensure the table exists before it's accessed.

Returns

  • :ok - When the table is successfully initialized
  • {:error, :table_exists} - When the table already exists

register_frame_handler(frame_type, handler_module)

@spec register_frame_handler(atom(), module() | nil) :: :ok | {:error, :table_missing}

Registers a custom frame handler for a specific frame type.

This allows for extending the WebSocket frame handling with custom implementations, such as for handling extensions.

Parameters

  • frame_type - The type of frame to register a handler for
  • handler_module - The module that implements the handler behavior

Returns

  • :ok - If the handler was registered successfully
  • {:error, :table_missing} - If the handler registry table doesn't exist

valid_close_code?(code)

@spec valid_close_code?(non_neg_integer()) :: boolean()

Checks if a WebSocket close code is valid.

Examples

iex> WebsockexNova.Gun.FrameCodec.valid_close_code?(1000)
true

iex> WebsockexNova.Gun.FrameCodec.valid_close_code?(999)
false

validate_close_code(code)

@spec validate_close_code(non_neg_integer()) :: validate_result()

Validates a WebSocket close code.

Examples

iex> WebsockexNova.Gun.FrameCodec.validate_close_code(1000)
:ok

iex> WebsockexNova.Gun.FrameCodec.validate_close_code(999)
{:error, :invalid_close_code}

iex> WebsockexNova.Gun.FrameCodec.validate_close_code(1005)
{:error, :reserved_close_code}

validate_control_frame_size(data)

@spec validate_control_frame_size(binary()) :: validate_result()

Validates the size of a control frame payload.

WebSocket protocol limits control frame payloads to 125 bytes.

Parameters

  • data - Binary payload data to validate

Returns

  • :ok - If the payload size is valid
  • {:error, :control_frame_too_large} - If payload exceeds 125 bytes

validate_frame(frame)

@spec validate_frame(frame()) :: validate_result()

Validates a WebSocket frame.

Checks if a frame is valid according to the WebSocket spec. Uses the appropriate frame handler based on the frame type.

Examples

iex> WebsockexNova.Gun.FrameCodec.validate_frame({:text, "Hello"})
:ok

iex> WebsockexNova.Gun.FrameCodec.validate_frame({:text, nil})
{:error, :invalid_text_data}

iex> WebsockexNova.Gun.FrameCodec.validate_frame({:close, 1000})
:ok