io-endpoint 0.14.0 → 0.15.1

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
2
  SHA256:
3
- metadata.gz: 0f51510c717c48af4dbb57bdc410ba223ca4bb5f7880c57ca37e8a95c33a1c59
4
- data.tar.gz: 1175cb1f51a2e242a87f3d807047ca01b4f42d06842d5162459cc9f8566eb196
3
+ metadata.gz: 52e4f0d4b8e0e46f2ad47c655f0b841fd9cbd4b26165139a5260546f5baa5167
4
+ data.tar.gz: a86e657651e34a15f300d67e1df05b7ef29b6e5624b61c2bc06df57269f005dd
5
5
  SHA512:
6
- metadata.gz: 616c3bc275c978686816bc6dbcfb5100101bea253e393693d7f319fca284b41955b58d59d2091cf2cc6f0f00bfbdf00b2b1ad8d04346d91f2af8a70f55817070
7
- data.tar.gz: 1e9b8a3e7e1d1379a270f92fef0075b938a708f7744f622e9c14ab5cb6e179e7e0ea465e03b9ce49eeec88bb9f2aeca126b397c92d0f7f4e378512a8327ce5ef
6
+ metadata.gz: b33453871ae938df8dc7c21bf5eb2db870a7433ec61015dc3aa0b1f1f572ff36f3bd46c3f447e53ee58891c4570215bcf14c8c06010433d6dcaf1956b7034659
7
+ data.tar.gz: 8a1143e06da6a04216f6e7a5a9af31530b3867e89771e739e28e67d68987dbb9be7e587bba86cfd934f7e80f85043f4cbfb10119dd11521bac4747d70708e840
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
- require 'socket'
6
+ require "socket"
7
7
 
8
- require_relative 'generic'
9
- require_relative 'wrapper'
8
+ require_relative "generic"
9
+ require_relative "wrapper"
10
10
 
11
11
  module IO::Endpoint
12
12
  class AddressEndpoint < Generic
@@ -37,13 +37,13 @@ module IO::Endpoint
37
37
  # @yield {|socket| ...} An optional block which will be passed the socket.
38
38
  # @parameter socket [Socket] The socket which has been bound.
39
39
  # @return [Array(Socket)] the bound socket
40
- def bind(wrapper = Wrapper.default, &block)
40
+ def bind(wrapper = self.wrapper, &block)
41
41
  [wrapper.bind(@address, **@options, &block)]
42
42
  end
43
43
 
44
44
  # Connects a socket to the given address. If a block is given, the socket will be automatically closed when the block exits.
45
45
  # @return [Socket] the connected socket
46
- def connect(wrapper = Wrapper.default, &block)
46
+ def connect(wrapper = self.wrapper, &block)
47
47
  wrapper.connect(@address, **@options, &block)
48
48
  end
49
49
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2024, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
- require_relative 'generic'
7
- require_relative 'composite_endpoint'
8
- require_relative 'address_endpoint'
6
+ require_relative "generic"
7
+ require_relative "composite_endpoint"
8
+ require_relative "address_endpoint"
9
9
 
10
10
  module IO::Endpoint
11
11
  class BoundEndpoint < Generic
@@ -62,10 +62,10 @@ module IO::Endpoint
62
62
  "\#<#{self.class} #{@sockets.size} bound sockets for #{@endpoint}>"
63
63
  end
64
64
 
65
- def bind(wrapper = Wrapper.default, &block)
65
+ def bind(wrapper = self.wrapper, &block)
66
66
  @sockets.map do |server|
67
67
  if block_given?
68
- wrapper.async do
68
+ wrapper.schedule do
69
69
  yield server
70
70
  end
71
71
  else
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023-2024, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
- require_relative 'generic'
6
+ require_relative "generic"
7
7
 
8
8
  module IO::Endpoint
9
9
  # A composite endpoint is a collection of endpoints that are used in order.
@@ -44,7 +44,7 @@ module IO::Endpoint
44
44
  end
45
45
  end
46
46
 
47
- def connect(wrapper = Wrapper.default, &block)
47
+ def connect(wrapper = self.wrapper, &block)
48
48
  last_error = nil
