tcp-client 1.0.0 → 1.0.1

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: 4ed9a12e8872f2399ace7bef72451c8f6b2d7821e4de069e095eb1ca7a5fcb96
4
- data.tar.gz: 4b6b744fb885e99ea320cdfbfe21a9ff1aceaa12beedec2f2b068ceb3e932cd2
3
+ metadata.gz: f087df088e9bdfc71ffd19b01d3f9f7a229f4db510a339a08ea7d02c07a32eda
4
+ data.tar.gz: 4b4d332dcdeb98a2bc81f3e7963973da21336e5b2d89199bfc9b0d2c92c9b122
5
5
  SHA512:
6
- metadata.gz: c4e7417600e74d3709a20b20f5d13804da51d0ff85670ca8a180bd173ae7f07ea513976c2b73c3436a852b5c51a1f6c99a61f917c4be769cd73cb91f9b65684a
7
- data.tar.gz: 197b43ef8e44faec4a6bcd397f71505b3f8f4714a3775248eeaf2984acca4444bd5f8e290cc99be9408870f4a862f1c724cfadd55c114be12a4651027f7d7fd4
6
+ metadata.gz: f0c31448b596bc77288424a2863528714db40576f7201f2927172d0c39cac4086fe976a315347d6da78a96ca022a33e31956533caa02c025b18b7b3e3129d97d
7
+ data.tar.gz: 69dd0aa063a8019c07976b6942f0d08df0f31036eb903040e63cfdc40844c0275396a879a2e7f27332ad9843b2a2ba4326fbccabee3d12e1a3b31a587cb5ba9a
data/.yardopts CHANGED
@@ -2,4 +2,9 @@
2
2
  --title 'tcp-client Documentation'
3
3
  --charset utf-8
4
4
  --markup markdown
