fluentd 0.14.7-x64-mingw32 → 0.14.10-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +2 -0
- data/CONTRIBUTING.md +6 -1
- data/ChangeLog +95 -0
- data/Rakefile +21 -0
- data/appveyor.yml +1 -0
- data/code-of-conduct.md +3 -0
- data/example/out_exec_filter.conf +42 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/agent.rb +2 -2
- data/lib/fluent/command/binlog_reader.rb +1 -1
- data/lib/fluent/command/cat.rb +15 -4
- data/lib/fluent/compat/output.rb +14 -9
- data/lib/fluent/compat/parser.rb +141 -11
- data/lib/fluent/config/configure_proxy.rb +2 -11
- data/lib/fluent/config/section.rb +8 -1
- data/lib/fluent/configurable.rb +1 -3
- data/lib/fluent/env.rb +1 -1
- data/lib/fluent/log.rb +1 -1
- data/lib/fluent/plugin/base.rb +17 -0
- data/lib/fluent/plugin/filter_parser.rb +108 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +14 -35
- data/lib/fluent/plugin/filter_stdout.rb +1 -1
- data/lib/fluent/plugin/formatter.rb +5 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +4 -0
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/formatter_tsv.rb +34 -0
- data/lib/fluent/plugin/in_exec.rb +48 -93
- data/lib/fluent/plugin/in_forward.rb +66 -265
- data/lib/fluent/plugin/in_http.rb +68 -65
- data/lib/fluent/plugin/in_monitor_agent.rb +8 -4
- data/lib/fluent/plugin/in_syslog.rb +42 -58
- data/lib/fluent/plugin/in_tail.rb +29 -14
- data/lib/fluent/plugin/in_tcp.rb +54 -14
- data/lib/fluent/plugin/in_udp.rb +49 -13
- data/lib/fluent/plugin/multi_output.rb +1 -3
- data/lib/fluent/plugin/out_exec.rb +58 -71
- data/lib/fluent/plugin/out_exec_filter.rb +199 -279
- data/lib/fluent/plugin/out_file.rb +172 -81
- data/lib/fluent/plugin/out_forward.rb +229 -206
- data/lib/fluent/plugin/out_stdout.rb +6 -21
- data/lib/fluent/plugin/output.rb +90 -59
- data/lib/fluent/plugin/parser.rb +121 -61
- data/lib/fluent/plugin/parser_csv.rb +9 -3
- data/lib/fluent/plugin/parser_json.rb +37 -35
- data/lib/fluent/plugin/parser_ltsv.rb +11 -19
- data/lib/fluent/plugin/parser_msgpack.rb +50 -0
- data/lib/fluent/plugin/parser_regexp.rb +15 -42
- data/lib/fluent/plugin/parser_tsv.rb +8 -3
- data/lib/fluent/plugin_helper.rb +10 -1
- data/lib/fluent/plugin_helper/child_process.rb +139 -73
- data/lib/fluent/plugin_helper/compat_parameters.rb +93 -4
- data/lib/fluent/plugin_helper/event_emitter.rb +14 -1
- data/lib/fluent/plugin_helper/event_loop.rb +24 -6
- data/lib/fluent/plugin_helper/extract.rb +16 -4
- data/lib/fluent/plugin_helper/formatter.rb +9 -11
- data/lib/fluent/plugin_helper/inject.rb +16 -1
- data/lib/fluent/plugin_helper/parser.rb +3 -3
- data/lib/fluent/plugin_helper/server.rb +494 -0
- data/lib/fluent/plugin_helper/socket.rb +101 -0
- data/lib/fluent/plugin_helper/socket_option.rb +84 -0
- data/lib/fluent/plugin_helper/timer.rb +1 -0
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/test/driver/base.rb +95 -49
- data/lib/fluent/test/driver/base_owner.rb +18 -8
- data/lib/fluent/test/driver/multi_output.rb +2 -1
- data/lib/fluent/test/driver/output.rb +29 -6
- data/lib/fluent/test/helpers.rb +3 -1
- data/lib/fluent/test/log.rb +4 -0
- data/lib/fluent/test/startup_shutdown.rb +13 -0
- data/lib/fluent/time.rb +14 -8
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +1 -1
- data/test/command/test_binlog_reader.rb +5 -1
- data/test/compat/test_parser.rb +10 -0
- data/test/config/test_configurable.rb +193 -0
- data/test/config/test_configure_proxy.rb +0 -43
- data/test/helper.rb +36 -1
- data/test/plugin/test_base.rb +16 -0
- data/test/plugin/test_filter_parser.rb +665 -0
- data/test/plugin/test_filter_record_transformer.rb +36 -100
- data/test/plugin/test_filter_stdout.rb +18 -27
- data/test/plugin/test_in_dummy.rb +1 -1
- data/test/plugin/test_in_exec.rb +206 -94
- data/test/plugin/test_in_forward.rb +268 -347
- data/test/plugin/test_in_http.rb +310 -186
- data/test/plugin/test_in_monitor_agent.rb +65 -35
- data/test/plugin/test_in_syslog.rb +39 -3
- data/test/plugin/test_in_tcp.rb +78 -62
- data/test/plugin/test_in_udp.rb +101 -80
- data/test/plugin/test_out_exec.rb +223 -68
- data/test/plugin/test_out_exec_filter.rb +520 -169
- data/test/plugin/test_out_file.rb +637 -177
- data/test/plugin/test_out_forward.rb +242 -234
- data/test/plugin/test_out_null.rb +1 -1
- data/test/plugin/test_out_secondary_file.rb +4 -2
- data/test/plugin/test_out_stdout.rb +14 -35
- data/test/plugin/test_output_as_buffered.rb +60 -2
- data/test/plugin/test_parser.rb +359 -0
- data/test/plugin/test_parser_csv.rb +1 -2
- data/test/plugin/test_parser_json.rb +3 -4
- data/test/plugin/test_parser_labeled_tsv.rb +1 -2
- data/test/plugin/test_parser_none.rb +1 -2
- data/test/plugin/test_parser_regexp.rb +8 -4
- data/test/plugin/test_parser_tsv.rb +4 -3
- data/test/plugin_helper/test_child_process.rb +184 -0
- data/test/plugin_helper/test_compat_parameters.rb +88 -1
- data/test/plugin_helper/test_extract.rb +0 -1
- data/test/plugin_helper/test_formatter.rb +5 -2
- data/test/plugin_helper/test_inject.rb +21 -0
- data/test/plugin_helper/test_parser.rb +6 -5
- data/test/plugin_helper/test_server.rb +905 -0
- data/test/test_event_time.rb +3 -1
- data/test/test_output.rb +53 -2
- data/test/test_plugin_classes.rb +20 -0
- data/test/test_root_agent.rb +139 -0
- data/test/test_test_drivers.rb +135 -0
- metadata +28 -8
- data/test/plugin/test_parser_base.rb +0 -32
@@ -14,34 +14,36 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require 'fcntl'
|
18
17
|
|
19
|
-
require '
|
18
|
+
require 'fluent/plugin/input'
|
19
|
+
require 'fluent/msgpack_factory'
|
20
20
|
require 'yajl'
|
21
|
+
require 'digest'
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
module Fluent
|
23
|
+
module Fluent::Plugin
|
25
24
|
class ForwardInput < Input
|
26
|
-
Plugin.register_input('forward', self)
|
25
|
+
Fluent::Plugin.register_input('forward', self)
|
27
26
|
|
28
|
-
|
27
|
+
# See the wiki page below for protocol specification
|
28
|
+
# https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
30
|
+
helpers :server
|
31
|
+
|
32
|
+
LISTEN_PORT = 24224
|
34
33
|
|
35
34
|
desc 'The port to listen to.'
|
36
35
|
config_param :port, :integer, default: LISTEN_PORT
|
37
36
|
desc 'The bind address to listen to.'
|
38
37
|
config_param :bind, :string, default: '0.0.0.0'
|
38
|
+
|
39
39
|
config_param :backlog, :integer, default: nil
|
40
40
|
# SO_LINGER 0 to send RST rather than FIN to avoid lots of connections sitting in TIME_WAIT at src
|
41
41
|
desc 'The timeout time used to set linger option.'
|
42
42
|
config_param :linger_timeout, :integer, default: 0
|
43
43
|
# This option is for Cool.io's loop wait timeout to avoid loop stuck at shutdown. Almost users don't need to change this value.
|
44
44
|
config_param :blocking_timeout, :time, default: 0.5
|
45
|
+
desc 'Try to resolve hostname from IP addresses or not.'
|
46
|
+
config_param :resolve_hostname, :bool, default: nil
|
45
47
|
desc 'Connections will be disconnected right after receiving first message if this value is true.'
|
46
48
|
config_param :deny_keepalive, :bool, default: false
|
47
49
|
|
@@ -88,6 +90,15 @@ module Fluent
|
|
88
90
|
def configure(conf)
|
89
91
|
super
|
90
92
|
|
93
|
+
if @source_hostname_key
|
94
|
+
# TODO: add test
|
95
|
+
if @resolve_hostname.nil?
|
96
|
+
@resolve_hostname = true
|
97
|
+
elsif !@resolve_hostname # user specifies "false" in config
|
98
|
+
raise Fluent::ConfigError, "resolve_hostname must be true with source_hostname_key"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
91
102
|
if @security
|
92
103
|
if @security.user_auth && @security.users.empty?
|
93
104
|
raise Fluent::ConfigError, "<user> sections required if user_auth enabled"
|
@@ -125,80 +136,38 @@ module Fluent
|
|
125
136
|
})
|
126
137
|
end
|
127
138
|
end
|
139
|
+
@lsock = @usock = nil
|
128
140
|
end
|
129
141
|
|
142
|
+
HEARTBEAT_UDP_PAYLOAD = "\0"
|
143
|
+
|
130
144
|
def start
|
131
145
|
super
|
132
146
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
147
|
+
server_create_connection(
|
148
|
+
:in_forward_server, @port,
|
149
|
+
bind: @bind,
|
150
|
+
shared: false,
|
151
|
+
resolve_name: @resolve_hostname,
|
152
|
+
linger_timeout: @linger_timeout,
|
153
|
+
backlog: @backlog,
|
154
|
+
&method(:handle_connection)
|
155
|
+
)
|
156
|
+
|
157
|
+
server_create(:in_forward_server_udp_heartbeat, @port, shared: false, proto: :udp, bind: @bind, resolve_name: @resolve_hostname, max_bytes: 128) do |data, sock|
|
158
|
+
log.trace "heartbeat udp data arrived", host: sock.remote_host, port: sock.remote_port, data: data
|
159
|
+
begin
|
160
|
+
sock.write HEARTBEAT_UDP_PAYLOAD
|
161
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
|
162
|
+
log.trace "error while heartbeat response", host: sock.remote_host, error: e
|
163
|
+
end
|
138
164
|
end
|
139
|
-
client = ServerEngine::SocketManager::Client.new(socket_manager_path)
|
140
|
-
|
141
|
-
@lsock = listen(client)
|
142
|
-
@loop.attach(@lsock)
|
143
|
-
|
144
|
-
@usock = client.listen_udp(@bind, @port)
|
145
|
-
@usock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
|
146
|
-
@hbr = HeartbeatRequestHandler.new(@usock, method(:on_heartbeat_request))
|
147
|
-
@loop.attach(@hbr)
|
148
|
-
|
149
|
-
@thread = Thread.new(&method(:run))
|
150
|
-
end
|
151
|
-
|
152
|
-
def shutdown
|
153
|
-
# In test cases it occasionally appeared that when detaching a watcher, another watcher is also detached.
|
154
|
-
# In the case in the iteration of watchers, a watcher that has been already detached is intended to be detached
|
155
|
-
# and therfore RuntimeError occurs saying that it is not attached to a loop.
|
156
|
-
# It occurs only when testing for sending responses to ForwardOutput.
|
157
|
-
# Sending responses needs to write the socket that is previously used only to read
|
158
|
-
# and a handler has 2 watchers that is used to read and to write.
|
159
|
-
# This problem occurs possibly because those watchers are thought to be related to each other
|
160
|
-
# and when detaching one of them the other is also detached for some reasons.
|
161
|
-
# As a workaround, check if watchers are attached before detaching them.
|
162
|
-
@loop.watchers.each {|w| w.detach if w.attached? }
|
163
|
-
@loop.stop
|
164
|
-
@usock.close
|
165
|
-
@thread.join
|
166
|
-
@lsock.close
|
167
|
-
|
168
|
-
super
|
169
|
-
end
|
170
|
-
|
171
|
-
def listen(client)
|
172
|
-
log.info "listening fluent socket on #{@bind}:#{@port}"
|
173
|
-
sock = client.listen_tcp(@bind, @port)
|
174
|
-
s = Coolio::TCPServer.new(sock, nil, Handler, @linger_timeout, log, method(:handle_connection))
|
175
|
-
s.listen(@backlog) unless @backlog.nil?
|
176
|
-
s
|
177
|
-
end
|
178
|
-
|
179
|
-
#config_param :path, :string, :default => DEFAULT_SOCKET_PATH
|
180
|
-
#def listen
|
181
|
-
# if File.exist?(@path)
|
182
|
-
# File.unlink(@path)
|
183
|
-
# end
|
184
|
-
# FileUtils.mkdir_p File.dirname(@path)
|
185
|
-
# log.debug "listening fluent socket on #{@path}"
|
186
|
-
# Coolio::UNIXServer.new(@path, Handler, method(:on_message))
|
187
|
-
#end
|
188
|
-
|
189
|
-
def run
|
190
|
-
@loop.run(@blocking_timeout)
|
191
|
-
rescue => e
|
192
|
-
log.error "unexpected error", error: e
|
193
|
-
log.error_backtrace
|
194
165
|
end
|
195
166
|
|
196
|
-
private
|
197
|
-
|
198
167
|
def handle_connection(conn)
|
199
168
|
send_data = ->(serializer, data){ conn.write serializer.call(data) }
|
200
169
|
|
201
|
-
log.trace "connected fluent socket",
|
170
|
+
log.trace "connected fluent socket", addr: conn.remote_addr, port: conn.remote_port
|
202
171
|
state = :established
|
203
172
|
nonce = nil
|
204
173
|
user_auth_salt = nil
|
@@ -212,7 +181,7 @@ module Fluent
|
|
212
181
|
state = :pingpong
|
213
182
|
end
|
214
183
|
|
215
|
-
log.trace "accepted fluent socket",
|
184
|
+
log.trace "accepted fluent socket", addr: conn.remote_addr, port: conn.remote_port
|
216
185
|
|
217
186
|
read_messages(conn) do |msg, chunk_size, serializer|
|
218
187
|
case state
|
@@ -228,15 +197,11 @@ module Fluent
|
|
228
197
|
log.debug "connection established", address: conn.remote_addr, port: conn.remote_port
|
229
198
|
state = :established
|
230
199
|
when :established
|
231
|
-
options = on_message(msg, chunk_size, conn.
|
200
|
+
options = on_message(msg, chunk_size, conn.remote_host)
|
232
201
|
if options && r = response(options)
|
233
|
-
send_data.call(serializer, r)
|
234
202
|
log.trace "sent response to fluent socket", address: conn.remote_addr, response: r
|
235
|
-
if @deny_keepalive
|
236
|
-
|
237
|
-
conn.close
|
238
|
-
end
|
239
|
-
end
|
203
|
+
conn.on_write_complete{ conn.close } if @deny_keepalive
|
204
|
+
send_data.call(serializer, r)
|
240
205
|
else
|
241
206
|
if @deny_keepalive
|
242
207
|
conn.close
|
@@ -252,7 +217,7 @@ module Fluent
|
|
252
217
|
feeder = nil
|
253
218
|
serializer = nil
|
254
219
|
bytes = 0
|
255
|
-
conn.
|
220
|
+
conn.data do |data|
|
256
221
|
# only for first call of callback
|
257
222
|
unless feeder
|
258
223
|
first = data[0]
|
@@ -288,30 +253,7 @@ module Fluent
|
|
288
253
|
nil
|
289
254
|
end
|
290
255
|
|
291
|
-
|
292
|
-
# 1: long time
|
293
|
-
# 2: object record
|
294
|
-
# }
|
295
|
-
#
|
296
|
-
# message Forward {
|
297
|
-
# 1: string tag
|
298
|
-
# 2: list<Entry> entries
|
299
|
-
# 3: object option (optional)
|
300
|
-
# }
|
301
|
-
#
|
302
|
-
# message PackedForward {
|
303
|
-
# 1: string tag
|
304
|
-
# 2: raw entries # msgpack stream of Entry
|
305
|
-
# 3: object option (optional)
|
306
|
-
# }
|
307
|
-
#
|
308
|
-
# message Message {
|
309
|
-
# 1: string tag
|
310
|
-
# 2: long? time
|
311
|
-
# 3: object record
|
312
|
-
# 4: object option (optional)
|
313
|
-
# }
|
314
|
-
def on_message(msg, chunk_size, peeraddr)
|
256
|
+
def on_message(msg, chunk_size, remote_host)
|
315
257
|
if msg.nil?
|
316
258
|
# for future TCP heartbeat_request
|
317
259
|
return
|
@@ -319,7 +261,7 @@ module Fluent
|
|
319
261
|
|
320
262
|
# TODO: raise an exception if broken chunk is generated by recoverable situation
|
321
263
|
unless msg.is_a?(Array)
|
322
|
-
log.warn "incoming chunk is broken:",
|
264
|
+
log.warn "incoming chunk is broken:", host: remote_host, msg: msg
|
323
265
|
return
|
324
266
|
end
|
325
267
|
|
@@ -327,10 +269,10 @@ module Fluent
|
|
327
269
|
entries = msg[1]
|
328
270
|
|
329
271
|
if @chunk_size_limit && (chunk_size > @chunk_size_limit)
|
330
|
-
log.warn "Input chunk size is larger than 'chunk_size_limit', dropped:", tag: tag,
|
272
|
+
log.warn "Input chunk size is larger than 'chunk_size_limit', dropped:", tag: tag, host: remote_host, limit: @chunk_size_limit, size: chunk_size
|
331
273
|
return
|
332
274
|
elsif @chunk_size_warn_limit && (chunk_size > @chunk_size_warn_limit)
|
333
|
-
log.warn "Input chunk size is larger than 'chunk_size_warn_limit':", tag: tag,
|
275
|
+
log.warn "Input chunk size is larger than 'chunk_size_warn_limit':", tag: tag, host: remote_host, limit: @chunk_size_warn_limit, size: chunk_size
|
334
276
|
end
|
335
277
|
|
336
278
|
case entries
|
@@ -338,28 +280,28 @@ module Fluent
|
|
338
280
|
# PackedForward
|
339
281
|
option = msg[2]
|
340
282
|
size = (option && option['size']) || 0
|
341
|
-
es_class = (option && option['compressed'] == 'gzip') ? CompressedMessagePackEventStream : MessagePackEventStream
|
283
|
+
es_class = (option && option['compressed'] == 'gzip') ? Fluent::CompressedMessagePackEventStream : Fluent::MessagePackEventStream
|
342
284
|
es = es_class.new(entries, nil, size.to_i)
|
343
|
-
es = check_and_skip_invalid_event(tag, es,
|
344
|
-
es = add_source_host(es,
|
285
|
+
es = check_and_skip_invalid_event(tag, es, remote_host) if @skip_invalid_event
|
286
|
+
es = add_source_host(es, remote_host) if @source_hostname_key
|
345
287
|
router.emit_stream(tag, es)
|
346
288
|
|
347
289
|
when Array
|
348
290
|
# Forward
|
349
291
|
es = if @skip_invalid_event
|
350
|
-
check_and_skip_invalid_event(tag, entries,
|
292
|
+
check_and_skip_invalid_event(tag, entries, remote_host)
|
351
293
|
else
|
352
|
-
es = MultiEventStream.new
|
294
|
+
es = Fluent::MultiEventStream.new
|
353
295
|
entries.each { |e|
|
354
296
|
record = e[1]
|
355
297
|
next if record.nil?
|
356
298
|
time = e[0]
|
357
|
-
time =
|
299
|
+
time = Fluent::Engine.now if time.nil? || time.to_i == 0 # `to_i == 0` for empty EventTime
|
358
300
|
es.add(time, record)
|
359
301
|
}
|
360
302
|
es
|
361
303
|
end
|
362
|
-
es = add_source_host(es,
|
304
|
+
es = add_source_host(es, remote_host) if @source_hostname_key
|
363
305
|
router.emit_stream(tag, es)
|
364
306
|
option = msg[2]
|
365
307
|
|
@@ -368,12 +310,12 @@ module Fluent
|
|
368
310
|
time = msg[1]
|
369
311
|
record = msg[2]
|
370
312
|
if @skip_invalid_event && invalid_event?(tag, time, record)
|
371
|
-
log.warn "got invalid event and drop it:",
|
313
|
+
log.warn "got invalid event and drop it:", host: remote_host, tag: tag, time: time, record: record
|
372
314
|
return msg[3] # retry never succeeded so return ack and drop incoming event.
|
373
315
|
end
|
374
316
|
return if record.nil?
|
375
|
-
time = Engine.now if time.to_i == 0
|
376
|
-
record[@source_hostname_key] =
|
317
|
+
time = Fluent::Engine.now if time.to_i == 0
|
318
|
+
record[@source_hostname_key] = remote_host if @source_hostname_key
|
377
319
|
router.emit(tag, time, record)
|
378
320
|
option = msg[3]
|
379
321
|
end
|
@@ -386,11 +328,11 @@ module Fluent
|
|
386
328
|
!((time.is_a?(Integer) || time.is_a?(::Fluent::EventTime)) && record.is_a?(Hash) && tag.is_a?(String))
|
387
329
|
end
|
388
330
|
|
389
|
-
def check_and_skip_invalid_event(tag, es,
|
390
|
-
new_es = MultiEventStream.new
|
331
|
+
def check_and_skip_invalid_event(tag, es, remote_host)
|
332
|
+
new_es = Fluent::MultiEventStream.new
|
391
333
|
es.each { |time, record|
|
392
334
|
if invalid_event?(tag, time, record)
|
393
|
-
log.warn "skip invalid event:",
|
335
|
+
log.warn "skip invalid event:", host: remote_host, tag: tag, time: time, record: record
|
394
336
|
next
|
395
337
|
end
|
396
338
|
new_es.add(time, record)
|
@@ -399,7 +341,7 @@ module Fluent
|
|
399
341
|
end
|
400
342
|
|
401
343
|
def add_source_host(es, host)
|
402
|
-
new_es = MultiEventStream.new
|
344
|
+
new_es = Fluent::MultiEventStream.new
|
403
345
|
es.each { |time, record|
|
404
346
|
record[@source_hostname_key] = host
|
405
347
|
new_es.add(time, record)
|
@@ -407,11 +349,6 @@ module Fluent
|
|
407
349
|
new_es
|
408
350
|
end
|
409
351
|
|
410
|
-
def source_message(peeraddr)
|
411
|
-
_, port, host, addr = peeraddr
|
412
|
-
"host: #{host}, addr: #{addr}, port: #{port}"
|
413
|
-
end
|
414
|
-
|
415
352
|
def select_authenticate_users(node, username)
|
416
353
|
if node.nil? || node[:users].empty?
|
417
354
|
@security.users.select{|u| u.username == username}
|
@@ -430,33 +367,6 @@ module Fluent
|
|
430
367
|
['HELO', {'nonce' => nonce, 'auth' => (@security ? user_auth_salt : ''), 'keepalive' => !@deny_keepalive}]
|
431
368
|
end
|
432
369
|
|
433
|
-
##### Authentication Handshake
|
434
|
-
#
|
435
|
-
# 1. (client) connect to server
|
436
|
-
# * Socket handshake, checks certificate and its significate (in client, if using SSL)
|
437
|
-
# 2. (server)
|
438
|
-
# * check network/domain acl (if enabled)
|
439
|
-
# * disconnect when failed
|
440
|
-
# 3. (server) send HELO
|
441
|
-
# * ['HELO', options(hash)]
|
442
|
-
# * options:
|
443
|
-
# * nonce: string (required)
|
444
|
-
# * auth: string or blank_string (string: authentication required, and its salt is this value)
|
445
|
-
# 4. (client) send PING
|
446
|
-
# * ['PING', selfhostname, sharedkey_salt, sha512_hex(sharedkey_salt + selfhostname + nonce + sharedkey), username || '', sha512_hex(auth_salt + username + password) || '']
|
447
|
-
# 5. (server) check PING
|
448
|
-
# * check sharedkey
|
449
|
-
# * check username / password (if required)
|
450
|
-
# * send PONG FAILURE if failed
|
451
|
-
# * ['PONG', false, 'reason of authentication failure', '', '']
|
452
|
-
# 6. (server) send PONG
|
453
|
-
# * ['PONG', bool(authentication result), 'reason if authentication failed', selfhostname, sha512_hex(salt + selfhostname + nonce + sharedkey)]
|
454
|
-
# 7. (client) check PONG
|
455
|
-
# * check sharedkey
|
456
|
-
# * disconnect when failed
|
457
|
-
# 8. connection established
|
458
|
-
# * send data from client
|
459
|
-
|
460
370
|
def check_ping(message, remote_addr, user_auth_salt, nonce)
|
461
371
|
log.debug "checking ping"
|
462
372
|
# ['PING', self_hostname, shared_key_salt, sha512_hex(shared_key_salt + self_hostname + nonce + shared_key), username || '', sha512_hex(auth_salt + username + password) || '']
|
@@ -504,114 +414,5 @@ module Fluent
|
|
504
414
|
shared_key_digest_hex = Digest::SHA512.new.update(reason_or_salt).update(@security.self_hostname).update(nonce).update(shared_key).hexdigest
|
505
415
|
['PONG', true, '', @security.self_hostname, shared_key_digest_hex]
|
506
416
|
end
|
507
|
-
|
508
|
-
class Handler < Coolio::Socket
|
509
|
-
attr_reader :protocol, :remote_port, :remote_addr, :remote_host
|
510
|
-
|
511
|
-
PEERADDR_FAILED = ["?", "?", "name resolusion failed", "?"]
|
512
|
-
|
513
|
-
def initialize(io, linger_timeout, log, on_connect_callback)
|
514
|
-
super(io)
|
515
|
-
|
516
|
-
@peeraddr = nil
|
517
|
-
if io.is_a?(TCPSocket) # for unix domain socket support in the future
|
518
|
-
@peeraddr = (io.peeraddr rescue PEERADDR_FAILED)
|
519
|
-
opt = [1, linger_timeout].pack('I!I!') # { int l_onoff; int l_linger; }
|
520
|
-
io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
|
521
|
-
end
|
522
|
-
|
523
|
-
### TODO: disabling name rev resolv
|
524
|
-
proto, port, host, addr = ( io.peeraddr rescue PEERADDR_FAILED )
|
525
|
-
if addr == '?'
|
526
|
-
port, addr = *Socket.unpack_sockaddr_in(io.getpeername) rescue nil
|
527
|
-
end
|
528
|
-
@protocol = proto
|
529
|
-
@remote_port = port
|
530
|
-
@remote_addr = addr
|
531
|
-
@remote_host = host
|
532
|
-
@writing = false
|
533
|
-
@closing = false
|
534
|
-
@mutex = Mutex.new
|
535
|
-
|
536
|
-
@chunk_counter = 0
|
537
|
-
@on_connect_callback = on_connect_callback
|
538
|
-
@log = log
|
539
|
-
@log.trace {
|
540
|
-
begin
|
541
|
-
remote_port, remote_addr = *Socket.unpack_sockaddr_in(@_io.getpeername)
|
542
|
-
rescue
|
543
|
-
remote_port = nil
|
544
|
-
remote_addr = nil
|
545
|
-
end
|
546
|
-
[ "accepted fluent socket", {address: remote_addr, port: remote_port, instance: self.object_id} ]
|
547
|
-
}
|
548
|
-
end
|
549
|
-
|
550
|
-
def on_connect
|
551
|
-
@on_connect_callback.call(self)
|
552
|
-
end
|
553
|
-
|
554
|
-
# API to register callback for data arrival
|
555
|
-
def on_data(&callback)
|
556
|
-
@on_read_callback = callback
|
557
|
-
end
|
558
|
-
|
559
|
-
def on_read(data)
|
560
|
-
@on_read_callback.call(data)
|
561
|
-
rescue => e
|
562
|
-
@log.error "unexpected error on reading data from client", address: @remote_addr, error: e
|
563
|
-
@log.error_backtrace
|
564
|
-
close
|
565
|
-
end
|
566
|
-
|
567
|
-
def on_write_complete
|
568
|
-
closing = @mutex.synchronize {
|
569
|
-
@writing = false
|
570
|
-
@closing
|
571
|
-
}
|
572
|
-
if closing
|
573
|
-
close
|
574
|
-
end
|
575
|
-
end
|
576
|
-
|
577
|
-
def close
|
578
|
-
writing = @mutex.synchronize {
|
579
|
-
@closing = true
|
580
|
-
@writing
|
581
|
-
}
|
582
|
-
unless writing
|
583
|
-
super
|
584
|
-
end
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
class HeartbeatRequestHandler < Coolio::IO
|
589
|
-
def initialize(io, callback)
|
590
|
-
super(io)
|
591
|
-
@io = io
|
592
|
-
@callback = callback
|
593
|
-
end
|
594
|
-
|
595
|
-
def on_readable
|
596
|
-
begin
|
597
|
-
msg, addr = @io.recvfrom(1024)
|
598
|
-
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
|
599
|
-
return
|
600
|
-
end
|
601
|
-
host = addr[3]
|
602
|
-
port = addr[1]
|
603
|
-
@callback.call(host, port, msg)
|
604
|
-
rescue
|
605
|
-
# TODO log?
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
def on_heartbeat_request(host, port, msg)
|
610
|
-
#log.trace "heartbeat request from #{host}:#{port}"
|
611
|
-
begin
|
612
|
-
@usock.send "\0", 0, host, port
|
613
|
-
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
|
614
|
-
end
|
615
|
-
end
|
616
417
|
end
|
617
418
|
end
|