49
49
 
50
50
  @endpoints.each do |endpoint|
@@ -57,7 +57,7 @@ module IO::Endpoint
57
57
  raise last_error
58
58
  end
59
59
 
60
- def bind(wrapper = Wrapper.default, &block)
60
+ def bind(wrapper = self.wrapper, &block)
61
61
  if block_given?
62
62
  @endpoints.each do |endpoint|
63
63
  endpoint.bind(&block)
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2024, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
- require_relative 'generic'
7
- require_relative 'composite_endpoint'
8
- require_relative 'socket_endpoint'
6
+ require_relative "generic"
7
+ require_relative "composite_endpoint"
8
+ require_relative "socket_endpoint"
9
9
 
10
- require 'openssl'
10
+ require "openssl"
11
11
 
12
12
  module IO::Endpoint
13
13
  class ConnectedEndpoint < Generic
@@ -41,7 +41,7 @@ module IO::Endpoint
41
41
  AddressEndpoint.new(socket.to_io.remote_address, **options)
42
42
  end
43
43
 
44
- def connect(wrapper = Wrapper.default, &block)
44
+ def connect(wrapper = self.wrapper, &block)
45
45
  if block_given?
46
46
  yield @socket
47
47
  else
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023-2024, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
6
  # require_relative 'address'
7
- require 'uri'
8
- require 'socket'
7
+ require "uri"
8
+ require "socket"
9
9
 
10
10
  module IO::Endpoint
11
11
  Address = Addrinfo
@@ -64,21 +64,21 @@ module IO::Endpoint
64
64
  # @yields {|socket| ...} An optional block which will be passed the socket.
65
65
  # @parameter socket [Socket] The socket which has been bound.
66
66
  # @returns [Array(Socket)] the bound socket
67
- def bind(wrapper = Wrapper.default, &block)
67
+ def bind(wrapper = self.wrapper, &block)
68
68
  raise NotImplementedError
69
69
  end
70
70
 
71
71
  # Connects a socket to the given address. If a block is given, the socket will be automatically closed when the block exits.
72
72
  # @parameter wrapper [Wrapper] The wrapper to use for connecting.
73
73
  # @return [Socket] the connected socket
74
- def connect(wrapper = Wrapper.default, &block)
74
+ def connect(wrapper = self.wrapper, &block)
75
75
  raise NotImplementedError
76
76
  end
77
77
 
78
78
  # Bind and accept connections on the given address.
79
79
  # @parameter wrapper [Wrapper] The wrapper to use for accepting connections.
80
80
  # @yields [Socket] The accepted socket.
81
- def accept(wrapper = Wrapper.default, &block)
81
+ def accept(wrapper = self.wrapper, &block)
82
82
  bind(wrapper) do |server|
83
83
  wrapper.accept(server, **@options, &block)
84
84
  end
@@ -109,5 +109,10 @@ module IO::Endpoint
109
109
 
110
110
  IO::Endpoint.public_send(uri.scheme, uri.host, uri.port, **options)
111
111
  end
112
+
113
+ # The default wrapper to use for binding, connecting, and accepting connections.
114
+ def wrapper
115
+ @options[:wrapper] || Wrapper.default
116
+ end
112
117
  end
113
118
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
- require_relative 'address_endpoint'
6
+ require_relative "address_endpoint"
7
7
 
8
8
  module IO::Endpoint
9
9
  class HostEndpoint < Generic
@@ -38,7 +38,7 @@ module IO::Endpoint
38
38
  # @yield [Socket] the socket which is being connected, may be invoked more than once
39
39
  # @return [Socket] the connected socket
40
40
  # @raise if no connection could complete successfully
41
- def connect(wrapper = Wrapper.default, &block)
41
+ def connect(wrapper = self.wrapper, &block)
42
42
  last_error = nil
43
43
 
44
44
  Addrinfo.foreach(*@specification) do |address|
@@ -63,7 +63,7 @@ module IO::Endpoint
63
63
  # Invokes the given block for every address which can be bound to.
