paho-mqtt 1.0.7 → 1.0.9

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.
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2016-2018 Pierre Goudet <p-goudet@ruby-dev.jp>
2
+ #
3
+ # All rights reserved. This program and the accompanying materials
4
+ # are made available under the terms of the Eclipse Public License v1.0
5
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
6
+ #
7
+ # The Eclipse Public License is available at
8
+ # https://eclipse.org/org/documents/epl-v10.php.
9
+ # and the Eclipse Distribution License is available at
10
+ # https://eclipse.org/org/documents/edl-v10.php.
11
+ #
12
+ # Contributors:
13
+ # Pierre Goudet - initial committer
14
+
15
+
16
+ module PahoMqtt
17
+ class Exception < ::StandardError
18
+ def initialize(msg="")
19
+ super
20
+ end
21
+ end
22
+
23
+ class ProtocolViolation < Exception
24
+ end
25
+
26
+ class WritingException < Exception
27
+ end
28
+
29
+ class ReadingException < Exception
30
+ end
31
+
32
+ class PacketException < Exception
33
+ end
34
+
35
+ class PacketFormatException < Exception
36
+ end
37
+
38
+ class ProtocolVersionException < Exception
39
+ end
40
+
41
+ class LowVersionException < Exception
42
+ end
43
+ end
@@ -21,9 +21,9 @@ module PahoMqtt
21
21
 
22
22
  def initialize
23
23
  @registered_callback = []
24
- @last_ping_resp = -1
25
- @publisher = nil
26
- @subscriber = nil
24
+ @last_ping_resp = -1
25
+ @publisher = nil
26
+ @subscriber = nil
27
27
  end
28
28
 
29
29
  def config_pubsub(publisher, subscriber)
@@ -52,7 +52,7 @@ module PahoMqtt
52
52
  end
53
53
 
54
54
  def handle_packet(packet)
55
- PahoMqtt.logger.info("New packet #{packet.class} recieved.") if PahoMqtt.logger?
55
+ PahoMqtt.logger.info("New packet #{packet.class} received.") if PahoMqtt.logger?
56
56
  type = packet_type(packet)
57
57
  self.send("handle_#{type}", packet)
58
58
  end
@@ -76,16 +76,17 @@ module PahoMqtt
76
76
  PahoMqtt.logger.error("The topics where the callback is trying to be unregistered have been found nil.") if PahoMqtt.logger?
77
77
  raise ArgumentError
78
78
  end
79
- @registered_callback.delete_if {|pair| pair.first == topic}
79
+ @registered_callback.delete_if { |pair| pair.first == topic }
80
80
  MQTT_ERR_SUCCESS
81
81
  end
82
82
 
83
83
  def handle_connack(packet)
84
84
  if packet.return_code == 0x00
85
- PahoMqtt.logger.debug("Connack receive and connection accepted.") if PahoMqtt.logger?
85
+ PahoMqtt.logger.debug(packet.return_msg) if PahoMqtt.logger?
86
86
  handle_connack_accepted(packet.session_present)
87
87
  else
88
- handle_connack_error(packet.return_code)
88
+ PahoMqtt.logger.warm(packet.return_msg) if PahoMqtt.logger?
89
+ MQTT_CS_DISCONNECTED
89
90
  end
90
91
  @on_connack.call(packet) unless @on_connack.nil?
91
92
  MQTT_CS_CONNECTED
@@ -99,7 +100,7 @@ module PahoMqtt
99
100
 
100
101
  def new_session?(session_flag)
101
102
  if !@clean_session && !session_flag
102
- PahoMqtt.logger.debug("New session created for the client") if PahoMqtt.logger?
103
+ PahoMqtt.logger.debug("New session created for the client.") if PahoMqtt.logger?
103
104
  end
104
105
  end
105
106
 
@@ -121,9 +122,9 @@ module PahoMqtt
121
122
 
122
123
  def handle_suback(packet)
123
124
  max_qos = packet.return_codes
