apiotics-paho-mqtt 1.0.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.
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