async-io 1.2.1 → 1.3.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
- SHA1:
3
- metadata.gz: c21728ab9008e3a380403814866827866f69cfa5
4
- data.tar.gz: 9459dcb16dc458acf1724865b12a53dccf548dc5
2
+ SHA256:
3
+ metadata.gz: 152518b09c63b90c002c9e4fa832d075898c75e613cc0405e8b1df947f0c3bdd
4
+ data.tar.gz: 4ddb1b1b688bbc37bfc6beb705866706aba4f1e43efe53126b03e0f3f57c4733
5
5
  SHA512:
6
- metadata.gz: 60deebccccfc2885880c6a226b8f7637ec1234894efc92cc125e04778555a65f69e4dac73547c0e11de360c575830258fb32093353109bd08fe6cc351d404b6d
7
- data.tar.gz: 43de7fec9b8046f1b6fbb7be981671879d2f2ad7479d791a651b1aad82301edb834a64de0d7d66e4059f8111f2bc8b899970ff8f17c26da55e00806f04546fcb
6
+ metadata.gz: b057c8c881f386afa0151fa220a9b51660b2487d124e8c45dbc45c240c2c682e83fd16b8c92c69b311bc2ae0d3b638fec4218ceb7e76c417367fcbc0852ec9be
7
+ data.tar.gz: db8b25d2bbc5c069586ce61f17a030b9469d22b1173b618adf826dabdffe5251f3e4e387338adeb89fee93dafd303365e729cdf8cf3217401f9d306b10152e95
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.add_dependency "async", "~> 1.0"
20
20
  spec.add_development_dependency "async-rspec", "~> 1.2"
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.13"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
  spec.add_development_dependency "rspec", "~> 3.0"
25
25
  end
@@ -34,12 +34,17 @@ module Async
34
34
  self.send(uri.scheme, uri.host, uri.port, **options)
35
35
  end
36
36
 
37
+ # args: nodename, service, family, socktype, protocol, flags
37
38
  def tcp(*args, **options)
38
- AddressEndpoint.new(Address.tcp(*args), **options)
39
+ args[3] = ::Socket::SOCK_STREAM
40
+
41
+ HostEndpoint.new(args, **options)
39
42
  end
40
43
 
41
44
  def udp(*args, **options)
42
- AddressEndpoint.new(Address.udp(*args), **options)
45
+ args[3] = ::Socket::SOCK_DGRAM
46
+
47
+ HostEndpoint.new(args, **options)
43
48
  end
44
49
 
45
50
  def unix(*args, **options)
@@ -47,7 +52,7 @@ module Async
47
52
  end
48
53
 
49
54
  def ssl(*args, **options)
50
- SecureEndpoint.new(Endpoint.tcp(*args, **options), **options)
55
+ SecureEndpoint.new(self.tcp(*args, **options), **options)
51
56
  end
52
57
 
53
58
  # Generate a list of endpoints from an array.
@@ -76,32 +81,6 @@ module Async
76
81
  super(specification, options)
77
82
  end
78
83
 
79
- def address
80
- specification.local_address
81
- end
82
-
83
- def to_sockaddr
84
- address.to_sockaddr
85
- end
86
-
87
- # This is how addresses are internally converted, e.g. within `Socket#sendto`.
88
- alias to_str to_sockaddr
89
-
90
- # SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, etc.
91
- def socket_type
92
- address.socktype
93
- end
94
-
95
- # PF_* eg PF_INET etc, normally identical to AF_* constants.
96
- def socket_domain
97
- address.afamily
98
- end
99
-
100
- # IPPROTO_TCP, IPPROTO_UDP, IPPROTO_IPX, etc.
101
- def socket_protocol
102
- address.protocol
103
- end
104
-
105
84
  def bind
106
85
  yield specification
107
86
  end
@@ -120,27 +99,50 @@ module Async
120
99
  end
121
100
  end
122
101
 
123
- # This class will open and close the socket automatically.
124
- class AddressEndpoint < Endpoint
125
- def address
126
- specification
102
+ class HostEndpoint < Endpoint
103
+ def bind(&block)
104
+ task = Task.current
105
+ tasks = []
106
+
107
+ task.annotate("binding to #{specification.inspect}")
108
+
109
+ Addrinfo.foreach(*specification).each do |address|
110
+ tasks << task.async do
111
+ Socket.bind(address, **options, &block)
112
+ end
113
+ end
114
+
115
+ tasks.each(&:wait)
127
116
  end
128
117
 
118
+ def connect(&block)
119
+ last_error = nil
120
+
121
+ Addrinfo.foreach(*specification).each do |address|
122
+ begin
123
+ return Socket.connect(address, &block)
124
+ rescue
125
+ last_error = $!
126
+ end
127
+ end
128
+
129
+ raise last_error
130
+ end
131
+ end
132
+
133
+ # This class will open and close the socket automatically.
134
+ class AddressEndpoint < Endpoint
129
135
  def bind(&block)
130
- Socket.bind(address, **options, &block)
136
+ Socket.bind(specification, **options, &block)
131
137
  end
132
138
 
133
139
  def connect(&block)
