mqtt 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
 - data/NEWS.md +27 -1
 - data/README.md +14 -5
 - data/lib/mqtt/client.rb +513 -478
 - data/lib/mqtt/openssl_fix.rb +29 -0
 - data/lib/mqtt/packet.rb +181 -234
 - data/lib/mqtt/proxy.rb +81 -85
 - data/lib/mqtt/sn/packet.rb +469 -512
 - data/lib/mqtt/version.rb +1 -1
 - data/lib/mqtt.rb +1 -8
 - data/spec/mqtt_client_spec.rb +173 -12
 - data/spec/mqtt_packet_spec.rb +10 -4
 - metadata +38 -11
 - data/lib/mqtt/patches/string_encoding.rb +0 -34
 
    
        data/lib/mqtt/packet.rb
    CHANGED
    
    | 
         @@ -1,10 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # encoding: BINARY
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module MQTT
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
4 
     | 
    
         
             
              # Class representing a MQTT Packet
         
     | 
| 
       6 
5 
     | 
    
         
             
              # Performs binary encoding and decoding of headers
         
     | 
| 
       7 
     | 
    
         
            -
              class  
     | 
| 
      
 6 
     | 
    
         
            +
              class Packet
         
     | 
| 
       8 
7 
     | 
    
         
             
                # The version number of the MQTT protocol to use (default 3.1.0)
         
     | 
| 
       9 
8 
     | 
    
         
             
                attr_accessor :version
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
         @@ -36,27 +35,29 @@ module MQTT 
     | 
|
| 
       36 
35 
     | 
    
         
             
                  multiplier = 1
         
     | 
| 
       37 
36 
     | 
    
         
             
                  body_length = 0
         
     | 
| 
       38 
37 
     | 
    
         
             
                  pos = 1
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  loop do
         
     | 
| 
       40 
40 
     | 
    
         
             
                    digit = read_byte(socket)
         
     | 
| 
       41 
41 
     | 
    
         
             
                    body_length += ((digit & 0x7F) * multiplier)
         
     | 
| 
       42 
42 
     | 
    
         
             
                    multiplier *= 0x80
         
     | 
| 
       43 
43 
     | 
    
         
             
                    pos += 1
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                    break if (digit & 0x80).zero? || pos > 4
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
       45 
46 
     | 
    
         | 
| 
       46 
47 
     | 
    
         
             
                  # Store the expected body length in the packet
         
     | 
| 
       47 
48 
     | 
    
         
             
                  packet.instance_variable_set('@body_length', body_length)
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
50 
     | 
    
         
             
                  # Read in the packet body
         
     | 