124
- id = packet.id
125
- topics = []
126
- topics = @subscriber.add_subscription(max_qos, id, topics)
125
+ id = packet.id
126
+ topics = []
127
+ topics = @subscriber.add_subscription(max_qos, id, topics)
127
128
  unless topics.empty?
128
129
  @on_suback.call(topics) unless @on_suback.nil?
129
130
  end
@@ -139,12 +140,12 @@ module PahoMqtt
139
140
  end
140
141
 
141
142
  def handle_publish(packet)
142
- id = packet.id
143
- qos = packet.qos
144
- if @publisher.do_publish(qos, id) == MQTT_ERR_SUCCESS
145
- @on_message.call(packet) unless @on_message.nil?
146
- check_callback(packet)
147
- end
143
+ id = packet.id
144
+ qos = packet.qos
145
+ if @publisher.do_publish(qos, id) == MQTT_ERR_SUCCESS
146
+ @on_message.call(packet) unless @on_message.nil?
147
+ check_callback(packet)
148
+ end
148
149
  end
149
150
 
150
151
  def handle_puback(packet)
@@ -175,18 +176,6 @@ module PahoMqtt
175
176
  end
176
177
  end
177
178
 
178
- def handle_connack_error(return_code)
179
- if return_code == 0x01
180
- raise LowVersionException
181
- elsif CONNACK_ERROR_MESSAGE.has_key(return_code.to_sym)
182
- PahoMqtt.logger.warm(CONNACK_ERRO_MESSAGE[return_code])
183
- MQTT_CS_DISCONNECTED
184
- else
185
- PahoMqtt.logger("Unknown return code for CONNACK packet: #{return_code}")
186
- raise PacketException
187
- end
188
- end
189
-
190
179
  def on_connack(&block)
191
180
  @on_connack = block if block_given?
192
181
  @on_connack
@@ -264,9 +253,8 @@ module PahoMqtt
264
253
  if PahoMqtt::PACKET_TYPES[3..13].include?(type)
265
254
  type.to_s.split('::').last.downcase
266
255
  else
267
- puts "Packet: #{packet.inspect}"
268
- PahoMqtt.logger.error("Received an unexpeceted packet: #{packet}") if PahoMqtt.logger?
269
- raise PacketException
256
+ PahoMqtt.logger.error("Received an unexpeceted packet: #{packet}.") if PahoMqtt.logger?
257
+ raise PacketException.new('Invalid packet type id')
270
258
  end
271
259
  end
272
260
 
@@ -277,7 +265,7 @@ module PahoMqtt
277
265
  end
278
266
  unless callbacks.empty?
279
267
  callbacks.each do |callback|
280
- callback.call(packet)
268
+ callback.call(packet)
281
269
  end
282
270
  end
283
271
  end
@@ -36,8 +36,8 @@ module PahoMqtt
36
36
 
37
37
  # Default attribute values
38
38
  ATTR_DEFAULTS = {
39
- :version => '3.1.0',
40
- :id => 0,
39
+ :version => '3.1.0',
40
+ :id => 0,
41
41
  :body_length => nil
42
42
  }
43
43
 
@@ -47,6 +47,7 @@ module PahoMqtt
47
47
  packet = create_from_header(
48
48
  read_byte(socket)
49
49
  )
50
+
50
51
  unless packet.nil?
51
52
  packet.validate_flags
52
53
 
@@ -59,22 +60,22 @@ module PahoMqtt
59
60
  body_length += ((digit & 0x7F) * multiplier)
60
61
  multiplier *= 0x80
61
62
  pos += 1
62
- end while ((digit & 0x80) != 0x00) and pos <= 4
63
+ end while ((digit & 0x80) != 0x00) && pos <= 4
63
64
 
64
65
  # Store the expected body length in the packet
65
66
  packet.instance_variable_set('@body_length', body_length)
66
67
 
67
68
  # Read in the packet body
68
- packet.parse_body( socket.read(body_length) )
69
+ packet.parse_body(socket.read(body_length))
69
70
  end