5
- 'lib/**/*.rb' - 'README.md' 'LICENSE'
5
+ --tag comment
6
+ --hide-tag comment
7
+ lib/**/*.rb
8
+ -
9
+ README.md
10
+ LICENSE
data/README.md CHANGED
@@ -54,7 +54,7 @@ gem install tcp-client
54
54
  You can use [Bundler](http://gembundler.com/) to add TCPClient to your own project:
55
55
 
56
56
  ```shell
57
- bundle add 'tcp-client'
57
+ bundle add tcp-client
58
58
  ```
59
59
 
60
60
  After that you only need one line of code to have everything together
@@ -336,7 +336,7 @@ class TCPClient
336
336
 
337
337
  private
338
338
 
339
- def as_seconds(value) = value&.to_f&.positive? ? value : nil
339
+ def as_seconds(value) = value.to_f.positive? ? value : nil
340
340
 
341
341
  def as_exception(value)
342
342
  return value if value.is_a?(Class) && value < Exception
@@ -2,15 +2,26 @@
2
2
 
3
3
  class TCPClient
4
4
  class Deadline
5
- def initialize(timeout)
6
- timeout = timeout&.to_f
7
- @deadline = timeout&.positive? ? now + timeout : nil
5
+ attr_accessor :exception
6
+
7
+ def initialize(timeout, exception)
8
+ @timeout = timeout.to_f
9
+ @exception = exception
10
+ @deadline = @timeout.positive? ? now + @timeout : nil
8
11
  end
9
12
 
10
13
  def valid? = !@deadline.nil?
11
14
 
12
15
  def remaining_time
13
- @deadline && (remaining = @deadline - now) > 0 ? remaining : nil
16
+ (remaining = @deadline - now) > 0 ? remaining : timed_out!(caller(1))
17
+ end
18
+
19
+ def timed_out!(call_stack = nil)
20
+ raise(
21
+ @exception,
22
+ "execution expired - #{@timeout} seconds",
23
+ call_stack || caller(1)
24
+ )
14
25
  end
15
26
 
16
27
  private
@@ -13,13 +13,13 @@ class TCPClient
13
13
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
14
14
  include WithDeadline
15
15
 
16
- def initialize(socket, address, configuration, deadline, exception)
16
+ def initialize(socket, address, configuration, deadline)
17
17
  ssl_params = Hash[configuration.ssl_params]
18
18
  super(socket, create_context(ssl_params))
19
19
  self.sync_close = true
20
20
  self.hostname = address.hostname
21
21
  check_new_session if @new_session
22
- deadline.valid? ? connect_with_deadline(deadline, exception) : connect
22
+ deadline.valid? ? connect_with_deadline(deadline) : connect
23
23
  post_connection_check(address.hostname) if should_verify?(ssl_params)
24
24
  end
25
25
 
@@ -41,8 +41,8 @@ class TCPClient
41
41
  end
42
42
  end
43
43
 
44
- def connect_with_deadline(deadline, exception)
45
- with_deadline(deadline, exception) { connect_nonblock(exception: false) }
44
+ def connect_with_deadline(deadline)
45
+ with_deadline(deadline) { connect_nonblock(exception: false) }
46
46
  end
47
47
 
48
48
  def should_verify?(ssl_params)
@@ -8,10 +8,10 @@ class TCPClient
8
8
  class TCPSocket < ::Socket
9
9
  include WithDeadline
10
10
 
11
- def initialize(address, configuration, deadline, exception)
11
+ def initialize(address, configuration, deadline)
12
12
  super(address.addrinfo.ipv6? ? :INET6 : :INET, :STREAM)
13
13
  configure(configuration)
14
- connect_to(as_addr_in(address), deadline, exception)
14
+ connect_to(as_addr_in(address), deadline)
15
15
  end
16
16
 
17
17
  private
@@ -21,11 +21,9 @@ class TCPClient
21
21
  ::Socket.pack_sockaddr_in(addrinfo.ip_port, addrinfo.ip_address)
22
22
  end
23
23
 
24
- def connect_to(addr, deadline, exception)
24
+ def connect_to(addr, deadline)
25
25
  return connect(addr) unless deadline.valid?
26
- with_deadline(deadline, exception) do
27
- connect_nonblock(addr, exception: false)
28
- end
26
+ with_deadline(deadline) { connect_nonblock(addr, exception: false) }
29
27
  end
30
28
 
31
29
  def configure(configuration)
@@ -2,5 +2,5 @@
2
2
 
3
3
  class TCPClient
4
4
  # The current version number.
5
- VERSION = '1.0.0'
5
+ VERSION = '1.0.1'
6
6
  end
@@ -2,22 +2,22 @@
2
2
 
3
3
  class TCPClient
4
4
  module WithDeadline
5
- def read_with_deadline(nbytes, deadline, exception)
6
- raise(exception) unless deadline.remaining_time
7
- return fetch_avail(deadline, exception) if nbytes.nil?
5
+ def read_with_deadline(nbytes, deadline)
6
+ deadline.remaining_time
7
+ return fetch_avail(deadline) if nbytes.nil?
8
8
  @read_buffer ||= ''.b
9
9
  while @read_buffer.bytesize < nbytes
10
- read = fetch_next(deadline, exception)
10
+ read = fetch_next(deadline)
11
11
  read ? @read_buffer << read : (break close)
12
12
  end
13
13
  fetch_slice(nbytes)
14
14
  end
15
15
 
16
- def read_to_with_deadline(sep, deadline, exception)
17
- raise(exception) unless deadline.remaining_time
16
+ def read_to_with_deadline(sep, deadline)
17
+ deadline.remaining_time
18
18
  @read_buffer ||= ''.b
19
19
  while (index = @read_buffer.index(sep)).nil?
20
- read = fetch_next(deadline, exception)
20
+ read = fetch_next(deadline)
21
21
  read ? @read_buffer << read : (break close)
22
22
  end
23
23
  return fetch_slice(index + sep.bytesize) if index
@@ -26,15 +26,13 @@ class TCPClient
26
26
  result
27
27
  end
28
28
 
29
- def write_with_deadline(data, deadline, exception)
29
+ def write_with_deadline(data, deadline)
30
30
  return 0 if (size = data.bytesize).zero?
31
- raise(exception) unless deadline.remaining_time
31
+ deadline.remaining_time
32
32
  result = 0
33
33
  while true
34
34
  written =
35
- with_deadline(deadline, exception) do
36
- write_nonblock(data, exception: false)
37
- end
35
+ with_deadline(deadline) { write_nonblock(data, exception: false) }
38
36
  return result if (result += written) >= size
39
37
  data = data.byteslice(written, data.bytesize - written)
40
38
  end
@@ -42,8 +40,8 @@ class TCPClient
42
40
 
43
41
  private
44
42
 
45
- def fetch_avail(deadline, exception)
46
- if (result = @read_buffer || fetch_next(deadline, exception)).nil?
43
+ def fetch_avail(deadline)
44
+ if (result = @read_buffer || fetch_next(deadline)).nil?
47
45
  close
48
46
  return ''.b
49
47
  end
@@ -59,27 +57,23 @@ class TCPClient
59
57
  result
60
58
  end
61
59
 
62
- def fetch_next(deadline, exception)
63
- with_deadline(deadline, exception) do
64
- read_nonblock(65_536, exception: false)
65
- end
60
+ def fetch_next(deadline)
61
+ with_deadline(deadline) { read_nonblock(65_536, exception: false) }
66
62
  end
67
63
 
68
- def with_deadline(deadline, exception)
64
+ def with_deadline(deadline)
69
65
  while true
70
66
  case ret = yield
71
67
  when :wait_writable
72
- remaining_time = deadline.remaining_time or raise(exception)
73
- wait_write[remaining_time] or raise(exception)
68
+ wait_write[deadline.remaining_time] or deadline.timed_out!
74
69
  when :wait_readable
75
- remaining_time = deadline.remaining_time or raise(exception)
76
- wait_read[remaining_time] or raise(exception)
70
+ wait_read[deadline.remaining_time] or deadline.timed_out!
77
71
  else
78
72
  return ret
79
73
  end
80
74
  end
81
75
  rescue Errno::ETIMEDOUT
82
- raise(exception)
76
+ deadline.timed_out!
83
77
  end
84
78
 
85
79
  def wait_write
data/lib/tcp-client.rb CHANGED
@@ -192,11 +192,15 @@ class TCPClient
192
192
  #
193
193
  def read(nbytes = nil, timeout: nil, exception: nil)
194
194
  raise(NotConnectedError) if closed?
195
- deadline = create_deadline(timeout, configuration.read_timeout)
195
+ deadline =
196
+ create_deadline(
197
+ timeout,
198
+ @configuration.read_timeout,
199
+ exception || @configuration.read_timeout_error
200
+ )
196
201
  return stem_errors { @socket.read(nbytes) } unless deadline.valid?
197
- exception ||= configuration.read_timeout_error
198
- stem_errors(exception) do
199
- @socket.read_with_deadline(nbytes, deadline, exception)
202
+ stem_errors(deadline.exception) do
203
+ @socket.read_with_deadline(nbytes, deadline)
200
204
  end
201
205
  end
202
206
 
@@ -221,13 +225,17 @@ class TCPClient
221
225
  #
222
226
  def readline(separator = $/, chomp: false, timeout: nil, exception: nil)
223
227
  raise(NotConnectedError) if closed?
224
- deadline = create_deadline(timeout, configuration.read_timeout)
228
+ deadline =
229
+ create_deadline(
230
+ timeout,
231
+ @configuration.read_timeout,
232
+ exception || @configuration.read_timeout_error
233
+ )
225
234
  deadline.valid? or
226
235
  return stem_errors { @socket.readline(separator, chomp: chomp) }
227
- exception ||= configuration.read_timeout_error
228
236
  line =
229
- stem_errors(exception) do
230
- @socket.read_to_with_deadline(separator, deadline, exception)
237
+ stem_errors(deadline.exception) do
238
+ @socket.read_to_with_deadline(separator, deadline)
231
239
  end
232
240
  chomp ? line.chomp : line
233
241
  end
@@ -265,7 +273,7 @@ class TCPClient
265
273
  def with_deadline(timeout)
266
274
  previous_deadline = @deadline
267
275
  raise(NoBlockGivenError) unless block_given?
268
- @deadline = Deadline.new(timeout)
276
+ @deadline = Deadline.new(timeout, TimeoutError)
269
277
  raise(InvalidDeadLineError, timeout) unless @deadline.valid?
270
278
  yield(self)
271
279
  ensure
@@ -292,36 +300,46 @@ class TCPClient
292
300
  #
293
301
  def write(*messages, timeout: nil, exception: nil)
294
302
  raise(NotConnectedError) if closed?
295
- deadline = create_deadline(timeout, configuration.write_timeout)
303
+ deadline =
304
+ create_deadline(
305
+ timeout,
306
+ @configuration.write_timeout,
307
+ exception || @configuration.write_timeout_error
308
+ )
296
309
  return stem_errors { @socket.write(*messages) } unless deadline.valid?
297
- exception ||= configuration.write_timeout_error
298
- stem_errors(exception) do
299
- messages.sum do |chunk|
300
- @socket.write_with_deadline(chunk.b, deadline, exception)
301
- end
310
+ stem_errors(deadline.exception) do
311
+ messages.sum { |chunk| @socket.write_with_deadline(chunk.b, deadline) }
302
312
  end
303
313
  end
304
314
 
305
315
  private
306
316
 
307
- def create_deadline(timeout, default)
308
- timeout.nil? && @deadline ? @deadline : Deadline.new(timeout || default)
317
+ def create_deadline(timeout, timeout_default, exception)
318
+ if timeout.nil? && @deadline
319
+ @deadline.exception = exception
320
+ return @deadline
321
+ end
322
+ Deadline.new(timeout || timeout_default, exception)
309
323
  end
310
324
 
311
325
  def create_socket(timeout, exception)
312
- deadline = create_deadline(timeout, configuration.connect_timeout)
313
- exception ||= configuration.connect_timeout_error
314
- stem_errors(exception) do
315
- @socket = TCPSocket.new(address, configuration, deadline, exception)
316
- return @socket unless configuration.ssl?
317
- SSLSocket.new(@socket, address, configuration, deadline, exception)
326
+ deadline =
327
+ create_deadline(
328
+ timeout,
329
+ @configuration.connect_timeout,
330
+ exception || @configuration.connect_timeout_error
331
+ )
332
+ stem_errors(deadline.exception) do
333
+ @socket = TCPSocket.new(address, @configuration, deadline)
334
+ return @socket unless @configuration.ssl?
335
+ SSLSocket.new(@socket, address, @configuration, deadline)
318
336
  end
319
337
  end
320
338
 
321
339
  def stem_errors(except = nil)
322
340
  yield
323
341
  rescue *NETWORK_ERRORS => e
324
- raise unless configuration.normalize_network_errors
342
+ raise unless @configuration.normalize_network_errors
325
343
  except && e.is_a?(except) ? raise : raise(NetworkError, e)
326
344
  end
327
345
 
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: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-03 00:00:00.000000000 Z
11
+ date: 2024-05-12 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
@@ -59,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
61
  requirements: []
62
- rubygems_version: 3.5.9
62
+ rubygems_version: 3.5.10
63
63
  signing_key:
64
64
  specification_version: 4
65
65
  summary: Use your TCP connections with working timeout.