lib/mqtt/packet.rb in mqtt-0.5.0 vs lib/mqtt/packet.rb in mqtt-0.6.0
- old
+ new
@@ -1,12 +1,11 @@
# encoding: BINARY
module MQTT
-
# Class representing a MQTT Packet
# Performs binary encoding and decoding of headers
- class MQTT::Packet
+ class Packet
# The version number of the MQTT protocol to use (default 3.1.0)
attr_accessor :version
# Identifier to link related control packets together
attr_accessor :id
@@ -34,110 +33,113 @@
# Read in the packet length
multiplier = 1
body_length = 0
pos = 1
- begin
+
+ loop do
digit = read_byte(socket)
body_length += ((digit & 0x7F) * multiplier)
multiplier *= 0x80
pos += 1
- end while ((digit & 0x80) != 0x00) and pos <= 4
+ break if (digit & 0x80).zero? || pos > 4
+ end
# Store the expected body length in the packet
packet.instance_variable_set('@body_length', body_length)
# Read in the packet body
- packet.parse_body( socket.read(body_length) )
+ packet.parse_body(socket.read(body_length))
- return packet
+ packet
end
# Parse buffer into new packet object
def self.parse(buffer)
packet = parse_header(buffer)
packet.parse_body(buffer)
- return packet
+ packet
end
# Parse the header and create a new packet object of the correct type
# The header is removed from the buffer passed into this function
def self.parse_header(buffer)
# Check that the packet is a long as the minimum packet size
if buffer.bytesize < 2
- raise ProtocolException.new("Invalid packet: less than 2 bytes long")
+ raise ProtocolException, 'Invalid packet: less than 2 bytes long'
end
# Create a new packet object
- bytes = buffer.unpack("C5")
+ bytes = buffer.unpack('C5')
packet = create_from_header(bytes.first)
packet.validate_flags
# Parse the packet length
body_length = 0
multiplier = 1
pos = 1
- begin
+
+ loop do
if buffer.bytesize <= pos
- raise ProtocolException.new("The packet length header is incomplete")
+ raise ProtocolException, 'The packet length header is incomplete'
end
+
digit = bytes[pos]
body_length += ((digit & 0x7F) * multiplier)
multiplier *= 0x80
pos += 1
- end while ((digit & 0x80) != 0x00) and pos <= 4
+ break if (digit & 0x80).zero? || pos > 4
+ end
# Store the expected body length in the packet
packet.instance_variable_set('@body_length', body_length)
# Delete the fixed header from the raw packet passed in
buffer.slice!(0...pos)
- return packet
+ packet
end
# Create a new packet object from the first byte of a MQTT packet
def self.create_from_header(byte)
# Work out the class
type_id = ((byte & 0xF0) >> 4)
packet_class = MQTT::PACKET_TYPES[type_id]
if packet_class.nil?
- raise ProtocolException.new("Invalid packet type identifier: #{type_id}")
+ raise ProtocolException, "Invalid packet type identifier: #{type_id}"
end
# Convert the last 4 bits of byte into array of true/false
- flags = (0..3).map { |i| byte & (2 ** i) != 0 }
+ flags = (0..3).map { |i| byte & (2**i) != 0 }
# Create a new packet object
packet_class.new(:flags => flags)
end
# Create a new empty packet
- def initialize(args={})
+ def initialize(args = {})
# We must set flags before the other values
@flags = [false, false, false, false]
update_attributes(ATTR_DEFAULTS.merge(args))
end
# Set packet attributes from a hash of attribute names and values
- def update_attributes(attr={})
- attr.each_pair do |k,v|
- if v.is_a?(Array) or v.is_a?(Hash)
+ def update_attributes(attr = {})
+ attr.each_pair do |k, v|
+ if v.is_a?(Array) || v.is_a?(Hash)
send("#{k}=", v.dup)
else
send("#{k}=", v)
end
end
end
# Get the identifer for this packet type
def type_id
index = MQTT::PACKET_TYPES.index(self.class)
- if index.nil?
- raise "Invalid packet type: #{self.class}"
- end
- return index
+ raise "Invalid packet type: #{self.class}" if index.nil?
+ index
end
# Get the name of the packet type as a string in capitals
# (like the MQTT specification uses)
#
@@ -156,83 +158,90 @@
@body_length = arg.to_i
end
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
- if buffer.bytesize != body_length
- raise ProtocolException.new(
- "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
- )
- end
+ return if buffer.bytesize == body_length
+
+ raise ProtocolException, "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
end
# Get serialisation of packet's body (variable header and payload)
def encode_body
'' # No body by default
end
-
# Serialise the packet
def to_s
# Encode the fixed header
header = [
((type_id.to_i & 0x0F) << 4) |
- (flags[3] ? 0x8 : 0x0) |
- (flags[2] ? 0x4 : 0x0) |
- (flags[1] ? 0x2 : 0x0) |
- (flags[0] ? 0x1 : 0x0)
+ (flags[3] ? 0x8 : 0x0) |
+ (flags[2] ? 0x4 : 0x0) |
+ (flags[1] ? 0x2 : 0x0) |
+ (flags[0] ? 0x1 : 0x0)
]
# Get the packet's variable header and payload
- body = self.encode_body
+ body = encode_body
# Check that that packet isn't too big
body_length = body.bytesize
- if body_length > 268435455
- raise "Error serialising packet: body is more than 256MB"
+ if body_length > 268_435_455
+ raise 'Error serialising packet: body is more than 256MB'
end
# Build up the body length field bytes
- begin
+ loop do
digit = (body_length % 128)
body_length = body_length.div(128)
# if there are more digits to encode, set the top bit of this digit
- digit |= 0x80 if (body_length > 0)
+ digit |= 0x80 if body_length > 0
header.push(digit)
- end while (body_length > 0)
+ break if body_length <= 0
+ end
# Convert header to binary and add on body
header.pack('C*') + body
end
# Check that fixed header flags are valid for types that don't use the flags
# @private
def validate_flags
- if flags != [false, false, false, false]
- raise ProtocolException.new("Invalid flags in #{type_name} packet header")
- end
+ return if flags == [false, false, false, false]
+
+ raise ProtocolException, "Invalid flags in #{type_name} packet header"
end
# Returns a human readable string
def inspect
"\#<#{self.class}>"
end
+ # Read and unpack a single byte from a socket
+ def self.read_byte(socket)
+ byte = socket.getbyte
+ raise ProtocolException, 'Failed to read byte from socket' if byte.nil?
+
+ byte
+ end
+
protected
# Encode an array of bytes and return them
def encode_bytes(*bytes)
bytes.pack('C*')
end
# Encode an array of bits and return them
def encode_bits(bits)
- [bits.map{|b| b ? '1' : '0'}.join].pack('b*')
+ [bits.map { |b| b ? '1' : '0' }.join].pack('b*')
end
# Encode a 16-bit unsigned integer and return it
def encode_short(val)
+ raise 'Value too big for short' if val > 0xffff
[val.to_i].pack('n')
end
# Encode a UTF-8 string and return it
# (preceded by the length of the string)
@@ -255,46 +264,30 @@
buffer.slice!(0...1).unpack('C').first
end
# Remove 8 bits from the front of buffer
def shift_bits(buffer)
- buffer.slice!(0...1).unpack('b8').first.split('').map {|b| b == '1'}
+ buffer.slice!(0...1).unpack('b8').first.split('').map { |b| b == '1' }
end
# Remove n bytes from the front of buffer
- def shift_data(buffer,bytes)
+ def shift_data(buffer, bytes)
buffer.slice!(0...bytes)
end
# Remove string from the front of buffer
def shift_string(buffer)
len = shift_short(buffer)
- str = shift_data(buffer,len)
+ str = shift_data(buffer, len)
# Strings in MQTT v3.1 are all UTF-8
str.force_encoding('UTF-8')
end
-
- private
-
- # Read and unpack a single byte from a socket
- def self.read_byte(socket)
- byte = socket.read(1)
- if byte.nil?
- raise ProtocolException.new("Failed to read byte from socket")
- end
- byte.unpack('C').first
- end
-
-
-
## PACKET SUBCLASSES ##
-
# Class representing an MQTT Publish message
class Publish < MQTT::Packet
-
# Duplicate delivery flag
attr_accessor :duplicate
# Retain flag
attr_accessor :retain
@@ -313,102 +306,88 @@
:topic => nil,
:payload => ''
}
# Create a new Publish packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
end
def duplicate
@flags[3]
end
# Set the DUP flag (true/false)
def duplicate=(arg)
- if arg.kind_of?(Integer)
- @flags[3] = (arg == 0x1)
- else
- @flags[3] = arg
- end
+ @flags[3] = arg.is_a?(Integer) ? (arg == 0x1) : arg
end
def retain
@flags[0]
end
# Set the retain flag (true/false)
def retain=(arg)
- if arg.kind_of?(Integer)
- @flags[0] = (arg == 0x1)
- else
- @flags[0] = arg
- end
+ @flags[0] = arg.is_a?(Integer) ? (arg == 0x1) : arg
end
def qos
(@flags[1] ? 0x01 : 0x00) | (@flags[2] ? 0x02 : 0x00)
end
# Set the Quality of Service level (0/1/2)
def qos=(arg)
@qos = arg.to_i
- if @qos < 0 or @qos > 2
- raise "Invalid QoS value: #{@qos}"
- else
- @flags[1] = (arg & 0x01 == 0x01)
- @flags[2] = (arg & 0x02 == 0x02)
- end
+ raise "Invalid QoS value: #{@qos}" if @qos < 0 || @qos > 2
+
+ @flags[1] = (arg & 0x01 == 0x01)
+ @flags[2] = (arg & 0x02 == 0x02)
end
# Get serialisation of packet's body
def encode_body
body = ''
- if @topic.nil? or @topic.to_s.empty?
- raise "Invalid topic name when serialising packet"
+ if @topic.nil? || @topic.to_s.empty?
+ raise 'Invalid topic name when serialising packet'
end
body += encode_string(@topic)
- body += encode_short(@id) unless qos == 0
+ body += encode_short(@id) unless qos.zero?
body += payload.to_s.dup.force_encoding('ASCII-8BIT')
- return body
+ body
end
# Parse the body (variable header and payload) of a Publish packet
def parse_body(buffer)
super(buffer)
@topic = shift_string(buffer)
- @id = shift_short(buffer) unless qos == 0
+ @id = shift_short(buffer) unless qos.zero?
@payload = buffer
end
# Check that fixed header flags are valid for this packet type
# @private
def validate_flags
- if qos == 3
- raise ProtocolException.new("Invalid packet: QoS value of 3 is not allowed")
- end
- if qos == 0 and duplicate
- raise ProtocolException.new("Invalid packet: DUP cannot be set for QoS 0")
- end
+ raise ProtocolException, 'Invalid packet: QoS value of 3 is not allowed' if qos == 3
+ raise ProtocolException, 'Invalid packet: DUP cannot be set for QoS 0' if qos.zero? && duplicate
end
# Returns a human readable string, summarising the properties of the packet
def inspect
- "\#<#{self.class}: " +
- "d#{duplicate ? '1' : '0'}, " +
- "q#{qos}, " +
- "r#{retain ? '1' : '0'}, " +
- "m#{id}, " +
- "'#{topic}', " +
- "#{inspect_payload}>"
+ "\#<#{self.class}: " \
+ "d#{duplicate ? '1' : '0'}, " \
+ "q#{qos}, " \
+ "r#{retain ? '1' : '0'}, " \
+ "m#{id}, " \
+ "'#{topic}', " \
+ "#{inspect_payload}>"
end
protected
def inspect_payload
str = payload.to_s
- if str.bytesize < 16 and str =~ /^[ -~]*$/
+ if str.bytesize < 16 && str =~ /^[ -~]*$/
"'#{str}'"
else
"... (#{str.bytesize} bytes)"
end
end
@@ -457,43 +436,42 @@
:will_topic => nil,
:will_qos => 0,
:will_retain => false,
:will_payload => '',
:username => nil,
- :password => nil,
+ :password => nil
}
# Create a new Client Connect packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
- if version == '3.1.0' or version == '3.1'
+ if version == '3.1.0' || version == '3.1'
self.protocol_name ||= 'MQIsdp'
self.protocol_level ||= 0x03
elsif version == '3.1.1'
self.protocol_name ||= 'MQTT'
self.protocol_level ||= 0x04
else
- raise ArgumentError.new("Unsupported protocol version: #{version}")
+ raise ArgumentError, "Unsupported protocol version: #{version}"
end
end
# Get serialisation of packet's body
def encode_body
body = ''
+
if @version == '3.1.0'
- if @client_id.nil? or @client_id.bytesize < 1
- raise "Client identifier too short while serialising packet"
- elsif @client_id.bytesize > 23
- raise "Client identifier too long when serialising packet"
- end
+ raise 'Client identifier too short while serialising packet' if @client_id.nil? || @client_id.bytesize < 1
+ raise 'Client identifier too long when serialising packet' if @client_id.bytesize > 23
end
+
body += encode_string(@protocol_name)
body += encode_bytes(@protocol_level.to_i)
if @keep_alive < 0
- raise "Invalid keep-alive value: cannot be less than 0"
+ raise 'Invalid keep-alive value: cannot be less than 0'
end
# Set the Connect flags
@connect_flags = 0
@connect_flags |= 0x02 if @clean_session
@@ -511,26 +489,24 @@
# The MQTT v3.1 specification says that the payload is a UTF-8 string
body += encode_string(@will_payload)
end
body += encode_string(@username) unless @username.nil?
body += encode_string(@password) unless @password.nil?
- return body
+ body
end
# Parse the body (variable header and payload) of a Connect packet
def parse_body(buffer)
super(buffer)
@protocol_name = shift_string(buffer)
@protocol_level = shift_byte(buffer).to_i
- if @protocol_name == 'MQIsdp' and @protocol_level == 3
+ if @protocol_name == 'MQIsdp' && @protocol_level == 3
@version = '3.1.0'
- elsif @protocol_name == 'MQTT' and @protocol_level == 4
+ elsif @protocol_name == 'MQTT' && @protocol_level == 4
@version = '3.1.1'
else
- raise ProtocolException.new(
- "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
- )
+ raise ProtocolException, "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
end
@connect_flags = shift_byte(buffer)
@clean_session = ((@connect_flags & 0x02) >> 1) == 0x01
@keep_alive = shift_short(buffer)
@@ -541,31 +517,30 @@
@will_retain = ((@connect_flags & 0x20) >> 5) == 0x01
@will_topic = shift_string(buffer)
# The MQTT v3.1 specification says that the payload is a UTF-8 string
@will_payload = shift_string(buffer)
end
- if ((@connect_flags & 0x80) >> 7) == 0x01 and buffer.bytesize > 0
+ if ((@connect_flags & 0x80) >> 7) == 0x01 && buffer.bytesize > 0
@username = shift_string(buffer)
end
- if ((@connect_flags & 0x40) >> 6) == 0x01 and buffer.bytesize > 0
+ if ((@connect_flags & 0x40) >> 6) == 0x01 && buffer.bytesize > 0 # rubocop: disable Style/GuardClause
@password = shift_string(buffer)
end
end
# Returns a human readable string, summarising the properties of the packet
def inspect
- str = "\#<#{self.class}: "
- str += "keep_alive=#{keep_alive}"
- str += ", clean" if clean_session
+ str = "\#<#{self.class}: " \
+ "keep_alive=#{keep_alive}"
+ str += ', clean' if clean_session
str += ", client_id='#{client_id}'"
str += ", username='#{username}'" unless username.nil?
- str += ", password=..." unless password.nil?
- str += ">"
+ str += ', password=...' unless password.nil?
+ str + '>'
end
# ---- Deprecated attributes and methods ---- #
- public
# @deprecated Please use {#protocol_level} instead
def protocol_version
protocol_level
end
@@ -583,14 +558,14 @@
# The return code (defaults to 0 for connection accepted)
attr_accessor :return_code
# Default attribute values
- ATTR_DEFAULTS = {:return_code => 0x00}
+ ATTR_DEFAULTS = { :return_code => 0x00 }
# Create a new Client Connect packet
- def initialize(args={})
+ def initialize(args = {})
# We must set flags before other attributes
@connack_flags = [false, false, false, false, false, false, false, false]
super(ATTR_DEFAULTS.merge(args))
end
@@ -599,56 +574,52 @@
@connack_flags[0]
end
# Set the Session Present flag
def session_present=(arg)
- if arg.kind_of?(Integer)
- @connack_flags[0] = (arg == 0x1)
- else
- @connack_flags[0] = arg
- end
+ @connack_flags[0] = arg.is_a?(Integer) ? (arg == 0x1) : arg
end
# Get a string message corresponding to a return code
def return_msg
case return_code
- when 0x00
- "Connection Accepted"
- when 0x01
- "Connection refused: unacceptable protocol version"
- when 0x02
- "Connection refused: client identifier rejected"
- when 0x03
- "Connection refused: server unavailable"
- when 0x04
- "Connection refused: bad user name or password"
- when 0x05
- "Connection refused: not authorised"
- else
- "Connection refused: error code #{return_code}"
+ when 0x00
+ 'Connection Accepted'
+ when 0x01
+ 'Connection refused: unacceptable protocol version'
+ when 0x02
+ 'Connection refused: client identifier rejected'
+ when 0x03
+ 'Connection refused: server unavailable'
+ when 0x04
+ 'Connection refused: bad user name or password'
+ when 0x05
+ 'Connection refused: not authorised'
+ else
+ "Connection refused: error code #{return_code}"
end
end
# Get serialisation of packet's body
def encode_body
body = ''
body += encode_bits(@connack_flags)
body += encode_bytes(@return_code.to_i)
- return body
+ body
end
# Parse the body (variable header and payload) of a Connect Acknowledgment packet
def parse_body(buffer)
super(buffer)
@connack_flags = shift_bits(buffer)
- unless @connack_flags[1,7] == [false, false, false, false, false, false, false]
- raise ProtocolException.new("Invalid flags in Connack variable header")
+ unless @connack_flags[1, 7] == [false, false, false, false, false, false, false]
+ raise ProtocolException, 'Invalid flags in Connack variable header'
end
@return_code = shift_byte(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Connect Acknowledgment packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Connect Acknowledgment packet'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % return_code
@@ -664,13 +635,13 @@
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Publish Acknowledgment packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Publish Acknowledgment packet'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % id
@@ -686,31 +657,30 @@
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Publish Received packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Publish Received packet'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % id
end
end
# Class representing an MQTT Publish Release packet
class Pubrel < MQTT::Packet
-
# Default attribute values
ATTR_DEFAULTS = {
- :flags => [false, true, false, false],
+ :flags => [false, true, false, false]
}
# Create a new Pubrel packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
end
# Get serialisation of packet's body
def encode_body
@@ -719,21 +689,20 @@
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Publish Release packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Publish Release packet'
end
# Check that fixed header flags are valid for this packet type
# @private
def validate_flags
- if @flags != [false, true, false, false]
- raise ProtocolException.new("Invalid flags in PUBREL packet header")
- end
+ return if @flags == [false, true, false, false]
+ raise ProtocolException, 'Invalid flags in PUBREL packet header'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % id
@@ -749,13 +718,13 @@
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Publish Complete packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Publish Complete packet'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % id
@@ -768,15 +737,15 @@
attr_accessor :topics
# Default attribute values
ATTR_DEFAULTS = {
:topics => [],
- :flags => [false, true, false, false],
+ :flags => [false, true, false, false]
}
# Create a new Subscribe packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
end
# Set one or more topic filters for the Subscribe packet
# The topics parameter should be one of the following:
@@ -790,29 +759,25 @@
# packet.topics = [['a/b',0], ['c/d',1]]
# packet.topics = {'a/b' => 0, 'c/d' => 1}
#
def topics=(value)
# Get input into a consistent state
- if value.is_a?(Array)
- input = value.flatten
- else
- input = [value]
- end
+ input = value.is_a?(Array) ? value.flatten : [value]
@topics = []
- while(input.length>0)
+ until input.empty?
item = input.shift
if item.is_a?(Hash)
# Convert hash into an ordered array of arrays
@topics += item.sort
elsif item.is_a?(String)
# Peek at the next item in the array, and remove it if it is an integer
if input.first.is_a?(Integer)
qos = input.shift
- @topics << [item,qos]
+ @topics << [item, qos]
else
- @topics << [item,0]
+ @topics << [item, 0]
end
else
# Meh?
raise "Invalid topics input: #{value.inspect}"
end
@@ -820,46 +785,43 @@
@topics
end
# Get serialisation of packet's body
def encode_body
- if @topics.empty?
- raise "no topics given when serialising packet"
- end
+ raise 'no topics given when serialising packet' if @topics.empty?
body = encode_short(@id)
topics.each do |item|
body += encode_string(item[0])
body += encode_bytes(item[1])
end
- return body
+ body
end
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
@topics = []
- while(buffer.bytesize>0)
+ while buffer.bytesize > 0
topic_name = shift_string(buffer)
topic_qos = shift_byte(buffer)
- @topics << [topic_name,topic_qos]
+ @topics << [topic_name, topic_qos]
end
end
# Check that fixed header flags are valid for this packet type
# @private
def validate_flags
- if @flags != [false, true, false, false]
- raise ProtocolException.new("Invalid flags in SUBSCRIBE packet header")
- end
+ return if @flags == [false, true, false, false]
+ raise ProtocolException, 'Invalid flags in SUBSCRIBE packet header'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
_str = "\#<#{self.class}: 0x%2.2X, %s>" % [
id,
- topics.map {|t| "'#{t[0]}':#{t[1]}"}.join(', ')
+ topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(', ')
]
end
end
# Class representing an MQTT Subscribe Acknowledgment packet
@@ -867,15 +829,15 @@
# An array of return codes, ordered by the topics that were subscribed to
attr_accessor :return_codes
# Default attribute values
ATTR_DEFAULTS = {
- :return_codes => [],
+ :return_codes => []
}
# Create a new Subscribe Acknowledgment packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
end
# Set the granted QoS value for each of the topics that were subscribed to
# Can either be an integer or an array or integers.
@@ -883,40 +845,37 @@
if value.is_a?(Array)
@return_codes = value
elsif value.is_a?(Integer)
@return_codes = [value]
else
- raise "return_codes should be an integer or an array of return codes"
+ raise 'return_codes should be an integer or an array of return codes'
end
end
# Get serialisation of packet's body
def encode_body
if @return_codes.empty?
- raise "no granted QoS given when serialising packet"
+ raise 'no granted QoS given when serialising packet'
end
body = encode_short(@id)
return_codes.each { |qos| body += encode_bytes(qos) }
- return body
+ body
end
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- while(buffer.bytesize>0)
- @return_codes << shift_byte(buffer)
- end
+ @return_codes << shift_byte(buffer) while buffer.bytesize > 0
end
# Returns a human readable string, summarising the properties of the packet
def inspect
- "\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map{|rc| "0x%2.2X" % rc}.join(',')]
+ "\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map { |rc| '0x%2.2X' % rc }.join(',')]
end
# ---- Deprecated attributes and methods ---- #
- public
# @deprecated Please use {#return_codes} instead
def granted_qos
return_codes
end
@@ -933,67 +892,58 @@
attr_accessor :topics
# Default attribute values
ATTR_DEFAULTS = {
:topics => [],
- :flags => [false, true, false, false],
+ :flags => [false, true, false, false]
}
# Create a new Unsubscribe packet
- def initialize(args={})
+ def initialize(args = {})
super(ATTR_DEFAULTS.merge(args))
end
# Set one or more topic paths to unsubscribe from
def topics=(value)
- if value.is_a?(Array)
- @topics = value
- else
- @topics = [value]
- end
+ @topics = value.is_a?(Array) ? value : [value]
end
# Get serialisation of packet's body
def encode_body
- if @topics.empty?
- raise "no topics given when serialising packet"
- end
+ raise 'no topics given when serialising packet' if @topics.empty?
body = encode_short(@id)
topics.each { |topic| body += encode_string(topic) }
- return body
+ body
end
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- while(buffer.bytesize>0)
- @topics << shift_string(buffer)
- end
+ @topics << shift_string(buffer) while buffer.bytesize > 0
end
# Check that fixed header flags are valid for this packet type
# @private
def validate_flags
- if @flags != [false, true, false, false]
- raise ProtocolException.new("Invalid flags in UNSUBSCRIBE packet header")
- end
+ return if @flags == [false, true, false, false]
+ raise ProtocolException, 'Invalid flags in UNSUBSCRIBE packet header'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X, %s>" % [
id,
- topics.map {|t| "'#{t}'"}.join(', ')
+ topics.map { |t| "'#{t}'" }.join(', ')
]
end
end
# Class representing an MQTT Unsubscribe Acknowledgment packet
class Unsuback < MQTT::Packet
# Create a new Unsubscribe Acknowledgment packet
- def initialize(args={})
+ def initialize(args = {})
super(args)
end
# Get serialisation of packet's body
def encode_body
@@ -1002,13 +952,13 @@
# Parse the body (variable header and payload) of a packet
def parse_body(buffer)
super(buffer)
@id = shift_short(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Unsubscribe Acknowledgment packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Unsubscribe Acknowledgment packet'
end
# Returns a human readable string, summarising the properties of the packet
def inspect
"\#<#{self.class}: 0x%2.2X>" % id
@@ -1016,56 +966,55 @@
end
# Class representing an MQTT Ping Request packet
class Pingreq < MQTT::Packet
# Create a new Ping Request packet
- def initialize(args={})
+ def initialize(args = {})
super(args)
end
# Check the body
def parse_body(buffer)
super(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Ping Request packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Ping Request packet'
end
end
# Class representing an MQTT Ping Response packet
class Pingresp < MQTT::Packet
# Create a new Ping Response packet
- def initialize(args={})
+ def initialize(args = {})
super(args)
end
# Check the body
def parse_body(buffer)
super(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Ping Response packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Ping Response packet'
end
end
# Class representing an MQTT Client Disconnect packet
class Disconnect < MQTT::Packet
# Create a new Client Disconnect packet
- def initialize(args={})
+ def initialize(args = {})
super(args)
end
# Check the body
def parse_body(buffer)
super(buffer)
- unless buffer.empty?
- raise ProtocolException.new("Extra bytes at end of Disconnect packet")
- end
+
+ return if buffer.empty?
+ raise ProtocolException, 'Extra bytes at end of Disconnect packet'
end
end
-
# ---- Deprecated attributes and methods ---- #
public
# @deprecated Please use {#id} instead
def message_id
@@ -1076,11 +1025,10 @@
def message_id=(args)
self.id = args
end
end
-
# An enumeration of the MQTT packet types
PACKET_TYPES = [
nil,
MQTT::Packet::Connect,
MQTT::Packet::Connack,
@@ -1096,7 +1044,6 @@
MQTT::Packet::Pingreq,
MQTT::Packet::Pingresp,
MQTT::Packet::Disconnect,
nil
]
-
end