Class: MQTT::Packet
- Inherits:
-
Object
- Object
- MQTT::Packet
- Defined in:
- lib/mqtt/packet.rb
Overview
Class representing a MQTT Packet Performs binary encoding and decoding of headers
Constant Summary
- DEFAULTS =
{ :duplicate => false, :qos => 0, :retain => false, :body_length => nil }
Instance Attribute Summary (collapse)
-
- (Object) body_length
Duplicate delivery flag Retain flag Quality of Service level The length of the parsed packet body.
-
- (Object) duplicate
Returns the value of attribute duplicate.
-
- (Object) qos
Returns the value of attribute qos.
-
- (Object) retain
Returns the value of attribute retain.
Class Method Summary (collapse)
-
+ (Object) parse(buffer)
Parse buffer into new packet object.
-
+ (Object) parse_header(buffer)
Parse the header and create a new packet object of the correct type The header is removed from the buffer passed into this function.
-
+ (Object) read(socket)
Read in a packet from a socket.
Instance Method Summary (collapse)
-
- (Object) encode_body
Get serialisation of packet's body (variable header and payload).
-
- (Packet) initialize(args = {})
constructor
Create a new empty packet.
-
- (Object) parse_body(buffer)
Parse the body (variable header and payload) of a packet.
-
- (Object) to_s
Serialise the packet.
-
- (Object) type_id
Get the identifer for this packet type.
- - (Object) update_attributes(attr = {})
Constructor Details
- (Packet) initialize(args = {})
Create a new empty packet
100 101 102 |
# File 'lib/mqtt/packet.rb', line 100 def initialize(args={}) update_attributes(DEFAULTS.merge(args)) end |
Instance Attribute Details
- (Object) body_length
Duplicate delivery flag Retain flag Quality of Service level The length of the parsed packet body
9 10 11 |
# File 'lib/mqtt/packet.rb', line 9 def body_length @body_length end |
- (Object) duplicate
Returns the value of attribute duplicate
6 7 8 |
# File 'lib/mqtt/packet.rb', line 6 def duplicate @duplicate end |
- (Object) qos
Returns the value of attribute qos
8 9 10 |
# File 'lib/mqtt/packet.rb', line 8 def qos @qos end |
- (Object) retain
Returns the value of attribute retain
7 8 9 |
# File 'lib/mqtt/packet.rb', line 7 def retain @retain end |
Class Method Details
+ (Object) parse(buffer)
Parse buffer into new packet object
52 53 54 55 56 |
# File 'lib/mqtt/packet.rb', line 52 def self.parse(buffer) packet = parse_header(buffer) packet.parse_body(buffer) return packet end |
+ (Object) parse_header(buffer)
Parse the header and create a new packet object of the correct type The header is removed from the buffer passed into this function
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/mqtt/packet.rb', line 60 def self.parse_header(buffer) # Work out the class type_id = ((buffer.unpack("C*")[0] & 0xF0) >> 4) packet_class = MQTT::PACKET_TYPES[type_id] if packet_class.nil? raise ProtocolException.new("Invalid packet type identifier: #{type_id}") end # Create a new packet object packet = packet_class.new( :duplicate => ((buffer.unpack("C*")[0] & 0x08) >> 3) == 0x01, :qos => ((buffer.unpack("C*")[0] & 0x06) >> 1), :retain => ((buffer.unpack("C*")[0] & 0x01) >> 0) == 0x01 ) # Parse the packet length body_length = 0 multiplier = 1 pos = 1 begin if buffer.length <= pos raise ProtocolException.new("The packet length header is incomplete") end digit = buffer.unpack("C*")[pos] body_length += ((digit & 0x7F) * multiplier) multiplier *= 0x80 pos += 1 end while ((digit & 0x80) != 0x00) and pos <= 4 # Store the expected body length in the packet packet.instance_variable_set('@body_length', body_length) # Delete the variable length header from the raw packet passed in buffer.slice!(0...pos) return packet end |
+ (Object) read(socket)
Read in a packet from a socket
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/mqtt/packet.rb', line 19 def self.read(socket) # Read in the packet header and work out the class header = read_byte(socket) type_id = ((header & 0xF0) >> 4) packet_class = MQTT::PACKET_TYPES[type_id] # Create a new packet object packet = packet_class.new( :duplicate => ((header & 0x08) >> 3), :qos => ((header & 0x06) >> 1), :retain => ((header & 0x01) >> 0) ) # Read in the packet length multiplier = 1 body_length = 0 begin digit = read_byte(socket) body_length += ((digit & 0x7F) * multiplier) multiplier *= 0x80 end while ((digit & 0x80) != 0x00) # FIXME: only allow 4 bytes? # 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) ) return packet end |
Instance Method Details
- (Object) encode_body
Get serialisation of packet's body (variable header and payload)
157 158 159 |
# File 'lib/mqtt/packet.rb', line 157 def encode_body '' # No body by default end |
- (Object) parse_body(buffer)
Parse the body (variable header and payload) of a packet
148 149 150 151 152 153 154 |
# File 'lib/mqtt/packet.rb', line 148 def parse_body(buffer) if buffer.length != body_length raise ProtocolException.new( "Failed to parse packet - input buffer (#{buffer.length}) is not the same as the body length buffer (#{body_length})" ) end end |
- (Object) to_s
Serialise the packet
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/mqtt/packet.rb', line 163 def to_s # Encode the fixed header header = [ ((type_id.to_i & 0x0F) << 4) | ((duplicate ? 0x1 : 0x0) << 3) | ((qos.to_i & 0x03) << 1) | (retain ? 0x1 : 0x0) ] # Get the packet's variable header and payload body = self.encode_body # Build up the body length field bytes body_length = body.length begin digit = (body_length % 128) body_length = (body_length / 128) # if there are more digits to encode, set the top bit of this digit digit |= 0x80 if (body_length > 0) header.push(digit) end while (body_length > 0) # Convert header to binary and add on body header.pack('C*') + body end |
- (Object) type_id
Get the identifer for this packet type
111 112 113 114 115 116 117 |
# File 'lib/mqtt/packet.rb', line 111 def type_id index = MQTT::PACKET_TYPES.index(self.class) if index.nil? raise "Invalid packet type: #{self.class}" end return index end |
- (Object) update_attributes(attr = {})
104 105 106 107 108 |
# File 'lib/mqtt/packet.rb', line 104 def update_attributes(attr={}) attr.each_pair do |k,v| send("#{k}=", v) end end |