Class: Cosmos::LengthStreamProtocol

Inherits:
StreamProtocol show all
Defined in:
lib/cosmos/streams/length_stream_protocol.rb

Overview

This StreamProtocol delineates packets using a length field at a fixed location in each packet.

Instance Attribute Summary

Attributes inherited from StreamProtocol

#bytes_read, #bytes_written, #interface, #post_read_data_callback, #post_read_packet_callback, #post_write_data_callback, #pre_write_packet_callback, #stream

Instance Method Summary collapse

Methods inherited from StreamProtocol

#connect, #connected?, #disconnect, #post_read_data, #post_read_packet, #post_write_data, #read, #write, #write_raw

Constructor Details

#initialize(length_bit_offset = 0, length_bit_size = 16, length_value_offset = 0, length_bytes_per_count = 1, length_endianness = 'BIG_ENDIAN', discard_leading_bytes = 0, sync_pattern = nil, max_length = nil, fill_length_and_sync_pattern = false) ⇒ LengthStreamProtocol

Returns a new instance of LengthStreamProtocol.

Parameters:

  • length_bit_offset (Integer) (defaults to: 0)

    The bit offset of the length field

  • length_bit_size (Integer) (defaults to: 16)

    The size in bits of the length field

  • length_value_offset (Integer) (defaults to: 0)

    The offset to apply to the length value once it has been read from the packet. The value in the length field itself plus the length value offset MUST equal the total bytes in the stream including any discarded bytes. For example: if your length field really means "length - 1" this value should be 1.

  • length_bytes_per_count (Integer) (defaults to: 1)

    The number of bytes per each length field 'count'. This is used if the units of the length field is something other than bytes, for example words.

  • length_endianness (String) (defaults to: 'BIG_ENDIAN')

    The endianness of the length field. Must be either BIG_ENDIAN or LITTLE_ENDIAN.

  • max_length (Integer) (defaults to: nil)

    The maximum allowed value of the length field

  • fill_length_and_sync_pattern (Boolean) (defaults to: false)

    Fill the length field and sync pattern when writing packets

  • discard_leading_bytes (Integer) (defaults to: 0)

    The number of bytes to discard from the binary data after reading from the Stream. Note that this is often used to remove a sync pattern from the final packet data.

  • sync_pattern (String) (defaults to: nil)

    String representing a hex number ("0x1234") that will be searched for in the raw Stream. Bytes encountered before this pattern is found are discarded.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/cosmos/streams/length_stream_protocol.rb', line 38

def initialize(
  length_bit_offset = 0,
  length_bit_size = 16,
  length_value_offset = 0,
  length_bytes_per_count = 1,
  length_endianness = 'BIG_ENDIAN',
  discard_leading_bytes = 0,
  sync_pattern = nil,
  max_length = nil,
  fill_length_and_sync_pattern = false
)
  super(discard_leading_bytes, sync_pattern, fill_length_and_sync_pattern)

  # Save length field attributes
  @length_bit_offset = Integer(length_bit_offset)
  @length_bit_size = Integer(length_bit_size)
  @length_value_offset = Integer(length_value_offset)
  @length_bytes_per_count = Integer(length_bytes_per_count)

  # Save endianness
  if length_endianness.to_s.upcase == 'LITTLE_ENDIAN'
    @length_endianness = :LITTLE_ENDIAN
  else
    @length_endianness = :BIG_ENDIAN
  end

  # Derive number of bytes required to contain entire length field
  if @length_endianness == :BIG_ENDIAN or ((@length_bit_offset % 8) == 0)
    length_bits_needed = @length_bit_offset + @length_bit_size
    length_bits_needed += 8 if (length_bits_needed % 8) != 0
    @length_bytes_needed = ((length_bits_needed - 1)/ 8) + 1
  else
    @length_bytes_needed = (length_bit_offset / 8) + 1
  end

  # Save max length setting
  @max_length = ConfigParser.handle_nil(max_length)
  @max_length = Integer(@max_length) if @max_length
end

Instance Method Details

#pre_write_packet(packet) ⇒ Object

See StreamProtocol#pre_write_packet



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/cosmos/streams/length_stream_protocol.rb', line 79

def pre_write_packet(packet)
  data = super(packet)
  if @fill_sync_pattern # and length
    # Fill the length field
    length = (data.length - @length_value_offset) / @length_bytes_per_count
    BinaryAccessor.write(length,
      @length_bit_offset,
      @length_bit_size,
      :UINT,
      data,
      @length_endianness,
      :ERROR)

    # Also write the new length field into the packet that will be logged if it exists in the packet
    if @discard_leading_bytes > 0
      # The write above did not write into the original packet
      original_length_bit_offset = @length_bit_offset - (@discard_leading_bytes * 8)
      if original_length_bit_offset >= 0
        original_data = packet.buffer(false)
        BinaryAccessor.write(length,
          original_length_bit_offset,
          @length_bit_size,
          :UINT,
          original_data,
          @length_endianness,
          :ERROR)
      end
    end
  end
  data
end