70
- return packet
71
+ packet
71
72
  end
72
73
 
73
74
  # Parse buffer into new packet object
74
75
  def self.parse(buffer)
75
76
  packet = parse_header(buffer)
76
77
  packet.parse_body(buffer)
77
- return packet
78
+ packet
78
79
  end
79
80
 
80
81
  # Parse the header and create a new packet object of the correct type
@@ -82,7 +83,8 @@ module PahoMqtt
82
83
  def self.parse_header(buffer)
83
84
  # Check that the packet is a long as the minimum packet size
84
85
  if buffer.bytesize < 2
85
- raise "Invalid packet: less than 2 bytes long"
86
+ raise PahoMqtt::PacketFormatException.new(
87
+ "Invalid packet: less than 2 bytes long")
86
88
  end
87
89
 
88
90
  # Create a new packet object
@@ -96,13 +98,14 @@ module PahoMqtt
96
98
  pos = 1
97
99
  begin
98
100
  if buffer.bytesize <= pos
99
- raise "The packet length header is incomplete"
101
+ raise PahoMqtt::PacketFormatException.new(
102
+ "The packet length header is incomplete")
100
103
  end
101
104
  digit = bytes[pos]
102
105
  body_length += ((digit & 0x7F) * multiplier)
103
106
  multiplier *= 0x80
104
107
  pos += 1
105
- end while ((digit & 0x80) != 0x00) and pos <= 4
108
+ end while ((digit & 0x80) != 0x00) && pos <= 4
106
109
 
107
110
  # Store the expected body length in the packet
108
111
  packet.instance_variable_set('@body_length', body_length)
@@ -110,7 +113,7 @@ module PahoMqtt
110
113
  # Delete the fixed header from the raw packet passed in
111
114
  buffer.slice!(0...pos)
112
115
 
113
- return packet
116
+ packet
114
117
  end
115
118
 
116
119
  # Create a new packet object from the first byte of a MQTT packet
@@ -120,7 +123,8 @@ module PahoMqtt
120
123
  type_id = ((byte & 0xF0) >> 4)
121
124
  packet_class = PahoMqtt::PACKET_TYPES[type_id]
122
125
  if packet_class.nil?
123
- raise "Invalid packet type identifier: #{type_id}"
126
+ raise PahoMqtt::PacketFormatException.new(
127
+ "Invalid packet type identifier: #{type_id}")
124
128
  end
125
129
 
126
130
  # Convert the last 4 bits of byte into array of true/false
@@ -141,7 +145,7 @@ module PahoMqtt
141
145
  # Set packet attributes from a hash of attribute names and values
142
146
  def update_attributes(attr={})
143
147
  attr.each_pair do |k,v|
144
- if v.is_a?(Array) or v.is_a?(Hash)
148
+ if v.is_a?(Array) || v.is_a?(Hash)
145
149
  send("#{k}=", v.dup)
146
150
  else
147
151
  send("#{k}=", v)
@@ -153,9 +157,10 @@ module PahoMqtt
153
157
  def type_id
154
158
  index = PahoMqtt::PACKET_TYPES.index(self.class)
155
159
  if index.nil?
156
- raise "Invalid packet type: #{self.class}"
160
+ raise PahoMqtt::PacketFormatException.new(
161
+ "Invalid packet type: #{self.class}")
157
162
  end
158
- return index
163
+ index
159
164
  end
160
165
 
161
166
  # Get the name of the packet type as a string in capitals
@@ -179,7 +184,8 @@ module PahoMqtt
179
184
  # Parse the body (variable header and payload) of a packet
180
185
  def parse_body(buffer)
181
186
  if buffer.bytesize != body_length
182
- raise "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
187
+ raise PahoMqtt::PacketFormatException.new(
188
+ "Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})")
183
189
  end
184
190
  end
185
191
 
@@ -205,7 +211,8 @@ module PahoMqtt
205
211
  # Check that that packet isn't too big
206
212
  body_length = body.bytesize
207
213
  if body_length > 268435455
