net_tcp_client 2.0.1 → 2.2.0

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
- 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
- MIIEogIBAAKCAQEApAeEPJjQwT10hLgBl8550gJeBuP43R8sDO63H2Q2QsgN0sLg
3
- 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
- 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
- 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
- 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
- XaFMyHLMknyh2+0vKz9sup533rk7fKUKhTtJ/QIDAQABAoIBAAnOYTt2L1S+Jc8h
8
- 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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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
- 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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