Class: Protocol::SP::Codec::Frame

Inherits:
Object
  • Object
show all
Defined in:
lib/protocol/sp/codec/frame.rb

Overview

SP/TCP frame encode/decode.

Wire format (per nng ‘src/sp/transport/tcp/tcp.c`):

8 bytes  body length, big-endian unsigned 64-bit
N bytes  body

SP messages are single-frame — there is no MORE flag and no multipart concept at the transport level.

Constant Summary collapse

HEADER_SIZE =
8
EMPTY_BODY =
"".b.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(body) ⇒ Frame

Returns a new instance of Frame.

Parameters:

  • body (String)

    frame body



25
26
27
# File 'lib/protocol/sp/codec/frame.rb', line 25

def initialize(body)
  @body = body.encoding == Encoding::BINARY ? body : body.b
end

Instance Attribute Details

#bodyString (readonly)

Returns frame body (binary).

Returns:

  • (String)

    frame body (binary)



21
22
23
# File 'lib/protocol/sp/codec/frame.rb', line 21

def body
  @body
end

Class Method Details

.encode(body) ⇒ String

Encodes a body into wire bytes without allocating a Frame.

Parameters:

  • body (String)

Returns:

  • (String)

    frozen binary wire representation



42
43
44
45
# File 'lib/protocol/sp/codec/frame.rb', line 42

def self.encode(body)
  body = body.encoding == Encoding::BINARY ? body : body.b
  ([body.bytesize].pack("Q>") << body).freeze
end

.read_from(io, max_message_size: nil) ⇒ Frame

Reads one frame from an IO-like object.

Parameters:

  • io (#read_exactly)

    must support read_exactly(n)

  • max_message_size (Integer, nil) (defaults to: nil)

    maximum body size, nil = unlimited

Returns:

Raises:

  • (Error)

    on oversized frame

  • (EOFError)

    if the connection is closed



55
56
57
58
59
60
61
62
63
64
# File 'lib/protocol/sp/codec/frame.rb', line 55

def self.read_from(io, max_message_size: nil)
  size = io.read_exactly(HEADER_SIZE).unpack1("Q>")

  if max_message_size && size > max_message_size
    raise Error, "frame size #{size} exceeds max_message_size #{max_message_size}"
  end

  body = size > 0 ? io.read_exactly(size) : EMPTY_BODY
  new(body)
end

Instance Method Details

#to_wireString

Encodes to wire bytes.

Returns:

  • (String)

    binary wire representation (length + body)



33
34
35
# File 'lib/protocol/sp/codec/frame.rb', line 33

def to_wire
  [@body.bytesize].pack("Q>") << @body
end