mqtt 0.5.0 → 0.6.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.
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 MQTT::Packet
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
- begin
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
- end while ((digit & 0x80) != 0x00) and pos <= 4
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( socket.read(body_length) )
51
+ packet.parse_body(socket.read(body_length))
51
52
 
52
- return packet
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
- return packet
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.new("Invalid packet: less than 2 bytes long")
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("C5")
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
- begin
80
+
81
+ loop do
80
82
  if buffer.bytesize <= pos
81
- raise ProtocolException.new("The packet length header is incomplete")
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
- end while ((digit & 0x80) != 0x00) and pos <= 4
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
- return packet
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.new("Invalid packet type identifier: #{type_id}")
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 ** i) != 0 }
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) or v.is_a?(Hash)
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
- raise "Invalid packet type: #{self.class}"
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 != body_length
162
- raise ProtocolException.new(
163
- "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
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
- (flags[3] ? 0x8 : 0x0) |
180
- (flags[2] ? 0x4 : 0x0) |
181
- (flags[1] ? 0x2 : 0x0) |
182
- (flags[0] ? 0x1 : 0x0)
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 = self.encode_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 > 268435455
191
- raise "Error serialising packet: body is more than 256MB"
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
- begin
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 (body_length > 0)
198
+ digit |= 0x80 if body_length > 0
200
199
  header.push(digit)
201
- end while (body_length > 0)
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 != [false, false, false, false]
211
- raise ProtocolException.new("Invalid flags in #{type_name} packet header")
212
- end
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
- if arg.kind_of?(Integer)
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
- if arg.kind_of?(Integer)
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 or @qos > 2
356
- raise "Invalid QoS value: #{@qos}"
357
- else
358
- @flags[1] = (arg & 0x01 == 0x01)
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? or @topic.to_s.empty?
367
- raise "Invalid topic name when serialising packet"
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 == 0
353
+ body += encode_short(@id) unless qos.zero?
371
354
  body += payload.to_s.dup.force_encoding('ASCII-8BIT')
372
- return body
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 == 0
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
- raise ProtocolException.new("Invalid packet: QoS value of 3 is not allowed")
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
- "d#{duplicate ? '1' : '0'}, " +
398
- "q#{qos}, " +
399
- "r#{retain ? '1' : '0'}, " +
400
- "m#{id}, " +
401
- "'#{topic}', " +
402
- "#{inspect_payload}>"
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 and str =~ /^[ -~]*$/
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 version == '3.1.0' or version == '3.1'
448
+ if version == '3.1.0' || version == '3.1'
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.new("Unsupported protocol version: #{version}")
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? or @client_id.bytesize < 1
485
- raise "Client identifier too short while serialising packet"
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 "Invalid keep-alive value: cannot be less than 0"
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
- return body
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' and @protocol_level == 3
502
+ if @protocol_name == 'MQIsdp' && @protocol_level == 3
525
503
  @version = '3.1.0'
526
- elsif @protocol_name == 'MQTT' and @protocol_level == 4
504
+ elsif @protocol_name == 'MQTT' && @protocol_level == 4
527
505
  @version = '3.1.1'
528
506
  else
529
- raise ProtocolException.new(
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 and buffer.bytesize > 0
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 and buffer.bytesize > 0
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
- str += "keep_alive=#{keep_alive}"
558
- str += ", clean" if clean_session
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 += ", password=..." unless password.nil?
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
- if arg.kind_of?(Integer)
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
- when 0x00
615
- "Connection Accepted"
616
- when 0x01
617
- "Connection refused: unacceptable protocol version"
618
- when 0x02
619
- "Connection refused: client identifier rejected"
620
- when 0x03
621
- "Connection refused: server unavailable"
622
- when 0x04
623
- "Connection refused: bad user name or password"
624
- when 0x05
625
- "Connection refused: not authorised"
626
- else
627
- "Connection refused: error code #{return_code}"
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
- return body
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.new("Invalid flags in Connack variable header")
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
- unless buffer.empty?
648
- raise ProtocolException.new("Extra bytes at end of Connect Acknowledgment packet")
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
- unless buffer.empty?
670
- raise ProtocolException.new("Extra bytes at end of Publish Acknowledgment packet")
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
- unless buffer.empty?
692
- raise ProtocolException.new("Extra bytes at end of Publish Received packet")
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
- unless buffer.empty?
725
- raise ProtocolException.new("Extra bytes at end of Publish Release packet")
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 != [false, true, false, false]
733
- raise ProtocolException.new("Invalid flags in PUBREL packet header")
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
- unless buffer.empty?
755
- raise ProtocolException.new("Extra bytes at end of Publish Complete packet")
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
- if value.is_a?(Array)
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
- while(input.length>0)
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
- return body
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(buffer.bytesize>0)
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 != [false, true, false, false]
852
- raise ProtocolException.new("Invalid flags in SUBSCRIBE packet header")
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 "return_codes should be an integer or an array of return codes"
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 "no granted QoS given when serialising packet"
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
- return body
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
- while(buffer.bytesize>0)
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| "0x%2.2X" % rc}.join(',')]
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
- if value.is_a?(Array)
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
- return body
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
- while(buffer.bytesize>0)
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 != [false, true, false, false]
978
- raise ProtocolException.new("Invalid flags in UNSUBSCRIBE packet header")
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
- unless buffer.empty?
1008
- raise ProtocolException.new("Extra bytes at end of Unsubscribe Acknowledgment packet")
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
- unless buffer.empty?
1029
- raise ProtocolException.new("Extra bytes at end of Ping Request packet")
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
- unless buffer.empty?
1045
- raise ProtocolException.new("Extra bytes at end of Ping Response packet")
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
- unless buffer.empty?
1061
- raise ProtocolException.new("Extra bytes at end of Disconnect packet")
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