134
- Socket.connect(address, &block)
140
+ Socket.connect(specification, &block)
135
141
  end
136
142
  end
137
143
 
138
144
  # This class doesn't exert ownership over the specified socket, wraps a native ::IO.
139
145
  class SocketEndpoint < Endpoint
140
- def address
141
- specification.local_address
142
- end
143
-
144
146
  def bind(&block)
145
147
  yield Socket.new(specification)
146
148
  end
@@ -151,10 +153,6 @@ module Async
151
153
  end
152
154
 
153
155
  class SecureEndpoint < Endpoint
154
- def address
155
- specification.address
156
- end
157
-
158
156
  def hostname
159
157
  options[:hostname]
160
158
  end
@@ -93,7 +93,7 @@ module Async
93
93
 
94
94
  protected
95
95
 
96
- if RUBY_VERSION >= "2.3"
96
+ if RUBY_ENGINE == "ruby" and RUBY_VERSION >= "2.3"
97
97
  def async_send(*args)
98
98
  async do
99
99
  @io.__send__(*args, exception: false)
@@ -114,7 +114,7 @@ module Async
114
114
  end
115
115
  end
116
116
  end
117
- elsif RUBY_VERSION >= "2.1"
117
+ elsif RUBY_ENGINE == "ruby" and RUBY_VERSION >= "2.1"
118
118
  def async_send(*args)
119
119
  async do
120
120
  @io.__send__(*args)
@@ -0,0 +1,57 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'generic'
22
+
23
+ module Async
24
+ module IO
25
+ # A cross-reactor/process notification pipe.
26
+ class Notification
27
+ def initialize
28
+ pipe = ::IO.pipe
29
+
30
+ @input = pipe.first
31
+ @output = pipe.last
32
+
33
+ @count = 0
34
+ end
35
+
36
+ def close
37
+ @input.close
38
+ @output.close
39
+ end
40
+
41
+ # Wait for signal to be called.
42
+ # @return [Object]
43
+ def wait
44
+ wrapper = Async::IO::Generic.new(@input)
45
+ wrapper.read(1)
46
+ ensure
47
+ wrapper.send(:close_monitor) if wrapper
48
+ end
49
+
50
+ # Signal to a given task that it should resume operations.
51
+ # @return [void]
52
+ def signal
53
+ @output.write(".")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -33,6 +33,10 @@ module Async
33
33
 
34
34
  wrap_blocking_method :sendmsg, :sendmsg_nonblock
35
35
  wrap_blocking_method :send, :sendmsg_nonblock, invert: false
36
+
37
+ def type
38
+ self.local_address.socktype
39
+ end
36
40
  end
37
41
 
38
42
  module ServerSocket
@@ -42,8 +46,8 @@ module Async
42
46
  wrapper = Socket.new(peer, self.reactor)
43
47
 
44
48
  if block_given?
45
- task.async do
46
- task.annotate "incoming connection #{address}"
49
+ task.async do |task|
50
+ task.annotate "incoming connection #{address.inspect}"
47
51
 
48
52
  begin
49
53
  yield wrapper, address
@@ -0,0 +1,64 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'notification'
22
+
23
+ module Async
24
+ module IO
25
+ # A cross-reactor/process notification pipe.
26
+ class Trap
27
+ def initialize(name)
28
+ @name = name
29
+ @notifications = []
30
+ end
31
+
32
+ def install!
33
+ Signal.trap(@name, &self.method(:trigger))
34
+
35
+ return self
36
+ end
37
+
38
+ # Block the calling task until the signal occurs.
39
+ def trap
40
+ task = Task.current
41
+ task.annotate("waiting for signal #{@name}")
42
+
43
+ notification = Notification.new
44
+ @notifications << notification
45
+
46
+ while true
47
+ notification.wait
48
+ yield
49
+ end
50
+ ensure
51
+ if notification
52
+ notification.close
53
+ @notifications.delete(notification)
54
+ end
55
+ end
56
+
57
+ # Signal all waiting tasks that the trap occurred.
58
+ # @return [void]
59
+ def trigger(signal_number = nil)
60
+ @notifications.each(&:signal)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.2.1"
23
+ VERSION = "1.3.0"
24
24
  end
25
25
  end
@@ -18,28 +18,25 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'async/io/endpoint'
21
+ # This seems to break rbx
22
+ # require 'async/io/endpoint'
22
23
 
23
24
  RSpec.describe Async::IO::Endpoint do
24
25
  include_context Async::RSpec::Reactor
25
26
 
26
- describe Async::IO::Endpoint.tcp('0.0.0.0', 1234) do
27
+ describe Async::IO::Endpoint.tcp('0.0.0.0', 5234, reuse_port: true) do
27
28
  it "should be a tcp binding" do
28
- expect(subject.socket_type).to be == ::Socket::SOCK_STREAM
29
- end
30
-
31
- it "should generate valid address" do
32
- expect(subject.address).to be == Async::IO::Address.tcp('0.0.0.0', 1234)
29
+ subject.bind do |server|
30
+ expect(server.local_address.socktype).to be == ::Socket::SOCK_STREAM
31
+ end
33
32
  end
