paho-mqtt 1.0.7 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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