tcp-client 0.7.0 → 0.9.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 +4 -4
- data/.gitignore +3 -1
- data/.yardopts +5 -0
- data/README.md +26 -17
- data/gems.rb +2 -1
- data/lib/tcp-client/address.rb +51 -1
- data/lib/tcp-client/configuration.rb +256 -56
- data/lib/tcp-client/default_configuration.rb +36 -2
- data/lib/tcp-client/errors.rb +85 -8
- data/lib/tcp-client/mixin/io_with_deadline.rb +2 -1
- data/lib/tcp-client/ssl_socket.rb +19 -2
- data/lib/tcp-client/version.rb +1 -1
- data/lib/tcp-client.rb +241 -42
- data/rakefile.rb +5 -9
- data/sample/google_ssl.rb +7 -6
- data/spec/helper.rb +12 -0
- data/spec/tcp-client/address_spec.rb +145 -0
- data/spec/tcp-client/configuration_spec.rb +270 -0
- data/spec/tcp-client/default_configuration_spec.rb +22 -0
- data/spec/tcp-client/version_spec.rb +13 -0
- data/spec/tcp_client_spec.rb +596 -0
- data/tcp-client.gemspec +12 -11
- metadata +32 -18
- data/test/helper.rb +0 -41
- data/test/tcp-client/address_test.rb +0 -65
- data/test/tcp-client/configuration_test.rb +0 -141
- data/test/tcp-client/deadline_test.rb +0 -26
- data/test/tcp-client/default_configuration_test.rb +0 -59
- data/test/tcp-client/version_test.rb +0 -9
- data/test/tcp_client_test.rb +0 -184
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d29104bd490679a8fcb517f949e021cd1d2da263f3a60d622790bc2349faffab
|
4
|
+
data.tar.gz: c7ebaf4f9f83eaf68b51bc47bb91fc5be5d446ef3e80b009bc93bca9d3508ef5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e8c282afbefecb35973f7c563cb07782f8dd0e5df760c89d79aa42424784818c5c0e056c40139554642da8b24823aa9fbb7149e0ed7234f40cc51ea5a7a8165
|
7
|
+
data.tar.gz: 2281b62117529f4bbeff55e297b67f8142235772b112d30f9530113e23ab4012242d5eb2fed4e8293a40836455259d37c91403f50714f292ee6e531250e4cc76
|
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
A TCP client implementation with working timeout support.
|
4
4
|
|
5
|
+
- Gem: [rubygems.org](https://rubygems.org/gems/tcp-client)
|
6
|
+
- Source: [github.com](https://github.com/mblumtritt/tcp-client)
|
7
|
+
- Help: [rubydoc.info](https://rubydoc.info/github/mblumtritt/tcp-client/main/index)
|
8
|
+
|
9
|
+
|
5
10
|
## Description
|
6
11
|
|
7
12
|
This Gem implements a TCP client with (optional) SSL support. It is an easy to use, versatile configurable client that can correctly handle time limits. Unlike other implementations, this client respects predefined/configurable time limits for each method (`connect`, `read`, `write`). Deadlines for a sequence of read/write actions can also be monitored.
|
@@ -11,24 +16,28 @@ This Gem implements a TCP client with (optional) SSL support. It is an easy to u
|
|
11
16
|
```ruby
|
12
17
|
require 'tcp-client'
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
# create a configuration:
|
20
|
+
# - don't use internal buffering
|
21
|
+
# - use TLS 1.2 or TLS 1.3
|
22
|
+
cfg = TCPClient::Configuration.create(
|
23
|
+
buffered: false,
|
24
|
+
ssl_params: {min_version: :TLS1_2, max_version: :TLS1_3}
|
25
|
+
)
|
26
|
+
|
27
|
+
# request to Google.com:
|
28
|
+
# - limit all network interactions to 1.5 seconds
|
29
|
+
# - use the Configuration cfg
|
30
|
+
# - send a simple HTTP get request
|
31
|
+
# - read 12 byte: "HTTP/1.1 " + 3 byte HTTP status code
|
32
|
+
TCPClient.with_deadline(1.5, 'www.google.com:443', cfg) do |client|
|
33
|
+
client.write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n") # >= 40
|
34
|
+
client.read(12) # => "HTTP/1.1 200"
|
28
35
|
end
|
29
36
|
```
|
30
37
|
|
31
|
-
|
38
|
+
For more samples see [the samples dir](https://github.com/mblumtritt/tcp-client/tree/main/sample)
|
39
|
+
|
40
|
+
## Installation
|
32
41
|
|
33
42
|
Use [Bundler](http://gembundler.com/) to use TCPClient in your own project:
|
34
43
|
|
@@ -41,13 +50,13 @@ gem 'tcp-client'
|
|
41
50
|
and install it by running Bundler:
|
42
51
|
|
43
52
|
```bash
|
44
|
-
|
53
|
+
bundle
|
45
54
|
```
|
46
55
|
|
47
56
|
To install the gem globally use:
|
48
57
|
|
49
58
|
```bash
|
50
|
-
|
59
|
+
gem install tcp-client
|
51
60
|
```
|
52
61
|
|
53
62
|
After that you need only a single line of code in your project to have all tools on board:
|
data/gems.rb
CHANGED
data/lib/tcp-client/address.rb
CHANGED
@@ -3,9 +3,51 @@
|
|
3
3
|
require 'socket'
|
4
4
|
|
5
5
|
class TCPClient
|
6
|
+
#
|
7
|
+
# The address used by a TCPClient
|
8
|
+
#
|
6
9
|
class Address
|
7
|
-
|
10
|
+
#
|
11
|
+
# @return [String] the host name
|
12
|
+
#
|
13
|
+
attr_reader :hostname
|
8
14
|
|
15
|
+
#
|
16
|
+
# @return [Addrinfo] the address info
|
17
|
+
#
|
18
|
+
attr_reader :addrinfo
|
19
|
+
|
20
|
+
#
|
21
|
+
# Initializes an address
|
22
|
+
# @overload initialize(addr)
|
23
|
+
# The addr can be specified as
|
24
|
+
#
|
25
|
+
# - a valid named address containing the port like "my.host.test:80"
|
26
|
+
# - a valid TCPv4 address like "142.250.181.206:80"
|
27
|
+
# - a valid TCPv6 address like
|
28
|
+
# "[2001:16b8:5093:3500:ad77:abe6:eb88:47b6]:80"
|
29
|
+
#
|
30
|
+
# @example create an Address instance with a host name and port
|
31
|
+
# Address.new('www.google.com:80')
|
32
|
+
#
|
33
|
+
# @param addr [String] address containing host and port name
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# @overload initialize(addrinfo)
|
37
|
+
#
|
38
|
+
# @example create an Address with an Addrinfo
|
39
|
+
# Address.new(Addrinfo.tcp('www.google.com', 'http'))
|
40
|
+
#
|
41
|
+
# @param addrinfo [Addrinfo] containing the addressed host and port
|
42
|
+
#
|
43
|
+
# @overload initialize(port)
|
44
|
+
# Adresses the port on the local machine.
|
45
|
+
#
|
46
|
+
# @example create an Address for localhost on port 80
|
47
|
+
# Address.new(80)
|
48
|
+
#
|
49
|
+
# @param port [Integer] the addressed port
|
50
|
+
#
|
9
51
|
def initialize(addr)
|
10
52
|
case addr
|
11
53
|
when self.class
|
@@ -20,20 +62,28 @@ class TCPClient
|
|
20
62
|
@addrinfo.freeze
|
21
63
|
end
|
22
64
|
|
65
|
+
#
|
66
|
+
# @return [String] text representation of self as "<host>:<port>"
|
67
|
+
#
|
23
68
|
def to_s
|
24
69
|
return "[#{@hostname}]:#{@addrinfo.ip_port}" if @hostname.index(':') # IP6
|
25
70
|
"#{@hostname}:#{@addrinfo.ip_port}"
|
26
71
|
end
|
27
72
|
|
73
|
+
#
|
74
|
+
# @return [Hash] containing the host and port
|
75
|
+
#
|
28
76
|
def to_h
|
29
77
|
{ host: @hostname, port: @addrinfo.ip_port }
|
30
78
|
end
|
31
79
|
|
80
|
+
# @!visibility private
|
32
81
|
def ==(other)
|
33
82
|
to_h == other.to_h
|
34
83
|
end
|
35
84
|
alias eql? ==
|
36
85
|
|
86
|
+
# @!visibility private
|
37
87
|
def equal?(other)
|
38
88
|
self.class == other.class && self == other
|
39
89
|
end
|
@@ -3,126 +3,326 @@
|
|
3
3
|
require_relative 'errors'
|
4
4
|
|
5
5
|
class TCPClient
|
6
|
+
#
|
7
|
+
# A Configuration is used to configure the behavior of a {TCPClient} instance.
|
8
|
+
#
|
9
|
+
# It allows to specify to monitor timeout, how to handle exceptions, if SSL
|
10
|
+
# should be used and to setup the underlying Socket.
|
11
|
+
#
|
6
12
|
class Configuration
|
13
|
+
#
|
14
|
+
# @overload create(options)
|
15
|
+
# Shorthand to create a new configuration with given options.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# config = TCPClient::Configuration.create(buffered: false)
|
19
|
+
#
|
20
|
+
# @param options [Hash] see {#initialize} for details
|
21
|
+
#
|
22
|
+
# @return [Configuration] the initialized configuration
|
23
|
+
#
|
24
|
+
# @overload create(&block)
|
25
|
+
# Shorthand to create a new configuration within a code block.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# config = TCPClient::Configuration.create do |cfg|
|
29
|
+
# cfg.buffered = false
|
30
|
+
# cfg.ssl_params = { min_version: :TLS1_2, max_version: :TLS1_3 }
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @yieldparam configuration {Configuration}
|
34
|
+
#
|
35
|
+
# @return [Configuration] the initialized configuration
|
36
|
+
#
|
7
37
|
def self.create(options = {})
|
8
|
-
|
9
|
-
yield(
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :buffered,
|
14
|
-
:keep_alive,
|
15
|
-
:reverse_lookup,
|
16
|
-
:connect_timeout,
|
17
|
-
:read_timeout,
|
18
|
-
:write_timeout,
|
19
|
-
:connect_timeout_error,
|
20
|
-
:read_timeout_error,
|
21
|
-
:write_timeout_error
|
22
|
-
attr_accessor :ssl_params
|
38
|
+
configuration = new(options)
|
39
|
+
yield(configuration) if block_given?
|
40
|
+
configuration
|
41
|
+
end
|
23
42
|
|
43
|
+
#
|
44
|
+
# Intializes the instance with given options.
|
45
|
+
#
|
46
|
+
# @param options [Hash]
|
47
|
+
# @option options [Boolean] :buffered, see {#buffered}
|
48
|
+
# @option options [Boolean] :keep_alive, see {#keep_alive}
|
49
|
+
# @option options [Boolean] :reverse_lookup, see {#reverse_lookup}
|
50
|
+
# @option options [Hash<Symbol, Object>] :ssl_params, see {#ssl_params}
|
51
|
+
# @option options [Numeric] :connect_timeout, see {#connect_timeout}
|
52
|
+
# @option options [Exception] :connect_timeout_error, see
|
53
|
+
# {#connect_timeout_error}
|
54
|
+
# @option options [Numeric] :read_timeout, see {#read_timeout}
|
55
|
+
# @option options [Exception] :read_timeout_error, see {#read_timeout_error}
|
56
|
+
# @option options [Numeric] :write_timeout, see {#write_timeout}
|
57
|
+
# @option options [Exception] :write_timeout_error, see
|
58
|
+
# {#write_timeout_error}
|
59
|
+
# @option options [Boolean] :normalize_network_errors, see
|
60
|
+
# {#normalize_network_errors}
|
61
|
+
#
|
62
|
+
#
|
24
63
|
def initialize(options = {})
|
25
64
|
@buffered = @keep_alive = @reverse_lookup = true
|
26
65
|
self.timeout = @ssl_params = nil
|
27
66
|
@connect_timeout_error = ConnectTimeoutError
|
28
67
|
@read_timeout_error = ReadTimeoutError
|
29
68
|
@write_timeout_error = WriteTimeoutError
|
69
|
+
@normalize_network_errors = false
|
30
70
|
options.each_pair { |attribute, value| set(attribute, value) }
|
31
71
|
end
|
32
72
|
|
33
|
-
|
34
|
-
|
35
|
-
|
73
|
+
# @!group Instance Attributes Socket Level
|
74
|
+
|
75
|
+
#
|
76
|
+
# Enables/disables use of Socket-level buffering
|
77
|
+
#
|
78
|
+
# @return [true] if the connection is allowed to use internal buffers
|
79
|
+
# (default)
|
80
|
+
# @return [false] if buffering is not allowed
|
81
|
+
#
|
82
|
+
attr_reader :buffered
|
83
|
+
|
84
|
+
def buffered=(value)
|
85
|
+
@buffered = value ? true : false
|
36
86
|
end
|
37
87
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
88
|
+
#
|
89
|
+
# Enables/disables use of Socket-level keep alive handling.
|
90
|
+
#
|
91
|
+
# @return [true] if the connection is allowed to use keep alive signals
|
92
|
+
# (default)
|
93
|
+
# @return [false] if the connection should not check keep alive
|
94
|
+
#
|
95
|
+
attr_reader :keep_alive
|
96
|
+
|
97
|
+
def keep_alive=(value)
|
98
|
+
@keep_alive = value ? true : false
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Enables/disables address lookup.
|
103
|
+
#
|
104
|
+
# @return [true] if the connection is allowed to lookup the address
|
105
|
+
# (default)
|
106
|
+
# @return [false] if the address lookup is not required
|
107
|
+
#
|
108
|
+
attr_reader :reverse_lookup
|
109
|
+
|
110
|
+
def reverse_lookup=(value)
|
111
|
+
@reverse_lookup = value ? true : false
|
42
112
|
end
|
43
113
|
|
114
|
+
#
|
115
|
+
# @!parse attr_reader :ssl?
|
116
|
+
# @return [Boolean] wheter SSL is configured, see {#ssl_params}
|
117
|
+
#
|
44
118
|
def ssl?
|
45
119
|
@ssl_params ? true : false
|
46
120
|
end
|
47
121
|
|
48
|
-
|
122
|
+
#
|
123
|
+
# Parameters used to initialize a SSL context.
|
124
|
+
#
|
125
|
+
# @return [Hash<Symbol, Object>] SSL parameters for the SSL context
|
126
|
+
# @return [nil] if no SSL should be used (default)
|
127
|
+
#
|
128
|
+
attr_reader :ssl_params
|
129
|
+
|
130
|
+
def ssl_params=(value)
|
49
131
|
@ssl_params =
|
50
|
-
if
|
51
|
-
Hash[value]
|
132
|
+
if value.respond_to?(:to_hash)
|
133
|
+
Hash[value.to_hash]
|
134
|
+
elsif value.respond_to?(:to_h)
|
135
|
+
Hash[value.to_h]
|
52
136
|
else
|
53
137
|
value ? {} : nil
|
54
138
|
end
|
55
139
|
end
|
140
|
+
alias ssl= ssl_params=
|
56
141
|
|
57
|
-
|
58
|
-
|
142
|
+
# @!endgroup
|
143
|
+
|
144
|
+
# @!group Instance Attributes Timeout Monitoring
|
145
|
+
|
146
|
+
#
|
147
|
+
# The maximum time in seconds to establish a connection.
|
148
|
+
#
|
149
|
+
# @return [Numeric] maximum time in seconds
|
150
|
+
# @return [nil] if the connect time should not be monitored (default)
|
151
|
+
#
|
152
|
+
# @see TCPClient#connect
|
153
|
+
#
|
154
|
+
attr_reader :connect_timeout
|
155
|
+
|
156
|
+
def connect_timeout=(value)
|
157
|
+
@connect_timeout = seconds(value)
|
59
158
|
end
|
60
159
|
|
61
|
-
|
62
|
-
|
160
|
+
#
|
161
|
+
# The exception class which will be raised if {TCPClient#connect} can not
|
162
|
+
# be finished in time.
|
163
|
+
#
|
164
|
+
# @return [Class] exception class raised
|
165
|
+
# @raise [NotAnExceptionError] if given argument is not an Exception class
|
166
|
+
#
|
167
|
+
attr_reader :connect_timeout_error
|
168
|
+
|
169
|
+
def connect_timeout_error=(value)
|
170
|
+
raise(NotAnExceptionError, value) unless exception_class?(value)
|
171
|
+
@connect_timeout_error = value
|
63
172
|
end
|
64
173
|
|
65
|
-
|
66
|
-
|
174
|
+
#
|
175
|
+
# The maximum time in seconds to read from a connection.
|
176
|
+
#
|
177
|
+
# @return [Numeric] maximum time in seconds
|
178
|
+
# @return [nil] if the read time should not be monitored (default)
|
179
|
+
#
|
180
|
+
# @see TCPClient#read
|
181
|
+
#
|
182
|
+
attr_reader :read_timeout
|
183
|
+
|
184
|
+
def read_timeout=(value)
|
185
|
+
@read_timeout = seconds(value)
|
67
186
|
end
|
68
187
|
|
69
|
-
|
70
|
-
|
188
|
+
#
|
189
|
+
# The exception class which will be raised if {TCPClient#read} can not be
|
190
|
+
# finished in time.
|
191
|
+
#
|
192
|
+
# @return [Class] exception class raised
|
193
|
+
# @raise [NotAnExceptionError] if given argument is not an Exception class
|
194
|
+
#
|
195
|
+
attr_reader :read_timeout_error
|
196
|
+
|
197
|
+
def read_timeout_error=(value)
|
198
|
+
raise(NotAnExceptionError, value) unless exception_class?(value)
|
199
|
+
@read_timeout_error = value
|
71
200
|
end
|
72
201
|
|
73
|
-
|
74
|
-
|
202
|
+
#
|
203
|
+
# The maximum time in seconds to write to a connection.
|
204
|
+
#
|
205
|
+
# @return [Numeric] maximum time in seconds
|
206
|
+
# @return [nil] if the write time should not be monitored (default)
|
207
|
+
#
|
208
|
+
# @see TCPClient#write
|
209
|
+
#
|
210
|
+
attr_reader :write_timeout
|
211
|
+
|
212
|
+
def write_timeout=(value)
|
213
|
+
@write_timeout = seconds(value)
|
75
214
|
end
|
76
215
|
|
77
|
-
|
78
|
-
|
216
|
+
#
|
217
|
+
# The exception class which will be raised if {TCPClient#write} can not be
|
218
|
+
# finished in time.
|
219
|
+
#
|
220
|
+
# @return [Class] exception class raised
|
221
|
+
# @raise [NotAnExceptionError] if given argument is not an Exception class
|
222
|
+
#
|
223
|
+
attr_reader :write_timeout_error
|
224
|
+
|
225
|
+
def write_timeout_error=(value)
|
226
|
+
raise(NotAnExceptionError, value) unless exception_class?(value)
|
227
|
+
@write_timeout_error = value
|
79
228
|
end
|
80
229
|
|
81
|
-
|
82
|
-
|
230
|
+
#
|
231
|
+
# @attribute [w] timeout
|
232
|
+
# Shorthand to set maximum time in seconds for all timeut monitoring.
|
233
|
+
#
|
234
|
+
# @return [Numeric] maximum time in seconds for any actwion
|
235
|
+
# @return [nil] if all timeout monitoring should be disabled (default)
|
236
|
+
#
|
237
|
+
# @see #connect_timeout
|
238
|
+
# @see #read_timeout
|
239
|
+
# @see #write_timeout
|
240
|
+
#
|
241
|
+
def timeout=(value)
|
242
|
+
@connect_timeout = @write_timeout = @read_timeout = seconds(value)
|
83
243
|
end
|
84
244
|
|
85
|
-
|
86
|
-
|
245
|
+
#
|
246
|
+
# @attribute [w] timeout_error
|
247
|
+
# Shorthand to set the exception class wich will by raised by any timeut.
|
248
|
+
#
|
249
|
+
# @return [Class] exception class raised
|
250
|
+
#
|
251
|
+
# @raise [NotAnExceptionError] if given argument is not an Exception class
|
252
|
+
#
|
253
|
+
# @see #connect_timeout_error
|
254
|
+
# @see #read_timeout_error
|
255
|
+
# @see #write_timeout_error
|
256
|
+
#
|
257
|
+
def timeout_error=(value)
|
258
|
+
raise(NotAnExceptionError, value) unless exception_class?(value)
|
87
259
|
@connect_timeout_error =
|
88
|
-
@read_timeout_error = @write_timeout_error =
|
260
|
+
@read_timeout_error = @write_timeout_error = value
|
89
261
|
end
|
90
262
|
|
91
|
-
|
92
|
-
raise(NotAnExceptionError, exception) unless exception_class?(exception)
|
93
|
-
@connect_timeout_error = exception
|
94
|
-
end
|
263
|
+
# @!endgroup
|
95
264
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
265
|
+
#
|
266
|
+
# Enables/disables if network exceptions should be raised as {NetworkError}.
|
267
|
+
#
|
268
|
+
# This allows to handle all network/socket related exceptions like
|
269
|
+
# `SocketError`, `OpenSSL::SSL::SSLError`, `IOError`, etc. in a uniform
|
270
|
+
# manner. If this option is set to true all these error cases are raised as
|
271
|
+
# {NetworkError} and can be easily captured.
|
272
|
+
#
|
273
|
+
# @return [true] if all network exceptions should be raised as
|
274
|
+
# {NetworkError}
|
275
|
+
# @return [false] if socket/system errors should not be normalzed (default)
|
276
|
+
#
|
277
|
+
attr_reader :normalize_network_errors
|
100
278
|
|
101
|
-
def
|
102
|
-
|
103
|
-
@write_timeout_error = exception
|
279
|
+
def normalize_network_errors=(value)
|
280
|
+
@normalize_network_errors = value ? true : false
|
104
281
|
end
|
105
282
|
|
283
|
+
#
|
284
|
+
# Convert `self` to a Hash containing all attributes.
|
285
|
+
#
|
286
|
+
# @return [Hash<Symbol, Object>]
|
287
|
+
#
|
288
|
+
# @see #initialize
|
289
|
+
#
|
106
290
|
def to_h
|
107
291
|
{
|
108
292
|
buffered: @buffered,
|
109
293
|
keep_alive: @keep_alive,
|
110
294
|
reverse_lookup: @reverse_lookup,
|
295
|
+
ssl_params: @ssl_params,
|
111
296
|
connect_timeout: @connect_timeout,
|
112
|
-
read_timeout: @read_timeout,
|
113
|
-
write_timeout: @write_timeout,
|
114
297
|
connect_timeout_error: @connect_timeout_error,
|
298
|
+
read_timeout: @read_timeout,
|
115
299
|
read_timeout_error: @read_timeout_error,
|
300
|
+
write_timeout: @write_timeout,
|
116
301
|
write_timeout_error: @write_timeout_error,
|
117
|
-
|
302
|
+
normalize_network_errors: @normalize_network_errors
|
118
303
|
}
|
119
304
|
end
|
120
305
|
|
306
|
+
# @!visibility private
|
307
|
+
def freeze
|
308
|
+
@ssl_params.freeze
|
309
|
+
super
|
310
|
+
end
|
311
|
+
|
312
|
+
# @!visibility private
|
313
|
+
def initialize_copy(_org)
|
314
|
+
super
|
315
|
+
@ssl_params = Hash[@ssl_params] if @ssl_params
|
316
|
+
self
|
317
|
+
end
|
318
|
+
|
319
|
+
# @!visibility private
|
121
320
|
def ==(other)
|
122
321
|
to_h == other.to_h
|
123
322
|
end
|
124
323
|
alias eql? ==
|
125
324
|
|
325
|
+
# @!visibility private
|
126
326
|
def equal?(other)
|
127
327
|
self.class == other.class && self == other
|
128
328
|
end
|
@@ -6,16 +6,50 @@ class TCPClient
|
|
6
6
|
@default_configuration = Configuration.new
|
7
7
|
|
8
8
|
class << self
|
9
|
+
#
|
10
|
+
# The default configuration.
|
11
|
+
# This is used by default if no dedicated configuration was specified to
|
12
|
+
# {.open} or {#connect}.
|
13
|
+
#
|
14
|
+
# @return [Configuration]
|
15
|
+
#
|
9
16
|
attr_reader :default_configuration
|
10
17
|
|
18
|
+
#
|
19
|
+
# Configure the {.default_configuration} which is used if no dedicated
|
20
|
+
# configuration was specified to {.open} or {#connect}.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# TCPClient.configure do |cfg|
|
24
|
+
# cfg.buffered = false
|
25
|
+
# cfg.ssl_params = { min_version: :TLS1_2, max_version: :TLS1_3 }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @param options [Hash] see {Configuration#initialize} for details
|
29
|
+
#
|
30
|
+
# @yieldparam cfg {Configuration} the new configuration
|
31
|
+
#
|
32
|
+
# @return [Configuration] the new default configuration
|
33
|
+
#
|
11
34
|
def configure(options = {}, &block)
|
12
35
|
@default_configuration = Configuration.create(options, &block)
|
13
36
|
end
|
14
37
|
end
|
15
38
|
|
16
39
|
class Configuration
|
17
|
-
|
18
|
-
|
40
|
+
class << self
|
41
|
+
#
|
42
|
+
# @!parse attr_reader :default
|
43
|
+
# @return [Configuration] used by default if no dedicated configuration
|
44
|
+
# was specified
|
45
|
+
#
|
46
|
+
# @see TCPClient.open
|
47
|
+
# @see TCPClient.with_deadline
|
48
|
+
# @see TCPClient#connect
|
49
|
+
#
|
50
|
+
def default
|
51
|
+
TCPClient.default_configuration
|
52
|
+
end
|
19
53
|
end
|
20
54
|
end
|
21
55
|
end
|