logstash-output-tcp 6.1.0 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d30cf25cfbc7e1cc2e72d5e1eb8ab8179d42b31413a549801a012d5e1be7e640
4
- data.tar.gz: 53632382865d4bade1e6d56e9872b1b5db690fd9b866cb4d0952dfa8d1156cee
3
+ metadata.gz: c907232f3196c96261615180d8c1fc85c7973dc94c31fbd5161bf657f9c32adb
4
+ data.tar.gz: 2787199dc0aa9904ae4387a97d7f8add642b8cbd5af37929a263604c0d15c1d1
5
5
  SHA512:
6
- metadata.gz: e48f3511c25df04edb79dfd0425c6a84d18808bce5f8d4910cabe024955e6c16f8b856a8ac7fac01cb7721e7628934101e14e7180497a7c6cc1096169290963e
7
- data.tar.gz: 94758e5adb6be529f4c70715aa0796d1a15bd8d17e91d35c63fdc1b29eccea58c0f36e4c29b0cf911a3691fade34c895922ca9b0384cd3df405f723a97ff642f
6
+ metadata.gz: e0a8adce0cb539e83d1305c5d52931710041d7f4d7b8e42098f141bfca50980f80c39bef88116de710463044b6cfb5a14e0a32d3e32c3058d76990bb5bbd5d3b
7
+ data.tar.gz: 754a94a8b98ed57b77390091ed6dc05538d28d6aea75e4e5c30a438c34696fe80f9cb56503ed1a81ee2832fccee347122fbb07afb755ea01d2070c2ce4384b21
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 6.1.1
2
+ - Fixes an issue where payloads larger than a connection's current TCP window could be silently truncated [#49](https://github.com/logstash-plugins/logstash-output-tcp/pull/49)
3
+
1
4
  ## 6.1.0