208
- raise "Error serialising packet: body is more than 256MB"
214
+ raise PahoMqtt::PacketFormatException.new(
215
+ "Error serialising packet: body is more than 256MB")
209
216
  end
210
217
 
211
218
  # Build up the body length field bytes
@@ -225,7 +232,8 @@ module PahoMqtt
225
232
  # @private
226
233
  def validate_flags
227
234
  if flags != [false, false, false, false]
228
- raise "Invalid flags in #{type_name} packet header"
235
+ raise PahoMqtt::PacketFormatException.new(
236
+ "Invalid flags in #{type_name} packet header")
229
237
  end
230
238
  end
231
239
 
@@ -243,7 +251,7 @@ module PahoMqtt
243
251
 
244
252
  # Encode an array of bits and return them
245
253
  def encode_bits(bits)
246
- [bits.map{|b| b ? '1' : '0'}.join].pack('b*')
254
+ [bits.map { |b| b ? '1' : '0' }.join].pack('b*')
247
255
  end
248
256
 
249
257
  # Encode a 16-bit unsigned integer and return it
@@ -274,7 +282,7 @@ module PahoMqtt
274
282
 
275
283
  # Remove 8 bits from the front of buffer
276
284
  def shift_bits(buffer)
277
- buffer.slice!(0...1).unpack('b8').first.split('').map {|b| b == '1'}
285
+ buffer.slice!(0...1).unpack('b8').first.split('').map { |b| b == '1' }
278
286
  end
279
287
 
280
288
  # Remove n bytes from the front of buffer
@@ -27,7 +27,7 @@ module PahoMqtt
27
27
  attr_accessor :return_code
28
28
 
29
29
  # Default attribute values
30
- ATTR_DEFAULTS = {:return_code => 0x00}
30
+ ATTR_DEFAULTS = { :return_code => 0x00 }
31
31
 
32
32
  # Create a new Client Connect packet
33
33
  def initialize(args={})
@@ -54,9 +54,9 @@ module PahoMqtt
54
54
  def return_msg
55
55
  case return_code
56
56
  when 0x00
57
- "Connection Accepted"
57
+ "Connection accepted"
58
58
  when 0x01
59
- "Connection refused: unacceptable protocol version"
59
+ raise LowVersionException
60
60
  when 0x02
61
61
  "Connection refused: client identifier rejected"
62
62
  when 0x03
@@ -75,19 +75,21 @@ module PahoMqtt
75
75
  body = ''
76
76
  body += encode_bits(@connack_flags)
77
77
  body += encode_bytes(@return_code.to_i)
78
- return body
78
+ body
79
79
  end
80
80
 
81
81
  # Parse the body (variable header and payload) of a Connect Acknowledgment packet
82
82
  def parse_body(buffer)
83
83
  super(buffer)
84
84
  @connack_flags = shift_bits(buffer)
85
- unless @connack_flags[1,7] == [false, false, false, false, false, false, false]
86
- raise "Invalid flags in Connack variable header"
85
+ unless @connack_flags[1, 7] == [false, false, false, false, false, false, false]
86
+ raise PacketFormatException.new(
87
+ "Invalid flags in Connack variable header")
87
88
  end
88
89
  @return_code = shift_byte(buffer)
89
90
  unless buffer.empty?
90
- raise "Extra bytes at end of Connect Acknowledgment packet"
91
+ raise PacketFormatException.new(
92
+ "Extra bytes at end of Connect Acknowledgment packet")
91
93
  end
92
94
  end
93
95
 
@@ -55,29 +55,30 @@ module PahoMqtt
55
55
 
56
56
  # Default attribute values
57
57
  ATTR_DEFAULTS = {
58
- :client_id => nil,
58
+ :client_id => nil,
59
59
  :clean_session => true,
60
- :keep_alive => 15,
61
- :will_topic => nil,
62
- :will_qos => 0,
63
- :will_retain => false,
64
- :will_payload => '',
65
- :username => nil,
66
- :password => nil,
60
+ :keep_alive => 15,
61
+ :will_topic => nil,
62
+ :will_qos => 0,
63
+ :will_retain => false,
64
+ :will_payload => '',
65
+ :username => nil,
66
+ :password => nil,
67
67
  }