64
64
  # @yield [Socket] the bound socket
65
65
  # @return [Array<Socket>] an array of bound sockets
66
- def bind(wrapper = Wrapper.default, &block)
66
+ def bind(wrapper = self.wrapper, &block)
67
67
  Addrinfo.foreach(*@specification).map do |address|
68
68
  wrapper.bind(address, **@options, &block)
69
69
  end
@@ -3,5 +3,5 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
- require_relative 'bound_endpoint'
7
- require_relative 'connected_endpoint'
6
+ require_relative "bound_endpoint"
7
+ require_relative "connected_endpoint"
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Samuel Williams.
4
+ # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
- require_relative 'generic'
6
+ require_relative "generic"
7
7
 
8
8
  module IO::Endpoint
9
9
  # This class doesn't exert ownership over the specified socket, wraps a native ::IO.
@@ -3,10 +3,10 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
- require_relative 'host_endpoint'
7
- require_relative 'generic'
6
+ require_relative "host_endpoint"
7
+ require_relative "generic"
8
8
 
9
- require 'openssl'
9
+ require "openssl"
10
10
 
11
11
  module OpenSSL
12
12
  module SSL
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Samuel Williams.
4
+ # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
- require_relative 'address_endpoint'
6
+ require_relative "address_endpoint"
7
7
 
8
8
  module IO::Endpoint
9
9
  # This class doesn't exert ownership over the specified unix socket and ensures exclusive access by using `flock` where possible.
@@ -5,6 +5,6 @@
5
5
 
6
6
  class IO
7
7
  module Endpoint
8
- VERSION = "0.14.0"
8
+ VERSION = "0.15.1"
9
9
  end
10
10
  end
@@ -1,14 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023-2024, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
- require 'socket'
6
+ require "socket"
7
7
 
8
8
  module IO::Endpoint
9
9
  class Wrapper
10
10
  include ::Socket::Constants
11
11
 
12
+ if Fiber.respond_to?(:scheduler)
13
+ def schedule(&block)
14
+ if Fiber.scheduler
15
+ Fiber.schedule(&block)
16
+ else
17
+ Thread.new(&block)
18
+ end
19
+ end
20
+ else
21
+ def schedule(&block)
22
+ Thread.new(&block)
23
+ end
24
+ end
25
+
26
+ # Legacy method for compatibility with older code.
27
+ def async(&block)
28
+ schedule(&block)
29
+ end
30
+
12
31
  def set_timeout(io, timeout)
13
32
  if io.respond_to?(:timeout=)
14
33
  io.timeout = timeout
@@ -30,8 +49,13 @@ module IO::Endpoint
30
49
  # It may not be supported by the protocol (e.g. UDP). ¯\_(ツ)_/¯
31
50
  end
32
51
 
33
- def async
34
- raise NotImplementedError
52
+ # Connect a socket to a remote address.
53
+ # This is an extension point for subclasses to provide additional functionality.
54
+ #
55
+ # @parameter socket [Socket] The socket to connect.
56
+ # @parameter remote_address [Address] The remote address to connect to.
57
+ def socket_connect(socket, remote_address)
58
+ socket.connect(remote_address.to_sockaddr)
35
59
  end
36
60
 
37
61
  # Establish a connection to a given `remote_address`.
@@ -72,7 +96,7 @@ module IO::Endpoint
72
96
  end
73
97
 
74
98
  begin
75
- socket.connect(remote_address.to_sockaddr)
99
+ socket_connect(socket, remote_address)
76
100
  rescue Exception
77
101
  socket.close
78
102
  raise
@@ -142,7 +166,7 @@ module IO::Endpoint
142
166
 
143
167
  return socket unless block_given?
144
168
 
145
- async do
169
+ schedule do
146
170
  begin
147
171
  yield socket
148
172
  ensure
@@ -151,11 +175,21 @@ module IO::Endpoint
151
175
  end
152
176
  end
153
177
 