2
5
  - Feat: ssl_supported_protocols (TLSv1.3) [#47](https://github.com/logstash-plugins/logstash-output-tcp/pull/47)
3
6
  - Fix: close server and client sockets on plugin close
@@ -56,18 +56,25 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
56
56
 
57
57
  class Client
58
58
 
59
- def initialize(socket, logger)
59
+ ##
60
+ # @param socket [Socket]
61
+ # @param logger_context [#log_warn&#log_error]
62
+ def initialize(socket, logger_context)
60
63
  @socket = socket
61
- @logger = logger
64
+ @logger_context = logger_context
62
65
  @queue = Queue.new
63
66
  end
64
67
 
65
68
  def run
66
69
  loop do
67
70
  begin
68
- @socket.write(@queue.pop)
71
+ remaining_payload = @queue.pop
72
+ while remaining_payload && remaining_payload.bytesize > 0
73
+ written_bytes_size = @socket.write(remaining_payload)
74
+ remaining_payload = remaining_payload.byteslice(written_bytes_size..-1)
75
+ end
69
76
  rescue => e
70
- log_warn 'socket write failed:', e, socket: (@socket ? @socket.to_s : nil)
77
+ @logger_context.log_warn 'socket write failed:', e, socket: (@socket ? @socket.to_s : nil)
71
78
  break
72
79
  end
73
80
  end
@@ -80,7 +87,7 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
80
87
  def close
81
88
  @socket.close
82
89
  rescue => e
83
- log_warn 'socket close failed:', e, socket: (@socket ? @socket.to_s : nil)
90
+ @logger_context.log_warn 'socket close failed:', e, socket: (@socket ? @socket.to_s : nil)
84
91
  end
85
92
  end # class Client
86
93
 
@@ -135,69 +142,85 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
135
142
  require "socket"
136
143
  require "stud/try"
137
144
  @closed = Concurrent::AtomicBoolean.new(false)
145
+ @thread_no = Concurrent::AtomicFixnum.new(0)
138
146
  setup_ssl if @ssl_enable
139
147
 
140
148
  if server?
141
- @logger.info("Starting tcp output listener", :address => "#{@host}:#{@port}")
142
- begin
143
- @server_socket = TCPServer.new(@host, @port)
144
- rescue Errno::EADDRINUSE
145
- @logger.error("Could not start tcp server: Address in use", host: @host, port: @port)
146
- raise
147
- end
148
- if @ssl_enable
149
- @server_socket = OpenSSL::SSL::SSLServer.new(@server_socket, @ssl_context)
150
- end # @ssl_enable
151
- @client_threads = Concurrent::Array.new
152
-
153
- @accept_thread = Thread.new(@server_socket) do |server_socket|
154
- LogStash::Util.set_thread_name("[#{pipeline_id}]|output|tcp|server_accept")
155
- loop do
156
- break if @closed.value
157
- client_socket = server_socket.accept_nonblock exception: false
158
- if client_socket == :wait_readable
159
- IO.select [ server_socket ]
160
- next
161
- end
162
- Thread.start(client_socket) do |client_socket|
163
- # monkeypatch a 'peer' method onto the socket.
164
- client_socket.instance_eval { class << self; include ::LogStash::Util::SocketPeer end }
165
- @logger.debug("accepted connection", client: client_socket.peer, server: "#{@host}:#{@port}")
166
- client = Client.new(client_socket, @logger)
167
- Thread.current[:client] = client
168
- LogStash::Util.set_thread_name("[#{pipeline_id}]|output|tcp|client_socket-#{@client_threads.size}")
169
- @client_threads << Thread.current
170
- client.run unless @closed.value
171
- end
149
+ run_as_server
150
+ else
151
+ run_as_client
152
+ end
153
+ end
154
+
155
+ def run_as_server
156
+ @logger.info("Starting tcp output listener", :address => "#{@host}:#{@port}")
157
+ begin
158
+ @server_socket = TCPServer.new(@host, @port)
159
+ rescue Errno::EADDRINUSE
160
+ @logger.error("Could not start tcp server: Address in use", host: @host, port: @port)
161
+ raise
162
+ end
163
+ if @ssl_enable
164
+ @server_socket = OpenSSL::SSL::SSLServer.new(@server_socket, @ssl_context)
165
+ end # @ssl_enable
166
+ @client_threads = Concurrent::Array.new
167
+
168
+ @accept_thread = Thread.new(@server_socket) do |server_socket|
169
+ LogStash::Util.set_thread_name("[#{pipeline_id}]|output|tcp|server_accept")
170
+ loop do
171
+ break if @closed.value
172
+ client_socket = server_socket.accept_nonblock exception: false
173
+ if client_socket == :wait_readable
174
+ IO.select [ server_socket ]
175
+ next
176
+ end
177
+ Thread.start(client_socket) do |client_socket|
178
+ # monkeypatch a 'peer' method onto the socket.
179
+ client_socket.extend(::LogStash::Util::SocketPeer)
180
+ @logger.debug("accepted connection", client: client_socket.peer, server: "#{@host}:#{@port}")
181
+ client = Client.new(client_socket, self)
182
+ Thread.current[:client] = client
183
+ LogStash::Util.set_thread_name("[#{pipeline_id}]|output|tcp|client_socket-#{@thread_no.increment}")
184
+ @client_threads << Thread.current
185
+ client.run unless @closed.value
172
186
  end
173
187
  end
188
+ end
174
189
 
175
- @codec.on_event do |event, payload|
176
- @client_threads.select!(&:alive?)
177
- @client_threads.each do |client_thread|
178
- client_thread[:client].write(payload)
179
- end
190
+ @codec.on_event do |event, payload|
191
+ @client_threads.select!(&:alive?)
192
+ @client_threads.each do |client_thread|
193
+ client_thread[:client].write(payload)
180
194
  end
181
- else
182
- client_socket = nil
183
- @codec.on_event do |event, payload|
184
- begin
185
- client_socket = connect unless client_socket
186
- r,w,e = IO.select([client_socket], [client_socket], [client_socket], nil)
195
+ end
196
+ end
197
+
198
+ def run_as_client
199
+ client_socket = nil
200
+ @codec.on_event do |event, payload|
201
+ begin
202
+ client_socket = connect unless client_socket
203
+
204
+ writable_io = nil
205
+ while writable_io.nil? || writable_io.any? == false
206
+ readable_io, writable_io, _ = IO.select([client_socket],[client_socket])
207
+
187
208
  # don't expect any reads, but a readable socket might
188
209
  # mean the remote end closed, so read it and throw it away.
189
210
  # we'll get an EOFError if it happens.
190
- client_socket.sysread(16384) if r.any?
211
+ readable_io.each { |readable| readable.sysread(16384) }
212
+ end
191
213
 
192
- # Now send the payload
193
- client_socket.syswrite(payload) if w.any?
194
- rescue => e
195
- log_warn "client socket failed:", e, host: @host, port: @port, socket: (client_socket ? client_socket.to_s : nil)
196
- client_socket.close rescue nil
197
- client_socket = nil
198
- sleep @reconnect_interval
199
- retry
214
+ while payload && payload.bytesize > 0
215
+ written_bytes_size = client_socket.syswrite(payload)
216
+ payload = payload.byteslice(written_bytes_size..-1)
200
217
  end
218
+ rescue => e
219
+ log_warn "client socket failed:", e, host: @host, port: @port, socket: (client_socket ? client_socket.to_s : nil)
220
+ client_socket.close rescue nil
221
+ client_socket = nil
222
+ sleep @reconnect_interval
223
+ retry
201
224
  end
202
225
  end
203
226
  end
@@ -219,6 +242,18 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
219
242
  end
220
243
  end
221
244
 
245
+ def log_warn(msg, e, backtrace: @logger.debug?, **details)
246
+ details = details.merge message: e.message, exception: e.class
247
+ details[:backtrace] = e.backtrace if backtrace
248
+ @logger.warn(msg, details)
249
+ end
250
+
251
+ def log_error(msg, e, backtrace: @logger.info?, **details)
252
+ details = details.merge message: e.message, exception: e.class
253
+ details[:backtrace] = e.backtrace if backtrace
254
+ @logger.error(msg, details)
255
+ end
256
+
222
257
  private
223
258
 
224
259
  def connect
@@ -235,7 +270,7 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
235
270
  raise
236
271
  end
237
272
  end
238
- client_socket.instance_eval { class << self; include ::LogStash::Util::SocketPeer end }
273
+ client_socket.extend(::LogStash::Util::SocketPeer)
239
274
  @logger.debug("opened connection", :client => client_socket.peer)
240
275
  return client_socket
241
276
  rescue => e
@@ -253,16 +288,4 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
253
288
  execution_context.pipeline_id || 'main'
254
289
  end
255
290
 
256
- def log_warn(msg, e, backtrace: @logger.debug?, **details)
257
- details = details.merge message: e.message, exception: e.class
258
- details[:backtrace] = e.backtrace if backtrace
259
- @logger.warn(msg, details)
260
- end
261
-
262
- def log_error(msg, e, backtrace: @logger.info?, **details)
263
- details = details.merge message: e.message, exception: e.class
264
- details[:backtrace] = e.backtrace if backtrace
265
- @logger.error(msg, details)
266
- end
267
-
268
291
  end # class LogStash::Outputs::Tcp
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-output-tcp'
4
- s.version = '6.1.0'
4
+ s.version = '6.1.1'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Writes events over a TCP socket"
7
7
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-tcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-06 00:00:00.000000000 Z
11
+ date: 2022-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement