tcp-client 0.11.3 → 0.12.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
2
  SHA256:
3
- metadata.gz: 7d7af455e50934e3a112047a9f8779993e890b44e01f100c78695ed52fdde979
4
- data.tar.gz: f144e06f7a7e5be0c2691bfafb536a3709a0a069b6280141b876b4a6b56b118d
3
+ metadata.gz: 1fc5d1bf109cf729758affe093ed44313d0e688c9c0098bf671f9c8e1250118c
4
+ data.tar.gz: 185ea5d345ecd2cceecafe6d19179a68919429df7269c5088bd89032749d6db3
5
5
  SHA512:
6
- metadata.gz: 82f2061ef746877f1152475e836d925181353d3b6f7e4a1592dafb5d6151cd495882da17801b487ccade8c5b46dfe75b63b9d8f9b16d781a22d51cb9e79e8227
7
- data.tar.gz: 1b42dc104cd5f9c0d02c98d4f020136658f428ce629347c7065101f55195c8f94e2bbaaf36e08a6adc74989b566f99042849c9fe2320df3a53872d8ef085528b
6
+ metadata.gz: b34d0fef41cafa8d915ed203a5a4a934f22d2ee37fbe4a1f992bef6278f3ebfb7715ff7b4672e01af98c81d7a39eb7d057d79499b41248db44cf4de730240b1d
7
+ data.tar.gz: 5125d264eb11b6c5358df65525ad8ac9806f69d4e3f5bccd3dc775a36ae1f49c6c3b3cb97b410e09bdc214275a3b95b0f576c3a52db77f79ef610203e29fabd9
data/README.md CHANGED
@@ -18,11 +18,14 @@ require 'tcp-client'
18
18
 
19
19
  # create a configuration:
20
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
- )
21
+ # - use at least TLS 1.2
22
+ cfg =
23
+ TCPClient::Configuration.create(
24
+ buffered: false,
25
+ ssl_params: {
26
+ min_version: :TLS1_2
27
+ }
28
+ )
26
29
 
27
30
  # request to Google.com:
28
31
  # - limit all network interactions to 1.5 seconds
@@ -52,13 +55,13 @@ gem 'tcp-client'
52
55
 
53
56
  and install it by running Bundler:
54
57
 
55
- ```bash
58
+ ```shell
56
59
  bundle
57
60
  ```
58
61
 
59
62
  To install the gem globally use:
60
63
 
61
- ```bash
64
+ ```shell
62
65
  gem install tcp-client
63
66
  ```
64
67
 
@@ -4,21 +4,46 @@ require 'socket'
4
4
 
5
5
  class TCPClient
6
6
  #
7
- # The address used by a TCPClient
7
+ # The address used by a TCPClient.
8
+ #
9
+ # @note An {Address} does not resolve the required TCP information until it is
10
+ # needed.
11
+ #
12
+ # This means that address resolution only occurs when an instance attribute
13
+ # is accessed or the address is frozen.
14
+ # To force the address resolution at a certain time, {#freeze} can be called.
8
15
  #
9
16
  class Address
10
17
  #
18
+ # @attribute [r] addrinfo
19
+ # @return [Addrinfo] the address info
20
+ #
21
+ def addrinfo
22
+ freeze if @addrinfo.nil?
23
+ @addrinfo
24
+ end
25
+
26
+ #
27
+ # @attribute [r] host
11
28
  # @return [String] the host name
12
29
  #
13
- attr_reader :hostname
30
+ def host
31
+ freeze if @host.nil?
32
+ @host
33
+ end
34
+ alias hostname host
14
35
 
15
36
  #
16
- # @return [Addrinfo] the address info
37
+ # @attribute [r] port
38
+ # @return [Integer] the port number
17
39
  #
18
- attr_reader :addrinfo
40
+ def port
41
+ addrinfo.ip_port
42
+ end
19
43
 
20
44
  #
21
45
  # Initializes an address
46
+ #
22
47
  # @overload initialize(addr)
23
48
  # The addr can be specified as
24
49
  #