34
33
  end
35
34
 
36
35
  describe Async::IO::SocketEndpoint.new(TCPServer.new('0.0.0.0', 1234)) do
37
- it "should be a tcp binding" do
38
- expect(subject.socket_type).to be == ::Socket::SOCK_STREAM
39
- end
40
-
41
- it "should generate valid address" do
42
- expect(subject.address).to be == Async::IO::Address.tcp('0.0.0.0', 1234)
36
+ it "should bind to given socket" do
37
+ subject.bind do |server|
38
+ expect(server.io).to be == subject.specification
39
+ end
43
40
  end
44
41
  end
45
42
  end
@@ -0,0 +1,44 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/notification'
22
+
23
+ RSpec.describe Async::IO::Notification do
24
+ include_context Async::RSpec::Reactor
25
+
26
+ it "should wait for notification" do
27
+ waiting_task = reactor.async do
28
+ subject.wait
29
+ end
30
+
31
+ expect(waiting_task.status).to be :running
32
+
33
+ signalling_task = reactor.async do
34
+ subject.signal
35
+ end
36
+
37
+ signalling_task.wait
38
+ waiting_task.wait
39
+
40
+ expect(waiting_task.status).to be :complete
41
+
42
+ subject.close
43
+ end
44
+ end
@@ -27,7 +27,7 @@ RSpec.describe Async::Reactor do
27
27
  include_context Async::RSpec::SSL::VerifiedContexts
28
28
 
29
29
  # Shared port for localhost network tests.
30
- let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 6779, reuse_port: true)}
30
+ let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 6779, reuse_port: true)}
31
31
  let(:server_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_context: server_context)}
32
32
  let(:client_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_context: client_context)}
33
33
 
@@ -0,0 +1,44 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/trap'
22
+
23
+ RSpec.describe Async::IO::Trap do
24
+ include_context Async::RSpec::Reactor
25
+
26
+ subject {described_class.new(:USR1)}
27
+
28
+ it "should wait for signal" do
29
+ trapped = false
30
+
31
+ waiting_task = reactor.async do
32
+ subject.trap do
33
+ trapped = true
34
+ break
35
+ end
36
+ end
37
+
38
+ subject.trigger
39
+
40
+ waiting_task.wait
41
+
42
+ expect(trapped).to be_truthy
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-07 00:00:00.000000000 Z
11
+ date: 2018-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.13'
47
+ version: '1.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.13'
54
+ version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -98,11 +98,13 @@ files:
98
98
  - lib/async/io/binary_string.rb
99
99
  - lib/async/io/endpoint.rb
100
100
  - lib/async/io/generic.rb
101
+ - lib/async/io/notification.rb
101
102
  - lib/async/io/protocol/line.rb
102
103
  - lib/async/io/socket.rb
103
104
  - lib/async/io/ssl_socket.rb
104
105
  - lib/async/io/stream.rb
105
106
  - lib/async/io/tcp_socket.rb
107
+ - lib/async/io/trap.rb
106
108
  - lib/async/io/udp_socket.rb
107
109
  - lib/async/io/unix_socket.rb
108
110
  - lib/async/io/version.rb
@@ -111,11 +113,13 @@ files:
111
113
  - spec/async/io/echo_spec.rb
112
114
  - spec/async/io/endpoint_spec.rb
113
115
  - spec/async/io/generic_spec.rb
116
+ - spec/async/io/notification_spec.rb
114
117
  - spec/async/io/protocol/line_spec.rb
115
118
  - spec/async/io/socket_spec.rb
116
119
  - spec/async/io/ssl_socket_spec.rb
117
120
  - spec/async/io/stream_spec.rb
118
121
  - spec/async/io/tcp_socket_spec.rb
122
+ - spec/async/io/trap_spec.rb
119
123
  - spec/async/io/udp_socket_spec.rb
120
124
  - spec/async/io/unix_socket_spec.rb
121
125
  - spec/async/io/wrap/tcp_spec.rb
@@ -139,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
143
  version: '0'
140
144
  requirements: []
141
145
  rubyforge_project:
142
- rubygems_version: 2.6.12
146
+ rubygems_version: 2.7.6
143
147
  signing_key:
144
148
  specification_version: 4
145
149
  summary: Provides support for asynchonous TCP, UDP, UNIX and SSL sockets.
@@ -148,11 +152,13 @@ test_files:
148
152
  - spec/async/io/echo_spec.rb
149
153
  - spec/async/io/endpoint_spec.rb
150
154
  - spec/async/io/generic_spec.rb
155
+ - spec/async/io/notification_spec.rb
151
156
  - spec/async/io/protocol/line_spec.rb
152
157
  - spec/async/io/socket_spec.rb
153
158
  - spec/async/io/ssl_socket_spec.rb
154
159
  - spec/async/io/stream_spec.rb
155
160
  - spec/async/io/tcp_socket_spec.rb
161
+ - spec/async/io/trap_spec.rb
156
162
  - spec/async/io/udp_socket_spec.rb
157
163
  - spec/async/io/unix_socket_spec.rb
158
164
  - spec/async/io/wrap/tcp_spec.rb