go-mqtt 0.0.1
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 +7 -0
- data/LICENSE.md +21 -0
- data/NEWS.md +150 -0
- data/README.md +237 -0
- data/lib/mqtt/client.rb +755 -0
- data/lib/mqtt/openssl_fix.rb +29 -0
- data/lib/mqtt/packet.rb +1049 -0
- data/lib/mqtt/proxy.rb +115 -0
- data/lib/mqtt/sn/packet.rb +720 -0
- data/lib/mqtt/version.rb +4 -0
- data/lib/mqtt.rb +48 -0
- data/spec/mqtt_client_spec.rb +1124 -0
- data/spec/mqtt_packet_spec.rb +2012 -0
- data/spec/mqtt_proxy_spec.rb +8 -0
- data/spec/mqtt_sn_packet_spec.rb +1721 -0
- data/spec/mqtt_version_spec.rb +23 -0
- data/spec/zz_client_integration_spec.rb +177 -0
- metadata +152 -0
data/lib/mqtt/proxy.rb
ADDED
@@ -0,0 +1,115 @@
|
|
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
|
6
|
+
|
7
|
+
# Port to bind listening socket to
|
8
|
+
attr_reader :local_port
|
9
|
+
|
10
|
+
# Address of upstream server to send packets upstream to
|
11
|
+
attr_reader :server_host
|
12
|
+
|
13
|
+
# Port of upstream server to send packets upstream to.
|
14
|
+
attr_reader :server_port
|
15
|
+
|
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
|
57
|
+
|
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
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
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)
|
88
|
+
|
89
|
+
# Timeout
|
90
|
+
raise 'Timeout in select' if selected.nil?
|
91
|
+
|
92
|
+
# Iterate through each of the sockets with data to read
|
93
|
+
if selected[0].include?(client_socket)
|
94
|
+
packet = MQTT::Packet.read(client_socket)
|
95
|
+
logger.debug "client -> <#{packet.type_name}>"
|
96
|
+
packet = @client_filter.call(packet) unless @client_filter.nil?
|
97
|
+
unless packet.nil?
|
98
|
+
server_socket.write(packet)
|
99
|
+
logger.debug "<#{packet.type_name}> -> server"
|
100
|
+
end
|
101
|
+
elsif selected[0].include?(server_socket)
|
102
|
+
packet = MQTT::Packet.read(server_socket)
|
103
|
+
logger.debug "server -> <#{packet.type_name}>"
|
104
|
+
packet = @server_filter.call(packet) unless @server_filter.nil?
|
105
|
+
unless packet.nil?
|
106
|
+
client_socket.write(packet)
|
107
|
+
logger.debug "<#{packet.type_name}> -> client"
|
108
|
+
end
|
109
|
+
else
|
110
|
+
logger.error 'Problem with select: socket is neither server or client'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|