net_tcp_client 2.0.1 → 2.2.0

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
- SHA1:
3
- metadata.gz: 729fc42e6f4a4480a26a68bbe970d6e7c79c4690
4
- data.tar.gz: 6b9184a059415db496de138d6f54952deb916f91
2
+ SHA256:
3
+ metadata.gz: 0fbfac671a1fd3e322491c53af87893a03aa035f53e86a4f85d6f5ef17d0c216
4
+ data.tar.gz: 46255870a86e694db1f292dc47053b395f7b5381de89cd5b81678ce3aec6487b
5
5
  SHA512:
6
- metadata.gz: 6adaab1f407ef8fd782bb72d0c8fc8dcf42b3de34ae5b5d6b09e4000479ea89a394e8912f24f7c682af3b0493d6f417a557377e53c78ba539516ea0ea648a394
7
- data.tar.gz: b597c576047fa6b7478c89aae82ee10ba0893dc49d3651548a57978f4e7236343eaaddcfeccc7e05b4113c9e77b65f2df0ac05babca3f54362051c75326141c2
6
+ metadata.gz: 90b89947b85fa29a317fa4815305d78f53995fc5bf808783f72b9795b62949eb148355987fa912fb159bfcd6b8e550b06235b1808dca4c36498bfb9ffec03b85
7
+ data.tar.gz: b480781347934dbf2f640e183c7b10e5d2dbd6f05c4e8b12dd7e7754366913168bd3f5e4376f533ddf243c3cac7f9cb5b6e3a5f77e39d80ebd2f3b9792529d3c
data/Rakefile CHANGED
@@ -1,8 +1,5 @@
1
- require 'rake/clean'
2
1
  require 'rake/testtask'
3
-
4
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
5
- require 'net/tcp_client/version'
2
+ require_relative 'lib/net/tcp_client/version'
6
3
 
7
4
  task :gem do
8
5
  system 'gem build net_tcp_client.gemspec'
@@ -15,14 +12,10 @@ task :publish => :gem do
15
12
  system "rm net_tcp_client-#{Net::TCPClient::VERSION}.gem"
16
13
  end
17
14
 
18
- desc 'Run Test Suite'
19
- task :test do
20
- Rake::TestTask.new(:functional) do |t|
21
- t.test_files = FileList['test/*_test.rb']
22
- t.verbose = true
23
- end
24
-
25
- Rake::Task['functional'].invoke
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.pattern = 'test/**/*_test.rb'
17
+ t.verbose = true
18
+ t.warning = true
26
19
  end
27
20
 
28
21
  task :default => :test
@@ -39,8 +39,7 @@ module Net
39
39
 
40
40
  attr_accessor :connect_timeout, :read_timeout, :write_timeout,
41
41
  :connect_retry_count, :connect_retry_interval, :retry_count,
42
- :policy, :close_on_error, :buffered, :ssl, :buffered,
43
- :proxy_server
42
+ :policy, :close_on_error, :buffered, :ssl, :proxy_server, :keepalive
44
43
  attr_reader :servers, :address, :socket, :ssl_handshake_timeout
45
44
 
46
45
  # Supports embedding user supplied data along with this connection
@@ -48,7 +47,7 @@ module Net
48
47
  # Not used or modified by TCPClient
49
48
  attr_accessor :user_data
50
49
 