@@ -49,46 +74,53 @@ class TCPClient
49
74
  # @param port [Integer] the addressed port
50
75
  #
51
76
  def initialize(addr)
52
- case addr
53
- when self.class
54
- init_from_selfclass(addr)
55
- when Addrinfo
56
- init_from_addrinfo(addr)
57
- when Integer
58
- init_from_addrinfo(Addrinfo.tcp(nil, addr))
59
- else
60
- init_from_string(addr)
61
- end
62
- @addrinfo.freeze
77
+ @addr = addr
63
78
  end
64
79
 
65
80
  #
66
- # @attribute [r] port
67
- # @return [Integer] the port number
81
+ # Convert `self` to a Hash containing host and port attribute.
68
82
  #
69
- def port
70
- @addrinfo.ip_port
83
+ # @return [Hash] host and port
84
+ #
85
+ def to_hash
86
+ { host: host, port: port }
87
+ end
88
+
89
+ #
90
+ # Convert `self` to a Hash containing host and port attribute.
91
+ #
92
+ # @overload to_h
93
+ # @overload to_h(&block)
94
+ # @return [Hash] host and port
95
+ #
96
+ def to_h(&block)
97
+ block ? to_hash.to_h(&block) : to_hash
71
98
  end
72
99
 
73
100
  #
74
101
  # @return [String] text representation of self as "host:port"
75
102
  #
76
103
  def to_s
77
- hostname.index(':') ? "[#{hostname}]:#{port}" : "#{hostname}:#{port}"
104
+ host.index(':') ? "[#{host}]:#{port}" : "#{host}:#{port}"
78
105
  end
79
106
 
80
107
  #
81
- # Convert `self` to a Hash containing host and port attribute.
108
+ # Force the address resolution and prevents further modifications of itself.
82
109
  #
83
- # @return [Hash] host and port
110
+ # @return [Address] itself
84
111
  #
85
- def to_h
86
- { host: hostname, port: port }
112
+ def freeze
113
+ return super if frozen?
114
+ solve
115
+ @addrinfo.freeze
116
+ @host.freeze
117
+ @addr = nil
118
+ super
87
119
  end
88
120
 
89
121
  # @!visibility private
90
122
  def ==(other)
91
- to_h == other.to_h
123
+ to_hash == other.to_h
92
124
  end
93
125
  alias eql? ==
94
126
 
@@ -99,26 +131,40 @@ class TCPClient
99
131
 
100
132
  private
101
133
 
102
- def init_from_selfclass(address)
103
- @hostname = address.hostname
134
+ def solve
135
+ case @addr
136
+ when self.class
137
+ from_self_class(@addr)
138
+ when Addrinfo
139
+ from_addrinfo(@addr)
140
+ when Integer
141
+ from_addrinfo(Addrinfo.tcp(nil, @addr))
142
+ else
143
+ from_string(@addr)
144
+ end
145
+ end
146
+
147
+ def from_self_class(address)
148
+ unless address.frozen?
149
+ @addr = address.instance_variable_get(:@addr)
150
+ return solve
151
+ end
104
152
  @addrinfo = address.addrinfo
153
+ @host = address.host
105
154
  end
106
155
 
107
- def init_from_addrinfo(addrinfo)
108
- @hostname = addrinfo.getnameinfo(Socket::NI_NUMERICSERV).first
156
+ def from_addrinfo(addrinfo)
157
+ @host = addrinfo.getnameinfo(Socket::NI_NUMERICSERV).first
109
158
  @addrinfo = addrinfo
110
159
  end
111
160
 
112
- def init_from_string(str)
113
- @hostname, port = from_string(str.to_s)
114
- if @hostname
115
- @addrinfo = Addrinfo.tcp(@hostname, port)
116
- else
117
- init_from_addrinfo(Addrinfo.tcp(nil, port)) unless @hostname
118
- end
161
+ def from_string(str)
162
+ @host, port = host_n_port(str.to_s)
163
+ return @addrinfo = Addrinfo.tcp(@host, port) if @host
164
+ from_addrinfo(Addrinfo.tcp(nil, port))
119
165
  end
