mqtt-ccutrer 1.0.3 → 1.1.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 +4 -4
- data/README.md +9 -2
- data/lib/mqtt/client.rb +65 -41
- data/lib/mqtt/packet.rb +113 -113
- data/lib/mqtt/proxy.rb +5 -5
- data/lib/mqtt/sn/packet.rb +80 -80
- data/lib/mqtt/version.rb +1 -1
- data/lib/mqtt-ccutrer.rb +1 -1
- data/lib/mqtt.rb +8 -8
- metadata +18 -131
- data/spec/zz_client_integration_spec.rb +0 -180
data/lib/mqtt/packet.rb
CHANGED
|
@@ -19,7 +19,7 @@ module MQTT
|
|
|
19
19
|
|
|
20
20
|
# Default attribute values
|
|
21
21
|
ATTR_DEFAULTS = {
|
|
22
|
-
version:
|
|
22
|
+
version: "3.1.0",
|
|
23
23
|
id: 0,
|
|
24
24
|
body_length: nil
|
|
25
25
|
}.freeze
|
|
@@ -42,7 +42,7 @@ module MQTT
|
|
|
42
42
|
body_length += ((digit & 0x7F) * multiplier)
|
|
43
43
|
multiplier *= 0x80
|
|
44
44
|
pos += 1
|
|
45
|
-
break if (
|
|
45
|
+
break if digit.nobits?(0x80) || pos > 4
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Store the expected body length in the packet
|
|
@@ -66,10 +66,10 @@ module MQTT
|
|
|
66
66
|
# The header is removed from the buffer passed into this function
|
|
67
67
|
def self.parse_header(buffer)
|
|
68
68
|
# Check that the packet is a long as the minimum packet size
|
|
69
|
-
raise ProtocolException,
|
|
69
|
+
raise ProtocolException, "Invalid packet: less than 2 bytes long" if buffer.bytesize < 2
|
|
70
70
|
|
|
71
71
|
# Create a new packet object
|
|
72
|
-
bytes = buffer.unpack(
|
|
72
|
+
bytes = buffer.unpack("C5")
|
|
73
73
|
packet = create_from_header(bytes.first)
|
|
74
74
|
packet.validate_flags
|
|
75
75
|
|
|
@@ -79,13 +79,13 @@ module MQTT
|
|
|
79
79
|
pos = 1
|
|
80
80
|
|
|
81
81
|
loop do
|
|
82
|
-
raise ProtocolException,
|
|
82
|
+
raise ProtocolException, "The packet length header is incomplete" if buffer.bytesize <= pos
|
|
83
83
|
|
|
84
84
|
digit = bytes[pos]
|
|
85
85
|
body_length += ((digit & 0x7F) * multiplier)
|
|
86
86
|
multiplier *= 0x80
|
|
87
87
|
pos += 1
|
|
88
|
-
break if (
|
|
88
|
+
break if digit.nobits?(0x80) || pos > 4
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
# Store the expected body length in the packet
|
|
@@ -105,10 +105,10 @@ module MQTT
|
|
|
105
105
|
raise ProtocolException, "Invalid packet type identifier: #{type_id}" if packet_class.nil?
|
|
106
106
|
|
|
107
107
|
# Convert the last 4 bits of byte into array of true/false
|
|
108
|
-
flags = (0..3).map { |i| byte & (2
|
|
108
|
+
flags = (0..3).map { |i| byte & (2**i) != 0 }
|
|
109
109
|
|
|
110
110
|
# Create a new packet object
|
|
111
|
-
packet_class.new(flags:
|
|
111
|
+
packet_class.new(flags:)
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
# Create a new empty packet
|
|
@@ -148,7 +148,7 @@ module MQTT
|
|
|
148
148
|
#
|
|
149
149
|
# Example: CONNACK
|
|
150
150
|
def type_name
|
|
151
|
-
self.class.name.split(
|
|
151
|
+
self.class.name.split("::").last.upcase
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
# Set the protocol version number
|
|
@@ -172,7 +172,7 @@ module MQTT
|
|
|
172
172
|
|
|
173
173
|
# Get serialisation of packet's body (variable header and payload)
|
|
174
174
|
def encode_body
|
|
175
|
-
|
|
175
|
+
"" # No body by default
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
# Serialise the packet
|
|
@@ -191,20 +191,20 @@ module MQTT
|
|
|
191
191
|
|
|
192
192
|
# Check that that packet isn't too big
|
|
193
193
|
body_length = body.bytesize
|
|
194
|
-
raise
|
|
194
|
+
raise "Error serialising packet: body is more than 256MB" if body_length > 268_435_455
|
|
195
195
|
|
|
196
196
|
# Build up the body length field bytes
|
|
197
197
|
loop do
|
|
198
198
|
digit = (body_length % 128)
|
|
199
199
|
body_length = body_length.div(128)
|
|
200
200
|
# if there are more digits to encode, set the top bit of this digit
|
|
201
|
-
digit |= 0x80 if body_length
|
|
201
|
+
digit |= 0x80 if body_length.positive?
|
|
202
202
|
header.push(digit)
|
|
203
203
|
break if body_length <= 0
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
# Convert header to binary and add on body
|
|
207
|
-
header.pack(
|
|
207
|
+
header.pack("C*") + body
|
|
208
208
|
end
|
|
209
209
|
|
|
210
210
|
# Check that fixed header flags are valid for types that don't use the flags
|
|
@@ -217,60 +217,60 @@ module MQTT
|
|
|
217
217
|
|
|
218
218
|
# Returns a human readable string
|
|
219
219
|
def inspect
|
|
220
|
-
"
|
|
220
|
+
"#<#{self.class}>"
|
|
221
221
|
end
|
|
222
222
|
|
|
223
223
|
# Read and unpack a single byte from a socket
|
|
224
224
|
def self.read_byte(socket)
|
|
225
|
-
byte = socket.
|
|
226
|
-
raise ProtocolException,
|
|
225
|
+
byte = socket.getbyte
|
|
226
|
+
raise ProtocolException, "Failed to read byte from socket" if byte.nil?
|
|
227
227
|
|
|
228
|
-
byte
|
|
228
|
+
byte
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
protected
|
|
232
232
|
|
|
233
233
|
# Encode an array of bytes and return them
|
|
234
234
|
def encode_bytes(*bytes)
|
|
235
|
-
bytes.pack(
|
|
235
|
+
bytes.pack("C*")
|
|
236
236
|
end
|
|
237
237
|
|
|
238
238
|
# Encode an array of bits and return them
|
|
239
239
|
def encode_bits(bits)
|
|
240
|
-
[bits.map { |b| b ?
|
|
240
|
+
[bits.map { |b| b ? "1" : "0" }.join].pack("b*")
|
|
241
241
|
end
|
|
242
242
|
|
|
243
243
|
# Encode a 16-bit unsigned integer and return it
|
|
244
244
|
def encode_short(val)
|
|
245
|
-
raise
|
|
245
|
+
raise "Value too big for short" if val > 0xffff
|
|
246
246
|
|
|
247
|
-
[val.to_i].pack(
|
|
247
|
+
[val.to_i].pack("n")
|
|
248
248
|
end
|
|
249
249
|
|
|
250
250
|
# Encode a UTF-8 string and return it
|
|
251
251
|
# (preceded by the length of the string)
|
|
252
252
|
def encode_string(str)
|
|
253
|
-
str = str.to_s.encode(
|
|
253
|
+
str = str.to_s.encode("UTF-8")
|
|
254
254
|
|
|
255
255
|
# Force to binary, when assembling the packet
|
|
256
|
-
str.force_encoding(
|
|
256
|
+
str.force_encoding("ASCII-8BIT")
|
|
257
257
|
encode_short(str.bytesize) + str
|
|
258
258
|
end
|
|
259
259
|
|
|
260
260
|
# Remove a 16-bit unsigned integer from the front of buffer
|
|
261
261
|
def shift_short(buffer)
|
|
262
262
|
bytes = buffer.slice!(0..1)
|
|
263
|
-
bytes.unpack1(
|
|
263
|
+
bytes.unpack1("n")
|
|
264
264
|
end
|
|
265
265
|
|
|
266
266
|
# Remove one byte from the front of the string
|
|
267
267
|
def shift_byte(buffer)
|
|
268
|
-
buffer.slice!(0...1).unpack1(
|
|
268
|
+
buffer.slice!(0...1).unpack1("C")
|
|
269
269
|
end
|
|
270
270
|
|
|
271
271
|
# Remove 8 bits from the front of buffer
|
|
272
272
|
def shift_bits(buffer)
|
|
273
|
-
buffer.slice!(0...1).unpack1(
|
|
273
|
+
buffer.slice!(0...1).unpack1("b8").chars.map { |b| b == "1" }
|
|
274
274
|
end
|
|
275
275
|
|
|
276
276
|
# Remove n bytes from the front of buffer
|
|
@@ -283,7 +283,7 @@ module MQTT
|
|
|
283
283
|
len = shift_short(buffer)
|
|
284
284
|
str = shift_data(buffer, len)
|
|
285
285
|
# Strings in MQTT v3.1 are all UTF-8
|
|
286
|
-
str.force_encoding(
|
|
286
|
+
str.force_encoding("UTF-8")
|
|
287
287
|
end
|
|
288
288
|
|
|
289
289
|
## PACKET SUBCLASSES ##
|
|
@@ -299,7 +299,7 @@ module MQTT
|
|
|
299
299
|
# Default attribute values
|
|
300
300
|
ATTR_DEFAULTS = {
|
|
301
301
|
topic: nil,
|
|
302
|
-
payload:
|
|
302
|
+
payload: ""
|
|
303
303
|
}.freeze
|
|
304
304
|
|
|
305
305
|
# Create a new Publish packet
|
|
@@ -335,7 +335,7 @@ module MQTT
|
|
|
335
335
|
# Set the Quality of Service level (0/1/2)
|
|
336
336
|
def qos=(arg)
|
|
337
337
|
@qos = arg.to_i
|
|
338
|
-
raise "Invalid QoS value: #{@qos}"
|
|
338
|
+
raise "Invalid QoS value: #{@qos}" unless (0..2).cover?(@qos)
|
|
339
339
|
|
|
340
340
|
@flags[1] = (arg & 0x01 == 0x01)
|
|
341
341
|
@flags[2] = (arg & 0x02 == 0x02)
|
|
@@ -343,18 +343,18 @@ module MQTT
|
|
|
343
343
|
|
|
344
344
|
# Get serialisation of packet's body
|
|
345
345
|
def encode_body
|
|
346
|
-
body =
|
|
347
|
-
raise
|
|
346
|
+
body = ""
|
|
347
|
+
raise "Invalid topic name when serialising packet" if @topic.nil? || @topic.to_s.empty?
|
|
348
348
|
|
|
349
349
|
body += encode_string(@topic)
|
|
350
350
|
body += encode_short(@id) unless qos.zero?
|
|
351
|
-
body += payload.to_s.dup.force_encoding(
|
|
351
|
+
body += payload.to_s.dup.force_encoding("ASCII-8BIT")
|
|
352
352
|
body
|
|
353
353
|
end
|
|
354
354
|
|
|
355
355
|
# Parse the body (variable header and payload) of a Publish packet
|
|
356
356
|
def parse_body(buffer)
|
|
357
|
-
super
|
|
357
|
+
super
|
|
358
358
|
@topic = shift_string(buffer)
|
|
359
359
|
@id = shift_short(buffer) unless qos.zero?
|
|
360
360
|
@payload = buffer
|
|
@@ -363,16 +363,16 @@ module MQTT
|
|
|
363
363
|
# Check that fixed header flags are valid for this packet type
|
|
364
364
|
# @private
|
|
365
365
|
def validate_flags
|
|
366
|
-
raise ProtocolException,
|
|
367
|
-
raise ProtocolException,
|
|
366
|
+
raise ProtocolException, "Invalid packet: QoS value of 3 is not allowed" if qos == 3
|
|
367
|
+
raise ProtocolException, "Invalid packet: DUP cannot be set for QoS 0" if qos.zero? && duplicate
|
|
368
368
|
end
|
|
369
369
|
|
|
370
370
|
# Returns a human readable string, summarising the properties of the packet
|
|
371
371
|
def inspect
|
|
372
|
-
"
|
|
373
|
-
"d#{duplicate ?
|
|
372
|
+
"#<#{self.class}: " \
|
|
373
|
+
"d#{duplicate ? "1" : "0"}, " \
|
|
374
374
|
"q#{qos}, " \
|
|
375
|
-
"r#{retain ?
|
|
375
|
+
"r#{retain ? "1" : "0"}, " \
|
|
376
376
|
"m#{id}, " \
|
|
377
377
|
"'#{topic}', " \
|
|
378
378
|
"#{inspect_payload}>"
|
|
@@ -433,7 +433,7 @@ module MQTT
|
|
|
433
433
|
will_topic: nil,
|
|
434
434
|
will_qos: 0,
|
|
435
435
|
will_retain: false,
|
|
436
|
-
will_payload:
|
|
436
|
+
will_payload: "",
|
|
437
437
|
username: nil,
|
|
438
438
|
password: nil
|
|
439
439
|
}.freeze
|
|
@@ -443,11 +443,11 @@ module MQTT
|
|
|
443
443
|
super(ATTR_DEFAULTS.merge(args))
|
|
444
444
|
|
|
445
445
|
case version
|
|
446
|
-
when
|
|
447
|
-
self.protocol_name ||=
|
|
446
|
+
when "3.1.0", "3.1"
|
|
447
|
+
self.protocol_name ||= "MQIsdp"
|
|
448
448
|
self.protocol_level ||= 0x03
|
|
449
|
-
when
|
|
450
|
-
self.protocol_name ||=
|
|
449
|
+
when "3.1.1"
|
|
450
|
+
self.protocol_name ||= "MQTT"
|
|
451
451
|
self.protocol_level ||= 0x04
|
|
452
452
|
else
|
|
453
453
|
raise ArgumentError, "Unsupported protocol version: #{version}"
|
|
@@ -456,17 +456,17 @@ module MQTT
|
|
|
456
456
|
|
|
457
457
|
# Get serialisation of packet's body
|
|
458
458
|
def encode_body
|
|
459
|
-
body =
|
|
459
|
+
body = ""
|
|
460
460
|
|
|
461
|
-
if @version ==
|
|
462
|
-
raise
|
|
463
|
-
raise
|
|
461
|
+
if @version == "3.1.0"
|
|
462
|
+
raise "Client identifier too short while serialising packet" if @client_id.nil? || @client_id.bytesize < 1
|
|
463
|
+
raise "Client identifier too long when serialising packet" if @client_id.bytesize > 23
|
|
464
464
|
end
|
|
465
465
|
|
|
466
466
|
body += encode_string(@protocol_name)
|
|
467
467
|
body += encode_bytes(@protocol_level.to_i)
|
|
468
468
|
|
|
469
|
-
raise
|
|
469
|
+
raise "Invalid keep-alive value: cannot be less than 0" if @keep_alive.negative?
|
|
470
470
|
|
|
471
471
|
# Set the Connect flags
|
|
472
472
|
@connect_flags = 0
|
|
@@ -492,13 +492,13 @@ module MQTT
|
|
|
492
492
|
|
|
493
493
|
# Parse the body (variable header and payload) of a Connect packet
|
|
494
494
|
def parse_body(buffer)
|
|
495
|
-
super
|
|
495
|
+
super
|
|
496
496
|
@protocol_name = shift_string(buffer)
|
|
497
497
|
@protocol_level = shift_byte(buffer).to_i
|
|
498
|
-
if @protocol_name ==
|
|
499
|
-
@version =
|
|
500
|
-
elsif @protocol_name ==
|
|
501
|
-
@version =
|
|
498
|
+
if @protocol_name == "MQIsdp" && @protocol_level == 3
|
|
499
|
+
@version = "3.1.0"
|
|
500
|
+
elsif @protocol_name == "MQTT" && @protocol_level == 4
|
|
501
|
+
@version = "3.1.1"
|
|
502
502
|
else
|
|
503
503
|
raise ProtocolException, "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
|
|
504
504
|
end
|
|
@@ -515,21 +515,21 @@ module MQTT
|
|
|
515
515
|
# The MQTT v3.1 specification says that the payload is a UTF-8 string
|
|
516
516
|
@will_payload = shift_string(buffer)
|
|
517
517
|
end
|
|
518
|
-
@username = shift_string(buffer) if ((@connect_flags & 0x80) >> 7) == 0x01 && buffer.
|
|
519
|
-
if ((@connect_flags & 0x40) >> 6) == 0x01 && buffer.
|
|
518
|
+
@username = shift_string(buffer) if ((@connect_flags & 0x80) >> 7) == 0x01 && !buffer.empty?
|
|
519
|
+
if ((@connect_flags & 0x40) >> 6) == 0x01 && !buffer.empty? # rubocop: disable Style/GuardClause
|
|
520
520
|
@password = shift_string(buffer)
|
|
521
521
|
end
|
|
522
522
|
end
|
|
523
523
|
|
|
524
524
|
# Returns a human readable string, summarising the properties of the packet
|
|
525
525
|
def inspect
|
|
526
|
-
str = "
|
|
526
|
+
str = "#<#{self.class}: " \
|
|
527
527
|
"keep_alive=#{keep_alive}"
|
|
528
|
-
str +=
|
|
528
|
+
str += ", clean" if clean_session
|
|
529
529
|
str += ", client_id='#{client_id}'"
|
|
530
530
|
str += ", username='#{username}'" unless username.nil?
|
|
531
|
-
str +=
|
|
532
|
-
str
|
|
531
|
+
str += ", password=..." unless password.nil?
|
|
532
|
+
"#{str}>"
|
|
533
533
|
end
|
|
534
534
|
|
|
535
535
|
# ---- Deprecated attributes and methods ---- #
|
|
@@ -574,17 +574,17 @@ module MQTT
|
|
|
574
574
|
def return_msg
|
|
575
575
|
case return_code
|
|
576
576
|
when 0x00
|
|
577
|
-
|
|
577
|
+
"Connection Accepted"
|
|
578
578
|
when 0x01
|
|
579
|
-
|
|
579
|
+
"Connection refused: unacceptable protocol version"
|
|
580
580
|
when 0x02
|
|
581
|
-
|
|
581
|
+
"Connection refused: client identifier rejected"
|
|
582
582
|
when 0x03
|
|
583
|
-
|
|
583
|
+
"Connection refused: server unavailable"
|
|
584
584
|
when 0x04
|
|
585
|
-
|
|
585
|
+
"Connection refused: bad user name or password"
|
|
586
586
|
when 0x05
|
|
587
|
-
|
|
587
|
+
"Connection refused: not authorised"
|
|
588
588
|
else
|
|
589
589
|
"Connection refused: error code #{return_code}"
|
|
590
590
|
end
|
|
@@ -592,7 +592,7 @@ module MQTT
|
|
|
592
592
|
|
|
593
593
|
# Get serialisation of packet's body
|
|
594
594
|
def encode_body
|
|
595
|
-
body =
|
|
595
|
+
body = ""
|
|
596
596
|
body += encode_bits(@connack_flags)
|
|
597
597
|
body += encode_bytes(@return_code.to_i)
|
|
598
598
|
body
|
|
@@ -600,22 +600,22 @@ module MQTT
|
|
|
600
600
|
|
|
601
601
|
# Parse the body (variable header and payload) of a Connect Acknowledgment packet
|
|
602
602
|
def parse_body(buffer)
|
|
603
|
-
super
|
|
603
|
+
super
|
|
604
604
|
@connack_flags = shift_bits(buffer)
|
|
605
605
|
unless @connack_flags[1, 7] == [false, false, false, false, false, false, false]
|
|
606
|
-
raise ProtocolException,
|
|
606
|
+
raise ProtocolException, "Invalid flags in Connack variable header"
|
|
607
607
|
end
|
|
608
608
|
|
|
609
609
|
@return_code = shift_byte(buffer)
|
|
610
610
|
|
|
611
611
|
return if buffer.empty?
|
|
612
612
|
|
|
613
|
-
raise ProtocolException,
|
|
613
|
+
raise ProtocolException, "Extra bytes at end of Connect Acknowledgment packet"
|
|
614
614
|
end
|
|
615
615
|
|
|
616
616
|
# Returns a human readable string, summarising the properties of the packet
|
|
617
617
|
def inspect
|
|
618
|
-
"
|
|
618
|
+
"#<#{self.class}: 0x%2.2X>" % return_code
|
|
619
619
|
end
|
|
620
620
|
end
|
|
621
621
|
|
|
@@ -628,17 +628,17 @@ module MQTT
|
|
|
628
628
|
|
|
629
629
|
# Parse the body (variable header and payload) of a packet
|
|
630
630
|
def parse_body(buffer)
|
|
631
|
-
super
|
|
631
|
+
super
|
|
632
632
|
@id = shift_short(buffer)
|
|
633
633
|
|
|
634
634
|
return if buffer.empty?
|
|
635
635
|
|
|
636
|
-
raise ProtocolException,
|
|
636
|
+
raise ProtocolException, "Extra bytes at end of Publish Acknowledgment packet"
|
|
637
637
|
end
|
|
638
638
|
|
|
639
639
|
# Returns a human readable string, summarising the properties of the packet
|
|
640
640
|
def inspect
|
|
641
|
-
"
|
|
641
|
+
"#<#{self.class}: 0x%2.2X>" % id
|
|
642
642
|
end
|
|
643
643
|
end
|
|
644
644
|
|
|
@@ -651,17 +651,17 @@ module MQTT
|
|
|
651
651
|
|
|
652
652
|
# Parse the body (variable header and payload) of a packet
|
|
653
653
|
def parse_body(buffer)
|
|
654
|
-
super
|
|
654
|
+
super
|
|
655
655
|
@id = shift_short(buffer)
|
|
656
656
|
|
|
657
657
|
return if buffer.empty?
|
|
658
658
|
|
|
659
|
-
raise ProtocolException,
|
|
659
|
+
raise ProtocolException, "Extra bytes at end of Publish Received packet"
|
|
660
660
|
end
|
|
661
661
|
|
|
662
662
|
# Returns a human readable string, summarising the properties of the packet
|
|
663
663
|
def inspect
|
|
664
|
-
"
|
|
664
|
+
"#<#{self.class}: 0x%2.2X>" % id
|
|
665
665
|
end
|
|
666
666
|
end
|
|
667
667
|
|
|
@@ -684,12 +684,12 @@ module MQTT
|
|
|
684
684
|
|
|
685
685
|
# Parse the body (variable header and payload) of a packet
|
|
686
686
|
def parse_body(buffer)
|
|
687
|
-
super
|
|
687
|
+
super
|
|
688
688
|
@id = shift_short(buffer)
|
|
689
689
|
|
|
690
690
|
return if buffer.empty?
|
|
691
691
|
|
|
692
|
-
raise ProtocolException,
|
|
692
|
+
raise ProtocolException, "Extra bytes at end of Publish Release packet"
|
|
693
693
|
end
|
|
694
694
|
|
|
695
695
|
# Check that fixed header flags are valid for this packet type
|
|
@@ -697,12 +697,12 @@ module MQTT
|
|
|
697
697
|
def validate_flags
|
|
698
698
|
return if @flags == [false, true, false, false]
|
|
699
699
|
|
|
700
|
-
raise ProtocolException,
|
|
700
|
+
raise ProtocolException, "Invalid flags in PUBREL packet header"
|
|
701
701
|
end
|
|
702
702
|
|
|
703
703
|
# Returns a human readable string, summarising the properties of the packet
|
|
704
704
|
def inspect
|
|
705
|
-
"
|
|
705
|
+
"#<#{self.class}: 0x%2.2X>" % id
|
|
706
706
|
end
|
|
707
707
|
end
|
|
708
708
|
|
|
@@ -715,17 +715,17 @@ module MQTT
|
|
|
715
715
|
|
|
716
716
|
# Parse the body (variable header and payload) of a packet
|
|
717
717
|
def parse_body(buffer)
|
|
718
|
-
super
|
|
718
|
+
super
|
|
719
719
|
@id = shift_short(buffer)
|
|
720
720
|
|
|
721
721
|
return if buffer.empty?
|
|
722
722
|
|
|
723
|
-
raise ProtocolException,
|
|
723
|
+
raise ProtocolException, "Extra bytes at end of Publish Complete packet"
|
|
724
724
|
end
|
|
725
725
|
|
|
726
726
|
# Returns a human readable string, summarising the properties of the packet
|
|
727
727
|
def inspect
|
|
728
|
-
"
|
|
728
|
+
"#<#{self.class}: 0x%2.2X>" % id
|
|
729
729
|
end
|
|
730
730
|
end
|
|
731
731
|
|
|
@@ -785,7 +785,7 @@ module MQTT
|
|
|
785
785
|
|
|
786
786
|
# Get serialisation of packet's body
|
|
787
787
|
def encode_body
|
|
788
|
-
raise
|
|
788
|
+
raise "no topics given when serialising packet" if @topics.empty?
|
|
789
789
|
|
|
790
790
|
body = encode_short(@id)
|
|
791
791
|
topics.each do |item|
|
|
@@ -797,10 +797,10 @@ module MQTT
|
|
|
797
797
|
|
|
798
798
|
# Parse the body (variable header and payload) of a packet
|
|
799
799
|
def parse_body(buffer)
|
|
800
|
-
super
|
|
800
|
+
super
|
|
801
801
|
@id = shift_short(buffer)
|
|
802
802
|
@topics = []
|
|
803
|
-
|
|
803
|
+
until buffer.empty?
|
|
804
804
|
topic_name = shift_string(buffer)
|
|
805
805
|
topic_qos = shift_byte(buffer)
|
|
806
806
|
@topics << [topic_name, topic_qos]
|
|
@@ -812,14 +812,14 @@ module MQTT
|
|
|
812
812
|
def validate_flags
|
|
813
813
|
return if @flags == [false, true, false, false]
|
|
814
814
|
|
|
815
|
-
raise ProtocolException,
|
|
815
|
+
raise ProtocolException, "Invalid flags in SUBSCRIBE packet header"
|
|
816
816
|
end
|
|
817
817
|
|
|
818
818
|
# Returns a human readable string, summarising the properties of the packet
|
|
819
819
|
def inspect
|
|
820
|
-
_str = "
|
|
820
|
+
_str = "#<#{self.class}: 0x%2.2X, %s>" % [
|
|
821
821
|
id,
|
|
822
|
-
topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(
|
|
822
|
+
topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(", ")
|
|
823
823
|
]
|
|
824
824
|
end
|
|
825
825
|
end
|
|
@@ -848,13 +848,13 @@ module MQTT
|
|
|
848
848
|
when Integer
|
|
849
849
|
@return_codes = [value]
|
|
850
850
|
else
|
|
851
|
-
raise
|
|
851
|
+
raise "return_codes should be an integer or an array of return codes"
|
|
852
852
|
end
|
|
853
853
|
end
|
|
854
854
|
|
|
855
855
|
# Get serialisation of packet's body
|
|
856
856
|
def encode_body
|
|
857
|
-
raise
|
|
857
|
+
raise "no granted QoS given when serialising packet" if @return_codes.empty?
|
|
858
858
|
|
|
859
859
|
body = encode_short(@id)
|
|
860
860
|
return_codes.each { |qos| body += encode_bytes(qos) }
|
|
@@ -863,14 +863,14 @@ module MQTT
|
|
|
863
863
|
|
|
864
864
|
# Parse the body (variable header and payload) of a packet
|
|
865
865
|
def parse_body(buffer)
|
|
866
|
-
super
|
|
866
|
+
super
|
|
867
867
|
@id = shift_short(buffer)
|
|
868
|
-
@return_codes << shift_byte(buffer)
|
|
868
|
+
@return_codes << shift_byte(buffer) until buffer.empty?
|
|
869
869
|
end
|
|
870
870
|
|
|
871
871
|
# Returns a human readable string, summarising the properties of the packet
|
|
872
872
|
def inspect
|
|
873
|
-
"
|
|
873
|
+
"#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map { |rc| "0x%2.2X" % rc }.join(",")]
|
|
874
874
|
end
|
|
875
875
|
|
|
876
876
|
# ---- Deprecated attributes and methods ---- #
|
|
@@ -909,7 +909,7 @@ module MQTT
|
|
|
909
909
|
|
|
910
910
|
# Get serialisation of packet's body
|
|
911
911
|
def encode_body
|
|
912
|
-
raise
|
|
912
|
+
raise "no topics given when serialising packet" if @topics.empty?
|
|
913
913
|
|
|
914
914
|
body = encode_short(@id)
|
|
915
915
|
topics.each { |topic| body += encode_string(topic) }
|
|
@@ -918,9 +918,9 @@ module MQTT
|
|
|
918
918
|
|
|
919
919
|
# Parse the body (variable header and payload) of a packet
|
|
920
920
|
def parse_body(buffer)
|
|
921
|
-
super
|
|
921
|
+
super
|
|
922
922
|
@id = shift_short(buffer)
|
|
923
|
-
@topics << shift_string(buffer)
|
|
923
|
+
@topics << shift_string(buffer) until buffer.empty?
|
|
924
924
|
end
|
|
925
925
|
|
|
926
926
|
# Check that fixed header flags are valid for this packet type
|
|
@@ -928,14 +928,14 @@ module MQTT
|
|
|
928
928
|
def validate_flags
|
|
929
929
|
return if @flags == [false, true, false, false]
|
|
930
930
|
|
|
931
|
-
raise ProtocolException,
|
|
931
|
+
raise ProtocolException, "Invalid flags in UNSUBSCRIBE packet header"
|
|
932
932
|
end
|
|
933
933
|
|
|
934
934
|
# Returns a human readable string, summarising the properties of the packet
|
|
935
935
|
def inspect
|
|
936
|
-
"
|
|
936
|
+
"#<#{self.class}: 0x%2.2X, %s>" % [
|
|
937
937
|
id,
|
|
938
|
-
topics.map { |t| "'#{t}'" }.join(
|
|
938
|
+
topics.map { |t| "'#{t}'" }.join(", ")
|
|
939
939
|
]
|
|
940
940
|
end
|
|
941
941
|
end
|
|
@@ -944,7 +944,7 @@ module MQTT
|
|
|
944
944
|
class Unsuback < MQTT::Packet
|
|
945
945
|
# Create a new Unsubscribe Acknowledgment packet
|
|
946
946
|
def initialize(args = {})
|
|
947
|
-
super
|
|
947
|
+
super
|
|
948
948
|
end
|
|
949
949
|
|
|
950
950
|
# Get serialisation of packet's body
|
|
@@ -954,17 +954,17 @@ module MQTT
|
|
|
954
954
|
|
|
955
955
|
# Parse the body (variable header and payload) of a packet
|
|
956
956
|
def parse_body(buffer)
|
|
957
|
-
super
|
|
957
|
+
super
|
|
958
958
|
@id = shift_short(buffer)
|
|
959
959
|
|
|
960
960
|
return if buffer.empty?
|
|
961
961
|
|
|
962
|
-
raise ProtocolException,
|
|
962
|
+
raise ProtocolException, "Extra bytes at end of Unsubscribe Acknowledgment packet"
|
|
963
963
|
end
|
|
964
964
|
|
|
965
965
|
# Returns a human readable string, summarising the properties of the packet
|
|
966
966
|
def inspect
|
|
967
|
-
"
|
|
967
|
+
"#<#{self.class}: 0x%2.2X>" % id
|
|
968
968
|
end
|
|
969
969
|
end
|
|
970
970
|
|
|
@@ -972,16 +972,16 @@ module MQTT
|
|
|
972
972
|
class Pingreq < MQTT::Packet
|
|
973
973
|
# Create a new Ping Request packet
|
|
974
974
|
def initialize(args = {})
|
|
975
|
-
super
|
|
975
|
+
super
|
|
976
976
|
end
|
|
977
977
|
|
|
978
978
|
# Check the body
|
|
979
979
|
def parse_body(buffer)
|
|
980
|
-
super
|
|
980
|
+
super
|
|
981
981
|
|
|
982
982
|
return if buffer.empty?
|
|
983
983
|
|
|
984
|
-
raise ProtocolException,
|
|
984
|
+
raise ProtocolException, "Extra bytes at end of Ping Request packet"
|
|
985
985
|
end
|
|
986
986
|
end
|
|
987
987
|
|
|
@@ -989,16 +989,16 @@ module MQTT
|
|
|
989
989
|
class Pingresp < MQTT::Packet
|
|
990
990
|
# Create a new Ping Response packet
|
|
991
991
|
def initialize(args = {})
|
|
992
|
-
super
|
|
992
|
+
super
|
|
993
993
|
end
|
|
994
994
|
|
|
995
995
|
# Check the body
|
|
996
996
|
def parse_body(buffer)
|
|
997
|
-
super
|
|
997
|
+
super
|
|
998
998
|
|
|
999
999
|
return if buffer.empty?
|
|
1000
1000
|
|
|
1001
|
-
raise ProtocolException,
|
|
1001
|
+
raise ProtocolException, "Extra bytes at end of Ping Response packet"
|
|
1002
1002
|
end
|
|
1003
1003
|
end
|
|
1004
1004
|
|
|
@@ -1006,16 +1006,16 @@ module MQTT
|
|
|
1006
1006
|
class Disconnect < MQTT::Packet
|
|
1007
1007
|
# Create a new Client Disconnect packet
|
|
1008
1008
|
def initialize(args = {})
|
|
1009
|
-
super
|
|
1009
|
+
super
|
|
1010
1010
|
end
|
|
1011
1011
|
|
|
1012
1012
|
# Check the body
|
|
1013
1013
|
def parse_body(buffer)
|
|
1014
|
-
super
|
|
1014
|
+
super
|
|
1015
1015
|
|
|
1016
1016
|
return if buffer.empty?
|
|
1017
1017
|
|
|
1018
|
-
raise ProtocolException,
|
|
1018
|
+
raise ProtocolException, "Extra bytes at end of Disconnect packet"
|
|
1019
1019
|
end
|
|
1020
1020
|
end
|
|
1021
1021
|
|