mqtt 0.4.0 → 0.6.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 +5 -13
- data/NEWS.md +15 -0
- data/README.md +1 -1
- data/lib/mqtt/client.rb +496 -469
- data/lib/mqtt/openssl_fix.rb +29 -0
- data/lib/mqtt/packet.rb +182 -235
- data/lib/mqtt/patches/string_encoding.rb +5 -7
- data/lib/mqtt/proxy.rb +85 -89
- data/lib/mqtt/sn/packet.rb +469 -512
- data/lib/mqtt/version.rb +1 -1
- data/lib/mqtt.rb +1 -3
- data/spec/mqtt_client_spec.rb +148 -16
- data/spec/mqtt_packet_spec.rb +8 -0
- data/spec/zz_client_integration_spec.rb +13 -2
- metadata +40 -27
@@ -11,12 +11,14 @@ class String
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def encode(encoding)
|
14
|
-
new =
|
14
|
+
new = dup
|
15
15
|
new.force_encoding(encoding)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
class Encoding
|
20
|
+
attr_reader :name
|
21
|
+
|
20
22
|
def initialize(name)
|
21
23
|
@name = name
|
22
24
|
end
|
@@ -24,11 +26,7 @@ class Encoding
|
|
24
26
|
def to_s
|
25
27
|
@name
|
26
28
|
end
|
27
|
-
|
28
|
-
def name
|
29
|
-
@name
|
30
|
-
end
|
31
29
|
|
32
|
-
UTF_8 = Encoding.new(
|
33
|
-
ASCII_8BIT = Encoding.new(
|
30
|
+
UTF_8 = Encoding.new('UTF-8')
|
31
|
+
ASCII_8BIT = Encoding.new('ASCII-8BIT')
|
34
32
|
end
|
data/lib/mqtt/proxy.rb
CHANGED
@@ -1,119 +1,115 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# Port to bind listening socket to
|
7
|
-
attr_reader :local_port
|
8
|
-
|
9
|
-
# Address of upstream server to send packets upstream to
|
10
|
-
attr_reader :server_host
|
11
|
-
|
12
|
-
# Port of upstream server to send packets upstream to.
|
13
|
-
attr_reader :server_port
|
14
|
-
|
15
|
-
# Time in seconds before disconnecting an idle connection
|
16
|
-
attr_reader :select_timeout
|
17
|
-
|
18
|
-
# Ruby Logger object to send informational messages to
|
19
|
-
attr_reader :logger
|
20
|
-
|
21
|
-
# Create a new MQTT Proxy instance.
|
22
|
-
#
|
23
|
-
# Possible argument keys:
|
24
|
-
#
|
25
|
-
# :local_host Address to bind listening socket to.
|
26
|
-
# :local_port Port to bind listening socket to.
|
27
|
-
# :server_host Address of upstream server to send packets upstream to.
|
28
|
-
# :server_port Port of upstream server to send packets upstream to.
|
29
|
-
# :select_timeout Time in seconds before disconnecting a connection.
|
30
|
-
# :logger Ruby Logger object to send informational messages to.
|
31
|
-
#
|
32
|
-
# NOTE: be careful not to connect to yourself!
|
33
|
-
def initialize(args={})
|
34
|
-
@local_host = args[:local_host] || '0.0.0.0'
|
35
|
-
@local_port = args[:local_port] || MQTT::DEFAULT_PORT
|
36
|
-
@server_host = args[:server_host]
|
37
|
-
@server_port = args[:server_port] || 18830
|
38
|
-
@select_timeout = args[:select_timeout] || 60
|
39
|
-
|
40
|
-
# Setup a logger
|
41
|
-
@logger = args[:logger]
|
42
|
-
if @logger.nil?
|
43
|
-
@logger = Logger.new(STDOUT)
|
44
|
-
@logger.level = Logger::INFO
|
45
|
-
end
|
1
|
+
module MQTT
|
2
|
+
# Class for implementing a proxy to filter/mangle MQTT packets.
|
3
|
+
class Proxy
|
4
|
+
# Address to bind listening socket to
|
5
|
+
attr_reader :local_host
|
46
6
|
|
47
|
-
#
|
48
|
-
|
49
|
-
@server_filter = nil
|
7
|
+
# Port to bind listening socket to
|
8
|
+
attr_reader :local_port
|
50
9
|
|
51
|
-
#
|
52
|
-
|
53
|
-
@logger.info "MQTT::Proxy listening on #{@local_host}:#{@local_port}"
|
54
|
-
end
|
10
|
+
# Address of upstream server to send packets upstream to
|
11
|
+
attr_reader :server_host
|
55
12
|
|
56
|
-
|
57
|
-
|
58
|
-
@client_filter = proc
|
59
|
-
end
|
13
|
+
# Port of upstream server to send packets upstream to.
|
14
|
+
attr_reader :server_port
|
60
15
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
16
|
+
# Time in seconds before disconnecting an idle connection
|
17
|
+
attr_reader :select_timeout
|
18
|
+
|
19
|
+
# Ruby Logger object to send informational messages to
|
20
|
+
attr_reader :logger
|
21
|
+
|
22
|
+
# A filter Proc for packets coming from the client (to the server).
|
23
|
+
attr_writer :client_filter
|
24
|
+
|
25
|
+
# A filter Proc for packets coming from the server (to the client).
|
26
|
+
attr_writer :server_filter
|
27
|
+
|
28
|
+
# Create a new MQTT Proxy instance.
|
29
|
+
#
|
30
|
+
# Possible argument keys:
|
31
|
+
#
|
32
|
+
# :local_host Address to bind listening socket to.
|
33
|
+
# :local_port Port to bind listening socket to.
|
34
|
+
# :server_host Address of upstream server to send packets upstream to.
|
35
|
+
# :server_port Port of upstream server to send packets upstream to.
|
36
|
+
# :select_timeout Time in seconds before disconnecting a connection.
|
37
|
+
# :logger Ruby Logger object to send informational messages to.
|
38
|
+
#
|
39
|
+
# NOTE: be careful not to connect to yourself!
|
40
|
+
def initialize(args = {})
|
41
|
+
@local_host = args[:local_host] || '0.0.0.0'
|
42
|
+
@local_port = args[:local_port] || MQTT::DEFAULT_PORT
|
43
|
+
@server_host = args[:server_host]
|
44
|
+
@server_port = args[:server_port] || 18_830
|
45
|
+
@select_timeout = args[:select_timeout] || 60
|
46
|
+
|
47
|
+
# Setup a logger
|
48
|
+
@logger = args[:logger]
|
49
|
+
if @logger.nil?
|
50
|
+
@logger = Logger.new(STDOUT)
|
51
|
+
@logger.level = Logger::INFO
|
52
|
+
end
|
53
|
+
|
54
|
+
# Default is not to have any filters
|
55
|
+
@client_filter = nil
|
56
|
+
@server_filter = nil
|
65
57
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
logger.
|
58
|
+
# Create TCP server socket
|
59
|
+
@server = TCPServer.open(@local_host, @local_port)
|
60
|
+
@logger.info "MQTT::Proxy listening on #{@local_host}:#{@local_port}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Start accepting connections and processing packets.
|
64
|
+
def run
|
65
|
+
loop do
|
66
|
+
# Wait for a client to connect and then create a thread for it
|
67
|
+
Thread.new(@server.accept) do |client_socket|
|
68
|
+
logger.info "Accepted client: #{client_socket.peeraddr.join(':')}"
|
69
|
+
server_socket = TCPSocket.new(@server_host, @server_port)
|
70
|
+
begin
|
71
|
+
process_packets(client_socket, server_socket)
|
72
|
+
rescue Exception => exp
|
73
|
+
logger.error exp.to_s
|
74
|
+
end
|
75
|
+
logger.info "Disconnected: #{client_socket.peeraddr.join(':')}"
|
76
|
+
server_socket.close
|
77
|
+
client_socket.close
|
77
78
|
end
|
78
|
-
logger.info "Disconnected: #{client_socket.peeraddr.join(':')}"
|
79
|
-
server_socket.close
|
80
|
-
client_socket.close
|
81
79
|
end
|
82
80
|
end
|
83
|
-
end
|
84
81
|
|
85
|
-
|
82
|
+
private
|
83
|
+
|
84
|
+
def process_packets(client_socket, server_socket)
|
85
|
+
loop do
|
86
|
+
# Wait for some data on either socket
|
87
|
+
selected = IO.select([client_socket, server_socket], nil, nil, @select_timeout)
|
86
88
|
|
87
|
-
def process_packets(client_socket,server_socket)
|
88
|
-
loop do
|
89
|
-
# Wait for some data on either socket
|
90
|
-
selected = IO.select([client_socket,server_socket], nil, nil, @select_timeout)
|
91
|
-
if selected.nil?
|
92
89
|
# Timeout
|
93
|
-
raise
|
94
|
-
|
90
|
+
raise 'Timeout in select' if selected.nil?
|
91
|
+
|
95
92
|
# Iterate through each of the sockets with data to read
|
96
93
|
if selected[0].include?(client_socket)
|
97
94
|
packet = MQTT::Packet.read(client_socket)
|
98
|
-
logger.debug "client -> <#{packet.
|
95
|
+
logger.debug "client -> <#{packet.type_name}>"
|
99
96
|
packet = @client_filter.call(packet) unless @client_filter.nil?
|
100
97
|
unless packet.nil?
|
101
98
|
server_socket.write(packet)
|
102
|
-
logger.debug "<#{packet.
|
99
|
+
logger.debug "<#{packet.type_name}> -> server"
|
103
100
|
end
|
104
101
|
elsif selected[0].include?(server_socket)
|
105
102
|
packet = MQTT::Packet.read(server_socket)
|
106
|
-
logger.debug "server -> <#{packet.
|
103
|
+
logger.debug "server -> <#{packet.type_name}>"
|
107
104
|
packet = @server_filter.call(packet) unless @server_filter.nil?
|
108
105
|
unless packet.nil?
|
109
106
|
client_socket.write(packet)
|
110
|
-
logger.debug "<#{packet.
|
107
|
+
logger.debug "<#{packet.type_name}> -> client"
|
111
108
|
end
|
112
109
|
else
|
113
|
-
logger.error
|
110
|
+
logger.error 'Problem with select: socket is neither server or client'
|
114
111
|
end
|
115
112
|
end
|
116
113
|
end
|
117
114
|
end
|
118
|
-
|
119
115
|
end
|