120
166
 
121
- def from_string(str)
167
+ def host_n_port(str)
122
168
  idx = str.rindex(':') or return nil, str.to_i
123
169
  name = str[0, idx].delete_prefix('[').delete_suffix(']')
124
170
  [name.empty? ? nil : name, str[idx + 1, str.size - idx].to_i]
@@ -268,7 +268,7 @@ class TCPClient
268
268
  #
269
269
  # @see #configure
270
270
  #
271
- def to_h
271
+ def to_hash
272
272
  {
273
273
  buffered: @buffered,
274
274
  keep_alive: @keep_alive,
@@ -284,6 +284,17 @@ class TCPClient
284
284
  }
285
285
  end
286
286
 
287
+ #
288
+ # @overload to_h
289
+ # @overload to_h(&block)
290
+ # @return [{Symbol => Object}] Hash containing all attributes
291
+ #
292
+ # @see #configure
293
+ #
294
+ def to_h(&block)
295
+ block ? to_hash.to_h(&block) : to_hash
296
+ end
297
+
287
298
  #
288
299
  # Configures the instance with given options Hash.
289
300
  #
@@ -326,7 +337,7 @@ class TCPClient
326
337
 
327
338
  # @!visibility private
328
339
  def ==(other)
329
- to_h == other.to_h
340
+ to_hash == other.to_h
330
341
  end
331
342
  alias eql? ==
332
343
 
@@ -12,7 +12,7 @@ class TCPClient
12
12
  end
13
13
 
14
14
  def remaining_time
15
- @deadline&.-(now)
15
+ @deadline && (remaining = @deadline - now) > 0 ? remaining : nil
16
16
  end
17
17
 
18
18
  private
@@ -48,7 +48,7 @@ class TCPClient
48
48
  return 0 if (size = data.bytesize).zero?
49
49
  raise(exception) unless deadline.remaining_time
50
50
  result = 0
51
- loop do
51
+ while true
52
52
  written =
53
53
  with_deadline(deadline, exception) do
54
54
  write_nonblock(data, exception: false)
@@ -84,7 +84,7 @@ class TCPClient
84
84
  end
85
85
 
86
86
  def with_deadline(deadline, exception)
87
- loop do
87
+ while true
88
88
  case ret = yield
89
89
  when :wait_writable
90
90
  remaining_time = deadline.remaining_time or raise(exception)
@@ -2,5 +2,5 @@
2
2
 
3
3
  class TCPClient
4
4
  # The current version number.
5
- VERSION = '0.11.3'
5
+ VERSION = '0.12.0'
6
6
  end
data/lib/tcp-client.rb CHANGED
@@ -161,7 +161,7 @@ class TCPClient
161
161
  close if @socket
162
162
  @configuration = (configuration || Configuration.default).dup
163
163
  raise(NoOpenSSLError) if @configuration.ssl? && !defined?(SSLSocket)
164
- @address = stem_errors { Address.new(address) }
164
+ @address = Address.new(address)
165
165
  @socket = create_socket(timeout, exception)
166
166
  self
167
167
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcp-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.3
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-15 00:00:00.000000000 Z
11
+ date: 2023-04-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  This gem implements a customizable TCP client class that gives you control
@@ -43,6 +43,7 @@ metadata:
43
43
  source_code_uri: https://github.com/mblumtritt/tcp-client
44
44
  bug_tracker_uri: https://github.com/mblumtritt/tcp-client/issues
45
45
  documentation_uri: https://rubydoc.info/gems/tcp-client
46
+ rubygems_mfa_required: 'true'
46
47
  post_install_message:
47
48
  rdoc_options: []
48
49
  require_paths:
@@ -58,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
59
  - !ruby/object:Gem::Version
59
60
  version: '0'
60
61
  requirements: []
61
- rubygems_version: 3.4.3
62
+ rubygems_version: 3.4.10
62
63
  signing_key:
63
64
  specification_version: 4
64
65
  summary: Use your TCP connections with working timeout.