51
- @@reconnect_on_errors = [
50
+ @reconnect_on_errors = [
52
51
  Errno::ECONNABORTED,
53
52
  Errno::ECONNREFUSED,
54
53
  Errno::ECONNRESET,
@@ -67,7 +66,7 @@ module Net
67
66
  # To add any additional errors to the standard list:
68
67
  # Net::TCPClient.reconnect_on_errors << Errno::EPROTO
69
68
  def self.reconnect_on_errors
70
- @@reconnect_on_errors
69
+ @reconnect_on_errors
71
70
  end
72
71
 
73
72
  # Create a connection, call the supplied block and close the connection on
@@ -129,7 +128,7 @@ module Net
129
128
  # Can be overridden by supplying a timeout in the write call
130
129
  # Default: 60
131
130
  #
132
- # :buffered [Boolean]
131
+ # :buffered [true|false]
133
132
  # Whether to use Nagle's Buffering algorithm (http://en.wikipedia.org/wiki/Nagle's_algorithm)
134
133
  # Recommend disabling for RPC style invocations where we don't want to wait for an
135
134
  # ACK from the server before sending the last partial segment
@@ -139,6 +138,11 @@ module Net
139
138
  # internal buffering.
140
139
  # Default: true
141
140
  #
141
+ # :keepalive [true|false]
142
+ # Makes the OS check connections even when not in use, so that failed connections fail immediately
143
+ # upon use instead of possibly taking considerable time to fail.
144
+ # Default: true
145
+ #
142
146
  # :connect_retry_count [Fixnum]
143
147
  # Number of times to retry connecting when a connection fails
144
148
  # Default: 10
@@ -242,40 +246,33 @@ module Net
242
246
  # verify_mode: OpenSSL::SSL::VERIFY_NONE
243
247
  # }
244
248
  # )
245
- def initialize(parameters={})
246
- params = parameters.dup
247
- @read_timeout = (params.delete(:read_timeout) || 60.0).to_f
248
- @write_timeout = (params.delete(:write_timeout) || 60.0).to_f
249
- @connect_timeout = (params.delete(:connect_timeout) || 10).to_f
250
- buffered = params.delete(:buffered)
251
- @buffered = buffered.nil? ? true : buffered
252
- @connect_retry_count = params.delete(:connect_retry_count) || 10
253
- @retry_count = params.delete(:retry_count) || 3
254
- @connect_retry_interval = (params.delete(:connect_retry_interval) || 0.5).to_f
255
- @on_connect = params.delete(:on_connect)
256
- @proxy_server = params.delete(:proxy_server)
257
- @policy = params.delete(:policy) || :ordered
258
- @close_on_error = params.delete(:close_on_error)
259
- @close_on_error = true if @close_on_error.nil?
260
- if @ssl = params.delete(:ssl)
261
- @ssl = {} if @ssl == true
249
+ def initialize(server: nil, servers: nil,
250
+ policy: :ordered, buffered: true, keepalive: true,
251
+ connect_timeout: 10.0, read_timeout: 60.0, write_timeout: 60.0,
252
+ connect_retry_count: 10, retry_count: 3, connect_retry_interval: 0.5, close_on_error: true,
253
+ on_connect: nil, proxy_server: nil, ssl: nil
254
+ )
255
+ @read_timeout = read_timeout.to_f
256
+ @write_timeout = write_timeout.to_f
257
+ @connect_timeout = connect_timeout.to_f
258
+ @buffered = buffered
259
+ @keepalive = keepalive
260
+ @connect_retry_count = connect_retry_count
261
+ @retry_count = retry_count
262
+ @connect_retry_interval = connect_retry_interval.to_f
263
+ @on_connect = on_connect
264
+ @proxy_server = proxy_server
265
+ @policy = policy
266
+ @close_on_error = close_on_error
267
+ if ssl
268
+ @ssl = ssl == true ? {} : ssl
262
269
  @ssl_handshake_timeout = (@ssl.delete(:handshake_timeout) || @connect_timeout).to_f
263
270
  end
271
+ @servers = [server] if server
272
+ @servers = servers if servers
264
273
 
265
- if server = params.delete(:server)
266
- @servers = [server]
267
- end
268
- if servers = params.delete(:servers)
269
- @servers = servers
270
- end
271
274
  raise(ArgumentError, 'Missing mandatory :server or :servers') unless @servers
272
275
 
273
- if params.delete(:logger)
274
- warn '[Deprecated] :logger option is no longer offered. Add semantic_logger gem to enable logging.' if $VERBOSE
275
- end
276
- raise(ArgumentError, "Invalid options: #{params.inspect}") if params.size > 0
277
-
278
- # Connect to the Server
279
276
  connect
280
277
  end
281
278
 
@@ -345,7 +342,7 @@ module Net
345
342
  #
346
343
  # Note: After a Net::TCPClient::ReadTimeout #read can be called again on
347
344
  # the same socket to read the response later.
348
- # If the application no longers want the connection after a
345
+ # If the application no longer wants the connection after a
349
346
  # Net::TCPClient::ReadTimeout, then the #close method _must_ be called
350
347
  # before calling _connect_ or _retry_on_connection_failure_ to create
351
348
  # a new connection
@@ -378,7 +375,7 @@ module Net
378
375
  # requested number of bytes from the server
379
376
  # Partial data will not be returned
380
377
  # Connection is _not_ closed and #read can be called again later
381
- # to read the respnse from the connection
378
+ # to read the response from the connection
382
379
  #
383
380
  # Parameters
384
381
  # length [Fixnum]
@@ -398,7 +395,7 @@ module Net
398
395
  #
399
396
  # Note: After a Net::TCPClient::ReadTimeout #read can be called again on
400
397
  # the same socket to read the response later.
401
- # If the application no longers want the connection after a
398
+ # If the application no longer wants the connection after a
402
399
  # Net::TCPClient::ReadTimeout, then the #close method _must_ be called
403
400
  # before calling _connect_ or _retry_on_connection_failure_ to create
404
401
  # a new connection
@@ -451,11 +448,11 @@ module Net
451
448
  # client.retry_on_connection_failure do
452
449
  # client.send("SETVALUE:#{count}\n")
453
450
  # end
454
- # # Server returns "SAVED" if the call was successfull
451
+ # # Server returns "SAVED" if the call was successful
455
452
  # result = client.read(20).strip
456
453
  #
457
454
  # Error handling is implemented as follows:
458
- # If a network failure occurrs during the block invocation the block
455
+ # If a network failure occurs during the block invocation the block
459
456
  # will be called again with a new connection to the server.
460
457
  # It will only be retried up to 3 times
461
458
  # The re-connect will independently retry and timeout using all the
@@ -572,10 +569,11 @@ module Net
572
569
  socket.sync = true
573
570
  socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
574
571
  end
572
+ socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) if keepalive
575
573
 
576
574
  socket_connect(socket, address, connect_timeout)
577
575
 
578
- @socket = ssl ? ssl_connect(socket, address, ssl_handshake_timeout) : socket
576
+ @socket = ssl ? ssl_connect(socket, address, ssl_handshake_timeout) : socket
579
577
  @address = address
580
578
 
581
579
  # Invoke user supplied Block every time a new connection has been established
@@ -612,8 +610,19 @@ module Net
612
610
  socket.write(data)
613
611
  else
614
612
  deadline = Time.now.utc + timeout
613
+ length = data.bytesize
614
+ total_count = 0
615
615
  non_blocking(socket, deadline) do
616
- socket.write_nonblock(data)
616
+ loop do
617
+ begin
618
+ count = socket.write_nonblock(data)
619
+ rescue Errno::EWOULDBLOCK
620
+ retry
621
+ end
622
+ total_count += count
623
+ return total_count if total_count >= length
624
+ data = data.byteslice(count..-1)
625
+ end
617
626
  end
618
627
  end
619
628
  rescue NonBlockingTimeout
@@ -682,6 +691,7 @@ module Net
682
691
  ssl_context.set_params(ssl.is_a?(Hash) ? ssl : {})
683
692
 
684
693
  ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
694
+ ssl_socket.hostname = address.host_name
685
695
  ssl_socket.sync_close = true
686
696
 
687
697
  begin
@@ -712,12 +722,19 @@ module Net
712
722
  # Raises Net::TCPClient::ConnectionFailure if the peer certificate does not match its hostname
713
723
  def ssl_verify(ssl_socket, address)
714
724
  unless OpenSSL::SSL.verify_certificate_identity(ssl_socket.peer_cert, address.host_name)
725
+ domains = extract_domains_from_cert(ssl_socket.peer_cert)
715
726
  ssl_socket.close
716
- message = "#connect SSL handshake failed due to a hostname mismatch with '#{address.to_s}'"
727
+ message = "#connect SSL handshake failed due to a hostname mismatch. Request address was: '#{address.to_s}'" +
728
+ " Certificate valid for hostnames: #{domains.map { |d| "'#{d}'"}.join(',')}"
717
729
  logger.error message if respond_to?(:logger)
718
730
  raise ConnectionFailure.new(message, address.to_s)
719
731
  end
720
732
  end
721
733
 
734
+ def extract_domains_from_cert(cert)
735
+ cert.subject.to_a.each{|oid, value|
736
+ return [value] if oid == "CN"
737
+ }
738
+ end
722
739
  end
723
740
  end
@@ -1,5 +1,5 @@
1
1
  module Net
2
2
  class TCPClient #:nodoc
3
- VERSION = '2.0.1'
3
+ VERSION = '2.2.0'.freeze
4
4
  end
5
5
  end
@@ -17,14 +17,13 @@ class Net::TCPClient::Policy::RandomTest < Minitest::Test
17
17
  it 'must return the servers in random order' do
18
18
  servers = %w(localhost:80 127.0.0.1:2000 lvh.me:2100)
19
19
  policy = Net::TCPClient::Policy::Random.new(servers)
20
- count = 0
21
20
 
22
21
  names = []
23
22
  # It is possible the random order is the supplied order.
24
23
  # Keep retrying until the order is different.
25
24
  3.times do
26
25
  policy.each { |address| names << address.host_name }
27
- break if names != %w(localhost:80 127.0.0.1:2000 lvh.me:2100)
26
+ break if names != %w(localhost 127.0.0.1 lvh.me)
28
27
  names = []
29
28
  end
30
29
 
@@ -8,15 +8,15 @@ require 'semantic_logger'
8
8
  def read_bson_document(io)
9
9
  bytebuf = BSON::ByteBuffer.new
10
10
  # Read 4 byte size of following BSON document
11
- bytes = io.read(4)
11
+ bytes = io.read(4)
12
12
  return unless bytes
13
13
  # Read BSON document
14
14
  sz = bytes.unpack("V")[0]
15
- bytebuf.append!(bytes)
16
- bytes = io.read(sz-4)
15
+ bytebuf.put_bytes(bytes)
16
+ bytes = io.read(sz - 4)
17
17
  return unless bytes
18
- bytebuf.append!(bytes)
19
- return BSON.deserialize(bytebuf)
18
+ bytebuf.put_bytes(bytes)
19
+ return Hash.from_bson(bytebuf)
20
20
  end
21
21
 
22
22
  def ssl_file_path(name)
@@ -41,18 +41,38 @@ class SimpleTCPServer
41
41
  tcp_server = TCPServer.open(port)
42
42
 
43
43
  if ssl
44
- context = OpenSSL::SSL::SSLContext.new
45
- context.set_params(ssl)
44
+ context = OpenSSL::SSL::SSLContext.new.tap do |context|
45
+ context.set_params(ssl)
46
+ context.servername_cb = proc {|socket, name|
47
+ if name == 'localhost'
48
+ OpenSSL::SSL::SSLContext.new.tap do |new_context|
49
+ new_context.cert = OpenSSL::X509::Certificate.new(File.open(ssl_file_path('localhost-server.pem')))
50
+ new_context.key = OpenSSL::PKey::RSA.new(File.open(ssl_file_path('localhost-server-key.pem')))
51
+ new_context.ca_file = ssl_file_path('ca.pem')
52
+ end
53
+ else
54
+ OpenSSL::SSL::SSLContext.new.tap do |new_context|
55
+ new_context.cert = OpenSSL::X509::Certificate.new(File.open(ssl_file_path('no-sni.pem')))
56
+ new_context.key = OpenSSL::PKey::RSA.new(File.open(ssl_file_path('no-sni-key.pem')))
57
+ new_context.ca_file = ssl_file_path('ca.pem')
58
+ end
59
+ end
60
+ }
61
+ end
46
62
  tcp_server = OpenSSL::SSL::SSLServer.new(tcp_server, context)
47
63
  end
48
64
 
49
65
  self.server = tcp_server
50
66
  self.thread = Thread.new do
51
- loop do
52
- logger.debug 'Waiting for a client to connect'
53
-
54
- # Wait for a client to connect
55
- on_request(server.accept)
67
+ begin
68
+ loop do
69
+ logger.debug 'Waiting for a client to connect'
70
+
71
+ # Wait for a client to connect
72
+ on_request(server.accept)
73
+ end
74
+ rescue IOError, Errno::EBADF => exc
75
+ logger.info('Thread terminated', exc)
56
76
  end
57
77
  end
58
78
  end
@@ -103,7 +123,7 @@ class SimpleTCPServer
103
123
  if reply = on_message(request)
104
124
  logger.debug 'Sending Reply'
105
125
  logger.trace 'Reply', reply
106
- client.print(BSON.serialize(reply))
126
+ client.print(reply.to_bson)
107
127
  else
108
128
  logger.debug 'Closing client since no reply is being sent back'
109
129
  server.close
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEA2kw7kGhFXbi4KG4L7G5m0cUbbGYK98Y7A2v1h6HMM57qdN1+
3
+ obz3RzFJRWV2xmzQ6uNBdJU8tkVDnvNOAwusHkTVMwUpgV+TK94U93NtVMl1Q9ah
4
+ sGEe2s+JzMucHnGwLMDKKp9C8n3ILcpVaviQUgOqqc1JbO3IcaRUgm7RbN5BStrX
5
+ 9IPe5N06VLhOjdoKjb1MtZ6HfP6y3oAo1WnkY/BI7Vs7T52sqlWPtLYvUEq91riy
6
+ ZUgdlcSi4vEGuT/r7IU52xtnjrPxfqcrZJHULjyylCRqrXCUU61umEIksQWtHYEH
7
+ Q2j+lvI+fX+m4g1bwCmZyyX9wJr3a7db6+9XgwIDAQABAoIBAG1KW0vaGFhqwbBk
8
+ IA4X29xL7YXgtL8F/MeixkNIav6xIjquJdb9z2NSNpfKy6NeGV5vtnaSvNmYZdlv
9
+ gHAf6OUimwa3H+eInRsKTb7xiBw53D7BdyPiC9uKqjfg/GF1k7lkMBMUtyTGenEK
10
+ aqdqmH6nHUtz3r3tcjwLBNBkgO8ajgy+Tld9XBmgbUYMJCYblS/1ZVl1dh4L9qOi
11
+ yjHhTZ87X+0pVujWzspw/lgt00S+AIBMWLkYhSaW11LgXsR7837ps9F62fNHfArY
12
+ 0Zad7LtzjSNqJJ/lNYxyip3fo3UcrpCuhuIKOudNC1FGgmUdKQlMpOBT1E71yvEX
13
+ W9BWA8ECgYEA8+nR7cGo9kDu72CgxGSwmU8DFhPD1ArzdUBElhaWd2vA4lsjlLNv
14
+ 0lS0UVLDb6Nd3fWZxJEftp89xx/j1PcPVlMPcg3/yrOrfx7K6o7cz3Ji49j+6kgo
15
+ eZ6fhnGtNQ0oZ8BHyNp59lVmFJpZJPOAmMGk6YqzcIa3LX87IK5aE6ECgYEA5R12
16
+ 5xRPxDQyxiXCBn7lLZZfmnScR0NewjB/lDz8DFGVX/9adMaQLgsCvg62XxA+99B6
17
+ 0upQeQI+8BjJAWC74tfIcpFgVuhFIVhrB//tzvUp/J3MzB3EdgsO1bXyQ6AmPX8j
18
+ qod6i4BlJ8E6P/V3U+Tr7TgF+G5L+x4w7rnl2KMCgYBCyIqKJrQ0eKLzN+nM3CTe
19
+ VRvrN44uyLDQMcCVt6mLGR2+3GVpmZfMZxTYD2kjb/+LfmuTvoiIYCFyG/Etple0
20
+ sxlPiTW4MmmKbMvyXRtoUVFyQT/KtecfJadYEFf0Zp3himwdOnSaVdeVXI176JAV
21
+ Qy/8IdXvwXL2KhfuYs6XAQKBgQDQg2w/CaE+szKyWpKmTr5MKtp/OzkvMgT/Phwd
22
+ 0RKiM216nG66cCuve53XUpRvF932sunVIiJyvrSA1k24z0yvOirW+a9v6JthqZJf
23
+ CXBoNX8sxIAqE71EoPOzU49UNGAY/6h5/ips40EsWRKmOsOKuoBst9vXKKpFtEhc
24
+ OxsPeQKBgBqkylA/tOaiWivaL9JTEgPkqOBu1GsuPihT7UnCqVCrRmWysrXXjbUp
25
+ C+AlxkRmKIgHhGPyCdVxWW7RB8JZ1mHbuxeRU5Es9v/yLLRyEuCgPuFx3Odi7sLv
26
+ SGHEzK5lu4MlZIkonsEJwti/FFguGQpktrH8ltpE7wdw7Ik+zb4z
27
+ -----END RSA PRIVATE KEY-----
@@ -1,19 +1,19 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIDCzCCAfOgAwIBAgIJANF9v1dJ6jhOMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
3
- BAMMEXRlc3QtdG1nYXJkbmVyLWNhMB4XDTE1MTEwNjA0NDk0NVoXDTE1MTIwNjA0
4
- NDk0NVowHDEaMBgGA1UEAwwRdGVzdC10bWdhcmRuZXItY2EwggEiMA0GCSqGSIb3
5
- DQEBAQUAA4IBDwAwggEKAoIBAQDIi3qxxegV2RYl8lEWu/iwb9tqsdEYQ1gAhdAS
6
- OJAJk8SfgvjlKnyx0rV2LXhORpp13uLMB5QKXS1B+JByCYEZrC3q9b9Cl58Nl4am
7
- ky6uI/AXvbEvzSAo2resea5JGpQDxl3UJC674QdVCGR7s7Wm7am/JEr8aami4V5O
8
- +CmLfdr030jPaNVcqVS2Bf0AqrxNa3nWoHsPh1MG2VJRVpnqIuqPVL7yRi39/cu2
9
- Kd1WjJPxpbrM8H2AClX2OY6fxa3RHUUyOaveOkX5AWYXtqoMs9Evv95m4hOVAogd
10
- KzBjdtpTiIM+bdlpxY0y2Dpc9oibRFiLFqooB9Bb8VsmE/2JAgMBAAGjUDBOMB0G
11
- A1UdDgQWBBQo+GvUH8j+YFYkWtwQl32d4fVoZTAfBgNVHSMEGDAWgBQo+GvUH8j+
12
- YFYkWtwQl32d4fVoZTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAH
13
- RvaXH9dN3fiRvMZ8+tXY7W57jspvYtQJjNxcVGU+Pn5fznrr0E3STPoSKy6+u9rQ
14
- L0Jzq9e0tjbMmdbMugRjSOdVUGtXaki/YaGNkbKOsMLHWSgFHVZF3gJ83KdDuuFK
15
- bMTqOmrQvCG+JECH3i/lh5GHLuZlCzOmBwhzWuorjQQy/MUxQHRkHPVk4Ik7pCXm
16
- HsNcp9l2L5oKG8I4X54ElGXHoshdIXKUS6yKcnTJlhI2nt6cQCMzKoiVA5TxNnvz
17
- jdCID4nezuHFyYI3KVxsR7PzqS2fmHcfC9qGqskn+QgJ4JcwvAhT3USj4muuu3mJ
18
- /F9cJiBN2yeRQuknI6de
2
+ MIIDFjCCAf4CCQD/szfmoKirZDANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJV
3
+ UzERMA8GA1UECAwITmVicmFza2ExDjAMBgNVBAcMBU9tYWhhMRowGAYDVQQKDBFu
4
+ ZXRfdGNwX2NsaWVudF9jYTAgFw0xOTAxMDkxNTE4NDRaGA8yMTE4MTIxNjE1MTg0
5
+ NFowTDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5lYnJhc2thMQ4wDAYDVQQHDAVP
6
+ bWFoYTEaMBgGA1UECgwRbmV0X3RjcF9jbGllbnRfY2EwggEiMA0GCSqGSIb3DQEB
7
+ AQUAA4IBDwAwggEKAoIBAQDaTDuQaEVduLgobgvsbmbRxRtsZgr3xjsDa/WHocwz
8
+ nup03X6hvPdHMUlFZXbGbNDq40F0lTy2RUOe804DC6weRNUzBSmBX5Mr3hT3c21U
9
+ yXVD1qGwYR7az4nMy5wecbAswMoqn0LyfcgtylVq+JBSA6qpzUls7chxpFSCbtFs
10
+ 3kFK2tf0g97k3TpUuE6N2gqNvUy1nod8/rLegCjVaeRj8EjtWztPnayqVY+0ti9Q
11
+ Sr3WuLJlSB2VxKLi8Qa5P+vshTnbG2eOs/F+pytkkdQuPLKUJGqtcJRTrW6YQiSx
12
+ Ba0dgQdDaP6W8j59f6biDVvAKZnLJf3Amvdrt1vr71eDAgMBAAEwDQYJKoZIhvcN
13
+ AQELBQADggEBAHSf+IOhDgw64nUuXZYVIK4TQDzqIpnZ8+djkvfqck+WcQmXQ5Vj
14
+ G4/8kXgghpA3N63XARb0QOpHk4yvPZKCx+k4xCUbbsvZClAS0ZMQlHpJKLF0xSiA
15
+ J9KaOj7HR5044To/McIHllQ812miWqmLtq6eaCxxzNILjzs1fVh4OXHM1ZbCyJGt
16
+ 8ekvy1GFNoJFaNvcUvPLFi+PmfArpooVRhON1aeMgk8+pgOJNCakKv7/+QFKPxPC
17
+ dWBVr/roSf9w1UbVEGNTUCbBjHVhlyeRRtMtzIfPfo8O/85Ie+P3JPEfS9hYmdb4
18
+ At7Gd0dMDALWDPxf6OIxT/LU4ryuf0SDmJE=
19
19
  -----END CERTIFICATE-----
@@ -1,27 +1,27 @@
1
1
  -----BEGIN RSA PRIVATE KEY-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- IC2LeF5EwNq7h6X7Har0j+e9h1/TESqvx60ph89AxecjsEqjOBKto5rBMTOaah9M
18
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
27
27
  -----END RSA PRIVATE KEY-----
@@ -1,18 +1,19 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIC+TCCAeGgAwIBAgIJANNH6Xe+/HxXMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
3
- BAMMEXRlc3QtdG1nYXJkbmVyLWNhMB4XDTE1MTEwNjA0NTMwMloXDTE1MTIwNjA0
4
- NTMwMlowKjEoMCYGA1UEAwwfdGVzdC10bWdhcmRuZXItbG9jYWxob3N0LXNlcnZl
5
- cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQHhDyY0ME9dIS4AZfO
6
- edICXgbj+N0fLAzutx9kNkLIDdLC4BtH840fKjY2H+tl8AAzLAhPT8IXmlUjPrER
7
- GxBrvNBtyCAkxT+Rz7qpuroIrmGaQwbWYIkhTNQO0oUk0dIAlqrrEWkfq/yDkRH7
8
- b0HI6niT9IWcWI8eFzvYwbn4kDKRqqj2lEAt3F7+Gg6C2GxwD/lx+BccAGxM/f6g
9
- U3gIjaKy9q7hSXqjB5SjyA7etdtyxZDGfKcZHvIKpoIInih+ePY/FR1EqcKNk28U
10
- iKgKzPD+sA0Ra2YpOmTBCF9d8rnrdl2hTMhyzJJ8odvtLys/bLqed965O3ylCoU7
11
- Sf0CAwEAAaMwMC4wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwFAYDVR0RBA0wC4IJ
12
- bG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4IBAQCR6ruCXgsTyeI+RtnhfVrWlsdF
13
- 69eQHxGeHLd882V7xN4XfIKtfpgMVp7UlXTS/Lgtw08x+2bPiPz8EPgXa0WoYRjg
14
- i5M/4lrK++YPMzIY4o8nJY7jRcwoWGzw3rQemrc4cjj7e9YnNLOSG/pww0ticV4F
15
- +85IjE9rRsO4m/yla+epJTZiqJ0lSnCCaeNyW4/f4bipgA6PfddmteaJFUt+c7wF
16
- N992bWpb8+x0ZXGg5+A6a0NVFMu2856WeVRwMKbNwfXObDYxCdHSOufcv9hsxL4j
17
- fiF/R2ts5QbxYSoG2gnRPYxmyn/fnNen3f1u6iY4f8PVmb+6SOu0DH4sDf49
2
+ MIIDJzCCAg8CCQDRgr9ZEAyEkTANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJV
3
+ UzERMA8GA1UECAwITmVicmFza2ExDjAMBgNVBAcMBU9tYWhhMRowGAYDVQQKDBFu
4
+ ZXRfdGNwX2NsaWVudF9jYTAgFw0xOTAxMDkxNTE5NTRaGA8yMTE4MTIxNjE1MTk1
5
+ NFowXTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5lYnJhc2thMQ4wDAYDVQQHDAVP
6
+ bWFoYTEXMBUGA1UECgwObmV0X3RjcF9jbGllbnQxEjAQBgNVBAMMCWxvY2FsaG9z
7
+ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8k0edkqMK/MjmNbgYG
8
+ r/Va1xem125YeCvmiKPi2ZOqownHL3f2fPp8eBxEeyN2aipxCVQxcICUyDCKyupp
9
+ 6z9eQfJOGk/zeZlnSc8twW4VeqWueyGmXqyVGhWWK8C9H0iV/KOIiec+1kz5KfCf
10
+ kB6rMh8HYuNoHAVuHhzbz3OOvXbMwVF3VeSFstJEcPymBAKs+e3f1ENO5GTYvHf3
11
+ qMHNtPgjWDS9WLnW4fcxDcWvdHFcayJkOpgGlj/F/I2G022MrIc64aeOdzd5Rsrf
12
+ WK2d+OyGCHckUIg+e2RL3fv0bElLDQ9e3CqKsbtZoy/QmVfDHOgD+S5GgCXjYcsz
13
+ qhECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAT8ZE0WCAhkbwKt4csU8eTRaY3iXn
14
+ bEDGaO+q+bVw4KpjmTdf6oIStmrA0v9vxUjB5Ghc8N7F1yQ0mSQ6IgtysFVG3zEp
15
+ EUOwNY4EndOxNsTVhKzN/4GIoMNoogjptevkFMWkVMGOA0a1IqbT6Rga/GbGPF+6
16
+ 16mgoLz8VfbOYn4SytifFR+8EGbeZxKSRtJFUtYg6sX4q9voQGAhfQXXiDDSXxnl
17
+ qug3RxueccvPHvJj3Yn6GyLqVjYyRC9xxildEtKyO932x3wdW/LSnXh8MsfP/EYt
18
+ hcDi0ydRutNYCAW+8ZisZdUnDADlA5PelacsaQTe8m3Nn97b+ASYnwyMSw==
18
19
  -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpQIBAAKCAQEAyLStTQ8EAeW+VtFFWLGjsTU5ChcjRnc1xlD91evX8Rvc5ZsS
3
+ xkbW9zLv30jRjljSmpGZIQR/KRSKLbLfCDfcCCjybOZbu6oTqKFRJ0gb6qKcwIOE
4
+ +ZaP6uulfbDnZiOoYIKALtBkXbepi36V6xBYfMcS+mpnRP0YHmxshX3iPH107YWE
5
+ 2qev+2tRY4Do899d00+bKFThD4tI3rEvmVJKcer87xx9EyC8WLJhWud2+t2J1gea
6
+ ZdpJVNzz3c0ex5vHT1pp6nK+B+H6DuIqT+MyOFuln++q5u6AEOu08tp2sPgTwXtx
7
+ powwauq7FVWAhZSjrlr6VMzMNfLAEBYE6bFA9QIDAQABAoIBAQC1bv8qpeRNgs4p
8
+ 1UwG/a6oRyClCn2M+b7W4+hTNbwj7bgmp6S1MNyq4pUNF9q3/3uC1xPCUTpSfIrc
9
+ /NG5sCVsCvf7kdJjN0BGNG4UQI9b8Fwbe8j9hynah+M2WHEWWC2h8NbHewL/5UOT
10
+ In+L217ijWOOlBl+t/zRo9oGYuHdI0JWKfJca99/Jcqrjhrj1pdViDszbiBjwOLV
11
+ 0qXnhgDEXnjWSXYVNar0lSgh8Rb8wGsgrypyfoXg832oN3C26pugugH/SR7d6oaD
12
+ OY0ySPfsIZi/V2iRkxIJtp6yECf3J4lNBrG2STjcHhZck+HuB/vz5Yk1qQqcfO6X
13
+ ObuYrbKBAoGBAOiw+615kwEFWEuCAtWgZzUMrWViO45HbmLGePOBY/nVX/3kAKrb
14
+ yhjYgMlzH3ITQUkTNdOYtZ0ZudkIfTITJ+bZK2EhXVgTd7Qi5YsI+fyUqfNf2nWK
15
+ mvRtKl12uN5Y7OtVeHrkrrrlN+a1aki+cdH2qSD3MwrtKs+JfKLff9QtAoGBANzP
16
+ eOrmgdFcjFoaJcak0iVNG8kke8stUzrc9lAiUbvZ7F8kQ9DW0rkYuoAbzV+SLQcu
17
+ hrbFf9RQ4AM5VSP4awQjv0Lj5UTgYF4GrHjsauKeEfMY96txmuW5C/3T1mYitLdl
18
+ fs/76S5+oj46/VI2/iIOYxiqLaO9EqEwgP/sQDTpAoGAUHyvgZDU7Xx4zx14d4ZV
19
+ TL9G1xPEf/FrWFVIjwoJl+hbnMmaBX+jBzcUTRo6HU5Vvb4cV0WyRFYat9y82W5Q
20
+ 1gP2glF1JTsOo8uSVKZVOi3+H0XfndrEwJlmFxAy4A4oXTqiQvgJDHKvBGlqCyF8
21
+ 42CLnfCDwlrI/SKUbw4Z/D0CgYEAoTVb22uU5axCz9l9MOzOe+sy2QQo2SprNHNz
22
+ 5QdZUuOEfeW1GThtujNCnhsuMpM/Cpo+Qhwo+nJdSh1Geq94Ohp7HbPShBmoYZ1P
23
+ uC0qz+6FvkzBLUsQwpz6E0PgqMq305lnHyOUl5xeiT56CdcabPTCBpTgI0X73vDR
24
+ jYcHTVkCgYEA1Uj47vC8jV1mBtzIKFfvo4W1tkAm1aSDOApzg0N7JEjvgHbeBqM6
25
+ i8dkJ3PgcqxIQ1np+0QTDVjbLgNqCsribJ/djbPDhH/LW9vPP5uUwm10qa7UOJ09
26
+ Jrc3b7r+ZQHPjr7upj5fUK1Xcs0oY7yHMuc8oLDNcdDIYqxP/RzjcOY=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDQTCCAikCCQDRgr9ZEAyEkjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJV
3
+ UzERMA8GA1UECAwITmVicmFza2ExDjAMBgNVBAcMBU9tYWhhMRowGAYDVQQKDBFu
4
+ ZXRfdGNwX2NsaWVudF9jYTAgFw0xOTAxMDkxNTIwMDhaGA8yMTE4MTIxNjE1MjAw
5
+ OFowdzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5lYnJhc2thMQ4wDAYDVQQHDAVP
6
+ bWFoYTEXMBUGA1UECgwObmV0X3RjcF9jbGllbnQxLDAqBgNVBAMMI25vLWhvc3Ru
7
+ YW1lLXdhcy1naXZlbi1mb3Itc25pbmkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
8
+ AQ8AMIIBCgKCAQEAyLStTQ8EAeW+VtFFWLGjsTU5ChcjRnc1xlD91evX8Rvc5ZsS
9
+ xkbW9zLv30jRjljSmpGZIQR/KRSKLbLfCDfcCCjybOZbu6oTqKFRJ0gb6qKcwIOE
10
+ +ZaP6uulfbDnZiOoYIKALtBkXbepi36V6xBYfMcS+mpnRP0YHmxshX3iPH107YWE
11
+ 2qev+2tRY4Do899d00+bKFThD4tI3rEvmVJKcer87xx9EyC8WLJhWud2+t2J1gea
12
+ ZdpJVNzz3c0ex5vHT1pp6nK+B+H6DuIqT+MyOFuln++q5u6AEOu08tp2sPgTwXtx
13
+ powwauq7FVWAhZSjrlr6VMzMNfLAEBYE6bFA9QIDAQABMA0GCSqGSIb3DQEBBQUA
14
+ A4IBAQB6hpp37TLk0+Pd9+gP/OE/7s9AEfcFSelTJZguDaDO/LqHxEXbokOKcQi5
15
+ g0vGxc/XK7RYdw+eEXzbXazQUTPQ6JAfpH0bVXfTvaFKMefHdcnB0NySnnHl2BfQ
16
+ 5cFjqHQwBV6jVIH0q125rC3F1aczDo5kyLk3UyMenY8zoZt8baacChvSqUXDBiSn
17
+ /04Pof//O3ky2B3DYyunQJZ1mQNs+FJdO5609BmlPvaoZfiFbMxGQcmV4D+0mQm+
18
+ CzxWZ4p8gDPDIO4mzVvDMbrRksg1CdG6WakuX1Vy94pX4JNiJ7e47lvuoWIL6DFp
19
+ 5mWIV72Ra4bU5ybNGZlrxLg/6ueD
20
+ -----END CERTIFICATE-----
@@ -7,46 +7,52 @@ require 'securerandom'
7
7
  class TCPClientTest < Minitest::Test
8
8
  describe Net::TCPClient do
9
9
  [false, true].each do |with_ssl|
10
- describe (with_ssl ? 'ssl' : 'non-ssl') do
10
+ describe (with_ssl ? 'with ssl' : 'without ssl') do
11
11
  describe '#connect' do
12
12
  it 'raises an exception when cannot reach server after 5 retries' do
13
13
  exception = assert_raises Net::TCPClient::ConnectionFailure do
14
- new_net_tcp_client(with_ssl,
14
+ new_net_tcp_client(
15
+ with_ssl,
15
16
  server: 'localhost:3300',
16
17
  connect_retry_interval: 0.1,
17
18
  connect_retry_count: 5
18
19
  )
19
20
  end
20
- assert_match(/Failed to connect to any of localhost:3300 after 5 retries/, exception.message)
21
+ assert_match(/Connection failure connecting to/, exception.message)
21
22
  assert_match Errno::ECONNREFUSED.to_s, exception.cause.class.to_s
22
23
  end
23
24
 
24
25
  it 'times out on connect' do
25
- # Create a TCP Server, but do not respond to connections
26
- server = TCPServer.open(2001)
26
+ unless with_ssl
27
+ skip('When not using SSL it will often connect anyway. Maybe a better way to test non-ssl?')
28
+ end
27
29
 
28
- exception = assert_raises Net::TCPClient::ConnectionFailure do
29
- 1000.times do
30
- new_net_tcp_client(with_ssl,
31
- server: 'localhost:2001',
32
- connect_timeout: 0.5,
33
- connect_retry_count: 3
34
- )
35
- end
30
+ # Create a TCP Server, but do not respond to connections to cause a connect timeout
31
+ server = TCPServer.open(2094)
32
+ sleep 1
33
+
34
+ exception = assert_raises Net::TCPClient::ConnectionTimeout do
35
+ new_net_tcp_client(
36
+ with_ssl,
37
+ server: 'localhost:2094',
38
+ connect_timeout: 0.5,
39
+ connect_retry_count: 3
40
+ )
36
41
  end
37
- assert_match(/Failed to connect to any of localhost:2001 after 3 retries/, exception.message)
42
+ assert_match(/Timed out after 0\.5 seconds/, exception.message)
38
43
  server.close
39
44
  end
40
45
  end
41
46
 
42
47
  describe 'with server' do
43
48
  before do
44
- @port = 2000 + SecureRandom.random_number(1000)
49
+ @port = 2000 + SecureRandom.random_number(1000)
45
50
  options = {port: @port}
46
51
  if with_ssl
47
52
  options[:ssl] = {
48
- cert: OpenSSL::X509::Certificate.new(File.open(ssl_file_path('localhost-server.pem'))),
49
- key: OpenSSL::PKey::RSA.new(File.open(ssl_file_path('localhost-server-key.pem'))),
53
+ # Purposefully serve a cert that doesn't match 'localhost' to force failures unless SNI works.
54
+ cert: OpenSSL::X509::Certificate.new(File.open(ssl_file_path('no-sni.pem'))),
55
+ key: OpenSSL::PKey::RSA.new(File.open(ssl_file_path('no-sni-key.pem'))),
50
56
  ca_file: ssl_file_path('ca.pem')
51
57
  }
52
58
  end
@@ -74,14 +80,15 @@ class TCPClientTest < Minitest::Test
74
80
  it 'read timeout, followed by successful read' do
75
81
  @read_timeout = 3.0
76
82
  # Need a custom client that does not auto close on error:
77
- @client = new_net_tcp_client(with_ssl,
83
+ @client = new_net_tcp_client(
84
+ with_ssl,
78
85
  server: @server_name,
79
86
  read_timeout: @read_timeout,
80
87
  close_on_error: false
81
88
  )
82
89
 
83
90
  request = {'action' => 'sleep', 'duration' => @read_timeout + 0.5}
84
- @client.write(BSON.serialize(request))
91
+ @client.write(request.to_bson)
85
92
 
86
93
  exception = assert_raises Net::TCPClient::ReadTimeout do
87
94
  # Read 4 bytes from server
@@ -96,12 +103,13 @@ class TCPClientTest < Minitest::Test
96
103
  end
97
104
 
98
105
  it 'infinite timeout' do
99
- @client = new_net_tcp_client(with_ssl,
106
+ @client = new_net_tcp_client(
107
+ with_ssl,
100
108
  server: @server_name,
101
109
  connect_timeout: -1
102
110
  )
103
111
  request = {'action' => 'test1'}
104
- @client.write(BSON.serialize(request))
112
+ @client.write(request.to_bson)
105
113
  reply = read_bson_document(@client)
106
114
  assert_equal 'test1', reply['result']
107
115
  @client.close
@@ -110,7 +118,8 @@ class TCPClientTest < Minitest::Test
110
118
 
111
119
  describe '#connect' do
112
120
  it 'calls on_connect after connection' do
113
- @client = new_net_tcp_client(with_ssl,
121
+ @client = new_net_tcp_client(
122
+ with_ssl,
114
123
  server: @server_name,
115
124
  read_timeout: 3,
116
125
  on_connect: Proc.new do |socket|
@@ -122,7 +131,7 @@ class TCPClientTest < Minitest::Test
122
131
  assert_equal 1, @client.user_data[:sequence]
123
132
 
124
133
  request = {'action' => 'test1'}
125
- @client.write(BSON.serialize(request))
134
+ @client.write(request.to_bson)
126
135
  reply = read_bson_document(@client)
127
136
  assert_equal 'test1', reply['result']
128
137
  end
@@ -130,14 +139,15 @@ class TCPClientTest < Minitest::Test
130
139
 
131
140
  describe 'failover' do
132
141
  it 'connects to second server when the first is down' do
133
- @client = new_net_tcp_client(with_ssl,
142
+ @client = new_net_tcp_client(
143
+ with_ssl,
134
144
  servers: ['localhost:1999', @server_name],
135
145
  read_timeout: 3
136
146
  )
137
147
  assert_equal "localhost[127.0.0.1]:#{@port}", @client.address.to_s
138
148
 
139
149
  request = {'action' => 'test1'}
140
- @client.write(BSON.serialize(request))
150
+ @client.write(request.to_bson)
141
151
  reply = read_bson_document(@client)
142
152
  assert_equal 'test1', reply['result']
143
153
  end
@@ -146,7 +156,8 @@ class TCPClientTest < Minitest::Test
146
156
  describe 'with client' do
147
157
  before do
148
158
  @read_timeout = 3.0
149
- @client = new_net_tcp_client(with_ssl,
159
+ @client = new_net_tcp_client(
160
+ with_ssl,
150
161
  server: @server_name,
151
162
  read_timeout: @read_timeout
152
163
  )
@@ -156,6 +167,7 @@ class TCPClientTest < Minitest::Test
156
167
 
157
168
  describe '#alive?' do
158
169
  it 'returns false once the connection is closed' do
170
+ skip "TODO: #alive? hangs with the latest SSL changes" if with_ssl
159
171
  assert @client.alive?
160
172
  @client.close
161
173
  refute @client.alive?
@@ -180,21 +192,21 @@ class TCPClientTest < Minitest::Test
180
192
  describe '#write' do
181
193
  it 'writes data' do
182
194
  request = {'action' => 'test1'}
183
- @client.write(BSON.serialize(request))
195
+ @client.write(request.to_bson)
184
196
  end
185
197
  end
186
198
 
187
199
  describe '#read' do
188
200
  it 'reads a response' do
189
201
  request = {'action' => 'test1'}
190
- @client.write(BSON.serialize(request))
202
+ @client.write(request.to_bson)
191
203
  reply = read_bson_document(@client)
192
204
  assert_equal 'test1', reply['result']
193
205
  end
194
206
 
195
207
  it 'times out on receive' do
196
208
  request = {'action' => 'sleep', 'duration' => @read_timeout + 0.5}
197
- @client.write(BSON.serialize(request))
209
+ @client.write(request.to_bson)
198
210
 
199
211
  exception = assert_raises Net::TCPClient::ReadTimeout do
200
212
  # Read 4 bytes from server
@@ -211,8 +223,8 @@ class TCPClientTest < Minitest::Test
211
223
  it 'retries on connection failure' do
212
224
  attempt = 0
213
225
  reply = @client.retry_on_connection_failure do
214
- request = {'action' => 'fail', 'attempt' => (attempt+=1)}
215
- @client.write(BSON.serialize(request))
226
+ request = {'action' => 'fail', 'attempt' => (attempt += 1)}
227
+ @client.write(request.to_bson)
216
228
  read_bson_document(@client)
217
229
  end
218
230
  assert_equal 'fail', reply['result']
@@ -234,7 +246,7 @@ class TCPClientTest < Minitest::Test
234
246
  params.merge!(
235
247
  ssl: {
236
248
  ca_file: ssl_file_path('ca.pem'),
237
- verify_mode: OpenSSL::SSL::VERIFY_NONE
249
+ verify_mode: OpenSSL::SSL::VERIFY_PEER
238
250
  }
239
251
  )
240
252
  end
@@ -8,7 +8,11 @@ require 'minitest/autorun'
8
8
  require 'minitest/reporters'
9
9
  require 'net/tcp_client'
10
10
 
11
- Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
12
-
13
11
  SemanticLogger.default_level = :trace
14
12
  SemanticLogger.add_appender(file_name: 'test.log', formatter: :color)
13
+
14
+ reporters = [
15
+ Minitest::Reporters::SpecReporter.new,
16
+ # SemanticLogger::Reporters::Minitest.new
17
+ ]
18
+ Minitest::Reporters.use!(reporters)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net_tcp_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-04 00:00:00.000000000 Z
11
+ date: 2019-02-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Net::TCPClient implements resilience features that many developers wish
14
14
  was already included in the standard Ruby libraries.
@@ -36,9 +36,12 @@ files:
36
36
  - test/policy/ordered_policy_test.rb
37
37
  - test/policy/random_policy_test.rb
38
38
  - test/simple_tcp_server.rb
39
+ - test/ssl_files/ca.key
39
40
  - test/ssl_files/ca.pem
40
41
  - test/ssl_files/localhost-server-key.pem
41
42
  - test/ssl_files/localhost-server.pem
43
+ - test/ssl_files/no-sni-key.pem
44
+ - test/ssl_files/no-sni.pem
42
45
  - test/tcp_client_test.rb
43
46
  - test/test_helper.rb
44
47
  homepage: https://github.com/rocketjob/net_tcp_client
@@ -60,20 +63,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
63
  - !ruby/object:Gem::Version
61
64
  version: '0'
62
65
  requirements: []
63
- rubyforge_project:
64
- rubygems_version: 2.5.1
66
+ rubygems_version: 3.0.2
65
67
  signing_key:
66
68
  specification_version: 4
67
69
  summary: Net::TCPClient is a TCP Socket Client with built-in timeouts, retries, and
68
70
  logging
69
71
  test_files:
70
- - test/address_test.rb
71
- - test/policy/custom_policy_test.rb
72
- - test/policy/ordered_policy_test.rb
73
- - test/policy/random_policy_test.rb
74
- - test/simple_tcp_server.rb
75
- - test/ssl_files/ca.pem
76
72
  - test/ssl_files/localhost-server-key.pem
77
73
  - test/ssl_files/localhost-server.pem
78
- - test/tcp_client_test.rb
74
+ - test/ssl_files/ca.pem
75
+ - test/ssl_files/no-sni-key.pem
76
+ - test/ssl_files/ca.key
77
+ - test/ssl_files/no-sni.pem
78
+ - test/simple_tcp_server.rb
79
79
  - test/test_helper.rb
80
+ - test/tcp_client_test.rb
81
+ - test/address_test.rb
82
+ - test/policy/ordered_policy_test.rb
83
+ - test/policy/random_policy_test.rb
84
+ - test/policy/custom_policy_test.rb