logstash-output-tcp 6.1.1 → 6.1.2

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 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