178
+ # Accept a connection from a bound socket.
179
+ # This is an extension point for subclasses to provide additional functionality.
180
+ #
181
+ # @parameter server [Socket] The bound server socket.
182
+ # @returns [Tuple(Socket, Address)] The connected socket and the remote address.
183
+ def socket_accept(server)
184
+ server.accept
185
+ end
186
+
154
187
  # Bind to a local address and accept connections in a loop.
155
188
  def accept(server, timeout: nil, linger: nil, **options, &block)
156
189
  # Ensure we use a `loop do ... end` so that state is not leaked between iterations:
190
+
157
191
  loop do
158
- socket, address = server.accept
192
+ socket, address = socket_accept(server)
159
193
 
160
194
  if linger
161
195
  socket.setsockopt(SOL_SOCKET, SO_LINGER, 1)
@@ -165,7 +199,7 @@ module IO::Endpoint
165
199
  set_timeout(socket, timeout)
166
200
  end
167
201
 
168
- async do
202
+ schedule do
169
203
  # Some sockets, notably SSL sockets, need application level negotiation before they are ready:
170
204
  if socket.respond_to?(:start)
171
205
  begin
@@ -183,31 +217,11 @@ module IO::Endpoint
183
217
  end
184
218
  end
185
219
  end
186
- end
187
-
188
- class ThreadWrapper < Wrapper
189
- def async(&block)
190
- ::Thread.new(&block)
191
- end
192
- end
193
-
194
- class FiberWrapper < Wrapper
195
- def async(&block)
196
- ::Fiber.schedule(&block)
197
- end
198
- end
199
-
200
- if Fiber.respond_to?(:scheduler)
201
- def Wrapper.default
202
- if Fiber.scheduler
203
- FiberWrapper.new
204
- else
205
- ThreadWrapper.new
206
- end
207
- end
208
- else
209
- def Wrapper.default
210
- ThreadWrapper.new
220
+
221
+ DEFAULT = new
222
+
223
+ def self.default
224
+ DEFAULT
211
225
  end
212
226
  end
213
227
  end
data/license.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2023-2024, by Samuel Williams.
3
+ Copyright, 2023-2025, by Samuel Williams.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-endpoint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -37,10 +36,8 @@ cert_chain:
37
36
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
38
37
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
39
38
  -----END CERTIFICATE-----
40
- date: 2024-10-12 00:00:00.000000000 Z
39
+ date: 2025-02-13 00:00:00.000000000 Z
41
40
  dependencies: []
42
- description:
43
- email:
44
41
  executables: []
45
42
  extensions: []
46
43
  extra_rdoc_files: []
@@ -66,7 +63,6 @@ licenses:
66
63
  metadata:
67
64
  documentation_uri: https://socketry.github.io/io-endpoint
68
65
  source_code_uri: https://github.com/socketry/io-endpoint.git
69
- post_install_message:
70
66
  rdoc_options: []
71
67
  require_paths:
72
68
  - lib
@@ -81,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
77
  - !ruby/object:Gem::Version
82
78
  version: '0'
83
79
  requirements: []
84
- rubygems_version: 3.5.11
85
- signing_key:
80
+ rubygems_version: 3.6.2
86
81
  specification_version: 4
87
82
  summary: Provides a separation of concerns interface for IO endpoints.
88
83
  test_files: []
metadata.gz.sig CHANGED
@@ -1,2 +1,4 @@
1
- ^�cC��|��Ta]}�e@�y�!M��!��"y%�s��M1LWDk�&���X���N
2
- Q0./���I�>�r߯{�{n֧�.)P����FM7+�N9�����J[�Rk;+�R�Qr�u�Z~�"[_at� !�Q�>�lFi��އ4�L� }� �,��L"Y�L|/
1
+ m�����h9tq]G�d���o}�W L,P��\d���N@��x\"���gx":M8 �����zar)��:�݊�˕�Hh{B�Z[�].l���*�5�&�s4bA���c�����=�1�m����x�a�z2�l%n��P�ջOčpmL���6����
2
+ @@���Nۏ��ܐ�Q}r���
3
+ �幊c��@ �\ �G6�����ޢ
4
+ �H�Y �ߍV��(�֑����R�R�4坼