nats 0.4.10 → 0.4.22
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.
- data/HISTORY.md +42 -0
- data/README.md +68 -56
- data/Rakefile +1 -1
- data/bin/nats-request +41 -0
- data/bin/nats-top +146 -0
- data/lib/nats/client.rb +190 -74
- data/lib/nats/server.rb +15 -0
- data/lib/nats/server/connection.rb +269 -0
- data/lib/nats/server/connz.rb +54 -0
- data/lib/nats/server/const.rb +24 -2
- data/lib/nats/server/options.rb +64 -3
- data/lib/nats/server/server.rb +73 -172
- data/lib/nats/server/sublist.rb +67 -16
- data/lib/nats/server/util.rb +45 -2
- data/lib/nats/server/varz.rb +35 -0
- data/nats.gemspec +12 -6
- metadata +64 -55
- data/ChangeLog +0 -11
data/lib/nats/server.rb
CHANGED
@@ -10,9 +10,12 @@ require "#{ep}/ext/bytesize"
|
|
10
10
|
require "#{ep}/ext/json"
|
11
11
|
require "#{ep}/server/server"
|
12
12
|
require "#{ep}/server/sublist"
|
13
|
+
require "#{ep}/server/connection"
|
13
14
|
require "#{ep}/server/options"
|
14
15
|
require "#{ep}/server/const"
|
15
16
|
require "#{ep}/server/util"
|
17
|
+
require "#{ep}/server/varz"
|
18
|
+
require "#{ep}/server/connz"
|
16
19
|
|
17
20
|
# Do setup
|
18
21
|
NATSD::Server.setup(ARGV.dup)
|
@@ -20,6 +23,7 @@ NATSD::Server.setup(ARGV.dup)
|
|
20
23
|
# Event Loop
|
21
24
|
EM.run {
|
22
25
|
log "Starting #{NATSD::APP_NAME} version #{NATSD::VERSION} on port #{NATSD::Server.port}"
|
26
|
+
log "TLS/SSL Support Enabled" if NATSD::Server.options[:ssl]
|
23
27
|
begin
|
24
28
|
EM.set_descriptor_table_size(32768) # Requires Root privileges
|
25
29
|
EventMachine::start_server(NATSD::Server.host, NATSD::Server.port, NATSD::Connection)
|
@@ -28,4 +32,15 @@ EM.run {
|
|
28
32
|
log_error
|
29
33
|
exit(1)
|
30
34
|
end
|
35
|
+
|
36
|
+
# Check to see if we need to fire up the http monitor port and server
|
37
|
+
if NATSD::Server.options[:http_port]
|
38
|
+
begin
|
39
|
+
NATSD::Server.start_http_server
|
40
|
+
rescue => e
|
41
|
+
log "Could not start monitoring server on port #{NATSD::Server.options[:http_port]}"
|
42
|
+
log_error
|
43
|
+
exit(1)
|
44
|
+
end
|
45
|
+
end
|
31
46
|
}
|
@@ -0,0 +1,269 @@
|
|
1
|
+
module NATSD #:nodoc: all
|
2
|
+
|
3
|
+
module Connection #:nodoc: all
|
4
|
+
|
5
|
+
attr_accessor :in_msgs, :out_msgs, :in_bytes, :out_bytes
|
6
|
+
attr_reader :cid, :closing, :last_activity, :writev_size
|
7
|
+
alias :closing? :closing
|
8
|
+
|
9
|
+
def flush_data
|
10
|
+
return if @writev.nil? || closing?
|
11
|
+
send_data(@writev.join)
|
12
|
+
@writev, @writev_size = nil, 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def queue_data(data)
|
16
|
+
EM.next_tick { flush_data } if @writev.nil?
|
17
|
+
(@writev ||= []) << data
|
18
|
+
@writev_size += data.bytesize
|
19
|
+
flush_data if @writev_size > MAX_WRITEV_SIZE
|
20
|
+
end
|
21
|
+
|
22
|
+
def client_info
|
23
|
+
@client_info ||= (get_peername.nil? ? 'N/A' : Socket.unpack_sockaddr_in(get_peername))
|
24
|
+
end
|
25
|
+
|
26
|
+
def info
|
27
|
+
{
|
28
|
+
:cid => cid,
|
29
|
+
:ip => client_info[1],
|
30
|
+
:port => client_info[0],
|
31
|
+
:subscriptions => @subscriptions.size,
|
32
|
+
:pending_size => get_outbound_data_size,
|
33
|
+
:in_msgs => @in_msgs,
|
34
|
+
:out_msgs => @out_msgs,
|
35
|
+
:in_bytes => @in_bytes,
|
36
|
+
:out_bytes => @out_bytes
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def max_connections_exceeded?
|
41
|
+
return false unless (Server.num_connections > Server.max_connections)
|
42
|
+
error_close MAX_CONNS_EXCEEDED
|
43
|
+
debug "Maximum #{Server.max_connections} connections exceeded, c:#{cid} will be closed"
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def post_init
|
48
|
+
@cid = Server.cid
|
49
|
+
@subscriptions = {}
|
50
|
+
@verbose = @pedantic = true # suppressed by most clients, but allows friendly telnet
|
51
|
+
@in_msgs = @out_msgs = @in_bytes = @out_bytes = 0
|
52
|
+
@writev_size = 0
|
53
|
+
@parse_state = AWAITING_CONTROL_LINE
|
54
|
+
send_info
|
55
|
+
debug "Client connection created", client_info, cid
|
56
|
+
if Server.ssl_required?
|
57
|
+
debug "Starting TLS/SSL", client_info, cid
|
58
|
+
flush_data
|
59
|
+
@ssl_pending = EM.add_timer(NATSD::Server.ssl_timeout) { connect_ssl_timeout }
|
60
|
+
start_tls(:verify_peer => true) if Server.ssl_required?
|
61
|
+
end
|
62
|
+
@auth_pending = EM.add_timer(NATSD::Server.auth_timeout) { connect_auth_timeout } if Server.auth_required?
|
63
|
+
@ping_timer = EM.add_periodic_timer(NATSD::Server.ping_interval) { send_ping }
|
64
|
+
@pings_outstanding = 0
|
65
|
+
Server.num_connections += 1
|
66
|
+
return if max_connections_exceeded?
|
67
|
+
end
|
68
|
+
|
69
|
+
def send_ping
|
70
|
+
return if @closing
|
71
|
+
if @pings_outstanding > NATSD::Server.ping_max
|
72
|
+
error_close UNRESPONSIVE
|
73
|
+
return
|
74
|
+
end
|
75
|
+
queue_data(PING_RESPONSE)
|
76
|
+
flush_data
|
77
|
+
@pings_outstanding += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
def connect_auth_timeout
|
81
|
+
error_close AUTH_REQUIRED
|
82
|
+
debug "Connection timeout due to lack of auth credentials", cid
|
83
|
+
end
|
84
|
+
|
85
|
+
def connect_ssl_timeout
|
86
|
+
error_close SSL_REQUIRED
|
87
|
+
debug "Connection timeout due to lack of TLS/SSL negotiations", cid
|
88
|
+
end
|
89
|
+
|
90
|
+
def receive_data(data)
|
91
|
+
@buf = @buf ? @buf << data : data
|
92
|
+
return close_connection if @buf =~ /(\006|\004)/ # ctrl+c or ctrl+d for telnet friendly
|
93
|
+
|
94
|
+
# while (@buf && !@buf.empty? && !@closing)
|
95
|
+
while (@buf && !@closing)
|
96
|
+
case @parse_state
|
97
|
+
when AWAITING_CONTROL_LINE
|
98
|
+
case @buf
|
99
|
+
when PUB_OP
|
100
|
+
ctrace('PUB OP', strip_op($&)) if NATSD::Server.trace_flag?
|
101
|
+
return connect_auth_timeout if @auth_pending
|
102
|
+
@buf = $'
|
103
|
+
@parse_state = AWAITING_MSG_PAYLOAD
|
104
|
+
@msg_sub, @msg_reply, @msg_size = $1, $3, $4.to_i
|
105
|
+
if (@msg_size > NATSD::Server.max_payload)
|
106
|
+
debug_print_msg_too_big(@msg_size)
|
107
|
+
error_close PAYLOAD_TOO_BIG
|
108
|
+
end
|
109
|
+
queue_data(INVALID_SUBJECT) if (@pedantic && !(@msg_sub =~ SUB_NO_WC))
|
110
|
+
when SUB_OP
|
111
|
+
ctrace('SUB OP', strip_op($&)) if NATSD::Server.trace_flag?
|
112
|
+
return connect_auth_timeout if @auth_pending
|
113
|
+
@buf = $'
|
114
|
+
sub, qgroup, sid = $1, $3, $4
|
115
|
+
return queue_data(INVALID_SUBJECT) if !($1 =~ SUB)
|
116
|
+
return queue_data(INVALID_SID_TAKEN) if @subscriptions[sid]
|
117
|
+
sub = Subscriber.new(self, sub, sid, qgroup, 0)
|
118
|
+
@subscriptions[sid] = sub
|
119
|
+
Server.subscribe(sub)
|
120
|
+
queue_data(OK) if @verbose
|
121
|
+
when UNSUB_OP
|
122
|
+
ctrace('UNSUB OP', strip_op($&)) if NATSD::Server.trace_flag?
|
123
|
+
return connect_auth_timeout if @auth_pending
|
124
|
+
@buf = $'
|
125
|
+
sid, sub = $1, @subscriptions[$1]
|
126
|
+
if sub
|
127
|
+
# If we have set max_responses, we will unsubscribe once we have received
|
128
|
+
# the appropriate amount of responses.
|
129
|
+
sub.max_responses = ($2 && $3) ? $3.to_i : nil
|
130
|
+
delete_subscriber(sub) unless (sub.max_responses && (sub.num_responses < sub.max_responses))
|
131
|
+
queue_data(OK) if @verbose
|
132
|
+
else
|
133
|
+
queue_data(INVALID_SID_NOEXIST) if @pedantic
|
134
|
+
end
|
135
|
+
when PING
|
136
|
+
ctrace('PING OP', strip_op($&)) if NATSD::Server.trace_flag?
|
137
|
+
@buf = $'
|
138
|
+
queue_data(PONG_RESPONSE)
|
139
|
+
flush_data
|
140
|
+
when PONG
|
141
|
+
ctrace('PONG OP', strip_op($&)) if NATSD::Server.trace_flag?
|
142
|
+
@buf = $'
|
143
|
+
@pings_outstanding -= 1
|
144
|
+
when CONNECT
|
145
|
+
ctrace('CONNECT OP', strip_op($&)) if NATSD::Server.trace_flag?
|
146
|
+
@buf = $'
|
147
|
+
begin
|
148
|
+
config = JSON.parse($1)
|
149
|
+
process_connect_config(config)
|
150
|
+
rescue => e
|
151
|
+
queue_data(INVALID_CONFIG)
|
152
|
+
log_error
|
153
|
+
end
|
154
|
+
when INFO
|
155
|
+
ctrace('INFO OP', strip_op($&)) if NATSD::Server.trace_flag?
|
156
|
+
return connect_auth_timeout if @auth_pending
|
157
|
+
@buf = $'
|
158
|
+
send_info
|
159
|
+
when UNKNOWN
|
160
|
+
ctrace('Unknown Op', strip_op($&)) if NATSD::Server.trace_flag?
|
161
|
+
return connect_auth_timeout if @auth_pending
|
162
|
+
@buf = $'
|
163
|
+
queue_data(UNKNOWN_OP)
|
164
|
+
else
|
165
|
+
# If we are here we do not have a complete line yet that we understand.
|
166
|
+
# If too big, cut the connection off.
|
167
|
+
if @buf.bytesize > NATSD::Server.max_control_line
|
168
|
+
debug_print_controlline_too_big(@buf.bytesize)
|
169
|
+
close_connection
|
170
|
+
end
|
171
|
+
return
|
172
|
+
end
|
173
|
+
@buf = nil if (@buf && @buf.empty?)
|
174
|
+
|
175
|
+
when AWAITING_MSG_PAYLOAD
|
176
|
+
return unless (@buf.bytesize >= (@msg_size + CR_LF_SIZE))
|
177
|
+
msg = @buf.slice(0, @msg_size)
|
178
|
+
ctrace('Processing msg', @msg_sub, @msg_reply, msg) if NATSD::Server.trace_flag?
|
179
|
+
queue_data(OK) if @verbose
|
180
|
+
Server.route_to_subscribers(@msg_sub, @msg_reply, msg)
|
181
|
+
@in_msgs += 1
|
182
|
+
@in_bytes += @msg_size
|
183
|
+
@buf = @buf.slice((@msg_size + CR_LF_SIZE), @buf.bytesize)
|
184
|
+
@msg_sub = @msg_size = @reply = nil
|
185
|
+
@parse_state = AWAITING_CONTROL_LINE
|
186
|
+
@buf = nil if (@buf && @buf.empty?)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def send_info
|
192
|
+
queue_data("INFO #{Server.info_string}#{CR_LF}")
|
193
|
+
end
|
194
|
+
|
195
|
+
def process_connect_config(config)
|
196
|
+
@verbose = config['verbose'] unless config['verbose'].nil?
|
197
|
+
@pedantic = config['pedantic'] unless config['pedantic'].nil?
|
198
|
+
|
199
|
+
return queue_data(OK) unless Server.auth_required?
|
200
|
+
|
201
|
+
EM.cancel_timer(@auth_pending)
|
202
|
+
if Server.auth_ok?(config['user'], config['pass'])
|
203
|
+
queue_data(OK) if @verbose
|
204
|
+
@auth_pending = nil
|
205
|
+
else
|
206
|
+
error_close AUTH_FAILED
|
207
|
+
debug "Authorization failed for connection", cid
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def delete_subscriber(sub)
|
212
|
+
ctrace('DELSUB OP', sub.subject, sub.qgroup, sub.sid) if NATSD::Server.trace_flag?
|
213
|
+
Server.unsubscribe(sub)
|
214
|
+
@subscriptions.delete(sub.sid)
|
215
|
+
end
|
216
|
+
|
217
|
+
def error_close(msg)
|
218
|
+
queue_data(msg)
|
219
|
+
flush_data
|
220
|
+
EM.next_tick { close_connection_after_writing }
|
221
|
+
@closing = true
|
222
|
+
end
|
223
|
+
|
224
|
+
def debug_print_controlline_too_big(line_size)
|
225
|
+
sizes = "#{pretty_size(line_size)} vs #{pretty_size(NATSD::Server.max_control_line)} max"
|
226
|
+
debug "Control line size exceeded (#{sizes}), closing connection.."
|
227
|
+
end
|
228
|
+
|
229
|
+
def debug_print_msg_too_big(msg_size)
|
230
|
+
sizes = "#{pretty_size(msg_size)} vs #{pretty_size(NATSD::Server.max_payload)} max"
|
231
|
+
debug "Message payload size exceeded (#{sizes}), closing connection"
|
232
|
+
end
|
233
|
+
|
234
|
+
def unbind
|
235
|
+
debug "Client connection closed", client_info, cid
|
236
|
+
Server.num_connections -= 1
|
237
|
+
@subscriptions.each_value { |sub| Server.unsubscribe(sub) }
|
238
|
+
EM.cancel_timer(@ssl_pending) if @ssl_pending
|
239
|
+
@ssl_pending = nil
|
240
|
+
EM.cancel_timer(@auth_pending) if @auth_pending
|
241
|
+
@auth_pending = nil
|
242
|
+
EM.cancel_timer(@ping_timer) if @ping_timer
|
243
|
+
@ping_timer = nil
|
244
|
+
|
245
|
+
@closing = true
|
246
|
+
end
|
247
|
+
|
248
|
+
def ssl_handshake_completed
|
249
|
+
EM.cancel_timer(@ssl_pending)
|
250
|
+
@ssl_pending = nil
|
251
|
+
cert = get_peer_cert
|
252
|
+
debug "Client Certificate:", cert ? cert : 'N/A', cid
|
253
|
+
end
|
254
|
+
|
255
|
+
# FIXME! Cert accepted by default
|
256
|
+
def ssl_verify_peer(cert)
|
257
|
+
true
|
258
|
+
end
|
259
|
+
|
260
|
+
def ctrace(*args)
|
261
|
+
trace(args, "c: #{cid}")
|
262
|
+
end
|
263
|
+
|
264
|
+
def strip_op(op='')
|
265
|
+
op.dup.sub(CR_LF, EMPTY)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module NATSD #:nodoc: all
|
2
|
+
|
3
|
+
class Connz
|
4
|
+
def call(env)
|
5
|
+
c_info = Server.dump_connections
|
6
|
+
qs = env['QUERY_STRING']
|
7
|
+
if (qs =~ /n=(\d+)/)
|
8
|
+
sort_key = :pending_size
|
9
|
+
n = $1.to_i
|
10
|
+
if (qs =~ /s=(\S+)/)
|
11
|
+
case $1.downcase
|
12
|
+
when 'in_msgs'; sort_key = :in_msgs
|
13
|
+
when 'msgs_from'; sort_key = :in_msgs
|
14
|
+
when 'out_msgs'; sort_key = :out_msgs
|
15
|
+
when 'msgs_to'; sort_key = :out_msgs
|
16
|
+
when 'in_bytes'; sort_key = :in_bytes
|
17
|
+
when 'bytes_from'; sort_key = :in_bytes
|
18
|
+
when 'out_bytes'; sort_key = :out_bytes
|
19
|
+
when 'bytes_to'; sort_key = :out_bytes
|
20
|
+
when 'subs'; sort_key = :subscriptions
|
21
|
+
when 'subscriptions'; sort_key = :subscriptions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
conns = c_info[:connections]
|
25
|
+
c_info[:connections] = conns.sort { |a,b| b[sort_key] <=> a[sort_key] } [0, n]
|
26
|
+
end
|
27
|
+
connz_json = JSON.pretty_generate(c_info) + "\n"
|
28
|
+
hdrs = RACK_JSON_HDR.dup
|
29
|
+
hdrs['Content-Length'] = connz_json.bytesize.to_s
|
30
|
+
[200, hdrs, connz_json]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Server
|
35
|
+
class << self
|
36
|
+
|
37
|
+
def dump_connections
|
38
|
+
conns, total = [], 0
|
39
|
+
ObjectSpace.each_object(NATSD::Connection) do |c|
|
40
|
+
next if c.closing?
|
41
|
+
total += c.info[:pending_size]
|
42
|
+
conns << c.info
|
43
|
+
end
|
44
|
+
{
|
45
|
+
:pending_size => total,
|
46
|
+
:num_connections => conns.size,
|
47
|
+
:connections => conns
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/lib/nats/server/const.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
module NATSD #:nodoc:
|
3
3
|
|
4
|
-
VERSION = '0.4.
|
4
|
+
VERSION = '0.4.22'
|
5
5
|
APP_NAME = 'nats-server'
|
6
6
|
|
7
7
|
DEFAULT_PORT = 4222
|
@@ -26,6 +26,7 @@ module NATSD #:nodoc:
|
|
26
26
|
CR_LF_SIZE = CR_LF.bytesize
|
27
27
|
EMPTY = ''.freeze
|
28
28
|
OK = "+OK#{CR_LF}".freeze
|
29
|
+
PING_RESPONSE = "PING#{CR_LF}".freeze
|
29
30
|
PONG_RESPONSE = "PONG#{CR_LF}".freeze
|
30
31
|
INFO_RESPONSE = "#{CR_LF}".freeze
|
31
32
|
|
@@ -38,8 +39,12 @@ module NATSD #:nodoc:
|
|
38
39
|
INVALID_CONFIG = "-ERR 'Invalid config, valid JSON required for connection configuration'#{CR_LF}".freeze
|
39
40
|
AUTH_REQUIRED = "-ERR 'Authorization is required'#{CR_LF}".freeze
|
40
41
|
AUTH_FAILED = "-ERR 'Authorization failed'#{CR_LF}".freeze
|
42
|
+
SSL_REQUIRED = "-ERR 'TSL/SSL is required'#{CR_LF}".freeze
|
43
|
+
SSL_FAILED = "-ERR 'TLS/SSL failed'#{CR_LF}".freeze
|
41
44
|
UNKNOWN_OP = "-ERR 'Unknown Protocol Operation'#{CR_LF}".freeze
|
42
45
|
SLOW_CONSUMER = "-ERR 'Slow consumer detected, connection dropped'#{CR_LF}".freeze
|
46
|
+
UNRESPONSIVE = "-ERR 'Unresponsive client detected, connection dropped'#{CR_LF}".freeze
|
47
|
+
MAX_CONNS_EXCEEDED = "-ERR 'Maximum client connections exceeded, connection dropped'#{CR_LF}".freeze
|
43
48
|
|
44
49
|
# Pedantic Mode
|
45
50
|
SUB = /^([^\.\*>\s]+|>$|\*)(\.([^\.\*>\s]+|>$|\*))*$/
|
@@ -56,7 +61,24 @@ module NATSD #:nodoc:
|
|
56
61
|
# Maximum outbound size per client
|
57
62
|
MAX_PENDING_SIZE = (10*1024*1024)
|
58
63
|
|
64
|
+
# Maximum pending bucket size
|
65
|
+
MAX_WRITEV_SIZE = (64*1024)
|
66
|
+
|
67
|
+
# Maximum connections default
|
68
|
+
DEFAULT_MAX_CONNECTIONS = (64*1024)
|
69
|
+
|
70
|
+
# TLS/SSL wait time
|
71
|
+
SSL_TIMEOUT = 0.5
|
72
|
+
|
59
73
|
# Authorization wait time
|
60
|
-
AUTH_TIMEOUT =
|
74
|
+
AUTH_TIMEOUT = SSL_TIMEOUT + 0.5
|
75
|
+
|
76
|
+
# Ping intervals
|
77
|
+
DEFAULT_PING_INTERVAL = 120
|
78
|
+
DEFAULT_PING_MAX = 2
|
79
|
+
|
80
|
+
# HTTP
|
81
|
+
RACK_JSON_HDR = { 'Content-Type' => 'application/json' }
|
82
|
+
RACK_TEXT_HDR = { 'Content-Type' => 'text/plain' }
|
61
83
|
|
62
84
|
end
|
data/lib/nats/server/options.rb
CHANGED
@@ -17,7 +17,9 @@ module NATSD
|
|
17
17
|
"(default: #{DEFAULT_HOST})") { |host| @options[:addr] = host }
|
18
18
|
opts.on("-p", "--port PORT", "Use PORT (default: #{DEFAULT_PORT})") { |port| @options[:port] = port.to_i }
|
19
19
|
opts.on("-d", "--daemonize", "Run daemonized in the background") { @options[:daemonize] = true }
|
20
|
-
opts.on("-P", "--pid FILE",
|
20
|
+
opts.on("-P", "--pid FILE", "File to store PID") { |file| @options[:pid_file] = file }
|
21
|
+
|
22
|
+
opts.on("-m", "--http_port PORT", "Use HTTP PORT ") { |port| @options[:http_port] = port.to_i }
|
21
23
|
|
22
24
|
opts.on("-c", "--config FILE", "Configuration File") { |file| @options[:config_file] = file }
|
23
25
|
|
@@ -35,6 +37,9 @@ module NATSD
|
|
35
37
|
opts.on("--user user", "User required for connections") { |user| @options[:user] = user }
|
36
38
|
opts.on("--pass password", "Password required for connections") { |pass| @options[:pass] = pass }
|
37
39
|
|
40
|
+
opts.separator ""
|
41
|
+
opts.on("--ssl", "Enable SSL") { |ssl| @options[:ssl] = true }
|
42
|
+
|
38
43
|
opts.separator ""
|
39
44
|
opts.separator "Advanced IO options:"
|
40
45
|
|
@@ -63,8 +68,13 @@ module NATSD
|
|
63
68
|
@options[:pass] = auth['pass'] if @options[:pass].nil?
|
64
69
|
@options[:token] = auth['token'] if @options[:token].nil?
|
65
70
|
@options[:auth_timeout] = auth['timeout'] if @options[:auth_timeout].nil?
|
71
|
+
# Multiple Users setup
|
72
|
+
@options[:users] = symbolize_users(auth['users']) || []
|
66
73
|
end
|
67
74
|
|
75
|
+
# TLS/SSL
|
76
|
+
@options[:ssl] = config['ssl'] if @options[:ssl].nil?
|
77
|
+
|
68
78
|
@options[:pid_file] = config['pid_file'] if @options[:pid_file].nil?
|
69
79
|
@options[:log_file] = config['log_file'] if @options[:log_file].nil?
|
70
80
|
@options[:log_time] = config['logtime'] if @options[:log_time].nil?
|
@@ -75,11 +85,26 @@ module NATSD
|
|
75
85
|
@options[:max_control_line] = config['max_control_line'] if config['max_control_line']
|
76
86
|
@options[:max_payload] = config['max_payload'] if config['max_payload']
|
77
87
|
@options[:max_pending] = config['max_pending'] if config['max_pending']
|
88
|
+
@options[:max_connections] = config['max_connections'] if config['max_connections']
|
78
89
|
|
79
90
|
# just set
|
80
|
-
@options[:noepoll]
|
91
|
+
@options[:noepoll] = config['no_epoll'] if config['no_epoll']
|
81
92
|
@options[:nokqueue] = config['no_kqueue'] if config['no_kqueue']
|
82
93
|
|
94
|
+
if http = config['http']
|
95
|
+
if @options[:http_net].nil?
|
96
|
+
@options[:http_net] = http['net'] || @options[:addr]
|
97
|
+
end
|
98
|
+
@options[:http_port] = http['port'] if @options[:http_port].nil?
|
99
|
+
@options[:http_user] = http['user'] if @options[:http_user].nil?
|
100
|
+
@options[:http_password] = http['password'] if @options[:http_password].nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
if ping = config['ping']
|
104
|
+
@options[:ping_interval] = ping['interval'] if @options[:ping_interval].nil?
|
105
|
+
@options[:ping_max] = ping['max_outstanding'] if @options[:ping_max].nil?
|
106
|
+
end
|
107
|
+
|
83
108
|
rescue => e
|
84
109
|
log "Could not read configuration file: #{e}"
|
85
110
|
exit
|
@@ -87,16 +112,29 @@ module NATSD
|
|
87
112
|
|
88
113
|
def setup_logs
|
89
114
|
return unless @options[:log_file]
|
90
|
-
$stdout.reopen(@options[:log_file],
|
115
|
+
$stdout.reopen(@options[:log_file], 'a')
|
91
116
|
$stdout.sync = true
|
92
117
|
$stderr.reopen($stdout)
|
93
118
|
end
|
94
119
|
|
120
|
+
def symbolize_users(users)
|
121
|
+
return nil unless users
|
122
|
+
auth_users = []
|
123
|
+
users.each do |u|
|
124
|
+
auth_users << { :user => u['user'], :pass => u['pass'] || u['password'] }
|
125
|
+
end
|
126
|
+
auth_users
|
127
|
+
end
|
128
|
+
|
95
129
|
def finalize_options
|
96
130
|
# Addr/Port
|
97
131
|
@options[:port] ||= DEFAULT_PORT
|
98
132
|
@options[:addr] ||= DEFAULT_HOST
|
99
133
|
|
134
|
+
# Max Connections
|
135
|
+
@options[:max_connections] ||= DEFAULT_MAX_CONNECTIONS
|
136
|
+
@max_connections = @options[:max_connections]
|
137
|
+
|
100
138
|
# Debug and Tracing
|
101
139
|
@debug_flag = @options[:debug]
|
102
140
|
@trace_flag = @options[:trace]
|
@@ -109,8 +147,28 @@ module NATSD
|
|
109
147
|
trace "TRACE is on"
|
110
148
|
|
111
149
|
# Authorization
|
150
|
+
|
151
|
+
# Multi-user setup for auth
|
152
|
+
if @options[:user]
|
153
|
+
# Multiple Users setup
|
154
|
+
@options[:users] ||= []
|
155
|
+
@options[:users].unshift({:user => @options[:user], :pass => @options[:pass]}) if @options[:user]
|
156
|
+
elsif @options[:users]
|
157
|
+
first = @options[:users].first
|
158
|
+
@options[:user], @options[:pass] = first[:user], first[:pass]
|
159
|
+
end
|
160
|
+
|
112
161
|
@auth_required = (not @options[:user].nil?)
|
113
162
|
|
163
|
+
@ssl_required = (not @options[:ssl].nil?)
|
164
|
+
|
165
|
+
# Pings
|
166
|
+
@options[:ping_interval] ||= DEFAULT_PING_INTERVAL
|
167
|
+
@ping_interval = @options[:ping_interval]
|
168
|
+
|
169
|
+
@options[:ping_max] ||= DEFAULT_PING_MAX
|
170
|
+
@ping_max = @options[:ping_max]
|
171
|
+
|
114
172
|
# Thresholds
|
115
173
|
@options[:max_control_line] ||= MAX_CONTROL_LINE_SIZE
|
116
174
|
@max_control_line = @options[:max_control_line]
|
@@ -123,6 +181,9 @@ module NATSD
|
|
123
181
|
|
124
182
|
@options[:auth_timeout] ||= AUTH_TIMEOUT
|
125
183
|
@auth_timeout = @options[:auth_timeout]
|
184
|
+
|
185
|
+
@options[:ssl_timeout] ||= SSL_TIMEOUT
|
186
|
+
@ssl_timeout = @options[:ssl_timeout]
|
126
187
|
end
|
127
188
|
|
128
189
|
end
|