lib/cosmos/streams/length_stream_protocol.rb in cosmos-3.5.1 vs lib/cosmos/streams/length_stream_protocol.rb in cosmos-3.5.2

- old
+ new

@@ -1,140 +1,140 @@ -# encoding: ascii-8bit - -# Copyright 2014 Ball Aerospace & Technologies Corp. -# All Rights Reserved. -# -# This program is free software; you can modify and/or redistribute it -# under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 3 with -# attribution addendums as found in the LICENSE.txt - -require 'cosmos/packets/binary_accessor' -require 'cosmos/streams/stream_protocol' -require 'cosmos/config/config_parser' - -module Cosmos - - # This StreamProtocol delineates packets using a length field at a fixed - # location in each packet. - class LengthStreamProtocol < StreamProtocol - - # @param length_bit_offset [Integer] The bit offset of the length field - # @param length_bit_size [Integer] The size in bits of the length field - # @param length_value_offset [Integer] 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. - # @param length_bytes_per_count [Integer] 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. - # @param length_endianness [String] The endianness of the length field. - # Must be either BIG_ENDIAN or LITTLE_ENDIAN. - # @param discard_leading_bytes (see StreamProtocol#initialize) - # @param sync_pattern (see StreamProtocol#initialize) - # @param max_length [Integer] The maximum allowed value of the length field - # @param fill_length_and_sync_pattern [Boolean] Fill the length field and sync - # pattern when writing packets - 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 - - # See StreamProtocol#pre_write_packet - 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 - - protected - - def reduce_to_single_packet - # Make sure we have at least enough data to reach the length field - read_minimum_size(@length_bytes_needed) - return nil if @data.length <= 0 - - # Determine the packet's length - length = BinaryAccessor.read(@length_bit_offset, - @length_bit_size, - :UINT, - @data, - @length_endianness) - raise "Length value received larger than max_length: #{length} > #{@max_length}" if @max_length and length > @max_length - packet_length = (length * @length_bytes_per_count) + @length_value_offset - - # Make sure we have enough data for the packet - read_minimum_size(packet_length) - return nil if @data.length <= 0 - - # Reduce to packet data and setup current_data for next packet - packet_data = @data[0..(packet_length - 1)] - @data.replace(@data[packet_length..-1]) - - packet_data - end - - end # class LengthStreamProtocol - -end # module Cosmos +# encoding: ascii-8bit + +# Copyright 2014 Ball Aerospace & Technologies Corp. +# All Rights Reserved. +# +# This program is free software; you can modify and/or redistribute it +# under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 3 with +# attribution addendums as found in the LICENSE.txt + +require 'cosmos/packets/binary_accessor' +require 'cosmos/streams/stream_protocol' +require 'cosmos/config/config_parser' + +module Cosmos + + # This StreamProtocol delineates packets using a length field at a fixed + # location in each packet. + class LengthStreamProtocol < StreamProtocol + + # @param length_bit_offset [Integer] The bit offset of the length field + # @param length_bit_size [Integer] The size in bits of the length field + # @param length_value_offset [Integer] 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. + # @param length_bytes_per_count [Integer] 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. + # @param length_endianness [String] The endianness of the length field. + # Must be either BIG_ENDIAN or LITTLE_ENDIAN. + # @param discard_leading_bytes (see StreamProtocol#initialize) + # @param sync_pattern (see StreamProtocol#initialize) + # @param max_length [Integer] The maximum allowed value of the length field + # @param fill_length_and_sync_pattern [Boolean] Fill the length field and sync + # pattern when writing packets + 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 + + # See StreamProtocol#pre_write_packet + 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 + + protected + + def reduce_to_single_packet + # Make sure we have at least enough data to reach the length field + read_minimum_size(@length_bytes_needed) + return nil if @data.length <= 0 + + # Determine the packet's length + length = BinaryAccessor.read(@length_bit_offset, + @length_bit_size, + :UINT, + @data, + @length_endianness) + raise "Length value received larger than max_length: #{length} > #{@max_length}" if @max_length and length > @max_length + packet_length = (length * @length_bytes_per_count) + @length_value_offset + + # Make sure we have enough data for the packet + read_minimum_size(packet_length) + return nil if @data.length <= 0 + + # Reduce to packet data and setup current_data for next packet + packet_data = @data[0..(packet_length - 1)] + @data.replace(@data[packet_length..-1]) + + packet_data + end + + end # class LengthStreamProtocol + +end # module Cosmos