From 3452fa3a82e81df9b723325a6583cac0c8d41b1b Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:11:58 +0100 Subject: [PATCH 1/6] Adapt license --- LICENSE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b9dd1f4..4938430 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2017-2021, Mike Blumtritt. All rights reserved. +Copyright (c) 2017-2025, Mike Blumtritt. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -26,3 +26,4 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + From aea89e1729b1018cc0843152bad4ea2cc9b3bcb0 Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:12:47 +0100 Subject: [PATCH 2/6] Remove deprecated error constants --- lib/tcp-client/errors.rb | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/tcp-client/errors.rb b/lib/tcp-client/errors.rb index fe3346e..2b9f3b7 100644 --- a/lib/tcp-client/errors.rb +++ b/lib/tcp-client/errors.rb @@ -129,19 +129,4 @@ class WriteTimeoutError < TimeoutError # def action = :write end - - NoOpenSSL = NoOpenSSLError # @!visibility private - NoBlockGiven = NoBlockGivenError # @!visibility private - InvalidDeadLine = InvalidDeadLineError # @!visibility private - UnknownAttribute = UnknownAttributeError # @!visibility private - NotAnException = NotAnExceptionError # @!visibility private - NotConnected = NotConnectedError # @!visibility private - deprecate_constant( - :NoOpenSSL, - :NoBlockGiven, - :InvalidDeadLine, - :UnknownAttribute, - :NotAnException, - :NotConnected - ) end From 3b9969bfa571fc0aa6cca651424ef03006d572c1 Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:29:00 +0100 Subject: [PATCH 3/6] Tidy-up --- lib/tcp-client.rb | 36 ++++++++++++++++----------------- lib/tcp-client/address.rb | 9 +++++---- lib/tcp-client/configuration.rb | 3 +-- lib/tcp-client/ssl_socket.rb | 2 ++ spec/lib/tcp-client_spec.rb | 6 +++--- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/tcp-client.rb b/lib/tcp-client.rb index 21e47c8..a2a4305 100644 --- a/lib/tcp-client.rb +++ b/lib/tcp-client.rb @@ -125,7 +125,7 @@ def closed? = @socket.nil? || @socket.closed? def close @socket&.close self - rescue *NETWORK_ERRORS + rescue *@@net_errors self ensure @socket = @deadline = nil @@ -338,26 +338,24 @@ def create_socket(timeout, exception) def stem_errors(except = nil) yield - rescue *NETWORK_ERRORS => e + rescue *@@net_errors => e raise unless @configuration.normalize_network_errors except && e.is_a?(except) ? raise : raise(NetworkError, e) end - NETWORK_ERRORS = - [ - Errno::EADDRNOTAVAIL, - Errno::ECONNABORTED, - Errno::ECONNREFUSED, - Errno::ECONNRESET, - Errno::EHOSTUNREACH, - Errno::EINVAL, - Errno::ENETUNREACH, - Errno::EPIPE, - IOError, - SocketError - ].tap do |errors| - errors << ::OpenSSL::SSL::SSLError if defined?(::OpenSSL::SSL::SSLError) - end - .freeze - private_constant(:NETWORK_ERRORS) + @@net_errors = [ + Errno::EADDRNOTAVAIL, + Errno::ECONNABORTED, + Errno::ECONNREFUSED, + Errno::EHOSTUNREACH, + Errno::ENETUNREACH, + Errno::ECONNRESET, + Errno::EINVAL, + Errno::EPIPE, + Errno::EPERM, + SocketError, + IOError + ] + @@net_errors << ::OpenSSL::SSL::SSLError if defined?(::OpenSSL::SSL::SSLError) + @@net_errors.freeze end diff --git a/lib/tcp-client/address.rb b/lib/tcp-client/address.rb index 24fc314..53e5eaa 100644 --- a/lib/tcp-client/address.rb +++ b/lib/tcp-client/address.rb @@ -100,10 +100,11 @@ def to_s = host.index(':') ? "[#{host}]:#{port}" : "#{host}:#{port}" # @return [Address] itself # def freeze - return super if frozen? - solve - @addrinfo.freeze - @host.freeze + unless frozen? + solve + @addrinfo.freeze + @host.freeze + end super end diff --git a/lib/tcp-client/configuration.rb b/lib/tcp-client/configuration.rb index 551146e..ea5a0bc 100644 --- a/lib/tcp-client/configuration.rb +++ b/lib/tcp-client/configuration.rb @@ -43,7 +43,6 @@ def self.create(options = nil) # def initialize(options = nil) @buffered = @keep_alive = @reverse_lookup = true - self.timeout = @ssl_params = nil @connect_timeout_error = ConnectTimeoutError @read_timeout_error = ReadTimeoutError @write_timeout_error = WriteTimeoutError @@ -107,7 +106,7 @@ def ssl? = @ssl_params ? true : false def ssl_params=(value) @ssl_params = if value.respond_to?(:to_hash) - Hash[value.to_hash] + value.to_hash.dup elsif value.respond_to?(:to_h) value.nil? ? nil : value.to_h.dup else diff --git a/lib/tcp-client/ssl_socket.rb b/lib/tcp-client/ssl_socket.rb index aac266b..7abee2d 100644 --- a/lib/tcp-client/ssl_socket.rb +++ b/lib/tcp-client/ssl_socket.rb @@ -53,6 +53,8 @@ def should_verify?(ssl_params) CONTEXT_CACHE_MODE = ::OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | ::OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE + + private_constant(:CONTEXT_CACHE_MODE) end private_constant(:SSLSocket) diff --git a/spec/lib/tcp-client_spec.rb b/spec/lib/tcp-client_spec.rb index 618799c..d15ca81 100644 --- a/spec/lib/tcp-client_spec.rb +++ b/spec/lib/tcp-client_spec.rb @@ -6,7 +6,7 @@ TCPClient::Configuration.create(buffered: false, reverse_lookup: false) end - describe 'a new instance' do + context 'with a new instance' do subject(:client) { TCPClient.new } it { is_expected.to be_closed } @@ -34,7 +34,7 @@ end end - describe 'a connected instance' do + context 'with a connected instance' do before { allow_any_instance_of(Socket).to receive(:connect) } it { is_expected.not_to be_closed } @@ -75,7 +75,7 @@ end end - describe 'an instance after #connect failed' do + context 'with an instance after #connect failed' do subject(:client) do TCPClient.new.tap do |instance| instance.connect('', configuration) From 79828e255f1fa94722d008f1b6267b9599072e65 Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:29:42 +0100 Subject: [PATCH 4/6] Optimise socket initialisation --- lib/tcp-client/tcp_socket.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/tcp-client/tcp_socket.rb b/lib/tcp-client/tcp_socket.rb index ab1f290..9c7ca17 100644 --- a/lib/tcp-client/tcp_socket.rb +++ b/lib/tcp-client/tcp_socket.rb @@ -9,18 +9,17 @@ class TCPSocket < ::Socket include WithDeadline def initialize(address, configuration, deadline) - super(address.addrinfo.ipv6? ? :INET6 : :INET, :STREAM) + addrinfo = address.addrinfo + super(addrinfo.ipv6? ? :INET6 : :INET, :STREAM) configure(configuration) - connect_to(as_addr_in(address), deadline) + connect_to( + ::Socket.pack_sockaddr_in(addrinfo.ip_port, addrinfo.ip_address), + deadline + ) end private - def as_addr_in(address) - addrinfo = address.addrinfo - ::Socket.pack_sockaddr_in(addrinfo.ip_port, addrinfo.ip_address) - end - def connect_to(addr, deadline) return connect(addr) unless deadline.valid? with_deadline(deadline) { connect_nonblock(addr, exception: false) } From f836f49557249b4627c2dea84b2cfda189ada339 Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:30:36 +0100 Subject: [PATCH 5/6] Optimize socket read with read size hinting --- lib/tcp-client/with_deadline.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tcp-client/with_deadline.rb b/lib/tcp-client/with_deadline.rb index ca2e6ad..cc7ee00 100644 --- a/lib/tcp-client/with_deadline.rb +++ b/lib/tcp-client/with_deadline.rb @@ -6,8 +6,8 @@ def read_with_deadline(nbytes, deadline) deadline.remaining_time return fetch_avail(deadline) if nbytes.nil? @read_buffer ||= ''.b - while @read_buffer.bytesize < nbytes - read = fetch_next(deadline) + while (diff = nbytes - @read_buffer.bytesize) > 0 + read = fetch_next(deadline, diff) read ? @read_buffer << read : (break close) end fetch_slice(nbytes) @@ -57,8 +57,8 @@ def fetch_slice(size) result end - def fetch_next(deadline) - with_deadline(deadline) { read_nonblock(65_536, exception: false) } + def fetch_next(deadline, size = 65_536) + with_deadline(deadline) { read_nonblock(size, exception: false) } end def with_deadline(deadline) From a7bd3cce23c319817d84c076782869f04ddd7023 Mon Sep 17 00:00:00 2001 From: Mike Blumtritt Date: Thu, 20 Mar 2025 09:30:56 +0100 Subject: [PATCH 6/6] Bump version to v1.0.2 --- lib/tcp-client/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tcp-client/version.rb b/lib/tcp-client/version.rb index 610e47d..190ea14 100644 --- a/lib/tcp-client/version.rb +++ b/lib/tcp-client/version.rb @@ -2,5 +2,5 @@ class TCPClient # The current version number. - VERSION = '1.0.1' + VERSION = '1.0.2' end