| 
       50 
     | 
    
         
            -
                  packet.parse_body( 
     | 
| 
      
 51 
     | 
    
         
            +
                  packet.parse_body(socket.read(body_length))
         
     | 
| 
       51 
52 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                   
     | 
| 
      
 53 
     | 
    
         
            +
                  packet
         
     | 
| 
       53 
54 
     | 
    
         
             
                end
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
                # Parse buffer into new packet object
         
     | 
| 
       56 
57 
     | 
    
         
             
                def self.parse(buffer)
         
     | 
| 
       57 
58 
     | 
    
         
             
                  packet = parse_header(buffer)
         
     | 
| 
       58 
59 
     | 
    
         
             
                  packet.parse_body(buffer)
         
     | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
      
 60 
     | 
    
         
            +
                  packet
         
     | 
| 
       60 
61 
     | 
    
         
             
                end
         
     | 
| 
       61 
62 
     | 
    
         | 
| 
       62 
63 
     | 
    
         
             
                # Parse the header and create a new packet object of the correct type
         
     | 
| 
         @@ -64,11 +65,11 @@ module MQTT 
     | 
|
| 
       64 
65 
     | 
    
         
             
                def self.parse_header(buffer)
         
     | 
| 
       65 
66 
     | 
    
         
             
                  # Check that the packet is a long as the minimum packet size
         
     | 
| 
       66 
67 
     | 
    
         
             
                  if buffer.bytesize < 2
         
     | 
| 
       67 
     | 
    
         
            -
                    raise ProtocolException 
     | 
| 
      
 68 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid packet: less than 2 bytes long'
         
     | 
| 
       68 
69 
     | 
    
         
             
                  end
         
     | 
| 
       69 
70 
     | 
    
         | 
| 
       70 
71 
     | 
    
         
             
                  # Create a new packet object
         
     | 
| 
       71 
     | 
    
         
            -
                  bytes = buffer.unpack( 
     | 
| 
      
 72 
     | 
    
         
            +
                  bytes = buffer.unpack('C5')
         
     | 
| 
       72 
73 
     | 
    
         
             
                  packet = create_from_header(bytes.first)
         
     | 
| 
       73 
74 
     | 
    
         
             
                  packet.validate_flags
         
     | 
| 
       74 
75 
     | 
    
         | 
| 
         @@ -76,15 +77,18 @@ module MQTT 
     | 
|
| 
       76 
77 
     | 
    
         
             
                  body_length = 0
         
     | 
| 
       77 
78 
     | 
    
         
             
                  multiplier = 1
         
     | 
| 
       78 
79 
     | 
    
         
             
                  pos = 1
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  loop do
         
     | 
| 
       80 
82 
     | 
    
         
             
                    if buffer.bytesize <= pos
         
     | 
| 
       81 
     | 
    
         
            -
                      raise ProtocolException 
     | 
| 
      
 83 
     | 
    
         
            +
                      raise ProtocolException, 'The packet length header is incomplete'
         
     | 
| 
       82 
84 
     | 
    
         
             
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
       83 
86 
     | 
    
         
             
                    digit = bytes[pos]
         
     | 
| 
       84 
87 
     | 
    
         
             
                    body_length += ((digit & 0x7F) * multiplier)
         
     | 
| 
       85 
88 
     | 
    
         
             
                    multiplier *= 0x80
         
     | 
| 
       86 
89 
     | 
    
         
             
                    pos += 1
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
                    break if (digit & 0x80).zero? || pos > 4
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
       88 
92 
     | 
    
         | 
| 
       89 
93 
     | 
    
         
             
                  # Store the expected body length in the packet
         
     | 
| 
       90 
94 
     | 
    
         
             
                  packet.instance_variable_set('@body_length', body_length)
         
     | 
| 
         @@ -92,7 +96,7 @@ module MQTT 
     | 
|
| 
       92 
96 
     | 
    
         
             
                  # Delete the fixed header from the raw packet passed in
         
     | 
| 
       93 
97 
     | 
    
         
             
                  buffer.slice!(0...pos)
         
     | 
| 
       94 
98 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                   
     | 
| 
      
 99 
     | 
    
         
            +
                  packet
         
     | 
| 
       96 
100 
     | 
    
         
             
                end
         
     | 
| 
       97 
101 
     | 
    
         | 
| 
       98 
102 
     | 
    
         
             
                # Create a new packet object from the first byte of a MQTT packet
         
     | 
| 
         @@ -101,27 +105,27 @@ module MQTT 
     | 
|
| 
       101 
105 
     | 
    
         
             
                  type_id = ((byte & 0xF0) >> 4)
         
     | 
| 
       102 
106 
     | 
    
         
             
                  packet_class = MQTT::PACKET_TYPES[type_id]
         
     | 
| 
       103 
107 
     | 
    
         
             
                  if packet_class.nil?
         
     | 
| 
       104 
     | 
    
         
            -
                    raise ProtocolException 
     | 
| 
      
 108 
     | 
    
         
            +
                    raise ProtocolException, "Invalid packet type identifier: #{type_id}"
         
     | 
| 
       105 
109 
     | 
    
         
             
                  end
         
     | 
| 
       106 
110 
     | 
    
         | 
| 
       107 
111 
     | 
    
         
             
                  # Convert the last 4 bits of byte into array of true/false
         
     | 
| 
       108 
     | 
    
         
            -
                  flags = (0..3).map { |i| byte & (2 
     | 
| 
      
 112 
     | 
    
         
            +
                  flags = (0..3).map { |i| byte & (2**i) != 0 }
         
     | 
| 
       109 
113 
     | 
    
         | 
| 
       110 
114 
     | 
    
         
             
                  # Create a new packet object
         
     | 
| 
       111 
115 
     | 
    
         
             
                  packet_class.new(:flags => flags)
         
     | 
| 
       112 
116 
     | 
    
         
             
                end
         
     | 
| 
       113 
117 
     | 
    
         | 
| 
       114 
118 
     | 
    
         
             
                # Create a new empty packet
         
     | 
| 
       115 
     | 
    
         
            -
                def initialize(args={})
         
     | 
| 
      
 119 
     | 
    
         
            +
                def initialize(args = {})
         
     | 
| 
       116 
120 
     | 
    
         
             
                  # We must set flags before the other values
         
     | 
| 
       117 
121 
     | 
    
         
             
                  @flags = [false, false, false, false]
         
     | 
| 
       118 
122 
     | 
    
         
             
                  update_attributes(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       119 
123 
     | 
    
         
             
                end
         
     | 
| 
       120 
124 
     | 
    
         | 
| 
       121 
125 
     | 
    
         
             
                # Set packet attributes from a hash of attribute names and values
         
     | 
| 
       122 
     | 
    
         
            -
                def update_attributes(attr={})
         
     | 
| 
       123 
     | 
    
         
            -
                  attr.each_pair do |k,v|
         
     | 
| 
       124 
     | 
    
         
            -
                    if v.is_a?(Array)  
     | 
| 
      
 126 
     | 
    
         
            +
                def update_attributes(attr = {})
         
     | 
| 
      
 127 
     | 
    
         
            +
                  attr.each_pair do |k, v|
         
     | 
| 
      
 128 
     | 
    
         
            +
                    if v.is_a?(Array) || v.is_a?(Hash)
         
     | 
| 
       125 
129 
     | 
    
         
             
                      send("#{k}=", v.dup)
         
     | 
| 
       126 
130 
     | 
    
         
             
                    else
         
     | 
| 
       127 
131 
     | 
    
         
             
                      send("#{k}=", v)
         
     | 
| 
         @@ -132,10 +136,8 @@ module MQTT 
     | 
|
| 
       132 
136 
     | 
    
         
             
                # Get the identifer for this packet type
         
     | 
| 
       133 
137 
     | 
    
         
             
                def type_id
         
     | 
| 
       134 
138 
     | 
    
         
             
                  index = MQTT::PACKET_TYPES.index(self.class)
         
     | 
| 
       135 
     | 
    
         
            -
                  if index.nil?
         
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
                  end
         
     | 
| 
       138 
     | 
    
         
            -
                  return index
         
     | 
| 
      
 139 
     | 
    
         
            +
                  raise "Invalid packet type: #{self.class}" if index.nil?
         
     | 
| 
      
 140 
     | 
    
         
            +
                  index
         
     | 
| 
       139 
141 
     | 
    
         
             
                end
         
     | 
| 
       140 
142 
     | 
    
         | 
| 
       141 
143 
     | 
    
         
             
                # Get the name of the packet type as a string in capitals
         
     | 
| 
         @@ -158,11 +160,9 @@ module MQTT 
     | 
|
| 
       158 
160 
     | 
    
         | 
| 
       159 
161 
     | 
    
         
             
                # Parse the body (variable header and payload) of a packet
         
     | 
| 
       160 
162 
     | 
    
         
             
                def parse_body(buffer)
         
     | 
| 
       161 
     | 
    
         
            -
                  if buffer.bytesize  
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
                    )
         
     | 
| 
       165 
     | 
    
         
            -
                  end
         
     | 
| 
      
 163 
     | 
    
         
            +
                  return if buffer.bytesize == body_length
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                  raise ProtocolException, "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
         
     | 
| 
       166 
166 
     | 
    
         
             
                end
         
     | 
| 
       167 
167 
     | 
    
         | 
| 
       168 
168 
     | 
    
         
             
                # Get serialisation of packet's body (variable header and payload)
         
     | 
| 
         @@ -170,35 +170,35 @@ module MQTT 
     | 
|
| 
       170 
170 
     | 
    
         
             
                  '' # No body by default
         
     | 
| 
       171 
171 
     | 
    
         
             
                end
         
     | 
| 
       172 
172 
     | 
    
         | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
173 
     | 
    
         
             
                # Serialise the packet
         
     | 
| 
       175 
174 
     | 
    
         
             
                def to_s
         
     | 
| 
       176 
175 
     | 
    
         
             
                  # Encode the fixed header
         
     | 
| 
       177 
176 
     | 
    
         
             
                  header = [
         
     | 
| 
       178 
177 
     | 
    
         
             
                    ((type_id.to_i & 0x0F) << 4) |
         
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
      
 178 
     | 
    
         
            +
                      (flags[3] ? 0x8 : 0x0) |
         
     | 
| 
      
 179 
     | 
    
         
            +
                      (flags[2] ? 0x4 : 0x0) |
         
     | 
| 
      
 180 
     | 
    
         
            +
                      (flags[1] ? 0x2 : 0x0) |
         
     | 
| 
      
 181 
     | 
    
         
            +
                      (flags[0] ? 0x1 : 0x0)
         
     | 
| 
       183 
182 
     | 
    
         
             
                  ]
         
     | 
| 
       184 
183 
     | 
    
         | 
| 
       185 
184 
     | 
    
         
             
                  # Get the packet's variable header and payload
         
     | 
| 
       186 
     | 
    
         
            -
                  body =  
     | 
| 
      
 185 
     | 
    
         
            +
                  body = encode_body
         
     | 
| 
       187 
186 
     | 
    
         | 
| 
       188 
187 
     | 
    
         
             
                  # Check that that packet isn't too big
         
     | 
| 
       189 
188 
     | 
    
         
             
                  body_length = body.bytesize
         
     | 
| 
       190 
     | 
    
         
            -
                  if body_length >  
     | 
| 
       191 
     | 
    
         
            -
                    raise  
     | 
| 
      
 189 
     | 
    
         
            +
                  if body_length > 268_435_455
         
     | 
| 
      
 190 
     | 
    
         
            +
                    raise 'Error serialising packet: body is more than 256MB'
         
     | 
| 
       192 
191 
     | 
    
         
             
                  end
         
     | 
| 
       193 
192 
     | 
    
         | 
| 
       194 
193 
     | 
    
         
             
                  # Build up the body length field bytes
         
     | 
| 
       195 
     | 
    
         
            -
                   
     | 
| 
      
 194 
     | 
    
         
            +
                  loop do
         
     | 
| 
       196 
195 
     | 
    
         
             
                    digit = (body_length % 128)
         
     | 
| 
       197 
196 
     | 
    
         
             
                    body_length = body_length.div(128)
         
     | 
| 
       198 
197 
     | 
    
         
             
                    # if there are more digits to encode, set the top bit of this digit
         
     | 
| 
       199 
     | 
    
         
            -
                    digit |= 0x80 if  
     | 
| 
      
 198 
     | 
    
         
            +
                    digit |= 0x80 if body_length > 0
         
     | 
| 
       200 
199 
     | 
    
         
             
                    header.push(digit)
         
     | 
| 
       201 
     | 
    
         
            -
             
     | 
| 
      
 200 
     | 
    
         
            +
                    break if body_length <= 0
         
     | 
| 
      
 201 
     | 
    
         
            +
                  end
         
     | 
| 
       202 
202 
     | 
    
         | 
| 
       203 
203 
     | 
    
         
             
                  # Convert header to binary and add on body
         
     | 
| 
       204 
204 
     | 
    
         
             
                  header.pack('C*') + body
         
     | 
| 
         @@ -207,9 +207,9 @@ module MQTT 
     | 
|
| 
       207 
207 
     | 
    
         
             
                # Check that fixed header flags are valid for types that don't use the flags
         
     | 
| 
       208 
208 
     | 
    
         
             
                # @private
         
     | 
| 
       209 
209 
     | 
    
         
             
                def validate_flags
         
     | 
| 
       210 
     | 
    
         
            -
                  if flags  
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
                   
     | 
| 
      
 210 
     | 
    
         
            +
                  return if flags == [false, false, false, false]
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                  raise ProtocolException, "Invalid flags in #{type_name} packet header"
         
     | 
| 
       213 
213 
     | 
    
         
             
                end
         
     | 
| 
       214 
214 
     | 
    
         | 
| 
       215 
215 
     | 
    
         
             
                # Returns a human readable string
         
     | 
| 
         @@ -217,6 +217,14 @@ module MQTT 
     | 
|
| 
       217 
217 
     | 
    
         
             
                  "\#<#{self.class}>"
         
     | 
| 
       218 
218 
     | 
    
         
             
                end
         
     | 
| 
       219 
219 
     | 
    
         | 
| 
      
 220 
     | 
    
         
            +
                # Read and unpack a single byte from a socket
         
     | 
| 
      
 221 
     | 
    
         
            +
                def self.read_byte(socket)
         
     | 
| 
      
 222 
     | 
    
         
            +
                  byte = socket.getbyte
         
     | 
| 
      
 223 
     | 
    
         
            +
                  raise ProtocolException, 'Failed to read byte from socket' if byte.nil?
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                  byte
         
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
       220 
228 
     | 
    
         
             
                protected
         
     | 
| 
       221 
229 
     | 
    
         | 
| 
       222 
230 
     | 
    
         
             
                # Encode an array of bytes and return them
         
     | 
| 
         @@ -226,11 +234,12 @@ module MQTT 
     | 
|
| 
       226 
234 
     | 
    
         | 
| 
       227 
235 
     | 
    
         
             
                # Encode an array of bits and return them
         
     | 
| 
       228 
236 
     | 
    
         
             
                def encode_bits(bits)
         
     | 
| 
       229 
     | 
    
         
            -
                  [bits.map{|b| b ? '1' : '0'}.join].pack('b*')
         
     | 
| 
      
 237 
     | 
    
         
            +
                  [bits.map { |b| b ? '1' : '0' }.join].pack('b*')
         
     | 
| 
       230 
238 
     | 
    
         
             
                end
         
     | 
| 
       231 
239 
     | 
    
         | 
| 
       232 
240 
     | 
    
         
             
                # Encode a 16-bit unsigned integer and return it
         
     | 
| 
       233 
241 
     | 
    
         
             
                def encode_short(val)
         
     | 
| 
      
 242 
     | 
    
         
            +
                  raise 'Value too big for short' if val > 0xffff
         
     | 
| 
       234 
243 
     | 
    
         
             
                  [val.to_i].pack('n')
         
     | 
| 
       235 
244 
     | 
    
         
             
                end
         
     | 
| 
       236 
245 
     | 
    
         | 
| 
         @@ -257,42 +266,26 @@ module MQTT 
     | 
|
| 
       257 
266 
     | 
    
         | 
| 
       258 
267 
     | 
    
         
             
                # Remove 8 bits from the front of buffer
         
     | 
| 
       259 
268 
     | 
    
         
             
                def shift_bits(buffer)
         
     | 
| 
       260 
     | 
    
         
            -
                  buffer.slice!(0...1).unpack('b8').first.split('').map {|b| b == '1'}
         
     | 
| 
      
 269 
     | 
    
         
            +
                  buffer.slice!(0...1).unpack('b8').first.split('').map { |b| b == '1' }
         
     | 
| 
       261 
270 
     | 
    
         
             
                end
         
     | 
| 
       262 
271 
     | 
    
         | 
| 
       263 
272 
     | 
    
         
             
                # Remove n bytes from the front of buffer
         
     | 
| 
       264 
     | 
    
         
            -
                def shift_data(buffer,bytes)
         
     | 
| 
      
 273 
     | 
    
         
            +
                def shift_data(buffer, bytes)
         
     | 
| 
       265 
274 
     | 
    
         
             
                  buffer.slice!(0...bytes)
         
     | 
| 
       266 
275 
     | 
    
         
             
                end
         
     | 
| 
       267 
276 
     | 
    
         | 
| 
       268 
277 
     | 
    
         
             
                # Remove string from the front of buffer
         
     | 
| 
       269 
278 
     | 
    
         
             
                def shift_string(buffer)
         
     | 
| 
       270 
279 
     | 
    
         
             
                  len = shift_short(buffer)
         
     | 
| 
       271 
     | 
    
         
            -
                  str = shift_data(buffer,len)
         
     | 
| 
      
 280 
     | 
    
         
            +
                  str = shift_data(buffer, len)
         
     | 
| 
       272 
281 
     | 
    
         
             
                  # Strings in MQTT v3.1 are all UTF-8
         
     | 
| 
       273 
282 
     | 
    
         
             
                  str.force_encoding('UTF-8')
         
     | 
| 
       274 
283 
     | 
    
         
             
                end
         
     | 
| 
       275 
284 
     | 
    
         | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
                private
         
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
     | 
    
         
            -
                # Read and unpack a single byte from a socket
         
     | 
| 
       280 
     | 
    
         
            -
                def self.read_byte(socket)
         
     | 
| 
       281 
     | 
    
         
            -
                  byte = socket.read(1)
         
     | 
| 
       282 
     | 
    
         
            -
                  if byte.nil?
         
     | 
| 
       283 
     | 
    
         
            -
                    raise ProtocolException.new("Failed to read byte from socket")
         
     | 
| 
       284 
     | 
    
         
            -
                  end
         
     | 
| 
       285 
     | 
    
         
            -
                  byte.unpack('C').first
         
     | 
| 
       286 
     | 
    
         
            -
                end
         
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
285 
     | 
    
         
             
                ## PACKET SUBCLASSES ##
         
     | 
| 
       291 
286 
     | 
    
         | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
287 
     | 
    
         
             
                # Class representing an MQTT Publish message
         
     | 
| 
       294 
288 
     | 
    
         
             
                class Publish < MQTT::Packet
         
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
       296 
289 
     | 
    
         
             
                  # Duplicate delivery flag
         
     | 
| 
       297 
290 
     | 
    
         
             
                  attr_accessor :duplicate
         
     | 
| 
       298 
291 
     | 
    
         | 
| 
         @@ -315,7 +308,7 @@ module MQTT 
     | 
|
| 
       315 
308 
     | 
    
         
             
                  }
         
     | 
| 
       316 
309 
     | 
    
         | 
| 
       317 
310 
     | 
    
         
             
                  # Create a new Publish packet
         
     | 
| 
       318 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 311 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       319 
312 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       320 
313 
     | 
    
         
             
                  end
         
     | 
| 
       321 
314 
     | 
    
         | 
| 
         @@ -325,11 +318,7 @@ module MQTT 
     | 
|
| 
       325 
318 
     | 
    
         | 
| 
       326 
319 
     | 
    
         
             
                  # Set the DUP flag (true/false)
         
     | 
| 
       327 
320 
     | 
    
         
             
                  def duplicate=(arg)
         
     | 
| 
       328 
     | 
    
         
            -
                     
     | 
| 
       329 
     | 
    
         
            -
                      @flags[3] = (arg == 0x1)
         
     | 
| 
       330 
     | 
    
         
            -
                    else
         
     | 
| 
       331 
     | 
    
         
            -
                      @flags[3] = arg
         
     | 
| 
       332 
     | 
    
         
            -
                    end
         
     | 
| 
      
 321 
     | 
    
         
            +
                    @flags[3] = arg.is_a?(Integer) ? (arg == 0x1) : arg
         
     | 
| 
       333 
322 
     | 
    
         
             
                  end
         
     | 
| 
       334 
323 
     | 
    
         | 
| 
       335 
324 
     | 
    
         
             
                  def retain
         
     | 
| 
         @@ -338,11 +327,7 @@ module MQTT 
     | 
|
| 
       338 
327 
     | 
    
         | 
| 
       339 
328 
     | 
    
         
             
                  # Set the retain flag (true/false)
         
     | 
| 
       340 
329 
     | 
    
         
             
                  def retain=(arg)
         
     | 
| 
       341 
     | 
    
         
            -
                     
     | 
| 
       342 
     | 
    
         
            -
                      @flags[0] = (arg == 0x1)
         
     | 
| 
       343 
     | 
    
         
            -
                    else
         
     | 
| 
       344 
     | 
    
         
            -
                      @flags[0] = arg
         
     | 
| 
       345 
     | 
    
         
            -
                    end
         
     | 
| 
      
 330 
     | 
    
         
            +
                    @flags[0] = arg.is_a?(Integer) ? (arg == 0x1) : arg
         
     | 
| 
       346 
331 
     | 
    
         
             
                  end
         
     | 
| 
       347 
332 
     | 
    
         | 
| 
       348 
333 
     | 
    
         
             
                  def qos
         
     | 
| 
         @@ -352,61 +337,55 @@ module MQTT 
     | 
|
| 
       352 
337 
     | 
    
         
             
                  # Set the Quality of Service level (0/1/2)
         
     | 
| 
       353 
338 
     | 
    
         
             
                  def qos=(arg)
         
     | 
| 
       354 
339 
     | 
    
         
             
                    @qos = arg.to_i
         
     | 
| 
       355 
     | 
    
         
            -
                    if @qos < 0  
     | 
| 
       356 
     | 
    
         
            -
             
     | 
| 
       357 
     | 
    
         
            -
                     
     | 
| 
       358 
     | 
    
         
            -
             
     | 
| 
       359 
     | 
    
         
            -
                      @flags[2] = (arg & 0x02 == 0x02)
         
     | 
| 
       360 
     | 
    
         
            -
                    end
         
     | 
| 
      
 340 
     | 
    
         
            +
                    raise "Invalid QoS value: #{@qos}" if @qos < 0 || @qos > 2
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                    @flags[1] = (arg & 0x01 == 0x01)
         
     | 
| 
      
 343 
     | 
    
         
            +
                    @flags[2] = (arg & 0x02 == 0x02)
         
     | 
| 
       361 
344 
     | 
    
         
             
                  end
         
     | 
| 
       362 
345 
     | 
    
         | 
| 
       363 
346 
     | 
    
         
             
                  # Get serialisation of packet's body
         
     | 
| 
       364 
347 
     | 
    
         
             
                  def encode_body
         
     | 
| 
       365 
348 
     | 
    
         
             
                    body = ''
         
     | 
| 
       366 
     | 
    
         
            -
                    if @topic.nil?  
     | 
| 
       367 
     | 
    
         
            -
                      raise  
     | 
| 
      
 349 
     | 
    
         
            +
                    if @topic.nil? || @topic.to_s.empty?
         
     | 
| 
      
 350 
     | 
    
         
            +
                      raise 'Invalid topic name when serialising packet'
         
     | 
| 
       368 
351 
     | 
    
         
             
                    end
         
     | 
| 
       369 
352 
     | 
    
         
             
                    body += encode_string(@topic)
         
     | 
| 
       370 
     | 
    
         
            -
                    body += encode_short(@id) unless qos 
     | 
| 
      
 353 
     | 
    
         
            +
                    body += encode_short(@id) unless qos.zero?
         
     | 
| 
       371 
354 
     | 
    
         
             
                    body += payload.to_s.dup.force_encoding('ASCII-8BIT')
         
     | 
| 
       372 
     | 
    
         
            -
                     
     | 
| 
      
 355 
     | 
    
         
            +
                    body
         
     | 
| 
       373 
356 
     | 
    
         
             
                  end
         
     | 
| 
       374 
357 
     | 
    
         | 
| 
       375 
358 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a Publish packet
         
     | 
| 
       376 
359 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       377 
360 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       378 
361 
     | 
    
         
             
                    @topic = shift_string(buffer)
         
     | 
| 
       379 
     | 
    
         
            -
                    @id = shift_short(buffer) unless qos 
     | 
| 
      
 362 
     | 
    
         
            +
                    @id = shift_short(buffer) unless qos.zero?
         
     | 
| 
       380 
363 
     | 
    
         
             
                    @payload = buffer
         
     | 
| 
       381 
364 
     | 
    
         
             
                  end
         
     | 
| 
       382 
365 
     | 
    
         | 
| 
       383 
366 
     | 
    
         
             
                  # Check that fixed header flags are valid for this packet type
         
     | 
| 
       384 
367 
     | 
    
         
             
                  # @private
         
     | 
| 
       385 
368 
     | 
    
         
             
                  def validate_flags
         
     | 
| 
       386 
     | 
    
         
            -
                    if qos == 3
         
     | 
| 
       387 
     | 
    
         
            -
             
     | 
| 
       388 
     | 
    
         
            -
                    end
         
     | 
| 
       389 
     | 
    
         
            -
                    if qos == 0 and duplicate
         
     | 
| 
       390 
     | 
    
         
            -
                      raise ProtocolException.new("Invalid packet: DUP cannot be set for QoS 0")
         
     | 
| 
       391 
     | 
    
         
            -
                    end
         
     | 
| 
      
 369 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid packet: QoS value of 3 is not allowed' if qos == 3
         
     | 
| 
      
 370 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid packet: DUP cannot be set for QoS 0' if qos.zero? && duplicate
         
     | 
| 
       392 
371 
     | 
    
         
             
                  end
         
     | 
| 
       393 
372 
     | 
    
         | 
| 
       394 
373 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
       395 
374 
     | 
    
         
             
                  def inspect
         
     | 
| 
       396 
     | 
    
         
            -
                    "\#<#{self.class}: "  
     | 
| 
       397 
     | 
    
         
            -
             
     | 
| 
       398 
     | 
    
         
            -
             
     | 
| 
       399 
     | 
    
         
            -
             
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
             
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
      
 375 
     | 
    
         
            +
                    "\#<#{self.class}: " \
         
     | 
| 
      
 376 
     | 
    
         
            +
                      "d#{duplicate ? '1' : '0'}, " \
         
     | 
| 
      
 377 
     | 
    
         
            +
                      "q#{qos}, " \
         
     | 
| 
      
 378 
     | 
    
         
            +
                      "r#{retain ? '1' : '0'}, " \
         
     | 
| 
      
 379 
     | 
    
         
            +
                      "m#{id}, " \
         
     | 
| 
      
 380 
     | 
    
         
            +
                      "'#{topic}', " \
         
     | 
| 
      
 381 
     | 
    
         
            +
                      "#{inspect_payload}>"
         
     | 
| 
       403 
382 
     | 
    
         
             
                  end
         
     | 
| 
       404 
383 
     | 
    
         | 
| 
       405 
384 
     | 
    
         
             
                  protected
         
     | 
| 
       406 
385 
     | 
    
         | 
| 
       407 
386 
     | 
    
         
             
                  def inspect_payload
         
     | 
| 
       408 
387 
     | 
    
         
             
                    str = payload.to_s
         
     | 
| 
       409 
     | 
    
         
            -
                    if str.bytesize < 16  
     | 
| 
      
 388 
     | 
    
         
            +
                    if str.bytesize < 16 && str =~ /^[ -~]*$/
         
     | 
| 
       410 
389 
     | 
    
         
             
                      "'#{str}'"
         
     | 
| 
       411 
390 
     | 
    
         
             
                    else
         
     | 
| 
       412 
391 
     | 
    
         
             
                      "... (#{str.bytesize} bytes)"
         
     | 
| 
         @@ -459,39 +438,38 @@ module MQTT 
     | 
|
| 
       459 
438 
     | 
    
         
             
                    :will_retain => false,
         
     | 
| 
       460 
439 
     | 
    
         
             
                    :will_payload => '',
         
     | 
| 
       461 
440 
     | 
    
         
             
                    :username => nil,
         
     | 
| 
       462 
     | 
    
         
            -
                    :password => nil 
     | 
| 
      
 441 
     | 
    
         
            +
                    :password => nil
         
     | 
| 
       463 
442 
     | 
    
         
             
                  }
         
     | 
| 
       464 
443 
     | 
    
         | 
| 
       465 
444 
     | 
    
         
             
                  # Create a new Client Connect packet
         
     | 
| 
       466 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 445 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       467 
446 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       468 
447 
     | 
    
         | 
| 
       469 
     | 
    
         
            -
                    if  
     | 
| 
      
 448 
     | 
    
         
            +
                    if ['3.1.0', '3.1'].include?(version)
         
     | 
| 
       470 
449 
     | 
    
         
             
                      self.protocol_name ||= 'MQIsdp'
         
     | 
| 
       471 
450 
     | 
    
         
             
                      self.protocol_level ||= 0x03
         
     | 
| 
       472 
451 
     | 
    
         
             
                    elsif version == '3.1.1'
         
     | 
| 
       473 
452 
     | 
    
         
             
                      self.protocol_name ||= 'MQTT'
         
     | 
| 
       474 
453 
     | 
    
         
             
                      self.protocol_level ||= 0x04
         
     | 
| 
       475 
454 
     | 
    
         
             
                    else
         
     | 
| 
       476 
     | 
    
         
            -
                      raise ArgumentError 
     | 
| 
      
 455 
     | 
    
         
            +
                      raise ArgumentError, "Unsupported protocol version: #{version}"
         
     | 
| 
       477 
456 
     | 
    
         
             
                    end
         
     | 
| 
       478 
457 
     | 
    
         
             
                  end
         
     | 
| 
       479 
458 
     | 
    
         | 
| 
       480 
459 
     | 
    
         
             
                  # Get serialisation of packet's body
         
     | 
| 
       481 
460 
     | 
    
         
             
                  def encode_body
         
     | 
| 
       482 
461 
     | 
    
         
             
                    body = ''
         
     | 
| 
      
 462 
     | 
    
         
            +
             
     | 
| 
       483 
463 
     | 
    
         
             
                    if @version == '3.1.0'
         
     | 
| 
       484 
     | 
    
         
            -
                      if @client_id.nil?  
     | 
| 
       485 
     | 
    
         
            -
             
     | 
| 
       486 
     | 
    
         
            -
                      elsif @client_id.bytesize > 23
         
     | 
| 
       487 
     | 
    
         
            -
                        raise "Client identifier too long when serialising packet"
         
     | 
| 
       488 
     | 
    
         
            -
                      end
         
     | 
| 
      
 464 
     | 
    
         
            +
                      raise 'Client identifier too short while serialising packet' if @client_id.nil? || @client_id.bytesize < 1
         
     | 
| 
      
 465 
     | 
    
         
            +
                      raise 'Client identifier too long when serialising packet' if @client_id.bytesize > 23
         
     | 
| 
       489 
466 
     | 
    
         
             
                    end
         
     | 
| 
      
 467 
     | 
    
         
            +
             
     | 
| 
       490 
468 
     | 
    
         
             
                    body += encode_string(@protocol_name)
         
     | 
| 
       491 
469 
     | 
    
         
             
                    body += encode_bytes(@protocol_level.to_i)
         
     | 
| 
       492 
470 
     | 
    
         | 
| 
       493 
471 
     | 
    
         
             
                    if @keep_alive < 0
         
     | 
| 
       494 
     | 
    
         
            -
                      raise  
     | 
| 
      
 472 
     | 
    
         
            +
                      raise 'Invalid keep-alive value: cannot be less than 0'
         
     | 
| 
       495 
473 
     | 
    
         
             
                    end
         
     | 
| 
       496 
474 
     | 
    
         | 
| 
       497 
475 
     | 
    
         
             
                    # Set the Connect flags
         
     | 
| 
         @@ -513,7 +491,7 @@ module MQTT 
     | 
|
| 
       513 
491 
     | 
    
         
             
                    end
         
     | 
| 
       514 
492 
     | 
    
         
             
                    body += encode_string(@username) unless @username.nil?
         
     | 
| 
       515 
493 
     | 
    
         
             
                    body += encode_string(@password) unless @password.nil?
         
     | 
| 
       516 
     | 
    
         
            -
                     
     | 
| 
      
 494 
     | 
    
         
            +
                    body
         
     | 
| 
       517 
495 
     | 
    
         
             
                  end
         
     | 
| 
       518 
496 
     | 
    
         | 
| 
       519 
497 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a Connect packet
         
     | 
| 
         @@ -521,14 +499,12 @@ module MQTT 
     | 
|
| 
       521 
499 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       522 
500 
     | 
    
         
             
                    @protocol_name = shift_string(buffer)
         
     | 
| 
       523 
501 
     | 
    
         
             
                    @protocol_level = shift_byte(buffer).to_i
         
     | 
| 
       524 
     | 
    
         
            -
                    if @protocol_name == 'MQIsdp'  
     | 
| 
      
 502 
     | 
    
         
            +
                    if @protocol_name == 'MQIsdp' && @protocol_level == 3
         
     | 
| 
       525 
503 
     | 
    
         
             
                      @version = '3.1.0'
         
     | 
| 
       526 
     | 
    
         
            -
                    elsif @protocol_name == 'MQTT'  
     | 
| 
      
 504 
     | 
    
         
            +
                    elsif @protocol_name == 'MQTT' && @protocol_level == 4
         
     | 
| 
       527 
505 
     | 
    
         
             
                      @version = '3.1.1'
         
     | 
| 
       528 
506 
     | 
    
         
             
                    else
         
     | 
| 
       529 
     | 
    
         
            -
                      raise ProtocolException 
     | 
| 
       530 
     | 
    
         
            -
                        "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
         
     | 
| 
       531 
     | 
    
         
            -
                      )
         
     | 
| 
      
 507 
     | 
    
         
            +
                      raise ProtocolException, "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
         
     | 
| 
       532 
508 
     | 
    
         
             
                    end
         
     | 
| 
       533 
509 
     | 
    
         | 
| 
       534 
510 
     | 
    
         
             
                    @connect_flags = shift_byte(buffer)
         
     | 
| 
         @@ -543,27 +519,26 @@ module MQTT 
     | 
|
| 
       543 
519 
     | 
    
         
             
                      # The MQTT v3.1 specification says that the payload is a UTF-8 string
         
     | 
| 
       544 
520 
     | 
    
         
             
                      @will_payload = shift_string(buffer)
         
     | 
| 
       545 
521 
     | 
    
         
             
                    end
         
     | 
| 
       546 
     | 
    
         
            -
                    if ((@connect_flags & 0x80) >> 7) == 0x01  
     | 
| 
      
 522 
     | 
    
         
            +
                    if ((@connect_flags & 0x80) >> 7) == 0x01 && buffer.bytesize > 0
         
     | 
| 
       547 
523 
     | 
    
         
             
                      @username = shift_string(buffer)
         
     | 
| 
       548 
524 
     | 
    
         
             
                    end
         
     | 
| 
       549 
     | 
    
         
            -
                    if ((@connect_flags & 0x40) >> 6) == 0x01  
     | 
| 
      
 525 
     | 
    
         
            +
                    if ((@connect_flags & 0x40) >> 6) == 0x01 && buffer.bytesize > 0 # rubocop: disable Style/GuardClause
         
     | 
| 
       550 
526 
     | 
    
         
             
                      @password = shift_string(buffer)
         
     | 
| 
       551 
527 
     | 
    
         
             
                    end
         
     | 
| 
       552 
528 
     | 
    
         
             
                  end
         
     | 
| 
       553 
529 
     | 
    
         | 
| 
       554 
530 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
       555 
531 
     | 
    
         
             
                  def inspect
         
     | 
| 
       556 
     | 
    
         
            -
                    str = "\#<#{self.class}: "
         
     | 
| 
       557 
     | 
    
         
            -
             
     | 
| 
       558 
     | 
    
         
            -
                    str +=  
     | 
| 
      
 532 
     | 
    
         
            +
                    str = "\#<#{self.class}: " \
         
     | 
| 
      
 533 
     | 
    
         
            +
                          "keep_alive=#{keep_alive}"
         
     | 
| 
      
 534 
     | 
    
         
            +
                    str += ', clean' if clean_session
         
     | 
| 
       559 
535 
     | 
    
         
             
                    str += ", client_id='#{client_id}'"
         
     | 
| 
       560 
536 
     | 
    
         
             
                    str += ", username='#{username}'" unless username.nil?
         
     | 
| 
       561 
     | 
    
         
            -
                    str +=  
     | 
| 
       562 
     | 
    
         
            -
                    str  
     | 
| 
      
 537 
     | 
    
         
            +
                    str += ', password=...' unless password.nil?
         
     | 
| 
      
 538 
     | 
    
         
            +
                    str + '>'
         
     | 
| 
       563 
539 
     | 
    
         
             
                  end
         
     | 
| 
       564 
540 
     | 
    
         | 
| 
       565 
541 
     | 
    
         
             
                  # ---- Deprecated attributes and methods  ---- #
         
     | 
| 
       566 
     | 
    
         
            -
                  public
         
     | 
| 
       567 
542 
     | 
    
         | 
| 
       568 
543 
     | 
    
         
             
                  # @deprecated Please use {#protocol_level} instead
         
     | 
| 
       569 
544 
     | 
    
         
             
                  def protocol_version
         
     | 
| 
         @@ -585,10 +560,10 @@ module MQTT 
     | 
|
| 
       585 
560 
     | 
    
         
             
                  attr_accessor :return_code
         
     | 
| 
       586 
561 
     | 
    
         | 
| 
       587 
562 
     | 
    
         
             
                  # Default attribute values
         
     | 
| 
       588 
     | 
    
         
            -
                  ATTR_DEFAULTS = {:return_code => 0x00}
         
     | 
| 
      
 563 
     | 
    
         
            +
                  ATTR_DEFAULTS = { :return_code => 0x00 }
         
     | 
| 
       589 
564 
     | 
    
         | 
| 
       590 
565 
     | 
    
         
             
                  # Create a new Client Connect packet
         
     | 
| 
       591 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 566 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       592 
567 
     | 
    
         
             
                    # We must set flags before other attributes
         
     | 
| 
       593 
568 
     | 
    
         
             
                    @connack_flags = [false, false, false, false, false, false, false, false]
         
     | 
| 
       594 
569 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
         @@ -601,30 +576,26 @@ module MQTT 
     | 
|
| 
       601 
576 
     | 
    
         | 
| 
       602 
577 
     | 
    
         
             
                  # Set the Session Present flag
         
     | 
| 
       603 
578 
     | 
    
         
             
                  def session_present=(arg)
         
     | 
| 
       604 
     | 
    
         
            -
                     
     | 
| 
       605 
     | 
    
         
            -
                      @connack_flags[0] = (arg == 0x1)
         
     | 
| 
       606 
     | 
    
         
            -
                    else
         
     | 
| 
       607 
     | 
    
         
            -
                      @connack_flags[0] = arg
         
     | 
| 
       608 
     | 
    
         
            -
                    end
         
     | 
| 
      
 579 
     | 
    
         
            +
                    @connack_flags[0] = arg.is_a?(Integer) ? (arg == 0x1) : arg
         
     | 
| 
       609 
580 
     | 
    
         
             
                  end
         
     | 
| 
       610 
581 
     | 
    
         | 
| 
       611 
582 
     | 
    
         
             
                  # Get a string message corresponding to a return code
         
     | 
| 
       612 
583 
     | 
    
         
             
                  def return_msg
         
     | 
| 
       613 
584 
     | 
    
         
             
                    case return_code
         
     | 
| 
       614 
     | 
    
         
            -
             
     | 
| 
       615 
     | 
    
         
            -
             
     | 
| 
       616 
     | 
    
         
            -
             
     | 
| 
       617 
     | 
    
         
            -
             
     | 
| 
       618 
     | 
    
         
            -
             
     | 
| 
       619 
     | 
    
         
            -
             
     | 
| 
       620 
     | 
    
         
            -
             
     | 
| 
       621 
     | 
    
         
            -
             
     | 
| 
       622 
     | 
    
         
            -
             
     | 
| 
       623 
     | 
    
         
            -
             
     | 
| 
       624 
     | 
    
         
            -
             
     | 
| 
       625 
     | 
    
         
            -
             
     | 
| 
       626 
     | 
    
         
            -
             
     | 
| 
       627 
     | 
    
         
            -
             
     | 
| 
      
 585 
     | 
    
         
            +
                    when 0x00
         
     | 
| 
      
 586 
     | 
    
         
            +
                      'Connection Accepted'
         
     | 
| 
      
 587 
     | 
    
         
            +
                    when 0x01
         
     | 
| 
      
 588 
     | 
    
         
            +
                      'Connection refused: unacceptable protocol version'
         
     | 
| 
      
 589 
     | 
    
         
            +
                    when 0x02
         
     | 
| 
      
 590 
     | 
    
         
            +
                      'Connection refused: client identifier rejected'
         
     | 
| 
      
 591 
     | 
    
         
            +
                    when 0x03
         
     | 
| 
      
 592 
     | 
    
         
            +
                      'Connection refused: server unavailable'
         
     | 
| 
      
 593 
     | 
    
         
            +
                    when 0x04
         
     | 
| 
      
 594 
     | 
    
         
            +
                      'Connection refused: bad user name or password'
         
     | 
| 
      
 595 
     | 
    
         
            +
                    when 0x05
         
     | 
| 
      
 596 
     | 
    
         
            +
                      'Connection refused: not authorised'
         
     | 
| 
      
 597 
     | 
    
         
            +
                    else
         
     | 
| 
      
 598 
     | 
    
         
            +
                      "Connection refused: error code #{return_code}"
         
     | 
| 
       628 
599 
     | 
    
         
             
                    end
         
     | 
| 
       629 
600 
     | 
    
         
             
                  end
         
     | 
| 
       630 
601 
     | 
    
         | 
| 
         @@ -633,20 +604,20 @@ module MQTT 
     | 
|
| 
       633 
604 
     | 
    
         
             
                    body = ''
         
     | 
| 
       634 
605 
     | 
    
         
             
                    body += encode_bits(@connack_flags)
         
     | 
| 
       635 
606 
     | 
    
         
             
                    body += encode_bytes(@return_code.to_i)
         
     | 
| 
       636 
     | 
    
         
            -
                     
     | 
| 
      
 607 
     | 
    
         
            +
                    body
         
     | 
| 
       637 
608 
     | 
    
         
             
                  end
         
     | 
| 
       638 
609 
     | 
    
         | 
| 
       639 
610 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a Connect Acknowledgment packet
         
     | 
| 
       640 
611 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       641 
612 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       642 
613 
     | 
    
         
             
                    @connack_flags = shift_bits(buffer)
         
     | 
| 
       643 
     | 
    
         
            -
                    unless @connack_flags[1,7] == [false, false, false, false, false, false, false]
         
     | 
| 
       644 
     | 
    
         
            -
                      raise ProtocolException 
     | 
| 
      
 614 
     | 
    
         
            +
                    unless @connack_flags[1, 7] == [false, false, false, false, false, false, false]
         
     | 
| 
      
 615 
     | 
    
         
            +
                      raise ProtocolException, 'Invalid flags in Connack variable header'
         
     | 
| 
       645 
616 
     | 
    
         
             
                    end
         
     | 
| 
       646 
617 
     | 
    
         
             
                    @return_code = shift_byte(buffer)
         
     | 
| 
       647 
     | 
    
         
            -
             
     | 
| 
       648 
     | 
    
         
            -
             
     | 
| 
       649 
     | 
    
         
            -
                    end
         
     | 
| 
      
 618 
     | 
    
         
            +
             
     | 
| 
      
 619 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 620 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Connect Acknowledgment packet'
         
     | 
| 
       650 
621 
     | 
    
         
             
                  end
         
     | 
| 
       651 
622 
     | 
    
         | 
| 
       652 
623 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -666,9 +637,9 @@ module MQTT 
     | 
|
| 
       666 
637 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       667 
638 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       668 
639 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       669 
     | 
    
         
            -
             
     | 
| 
       670 
     | 
    
         
            -
             
     | 
| 
       671 
     | 
    
         
            -
                    end
         
     | 
| 
      
 640 
     | 
    
         
            +
             
     | 
| 
      
 641 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 642 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Publish Acknowledgment packet'
         
     | 
| 
       672 
643 
     | 
    
         
             
                  end
         
     | 
| 
       673 
644 
     | 
    
         | 
| 
       674 
645 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -688,9 +659,9 @@ module MQTT 
     | 
|
| 
       688 
659 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       689 
660 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       690 
661 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       691 
     | 
    
         
            -
             
     | 
| 
       692 
     | 
    
         
            -
             
     | 
| 
       693 
     | 
    
         
            -
                    end
         
     | 
| 
      
 662 
     | 
    
         
            +
             
     | 
| 
      
 663 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 664 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Publish Received packet'
         
     | 
| 
       694 
665 
     | 
    
         
             
                  end
         
     | 
| 
       695 
666 
     | 
    
         | 
| 
       696 
667 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -701,14 +672,13 @@ module MQTT 
     | 
|
| 
       701 
672 
     | 
    
         | 
| 
       702 
673 
     | 
    
         
             
                # Class representing an MQTT Publish Release packet
         
     | 
| 
       703 
674 
     | 
    
         
             
                class Pubrel < MQTT::Packet
         
     | 
| 
       704 
     | 
    
         
            -
             
     | 
| 
       705 
675 
     | 
    
         
             
                  # Default attribute values
         
     | 
| 
       706 
676 
     | 
    
         
             
                  ATTR_DEFAULTS = {
         
     | 
| 
       707 
     | 
    
         
            -
                    :flags => [false, true, false, false] 
     | 
| 
      
 677 
     | 
    
         
            +
                    :flags => [false, true, false, false]
         
     | 
| 
       708 
678 
     | 
    
         
             
                  }
         
     | 
| 
       709 
679 
     | 
    
         | 
| 
       710 
680 
     | 
    
         
             
                  # Create a new Pubrel packet
         
     | 
| 
       711 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 681 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       712 
682 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       713 
683 
     | 
    
         
             
                  end
         
     | 
| 
       714 
684 
     | 
    
         | 
| 
         @@ -721,17 +691,16 @@ module MQTT 
     | 
|
| 
       721 
691 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       722 
692 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       723 
693 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       724 
     | 
    
         
            -
             
     | 
| 
       725 
     | 
    
         
            -
             
     | 
| 
       726 
     | 
    
         
            -
                    end
         
     | 
| 
      
 694 
     | 
    
         
            +
             
     | 
| 
      
 695 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 696 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Publish Release packet'
         
     | 
| 
       727 
697 
     | 
    
         
             
                  end
         
     | 
| 
       728 
698 
     | 
    
         | 
| 
       729 
699 
     | 
    
         
             
                  # Check that fixed header flags are valid for this packet type
         
     | 
| 
       730 
700 
     | 
    
         
             
                  # @private
         
     | 
| 
       731 
701 
     | 
    
         
             
                  def validate_flags
         
     | 
| 
       732 
     | 
    
         
            -
                    if @flags  
     | 
| 
       733 
     | 
    
         
            -
             
     | 
| 
       734 
     | 
    
         
            -
                    end
         
     | 
| 
      
 702 
     | 
    
         
            +
                    return if @flags == [false, true, false, false]
         
     | 
| 
      
 703 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid flags in PUBREL packet header'
         
     | 
| 
       735 
704 
     | 
    
         
             
                  end
         
     | 
| 
       736 
705 
     | 
    
         | 
| 
       737 
706 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -751,9 +720,9 @@ module MQTT 
     | 
|
| 
       751 
720 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       752 
721 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       753 
722 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       754 
     | 
    
         
            -
             
     | 
| 
       755 
     | 
    
         
            -
             
     | 
| 
       756 
     | 
    
         
            -
                    end
         
     | 
| 
      
 723 
     | 
    
         
            +
             
     | 
| 
      
 724 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 725 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Publish Complete packet'
         
     | 
| 
       757 
726 
     | 
    
         
             
                  end
         
     | 
| 
       758 
727 
     | 
    
         | 
| 
       759 
728 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -770,11 +739,11 @@ module MQTT 
     | 
|
| 
       770 
739 
     | 
    
         
             
                  # Default attribute values
         
     | 
| 
       771 
740 
     | 
    
         
             
                  ATTR_DEFAULTS = {
         
     | 
| 
       772 
741 
     | 
    
         
             
                    :topics => [],
         
     | 
| 
       773 
     | 
    
         
            -
                    :flags => [false, true, false, false] 
     | 
| 
      
 742 
     | 
    
         
            +
                    :flags => [false, true, false, false]
         
     | 
| 
       774 
743 
     | 
    
         
             
                  }
         
     | 
| 
       775 
744 
     | 
    
         | 
| 
       776 
745 
     | 
    
         
             
                  # Create a new Subscribe packet
         
     | 
| 
       777 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 746 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       778 
747 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       779 
748 
     | 
    
         
             
                  end
         
     | 
| 
       780 
749 
     | 
    
         | 
| 
         @@ -792,14 +761,10 @@ module MQTT 
     | 
|
| 
       792 
761 
     | 
    
         
             
                  #
         
     | 
| 
       793 
762 
     | 
    
         
             
                  def topics=(value)
         
     | 
| 
       794 
763 
     | 
    
         
             
                    # Get input into a consistent state
         
     | 
| 
       795 
     | 
    
         
            -
                     
     | 
| 
       796 
     | 
    
         
            -
                      input = value.flatten
         
     | 
| 
       797 
     | 
    
         
            -
                    else
         
     | 
| 
       798 
     | 
    
         
            -
                      input = [value]
         
     | 
| 
       799 
     | 
    
         
            -
                    end
         
     | 
| 
      
 764 
     | 
    
         
            +
                    input = value.is_a?(Array) ? value.flatten : [value]
         
     | 
| 
       800 
765 
     | 
    
         | 
| 
       801 
766 
     | 
    
         
             
                    @topics = []
         
     | 
| 
       802 
     | 
    
         
            -
                     
     | 
| 
      
 767 
     | 
    
         
            +
                    until input.empty?
         
     | 
| 
       803 
768 
     | 
    
         
             
                      item = input.shift
         
     | 
| 
       804 
769 
     | 
    
         
             
                      if item.is_a?(Hash)
         
     | 
| 
       805 
770 
     | 
    
         
             
                        # Convert hash into an ordered array of arrays
         
     | 
| 
         @@ -808,9 +773,9 @@ module MQTT 
     | 
|
| 
       808 
773 
     | 
    
         
             
                        # Peek at the next item in the array, and remove it if it is an integer
         
     | 
| 
       809 
774 
     | 
    
         
             
                        if input.first.is_a?(Integer)
         
     | 
| 
       810 
775 
     | 
    
         
             
                          qos = input.shift
         
     | 
| 
       811 
     | 
    
         
            -
                          @topics << [item,qos]
         
     | 
| 
      
 776 
     | 
    
         
            +
                          @topics << [item, qos]
         
     | 
| 
       812 
777 
     | 
    
         
             
                        else
         
     | 
| 
       813 
     | 
    
         
            -
                          @topics << [item,0]
         
     | 
| 
      
 778 
     | 
    
         
            +
                          @topics << [item, 0]
         
     | 
| 
       814 
779 
     | 
    
         
             
                        end
         
     | 
| 
       815 
780 
     | 
    
         
             
                      else
         
     | 
| 
       816 
781 
     | 
    
         
             
                        # Meh?
         
     | 
| 
         @@ -822,15 +787,13 @@ module MQTT 
     | 
|
| 
       822 
787 
     | 
    
         | 
| 
       823 
788 
     | 
    
         
             
                  # Get serialisation of packet's body
         
     | 
| 
       824 
789 
     | 
    
         
             
                  def encode_body
         
     | 
| 
       825 
     | 
    
         
            -
                    if @topics.empty?
         
     | 
| 
       826 
     | 
    
         
            -
                      raise "no topics given when serialising packet"
         
     | 
| 
       827 
     | 
    
         
            -
                    end
         
     | 
| 
      
 790 
     | 
    
         
            +
                    raise 'no topics given when serialising packet' if @topics.empty?
         
     | 
| 
       828 
791 
     | 
    
         
             
                    body = encode_short(@id)
         
     | 
| 
       829 
792 
     | 
    
         
             
                    topics.each do |item|
         
     | 
| 
       830 
793 
     | 
    
         
             
                      body += encode_string(item[0])
         
     | 
| 
       831 
794 
     | 
    
         
             
                      body += encode_bytes(item[1])
         
     | 
| 
       832 
795 
     | 
    
         
             
                    end
         
     | 
| 
       833 
     | 
    
         
            -
                     
     | 
| 
      
 796 
     | 
    
         
            +
                    body
         
     | 
| 
       834 
797 
     | 
    
         
             
                  end
         
     | 
| 
       835 
798 
     | 
    
         | 
| 
       836 
799 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a packet
         
     | 
| 
         @@ -838,26 +801,25 @@ module MQTT 
     | 
|
| 
       838 
801 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       839 
802 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       840 
803 
     | 
    
         
             
                    @topics = []
         
     | 
| 
       841 
     | 
    
         
            -
                    while 
     | 
| 
      
 804 
     | 
    
         
            +
                    while buffer.bytesize > 0
         
     | 
| 
       842 
805 
     | 
    
         
             
                      topic_name = shift_string(buffer)
         
     | 
| 
       843 
806 
     | 
    
         
             
                      topic_qos = shift_byte(buffer)
         
     | 
| 
       844 
     | 
    
         
            -
                      @topics << [topic_name,topic_qos]
         
     | 
| 
      
 807 
     | 
    
         
            +
                      @topics << [topic_name, topic_qos]
         
     | 
| 
       845 
808 
     | 
    
         
             
                    end
         
     | 
| 
       846 
809 
     | 
    
         
             
                  end
         
     | 
| 
       847 
810 
     | 
    
         | 
| 
       848 
811 
     | 
    
         
             
                  # Check that fixed header flags are valid for this packet type
         
     | 
| 
       849 
812 
     | 
    
         
             
                  # @private
         
     | 
| 
       850 
813 
     | 
    
         
             
                  def validate_flags
         
     | 
| 
       851 
     | 
    
         
            -
                    if @flags  
     | 
| 
       852 
     | 
    
         
            -
             
     | 
| 
       853 
     | 
    
         
            -
                    end
         
     | 
| 
      
 814 
     | 
    
         
            +
                    return if @flags == [false, true, false, false]
         
     | 
| 
      
 815 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid flags in SUBSCRIBE packet header'
         
     | 
| 
       854 
816 
     | 
    
         
             
                  end
         
     | 
| 
       855 
817 
     | 
    
         | 
| 
       856 
818 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
       857 
819 
     | 
    
         
             
                  def inspect
         
     | 
| 
       858 
820 
     | 
    
         
             
                    _str = "\#<#{self.class}: 0x%2.2X, %s>" % [
         
     | 
| 
       859 
821 
     | 
    
         
             
                      id,
         
     | 
| 
       860 
     | 
    
         
            -
                      topics.map {|t| "'#{t[0]}':#{t[1]}"}.join(', ')
         
     | 
| 
      
 822 
     | 
    
         
            +
                      topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(', ')
         
     | 
| 
       861 
823 
     | 
    
         
             
                    ]
         
     | 
| 
       862 
824 
     | 
    
         
             
                  end
         
     | 
| 
       863 
825 
     | 
    
         
             
                end
         
     | 
| 
         @@ -869,11 +831,11 @@ module MQTT 
     | 
|
| 
       869 
831 
     | 
    
         | 
| 
       870 
832 
     | 
    
         
             
                  # Default attribute values
         
     | 
| 
       871 
833 
     | 
    
         
             
                  ATTR_DEFAULTS = {
         
     | 
| 
       872 
     | 
    
         
            -
                    :return_codes => [] 
     | 
| 
      
 834 
     | 
    
         
            +
                    :return_codes => []
         
     | 
| 
       873 
835 
     | 
    
         
             
                  }
         
     | 
| 
       874 
836 
     | 
    
         | 
| 
       875 
837 
     | 
    
         
             
                  # Create a new Subscribe Acknowledgment packet
         
     | 
| 
       876 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 838 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       877 
839 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       878 
840 
     | 
    
         
             
                  end
         
     | 
| 
       879 
841 
     | 
    
         | 
| 
         @@ -885,36 +847,33 @@ module MQTT 
     | 
|
| 
       885 
847 
     | 
    
         
             
                    elsif value.is_a?(Integer)
         
     | 
| 
       886 
848 
     | 
    
         
             
                      @return_codes = [value]
         
     | 
| 
       887 
849 
     | 
    
         
             
                    else
         
     | 
| 
       888 
     | 
    
         
            -
                      raise  
     | 
| 
      
 850 
     | 
    
         
            +
                      raise 'return_codes should be an integer or an array of return codes'
         
     | 
| 
       889 
851 
     | 
    
         
             
                    end
         
     | 
| 
       890 
852 
     | 
    
         
             
                  end
         
     | 
| 
       891 
853 
     | 
    
         | 
| 
       892 
854 
     | 
    
         
             
                  # Get serialisation of packet's body
         
     | 
| 
       893 
855 
     | 
    
         
             
                  def encode_body
         
     | 
| 
       894 
856 
     | 
    
         
             
                    if @return_codes.empty?
         
     | 
| 
       895 
     | 
    
         
            -
                      raise  
     | 
| 
      
 857 
     | 
    
         
            +
                      raise 'no granted QoS given when serialising packet'
         
     | 
| 
       896 
858 
     | 
    
         
             
                    end
         
     | 
| 
       897 
859 
     | 
    
         
             
                    body = encode_short(@id)
         
     | 
| 
       898 
860 
     | 
    
         
             
                    return_codes.each { |qos| body += encode_bytes(qos) }
         
     | 
| 
       899 
     | 
    
         
            -
                     
     | 
| 
      
 861 
     | 
    
         
            +
                    body
         
     | 
| 
       900 
862 
     | 
    
         
             
                  end
         
     | 
| 
       901 
863 
     | 
    
         | 
| 
       902 
864 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a packet
         
     | 
| 
       903 
865 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       904 
866 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       905 
867 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       906 
     | 
    
         
            -
                     
     | 
| 
       907 
     | 
    
         
            -
                      @return_codes << shift_byte(buffer)
         
     | 
| 
       908 
     | 
    
         
            -
                    end
         
     | 
| 
      
 868 
     | 
    
         
            +
                    @return_codes << shift_byte(buffer) while buffer.bytesize > 0
         
     | 
| 
       909 
869 
     | 
    
         
             
                  end
         
     | 
| 
       910 
870 
     | 
    
         | 
| 
       911 
871 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
       912 
872 
     | 
    
         
             
                  def inspect
         
     | 
| 
       913 
     | 
    
         
            -
                    "\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map{|rc|  
     | 
| 
      
 873 
     | 
    
         
            +
                    "\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map { |rc| '0x%2.2X' % rc }.join(',')]
         
     | 
| 
       914 
874 
     | 
    
         
             
                  end
         
     | 
| 
       915 
875 
     | 
    
         | 
| 
       916 
876 
     | 
    
         
             
                  # ---- Deprecated attributes and methods  ---- #
         
     | 
| 
       917 
     | 
    
         
            -
                  public
         
     | 
| 
       918 
877 
     | 
    
         | 
| 
       919 
878 
     | 
    
         
             
                  # @deprecated Please use {#return_codes} instead
         
     | 
| 
       920 
879 
     | 
    
         
             
                  def granted_qos
         
     | 
| 
         @@ -935,55 +894,46 @@ module MQTT 
     | 
|
| 
       935 
894 
     | 
    
         
             
                  # Default attribute values
         
     | 
| 
       936 
895 
     | 
    
         
             
                  ATTR_DEFAULTS = {
         
     | 
| 
       937 
896 
     | 
    
         
             
                    :topics => [],
         
     | 
| 
       938 
     | 
    
         
            -
                    :flags => [false, true, false, false] 
     | 
| 
      
 897 
     | 
    
         
            +
                    :flags => [false, true, false, false]
         
     | 
| 
       939 
898 
     | 
    
         
             
                  }
         
     | 
| 
       940 
899 
     | 
    
         | 
| 
       941 
900 
     | 
    
         
             
                  # Create a new Unsubscribe packet
         
     | 
| 
       942 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 901 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       943 
902 
     | 
    
         
             
                    super(ATTR_DEFAULTS.merge(args))
         
     | 
| 
       944 
903 
     | 
    
         
             
                  end
         
     | 
| 
       945 
904 
     | 
    
         | 
| 
       946 
905 
     | 
    
         
             
                  # Set one or more topic paths to unsubscribe from
         
     | 
| 
       947 
906 
     | 
    
         
             
                  def topics=(value)
         
     | 
| 
       948 
     | 
    
         
            -
                     
     | 
| 
       949 
     | 
    
         
            -
                      @topics = value
         
     | 
| 
       950 
     | 
    
         
            -
                    else
         
     | 
| 
       951 
     | 
    
         
            -
                      @topics = [value]
         
     | 
| 
       952 
     | 
    
         
            -
                    end
         
     | 
| 
      
 907 
     | 
    
         
            +
                    @topics = value.is_a?(Array) ? value : [value]
         
     | 
| 
       953 
908 
     | 
    
         
             
                  end
         
     | 
| 
       954 
909 
     | 
    
         | 
| 
       955 
910 
     | 
    
         
             
                  # Get serialisation of packet's body
         
     | 
| 
       956 
911 
     | 
    
         
             
                  def encode_body
         
     | 
| 
       957 
     | 
    
         
            -
                    if @topics.empty?
         
     | 
| 
       958 
     | 
    
         
            -
                      raise "no topics given when serialising packet"
         
     | 
| 
       959 
     | 
    
         
            -
                    end
         
     | 
| 
      
 912 
     | 
    
         
            +
                    raise 'no topics given when serialising packet' if @topics.empty?
         
     | 
| 
       960 
913 
     | 
    
         
             
                    body = encode_short(@id)
         
     | 
| 
       961 
914 
     | 
    
         
             
                    topics.each { |topic| body += encode_string(topic) }
         
     | 
| 
       962 
     | 
    
         
            -
                     
     | 
| 
      
 915 
     | 
    
         
            +
                    body
         
     | 
| 
       963 
916 
     | 
    
         
             
                  end
         
     | 
| 
       964 
917 
     | 
    
         | 
| 
       965 
918 
     | 
    
         
             
                  # Parse the body (variable header and payload) of a packet
         
     | 
| 
       966 
919 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       967 
920 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       968 
921 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       969 
     | 
    
         
            -
                     
     | 
| 
       970 
     | 
    
         
            -
                      @topics << shift_string(buffer)
         
     | 
| 
       971 
     | 
    
         
            -
                    end
         
     | 
| 
      
 922 
     | 
    
         
            +
                    @topics << shift_string(buffer) while buffer.bytesize > 0
         
     | 
| 
       972 
923 
     | 
    
         
             
                  end
         
     | 
| 
       973 
924 
     | 
    
         | 
| 
       974 
925 
     | 
    
         
             
                  # Check that fixed header flags are valid for this packet type
         
     | 
| 
       975 
926 
     | 
    
         
             
                  # @private
         
     | 
| 
       976 
927 
     | 
    
         
             
                  def validate_flags
         
     | 
| 
       977 
     | 
    
         
            -
                    if @flags  
     | 
| 
       978 
     | 
    
         
            -
             
     | 
| 
       979 
     | 
    
         
            -
                    end
         
     | 
| 
      
 928 
     | 
    
         
            +
                    return if @flags == [false, true, false, false]
         
     | 
| 
      
 929 
     | 
    
         
            +
                    raise ProtocolException, 'Invalid flags in UNSUBSCRIBE packet header'
         
     | 
| 
       980 
930 
     | 
    
         
             
                  end
         
     | 
| 
       981 
931 
     | 
    
         | 
| 
       982 
932 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
       983 
933 
     | 
    
         
             
                  def inspect
         
     | 
| 
       984 
934 
     | 
    
         
             
                    "\#<#{self.class}: 0x%2.2X, %s>" % [
         
     | 
| 
       985 
935 
     | 
    
         
             
                      id,
         
     | 
| 
       986 
     | 
    
         
            -
                      topics.map {|t| "'#{t}'"}.join(', ')
         
     | 
| 
      
 936 
     | 
    
         
            +
                      topics.map { |t| "'#{t}'" }.join(', ')
         
     | 
| 
       987 
937 
     | 
    
         
             
                    ]
         
     | 
| 
       988 
938 
     | 
    
         
             
                  end
         
     | 
| 
       989 
939 
     | 
    
         
             
                end
         
     | 
| 
         @@ -991,7 +941,7 @@ module MQTT 
     | 
|
| 
       991 
941 
     | 
    
         
             
                # Class representing an MQTT Unsubscribe Acknowledgment packet
         
     | 
| 
       992 
942 
     | 
    
         
             
                class Unsuback < MQTT::Packet
         
     | 
| 
       993 
943 
     | 
    
         
             
                  # Create a new Unsubscribe Acknowledgment packet
         
     | 
| 
       994 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 944 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       995 
945 
     | 
    
         
             
                    super(args)
         
     | 
| 
       996 
946 
     | 
    
         
             
                  end
         
     | 
| 
       997 
947 
     | 
    
         | 
| 
         @@ -1004,9 +954,9 @@ module MQTT 
     | 
|
| 
       1004 
954 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       1005 
955 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       1006 
956 
     | 
    
         
             
                    @id = shift_short(buffer)
         
     | 
| 
       1007 
     | 
    
         
            -
             
     | 
| 
       1008 
     | 
    
         
            -
             
     | 
| 
       1009 
     | 
    
         
            -
                    end
         
     | 
| 
      
 957 
     | 
    
         
            +
             
     | 
| 
      
 958 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 959 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Unsubscribe Acknowledgment packet'
         
     | 
| 
       1010 
960 
     | 
    
         
             
                  end
         
     | 
| 
       1011 
961 
     | 
    
         | 
| 
       1012 
962 
     | 
    
         
             
                  # Returns a human readable string, summarising the properties of the packet
         
     | 
| 
         @@ -1018,52 +968,51 @@ module MQTT 
     | 
|
| 
       1018 
968 
     | 
    
         
             
                # Class representing an MQTT Ping Request packet
         
     | 
| 
       1019 
969 
     | 
    
         
             
                class Pingreq < MQTT::Packet
         
     | 
| 
       1020 
970 
     | 
    
         
             
                  # Create a new Ping Request packet
         
     | 
| 
       1021 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 971 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       1022 
972 
     | 
    
         
             
                    super(args)
         
     | 
| 
       1023 
973 
     | 
    
         
             
                  end
         
     | 
| 
       1024 
974 
     | 
    
         | 
| 
       1025 
975 
     | 
    
         
             
                  # Check the body
         
     | 
| 
       1026 
976 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       1027 
977 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       1028 
     | 
    
         
            -
             
     | 
| 
       1029 
     | 
    
         
            -
             
     | 
| 
       1030 
     | 
    
         
            -
                    end
         
     | 
| 
      
 978 
     | 
    
         
            +
             
     | 
| 
      
 979 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 980 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Ping Request packet'
         
     | 
| 
       1031 
981 
     | 
    
         
             
                  end
         
     | 
| 
       1032 
982 
     | 
    
         
             
                end
         
     | 
| 
       1033 
983 
     | 
    
         | 
| 
       1034 
984 
     | 
    
         
             
                # Class representing an MQTT Ping Response packet
         
     | 
| 
       1035 
985 
     | 
    
         
             
                class Pingresp < MQTT::Packet
         
     | 
| 
       1036 
986 
     | 
    
         
             
                  # Create a new Ping Response packet
         
     | 
| 
       1037 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 987 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       1038 
988 
     | 
    
         
             
                    super(args)
         
     | 
| 
       1039 
989 
     | 
    
         
             
                  end
         
     | 
| 
       1040 
990 
     | 
    
         | 
| 
       1041 
991 
     | 
    
         
             
                  # Check the body
         
     | 
| 
       1042 
992 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       1043 
993 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       1044 
     | 
    
         
            -
             
     | 
| 
       1045 
     | 
    
         
            -
             
     | 
| 
       1046 
     | 
    
         
            -
                    end
         
     | 
| 
      
 994 
     | 
    
         
            +
             
     | 
| 
      
 995 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 996 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Ping Response packet'
         
     | 
| 
       1047 
997 
     | 
    
         
             
                  end
         
     | 
| 
       1048 
998 
     | 
    
         
             
                end
         
     | 
| 
       1049 
999 
     | 
    
         | 
| 
       1050 
1000 
     | 
    
         
             
                # Class representing an MQTT Client Disconnect packet
         
     | 
| 
       1051 
1001 
     | 
    
         
             
                class Disconnect < MQTT::Packet
         
     | 
| 
       1052 
1002 
     | 
    
         
             
                  # Create a new Client Disconnect packet
         
     | 
| 
       1053 
     | 
    
         
            -
                  def initialize(args={})
         
     | 
| 
      
 1003 
     | 
    
         
            +
                  def initialize(args = {})
         
     | 
| 
       1054 
1004 
     | 
    
         
             
                    super(args)
         
     | 
| 
       1055 
1005 
     | 
    
         
             
                  end
         
     | 
| 
       1056 
1006 
     | 
    
         | 
| 
       1057 
1007 
     | 
    
         
             
                  # Check the body
         
     | 
| 
       1058 
1008 
     | 
    
         
             
                  def parse_body(buffer)
         
     | 
| 
       1059 
1009 
     | 
    
         
             
                    super(buffer)
         
     | 
| 
       1060 
     | 
    
         
            -
             
     | 
| 
       1061 
     | 
    
         
            -
             
     | 
| 
       1062 
     | 
    
         
            -
                    end
         
     | 
| 
      
 1010 
     | 
    
         
            +
             
     | 
| 
      
 1011 
     | 
    
         
            +
                    return if buffer.empty?
         
     | 
| 
      
 1012 
     | 
    
         
            +
                    raise ProtocolException, 'Extra bytes at end of Disconnect packet'
         
     | 
| 
       1063 
1013 
     | 
    
         
             
                  end
         
     | 
| 
       1064 
1014 
     | 
    
         
             
                end
         
     | 
| 
       1065 
1015 
     | 
    
         | 
| 
       1066 
     | 
    
         
            -
             
     | 
| 
       1067 
1016 
     | 
    
         
             
                # ---- Deprecated attributes and methods  ---- #
         
     | 
| 
       1068 
1017 
     | 
    
         
             
                public
         
     | 
| 
       1069 
1018 
     | 
    
         | 
| 
         @@ -1078,7 +1027,6 @@ module MQTT 
     | 
|
| 
       1078 
1027 
     | 
    
         
             
                end
         
     | 
| 
       1079 
1028 
     | 
    
         
             
              end
         
     | 
| 
       1080 
1029 
     | 
    
         | 
| 
       1081 
     | 
    
         
            -
             
     | 
| 
       1082 
1030 
     | 
    
         
             
              # An enumeration of the MQTT packet types
         
     | 
| 
       1083 
1031 
     | 
    
         
             
              PACKET_TYPES = [
         
     | 
| 
       1084 
1032 
     | 
    
         
             
                nil,
         
     | 
| 
         @@ -1098,5 +1046,4 @@ module MQTT 
     | 
|
| 
       1098 
1046 
     | 
    
         
             
                MQTT::Packet::Disconnect,
         
     | 
| 
       1099 
1047 
     | 
    
         
             
                nil
         
     | 
| 
       1100 
1048 
     | 
    
         
             
              ]
         
     | 
| 
       1101 
     | 
    
         
            -
             
     | 
| 
       1102 
1049 
     | 
    
         
             
            end
         
     |