68
68
 
69
69
  # Create a new Client Connect packet
70
70
  def initialize(args={})
71
71
  super(ATTR_DEFAULTS.merge(args))
72
72
 
73
- if version == '3.1.0' or version == '3.1'
73
+ if version == '3.1.0' || version == '3.1'
74
74
  self.protocol_name ||= 'MQIsdp'
75
75
  self.protocol_level ||= 0x03
76
76
  elsif version == '3.1.1'
77
77
  self.protocol_name ||= 'MQTT'
78
78
  self.protocol_level ||= 0x04
79
79
  else
80
- raise ArgumentError.new("Unsupported protocol version: #{version}")
80
+ raise PahoMqtt::PacketFormatException.new(
81
+ "Unsupported protocol version: #{version}")
81
82
  end
82
83
  end
83
84
 
@@ -88,7 +89,8 @@ module PahoMqtt
88
89
  body += encode_string(@protocol_name)
89
90
  body += encode_bytes(@protocol_level.to_i)
90
91
  if @keep_alive < 0
91
- raise "Invalid keep-alive value: cannot be less than 0"
92
+ raise PahoMqtt::PacketFormatException.new(
93
+ "Invalid keep-alive value: cannot be less than 0")
92
94
  end
93
95
 
94
96
  body += encode_flags(@connect_flags)
@@ -106,10 +108,12 @@ module PahoMqtt
106
108
 
107
109
  def check_version
108
110
  if @version == '3.1.0'
109
- if @client_id.nil? or @client_id.bytesize < 1
110
- raise "Client identifier too short while serialising packet"
111
+ if @client_id.nil? || @client_id.bytesize < 1
112
+ raise PahoMqtt::PacketFormatException.new(
113
+ "Client identifier too short while serialising packet")
111
114
  elsif @client_id.bytesize > 23
112
- raise "Client identifier too long when serialising packet"
115
+ raise PahoMqtt::PacketFormatException.new(
116
+ "Client identifier too long when serialising packet")
113
117
  end
114
118
  end
115
119
  end
@@ -131,12 +135,13 @@ module PahoMqtt
131
135
  super(buffer)
132
136
  @protocol_name = shift_string(buffer)
133
137
  @protocol_level = shift_byte(buffer).to_i
134
- if @protocol_name == 'MQIsdp' and @protocol_level == 3
138
+ if @protocol_name == 'MQIsdp' && @protocol_level == 3
135
139
  @version = '3.1.0'
136
- elsif @protocol_name == 'MQTT' and @protocol_level == 4
140
+ elsif @protocol_name == 'MQTT' && @protocol_level == 4
137
141
  @version = '3.1.1'
138
142
  else
139
- raise "Unsupported protocol: #{@protocol_name}/#{@protocol_level}"
143
+ raise PahoMqtt::PacketFormatException.new(
144
+ "Unsupported protocol: #{@protocol_name}/#{@protocol_level}")
140
145
  end
141
146
 
142
147
  @connect_flags = shift_byte(buffer)
@@ -155,10 +160,10 @@ module PahoMqtt
155
160
  # The MQTT v3.1 specification says that the payload is a UTF-8 string
156
161
  @will_payload = shift_string(buffer)
157
162
  end
158
- if ((@connect_flags & 0x80) >> 7) == 0x01 and buffer.bytesize > 0
163
+ if ((@connect_flags & 0x80) >> 7) == 0x01 && buffer.bytesize > 0
159
164
  @username = shift_string(buffer)
160
165
  end
161
- if ((@connect_flags & 0x40) >> 6) == 0x01 and buffer.bytesize > 0
166
+ if ((@connect_flags & 0x40) >> 6) == 0x01 && buffer.bytesize > 0
162
167
  @password = shift_string(buffer)
163
168
  end
164
169
  end