logstash-output-tcp 6.1.1 → 6.1.2

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: c907232f3196c96261615180d8c1fc85c7973dc94c31fbd5161bf657f9c32adb
4
- data.tar.gz: 2787199dc0aa9904ae4387a97d7f8add642b8cbd5af37929a263604c0d15c1d1
3
+ metadata.gz: dd2acefd6c26058e3e2afc94abb73de74e2816ca57a6379229909434ad4c72e9
4
+ data.tar.gz: 38633ca4cf74d5360fa3644b9624cb21db997e9cda5ff8846f5ca510b811c133
5
5
  SHA512:
6
- metadata.gz: e0a8adce0cb539e83d1305c5d52931710041d7f4d7b8e42098f141bfca50980f80c39bef88116de710463044b6cfb5a14e0a32d3e32c3058d76990bb5bbd5d3b
7
- data.tar.gz: 754a94a8b98ed57b77390091ed6dc05538d28d6aea75e4e5c30a438c34696fe80f9cb56503ed1a81ee2832fccee347122fbb07afb755ea01d2070c2ce4384b21
6
+ metadata.gz: ef785946ab821ca9347ef5fd04e17909ef573155ce790955640b875582a268363c436c3fa6a6c8c8cc19d086a6a9e6d5b8452448be59fbd80328481a7e0f292e
7
+ data.tar.gz: ac1c3b27079ecb0bb91eaa4a11eea17a1f79d4b6d935e72d82085b34f6731ee2ed6e6240250e4c18429b669d1430875d8ef958aa4c009ae71bb75d3e73f6a414
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 6.1.2
2
+ - Changed the client mode to write using the non-blocking method. [#52](https://github.com/logstash-plugins/logstash-output-tcp/pull/52)
3
+
1
4
  ## 6.1.1
2
5
  - 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
6
 
@@ -200,20 +200,17 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
200
200
  @codec.on_event do |event, payload|
201
201
  begin
202
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
-
208
- # don't expect any reads, but a readable socket might
209
- # mean the remote end closed, so read it and throw it away.
210
- # we'll get an EOFError if it happens.
211
- readable_io.each { |readable| readable.sysread(16384) }
212
- end
213
-
214
203
  while payload && payload.bytesize > 0
215
- written_bytes_size = client_socket.syswrite(payload)
216
- payload = payload.byteslice(written_bytes_size..-1)
204
+ begin
205
+ written_bytes_size = client_socket.write_nonblock(payload)
206
+ payload = payload.byteslice(written_bytes_size..-1)
207
+ rescue IO::WaitReadable
208
+ IO.select([client_socket])
209
+ retry
210
+ rescue IO::WaitWritable
211
+ IO.select(nil, [client_socket])
212
+ retry
213
+ end
217
214
  end
218
215
  rescue => e
219
216
  log_warn "client socket failed:", e, host: @host, port: @port, socket: (client_socket ? client_socket.to_s : nil)
@@ -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.1'
4
+ s.version = '6.1.2'
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"
@@ -108,6 +108,33 @@ describe LogStash::Outputs::Tcp do
108
108
  end
109
109
  end
110
110
 
111
+ context "client mode" do
112
+ before { subject.register }
113
+
114
+ let(:config) { super().merge 'mode' => 'client' }
115
+
116
+ it 'writes payload data' do
117
+ Thread.start { sleep 0.25; subject.receive event }
118
+
119
+ socket = server.accept
120
+ read = socket.sysread(100)
121
+
122
+ expect( read.size ).to be > 0
123
+ expect( read ).to eq(JSON.generate(event))
124
+ end
125
+
126
+ it 'writes payload data in multiple operations' do
127
+ full_payload = JSON.generate(event)
128
+ Thread.start { sleep 0.25; subject.receive event }
129
+
130
+ socket = server.accept
131
+ first_read = socket.sysread((full_payload.length / 2))
132
+ second_read = socket.sysread(((full_payload.length / 2) + 1))
133
+
134
+ expect( "#{first_read}#{second_read}" ).to eq(full_payload)
135
+ end
136
+ end
137
+
111
138
  context "when enabling SSL" do
112
139
  let(:config) { super().merge("ssl_enable" => true, 'codec' => 'plain') }
113
140
  context "and not providing a certificate/key pair" do
@@ -227,5 +254,58 @@ describe LogStash::Outputs::Tcp do
227
254
 
228
255
  end
229
256
  end
257
+
258
+ context "and protocol is TLSv1.3" do
259
+ let(:key_file) { File.join(FIXTURES_PATH, 'plaintext/instance.key') }
260
+ let(:crt_file) { File.join(FIXTURES_PATH, 'plaintext/instance.crt') }
261
+ let(:config) { super().merge("ssl_cert" => crt_file, "ssl_key" => key_file) }
262
+
263
+ let(:secure_server) do
264
+ ssl_context = OpenSSL::SSL::SSLContext.new
265
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
266
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(crt_file))
267
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.read(key_file), nil)
268
+ ssl_context.min_version = OpenSSL::SSL::TLS1_3_VERSION
269
+ OpenSSL::SSL::SSLServer.new(server, ssl_context)
270
+ end
271
+
272
+ before(:each) do
273
+ subject.register
274
+ end
275
+
276
+ after(:each) do
277
+ secure_server.close rescue nil
278
+ end
279
+
280
+ let(:message) { "a" }
281
+ let(:buffer) { "" }
282
+
283
+ # This test confirms that this plugin is able to write to a TLS socket
284
+ # multiple times.
285
+ # Previous implementation performed an IO.select first and called sysread
286
+ # if select signaled the socket was ready to read.
287
+ # For TLS1_3, due to control messages it may happen that the underlying
288
+ # socket is marked as readable but there is no new data available,
289
+ # causing a read to block forever.
290
+ # This test will raise a Timeout exception with the old implementation.
291
+ it 'successfully writes two messages' do
292
+ thread = Thread.start do
293
+ expect {
294
+ client = secure_server.accept
295
+ Timeout::timeout(5) do
296
+ buffer << client.sysread(1) # read first message
297
+ subject.receive(message)
298
+ buffer << client.sysread(1) # read second message
299
+ client.close
300
+ end
301
+ }.to_not raise_error
302
+ end
303
+ sleep 0.1 until thread.status == "sleep" # wait for TCP port to open
304
+ subject.receive(message) # send first message to unblock call to `accept`
305
+ thread.join(2)
306
+
307
+ expect(buffer).to eq(message * 2)
308
+ end
309
+ end
230
310
  end
231
311
  end
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.1
4
+ version: 6.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-21 00:00:00.000000000 Z
11
+ date: 2023-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -171,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubygems_version: 3.1.6
174
+ rubygems_version: 3.2.33
175
175
  signing_key:
176
176
  specification_version: 4
177
177
  summary: Writes events over a TCP socket