apiotics-paho-mqtt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +4 -0
  7. data/README.md +322 -0
  8. data/Rakefile +6 -0
  9. data/apiotics-paho-mqtt.gemspec +33 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/paho-mqtt.rb +165 -0
  13. data/lib/paho_mqtt/client.rb +417 -0
  14. data/lib/paho_mqtt/connection_helper.rb +169 -0
  15. data/lib/paho_mqtt/exception.rb +43 -0
  16. data/lib/paho_mqtt/handler.rb +273 -0
  17. data/lib/paho_mqtt/packet/base.rb +315 -0
  18. data/lib/paho_mqtt/packet/connack.rb +102 -0
  19. data/lib/paho_mqtt/packet/connect.rb +183 -0
  20. data/lib/paho_mqtt/packet/disconnect.rb +38 -0
  21. data/lib/paho_mqtt/packet/pingreq.rb +29 -0
  22. data/lib/paho_mqtt/packet/pingresp.rb +38 -0
  23. data/lib/paho_mqtt/packet/puback.rb +44 -0
  24. data/lib/paho_mqtt/packet/pubcomp.rb +44 -0
  25. data/lib/paho_mqtt/packet/publish.rb +148 -0
  26. data/lib/paho_mqtt/packet/pubrec.rb +44 -0
  27. data/lib/paho_mqtt/packet/pubrel.rb +62 -0
  28. data/lib/paho_mqtt/packet/suback.rb +75 -0
  29. data/lib/paho_mqtt/packet/subscribe.rb +124 -0
  30. data/lib/paho_mqtt/packet/unsuback.rb +49 -0
  31. data/lib/paho_mqtt/packet/unsubscribe.rb +84 -0
  32. data/lib/paho_mqtt/packet.rb +33 -0
  33. data/lib/paho_mqtt/publisher.rb +191 -0
  34. data/lib/paho_mqtt/sender.rb +86 -0
  35. data/lib/paho_mqtt/ssl_helper.rb +42 -0
  36. data/lib/paho_mqtt/subscriber.rb +163 -0
  37. data/lib/paho_mqtt/version.rb +3 -0
  38. data/samples/client_blocking(reading).rb +30 -0
  39. data/samples/client_blocking(writing).rb +18 -0
  40. data/samples/getting_started.rb +49 -0
  41. data/samples/test_client.rb +70 -0
  42. metadata +127 -0
@@ -0,0 +1,75 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module PahoMqtt
21
+ module Packet
22
+ class Suback < PahoMqtt::Packet::Base
23
+ # An array of return codes, ordered by the topics that were subscribed to
24
+ attr_accessor :return_codes
25
+
26
+ # Default attribute values
27
+ ATTR_DEFAULTS = {
28
+ :return_codes => [],
29
+ }
30
+
31
+ # Create a new Subscribe Acknowledgment packet
32
+ def initialize(args={})
33
+ super(ATTR_DEFAULTS.merge(args))
34
+ end
35
+
36
+ # Set the granted QoS value for each of the topics that were subscribed to
37
+ # Can either be an integer or an array or integers.
38
+ def return_codes=(value)
39
+ if value.is_a?(Array)
40
+ @return_codes = value
41
+ elsif value.is_a?(Integer)
42
+ @return_codes = [value]
43
+ else
44
+ raise PahoMqtt::PacketFormatException.new(
45
+ "return_codes should be an integer or an array of return codes")
46
+ end
47
+ end
48
+
49
+ # Get serialisation of packet's body
50
+ def encode_body
51
+ if @return_codes.empty?
52
+ raise PahoMqtt::PacketFormatException.new(
53
+ "No granted QoS given when serialising packet")
54
+ end
55
+ body = encode_short(@id)
56
+ return_codes.each { |qos| body += encode_bytes(qos) }
57
+ return body
58
+ end
59
+
60
+ # Parse the body (variable header and payload) of a packet
61
+ def parse_body(buffer)
62
+ super(buffer)
63
+ @id = shift_short(buffer)
64
+ while buffer.bytesize > 0
65
+ @return_codes << shift_byte(buffer)
66
+ end
67
+ end
68
+
69
+ # Returns a human readable string, summarising the properties of the packet
70
+ def inspect
71
+ "\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map { |rc| "0x%2.2X" % rc }.join(',')]
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,124 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module PahoMqtt
21
+ module Packet
22
+ class Subscribe < PahoMqtt::Packet::Base
23
+ # One or more topic filters to subscribe to
24
+ attr_accessor :topics
25
+
26
+ # Default attribute values
27
+ ATTR_DEFAULTS = {
28
+ :topics => [],
29
+ :flags => [false, true, false, false],
30
+ }
31
+
32
+ # Create a new Subscribe packet
33
+ def initialize(args={})
34
+ super(ATTR_DEFAULTS.merge(args))
35
+ end
36
+
37
+ # Set one or more topic filters for the Subscribe packet
38
+ # The topics parameter should be one of the following:
39
+ # * String: subscribe to one topic with QoS 0
40
+ # * Array: subscribe to multiple topics with QoS 0
41
+ # * Hash: subscribe to multiple topics where the key is the topic and the value is the QoS level
42
+ #
43
+ # For example:
44
+ # packet.topics = 'a/b'
45
+ # packet.topics = ['a/b', 'c/d']
46
+ # packet.topics = [['a/b',0], ['c/d',1]]
47
+ # packet.topics = {'a/b' => 0, 'c/d' => 1}
48
+ #
49
+ def topics=(value)
50
+ # Get input into a consistent state
51
+ if value.is_a?(Array)
52
+ input = value.flatten
53
+ else
54
+ input = [value]
55
+ end
56
+
57
+ @topics = []
58
+ while(input.length>0)
59
+ item = input.shift
60
+ if item.is_a?(Hash)
61
+ # Convert hash into an ordered array of arrays
62
+ @topics += item.sort
63
+ elsif item.is_a?(String)
64
+ # Peek at the next item in the array, and remove it if it is an integer
65
+ if input.first.is_a?(Integer)
66
+ qos = input.shift
67
+ @topics << [item, qos]
68
+ else
69
+ @topics << [item, 0]
70
+ end
71
+ else
72
+ # Meh?
73
+ raise PahoMqtt::PacketFormatException.new(
74
+ "Invalid topics input: #{value.inspect}")
75
+ end
76
+ end
77
+ @topics
78
+ end
79
+
80
+ # Get serialisation of packet's body
81
+ def encode_body
82
+ if @topics.empty?
83
+ raise PahoMqtt::PacketFormatException.new(
84
+ "No topics given when serialising packet")
85
+ end
86
+ body = encode_short(@id)
87
+ topics.each do |item|
88
+ body += encode_string(item[0])
89
+ body += encode_bytes(item[1])
90
+ end
91
+ return body
92
+ end
93
+
94
+ # Parse the body (variable header and payload) of a packet
95
+ def parse_body(buffer)
96
+ super(buffer)
97
+ @id = shift_short(buffer)
98
+ @topics = []
99
+ while(buffer.bytesize>0)
100
+ topic_name = shift_string(buffer)
101
+ topic_qos = shift_byte(buffer)
102
+ @topics << [topic_name, topic_qos]
103
+ end
104
+ end
105
+
106
+ # Check that fixed header flags are valid for this packet type
107
+ # @private
108
+ def validate_flags
109
+ if @flags != [false, true, false, false]
110
+ raise PahoMqtt::PacketFormatException.new(
111
+ "Invalid flags in SUBSCRIBE packet header")
112
+ end
113
+ end
114
+
115
+ # Returns a human readable string, summarising the properties of the packet
116
+ def inspect
117
+ _str = "\#<#{self.class}: 0x%2.2X, %s>" % [
118
+ id,
119
+ topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(', ')
120
+ ]
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module PahoMqtt
21
+ module Packet
22
+ class Unsuback < PahoMqtt::Packet::Base
23
+ # Create a new Unsubscribe Acknowledgment packet
24
+ def initialize(args={})
25
+ super(args)
26
+ end
27
+
28
+ # Get serialisation of packet's body
29
+ def encode_body
30
+ encode_short(@id)
31
+ end
32
+
33
+ # Parse the body (variable header and payload) of a packet
34
+ def parse_body(buffer)
35
+ super(buffer)
36
+ @id = shift_short(buffer)
37
+ unless buffer.empty?
38
+ raise PahoMqtt::PacketFormatException.new(
39
+ "Extra bytes at end of Unsubscribe Acknowledgment packet")
40
+ end
41
+ end
42
+
43
+ # Returns a human readable string, summarising the properties of the packet
44
+ def inspect
45
+ "\#<#{self.class}: 0x%2.2X>" % id
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module PahoMqtt
21
+ module Packet
22
+ class Unsubscribe < PahoMqtt::Packet::Base
23
+ # One or more topic paths to unsubscribe from
24
+ attr_accessor :topics
25
+
26
+ # Default attribute values
27
+ ATTR_DEFAULTS = {
28
+ :topics => [],
29
+ :flags => [false, true, false, false],
30
+ }
31
+
32
+ # Create a new Unsubscribe packet
33
+ def initialize(args={})
34
+ super(ATTR_DEFAULTS.merge(args))
35
+ end
36
+
37
+ # Set one or more topic paths to unsubscribe from
38
+ def topics=(value)
39
+ if value.is_a?(Array)
40
+ @topics = value
41
+ else
42
+ @topics = [value]
43
+ end
44
+ end
45
+
46
+ # Get serialisation of packet's body
47
+ def encode_body
48
+ if @topics.empty?
49
+ raise PahoMqtt::PacketFormatException.new(
50
+ "No topics given when serialising packet")
51
+ end
52
+ body = encode_short(@id)
53
+ topics.each { |topic| body += encode_string(topic) }
54
+ return body
55
+ end
56
+
57
+ # Parse the body (variable header and payload) of a packet
58
+ def parse_body(buffer)
59
+ super(buffer)
60
+ @id = shift_short(buffer)
61
+ while buffer.bytesize > 0
62
+ @topics << shift_string(buffer)
63
+ end
64
+ end
65
+
66
+ # Check that fixed header flags are valid for this packet type
67
+ # @private
68
+ def validate_flags
69
+ if @flags != [false, true, false, false]
70
+ raise PahoMqtt::PacketFormatException.new(
71
+ "Invalid flags in UNSUBSCRIBE packet header")
72
+ end
73
+ end
74
+
75
+ # Returns a human readable string, summarising the properties of the packet
76
+ def inspect
77
+ "\#<#{self.class}: 0x%2.2X, %s>" % [
78
+ id,
79
+ topics.map { |t| "'#{t}'" }.join(', ')
80
+ ]
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: BINARY
2
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
3
+ #
4
+ # All rights reserved. This program and the accompanying materials
5
+ # are made available under the terms of the Eclipse Public License v1.0
6
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
7
+ #
8
+ # The Eclipse Public License is available at
9
+ # https://eclipse.org/org/documents/epl-v10.php.
10
+ # and the Eclipse Distribution License is available at
11
+ # https://eclipse.org/org/documents/edl-v10.php.
12
+ #
13
+ # Contributors:
14
+ # Pierre Goudet - initial committer
15
+
16
+ require "paho_mqtt/packet/base"
17
+ require "paho_mqtt/packet/connect"
18
+ require "paho_mqtt/packet/connack"
19
+ require "paho_mqtt/packet/publish"
20
+ require "paho_mqtt/packet/puback"
21
+ require "paho_mqtt/packet/pubrec"
22
+ require "paho_mqtt/packet/pubrel"
23
+ require "paho_mqtt/packet/pubcomp"
24
+ require "paho_mqtt/packet/subscribe"
25
+ require "paho_mqtt/packet/suback"
26
+ require "paho_mqtt/packet/unsubscribe"
27
+ require "paho_mqtt/packet/unsuback"
28
+ require "paho_mqtt/packet/pingreq"
29
+ require "paho_mqtt/packet/pingresp"
30
+ require "paho_mqtt/packet/disconnect"
31
+
32
+ module PahoMqtt
33
+ end
@@ -0,0 +1,191 @@
1
+ # Copyright (c) 2016-2017 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
+ module PahoMqtt
16
+ class Publisher
17
+
18
+ def initialize(sender)
19
+ @waiting_puback = []
20
+ @waiting_pubrec = []
21
+ @waiting_pubrel = []
22
+ @waiting_pubcomp = []
23
+ @puback_mutex = Mutex.new
24
+ @pubrec_mutex = Mutex.new
25
+ @pubrel_mutex = Mutex.new
26
+ @pubcomp_mutex = Mutex.new
27
+ @sender = sender
28
+ end
29
+
30
+ def sender=(sender)
31
+ @sender = sender
32
+ end
33
+
34
+ def send_publish(topic, payload, retain, qos, new_id)
35
+ packet = PahoMqtt::Packet::Publish.new(
36
+ :id => new_id,
37
+ :topic => topic,
38
+ :payload => payload,
39
+ :retain => retain,
40
+ :qos => qos
41
+ )
42
+ case qos
43
+ when 1
44
+ @puback_mutex.synchronize do
45
+ if @waiting_puback.length >= MAX_PUBACK
46
+ PahoMqtt.logger.error('PUBACK queue is full, could not send with qos=1') if PahoMqtt.logger?
47
+ return MQTT_ERR_FAIL
48
+ end
49
+ @waiting_puback.push(:id => new_id, :packet => packet, :timestamp => Time.now)
50
+ end
51
+ when 2
52
+ @pubrec_mutex.synchronize do
53
+ if @waiting_pubrec.length >= MAX_PUBREC
54
+ PahoMqtt.logger.error('PUBREC queue is full, could not send with qos=2') if PahoMqtt.logger?
55
+ return MQTT_ERR_FAIL
56
+ end
57
+ @waiting_pubrec.push(:id => new_id, :packet => packet, :timestamp => Time.now)
58
+ end
59
+ end
60
+ @sender.append_to_writing(packet)
61
+ MQTT_ERR_SUCCESS
62
+ end
63
+
64
+ def do_publish(qos, packet_id)
65
+ case qos
66
+ when 0
67
+ when 1
68
+ send_puback(packet_id)
69
+ when 2
70
+ send_pubrec(packet_id)
71
+ else
72
+ PahoMqtt.logger.error("The packet QoS value is invalid in publish.") if PahoMqtt.logger?
73
+ raise PacketException.new('Invalid publish QoS value')
74
+ end
75
+ MQTT_ERR_SUCCESS
76
+ end
77
+
78
+ def send_puback(packet_id)
79
+ packet = PahoMqtt::Packet::Puback.new(
80
+ :id => packet_id
81
+ )
82
+ @sender.append_to_writing(packet)
83
+ MQTT_ERR_SUCCESS
84
+ end
85
+
86
+ def do_puback(packet_id)
87
+ @puback_mutex.synchronize do
88
+ @waiting_puback.delete_if { |pck| pck[:id] == packet_id }
89
+ end
90
+ MQTT_ERR_SUCCESS
91
+ end
92
+
93
+ def send_pubrec(packet_id)
94
+ packet = PahoMqtt::Packet::Pubrec.new(
95
+ :id => packet_id
96
+ )
97
+ @pubrel_mutex.synchronize do
98
+ if @waiting_pubrel.length >= MAX_PUBREL
99
+ PahoMqtt.logger.error('PUBREL queue is full, could not acknowledge qos=2') if PahoMqtt.logger?
100
+ return MQTT_ERR_FAIL
101
+ end
102
+ @waiting_pubrel.push(:id => packet_id , :packet => packet, :timestamp => Time.now)
103
+ end
104
+ @sender.append_to_writing(packet)
105
+ MQTT_ERR_SUCCESS
106
+ end
107
+
108
+ def do_pubrec(packet_id)
109
+ @pubrec_mutex.synchronize do
110
+ @waiting_pubrec.delete_if { |pck| pck[:id] == packet_id }
111
+ end
112
+ send_pubrel(packet_id)
113
+ MQTT_ERR_SUCCESS
114
+ end
115
+
116
+ def send_pubrel(packet_id)
117
+ packet = PahoMqtt::Packet::Pubrel.new(
118
+ :id => packet_id
119
+ )
120
+ @pubcomp_mutex.synchronize do
121
+ if @waiting_pubcomp.length >= MAX_PUBCOMP
122
+ PahoMqtt.logger.error('PUBCOMP queue is full, could not acknowledge qos=2') if PahoMqtt.logger?
123
+ return MQTT_ERR_FAIL
124
+ end
125
+ @waiting_pubcomp.push(:id => packet_id, :packet => packet, :timestamp => Time.now)
126
+ end
127
+ @sender.append_to_writing(packet)
128
+ MQTT_ERR_SUCCESS
129
+ end
130
+
131
+ def do_pubrel(packet_id)
132
+ @pubrel_mutex.synchronize do
133
+ @waiting_pubrel.delete_if { |pck| pck[:id] == packet_id }
134
+ end
135
+ send_pubcomp(packet_id)
136
+ MQTT_ERR_SUCCESS
137
+ end
138
+
139
+ def send_pubcomp(packet_id)
140
+ packet = PahoMqtt::Packet::Pubcomp.new(
141
+ :id => packet_id
142
+ )
143
+ @sender.append_to_writing(packet)
144
+ MQTT_ERR_SUCCESS
145
+ end
146
+
147
+ def do_pubcomp(packet_id)
148
+ @pubcomp_mutex.synchronize do
149
+ @waiting_pubcomp.delete_if { |pck| pck[:id] == packet_id }
150
+ end
151
+ MQTT_ERR_SUCCESS
152
+ end
153
+
154
+ def config_all_message_queue
155
+ config_message_queue(@waiting_puback, @puback_mutex)
156
+ config_message_queue(@waiting_pubrec, @pubrec_mutex)
157
+ config_message_queue(@waiting_pubrel, @pubrel_mutex)
158
+ config_message_queue(@waiting_pubcomp, @pubcomp_mutex)
159
+ end
160
+
161
+ def config_message_queue(queue, mutex)
162
+ mutex.synchronize do
163
+ queue.each do |pck|
164
+ pck[:timestamp] = Time.now
165
+ end
166
+ end
167
+ end
168
+
169
+ def check_waiting_publisher
170
+ @sender.check_ack_alive(@waiting_puback, @puback_mutex)
171
+ @sender.check_ack_alive(@waiting_pubrec, @pubrec_mutex)
172
+ @sender.check_ack_alive(@waiting_pubrel, @pubrel_mutex)
173
+ @sender.check_ack_alive(@waiting_pubcomp, @pubcomp_mutex)
174
+ end
175
+
176
+ def flush_publisher
177
+ @puback_mutex.synchronize do
178
+ @waiting_puback = []
179
+ end
180
+ @pubrec_mutex.synchronize do
181
+ @waiting_pubrec = []
182
+ end
183
+ @pubrel_mutex.synchronize do
184
+ @waiting_pubrel = []
185
+ end
186
+ @pubcomp_mutex.synchronize do
187
+ @waiting_pubcomp = []
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,86 @@
1
+ # Copyright (c) 2016-2017 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
+ module PahoMqtt
16
+ class Sender
17
+
18
+ attr_accessor :last_ping_req
19
+
20
+ def initialize(ack_timeout)
21
+ @socket = nil
22
+ @writing_queue = []
23
+ @writing_mutex = Mutex.new
24
+ @last_ping_req = -1
25
+ @ack_timeout = ack_timeout
26
+ end
27
+
28
+ def socket=(socket)
29
+ @socket = socket
30
+ end
31
+
32
+ def send_packet(packet)
33
+ begin
34
+ @socket.write(packet.to_s) unless @socket.nil? || @socket.closed?
35
+ @last_ping_req = Time.now
36
+ MQTT_ERR_SUCCESS
37
+ rescue StandardError
38
+ raise WritingException
39
+ end
40
+ end
41
+
42
+ def append_to_writing(packet)
43
+ @writing_mutex.synchronize do
44
+ @writing_queue.push(packet) unless @writing_queue.length >= MAX_WRITING
45
+ end
46
+ MQTT_ERR_SUCCESS
47
+ end
48
+
49
+ def writing_loop(max_packet)
50
+ @writing_mutex.synchronize do
51
+ cnt = 0
52
+ while !@writing_queue.empty? && cnt < max_packet do
53
+ packet = @writing_queue.shift
54
+ send_packet(packet)
55
+ cnt += 1
56
+ end
57
+ end
58
+ MQTT_ERR_SUCCESS
59
+ end
60
+
61
+ def flush_waiting_packet(sending=true)
62
+ if sending
63
+ @writing_mutex.synchronize do
64
+ @writing_queue.each do |m|
65
+ send_packet(m)
66
+ end
67
+ end
68
+ else
69
+ @writing_queue = []
70
+ end
71
+ end
72
+
73
+ def check_ack_alive(queue, mutex)
74
+ mutex.synchronize do
75
+ now = Time.now
76
+ queue.each do |pck|
77
+ if now >= pck[:timestamp] + @ack_timeout
78
+ pck[:packet].dup ||= true unless pck[:packet].class == PahoMqtt::Packet::Subscribe || pck[:packet].class == PahoMqtt::Packet::Unsubscribe
79
+ append_to_writing(pck[:packet])
80
+ pck[:timestamp] = now
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright (c) 2016-2017 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
+ require 'openssl'
16
+
17
+ module PahoMqtt
18
+ module SSLHelper
19
+ extend self
20
+
21
+ def config_ssl_context(cert_path, key_path, ca_path=nil)
22
+ ssl_context = OpenSSL::SSL::SSLContext.new
23
+ set_cert(cert_path, ssl_context)
24
+ set_key(key_path, ssl_context)
25
+ set_root_ca(ca_path, ssl_context)
26
+ #ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER unless ca_path.nil?
27
+ ssl_context
28
+ end
29
+
30
+ def set_cert(cert_path, ssl_context)
31
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
32
+ end
33
+
34
+ def set_key(key_path, ssl_context)
35
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.read(key_path))
36
+ end
37
+
38
+ def set_root_ca(ca_path, ssl_context)
39
+ ssl_context.ca_file = ca_path
40
+ end
41
+ end
42
+ end