async-io 1.15.5 → 1.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/async-io.gemspec +0 -1
- data/lib/async/io/socket.rb +2 -2
- data/lib/async/io/stream.rb +12 -12
- data/lib/async/io/tcp_socket.rb +38 -1
- data/lib/async/io/version.rb +1 -1
- data/spec/async/io/socket_spec.rb +10 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11d4123b62b4c9d36348dffe2ce2e450924d491db1b3bd4f4ded739140637300
|
4
|
+
data.tar.gz: f707c236c48b1169dc1d26fe9101782c7c11ab26c9c05a6e5cd19bfa784183ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8f33cc994bf02d7ece78d249bf85418c9f5de2c079f49053cb4f7534e5d04b12f40a468fc7ef095c0cbacd04c1fe37291726b20c07f2f34c52453ac9b8ce4cb
|
7
|
+
data.tar.gz: 65424003ca8e5904e4984af6bf558f8e7378e873f6f1ec018aea0669187786ef3d348c4c546a5ecb8e80edc526eb41eb5ac09242f714263fec1badacad3d9cf9
|
data/async-io.gemspec
CHANGED
@@ -14,7 +14,6 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.executables = spec.files.grep(%r{^bin/}).map{|f| File.basename(f)}
|
15
15
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
16
|
spec.require_paths = ["lib"]
|
17
|
-
spec.has_rdoc = "yard"
|
18
17
|
|
19
18
|
spec.add_dependency "async", "~> 1.3"
|
20
19
|
spec.add_development_dependency "async-rspec", "~> 1.10"
|
data/lib/async/io/socket.rb
CHANGED
@@ -123,7 +123,7 @@ module Async
|
|
123
123
|
# @param local_address [Addrinfo] The local address to bind to before connecting.
|
124
124
|
# @option protcol [Integer] The socket protocol to use.
|
125
125
|
def self.connect(remote_address, local_address = nil, reuse_port: false, task: Task.current, **options)
|
126
|
-
|
126
|
+
Async.logger.debug(self) {"Connecting to #{remote_address.inspect}"}
|
127
127
|
|
128
128
|
task.annotate "connecting to #{remote_address.inspect}"
|
129
129
|
|
@@ -140,7 +140,7 @@ module Async
|
|
140
140
|
begin
|
141
141
|
wrapper.connect(remote_address.to_sockaddr)
|
142
142
|
task.annotate "connected to #{remote_address.inspect}"
|
143
|
-
rescue
|
143
|
+
rescue Exception
|
144
144
|
wrapper.close
|
145
145
|
raise
|
146
146
|
end
|
data/lib/async/io/stream.rb
CHANGED
@@ -79,10 +79,12 @@ module Async
|
|
79
79
|
return consume_read_buffer(size)
|
80
80
|
end
|
81
81
|
|
82
|
+
alias readpartial read_partial
|
83
|
+
|
82
84
|
# Efficiently read data from the stream until encountering pattern.
|
83
85
|
# @param pattern [String] The pattern to match.
|
84
86
|
# @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
|
85
|
-
def read_until(pattern, offset = 0)
|
87
|
+
def read_until(pattern, offset = 0, chomp: true)
|
86
88
|
until index = @read_buffer.index(pattern, offset)
|
87
89
|
offset = @read_buffer.size
|
88
90
|
|
@@ -90,7 +92,7 @@ module Async
|
|
90
92
|
end
|
91
93
|
|
92
94
|
@read_buffer.freeze
|
93
|
-
matched = @read_buffer.byteslice(0, index)
|
95
|
+
matched = @read_buffer.byteslice(0, index+(chomp ? 0 : pattern.bytesize))
|
94
96
|
@read_buffer = @read_buffer.byteslice(index+pattern.bytesize, @read_buffer.bytesize)
|
95
97
|
|
96
98
|
return matched
|
@@ -120,14 +122,14 @@ module Async
|
|
120
122
|
|
121
123
|
return string.bytesize
|
122
124
|
end
|
123
|
-
|
125
|
+
|
124
126
|
# Writes `string` to the stream and returns self.
|
125
127
|
def <<(string)
|
126
128
|
write(string)
|
127
129
|
|
128
130
|
return self
|
129
131
|
end
|
130
|
-
|
132
|
+
|
131
133
|
# Flushes buffered data to the stream.
|
132
134
|
def flush
|
133
135
|
unless @write_buffer.empty?
|
@@ -135,13 +137,11 @@ module Async
|
|
135
137
|
@write_buffer.clear
|
136
138
|
end
|
137
139
|
end
|
138
|
-
|
139
|
-
def gets(separator =
|
140
|
-
|
141
|
-
|
142
|
-
read_until(separator)
|
140
|
+
|
141
|
+
def gets(separator = $/, **options)
|
142
|
+
read_until(separator, **options)
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def puts(*args, separator: $/)
|
146
146
|
args.each do |arg|
|
147
147
|
@write_buffer << arg << separator
|
@@ -171,7 +171,7 @@ module Async
|
|
171
171
|
@io.close
|
172
172
|
end
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
# Returns true if the stream is at file which means there is no more data to be read.
|
176
176
|
def eof?
|
177
177
|
fill_read_buffer if !@eof && @read_buffer.empty?
|
@@ -203,7 +203,7 @@ module Async
|
|
203
203
|
return false
|
204
204
|
end
|
205
205
|
end
|
206
|
-
|
206
|
+
|
207
207
|
# Consumes at most `size` bytes from the buffer.
|
208
208
|
# @param size [Integer|nil] The amount of data to consume. If nil, consume entire buffer.
|
209
209
|
def consume_read_buffer(size = nil)
|
data/lib/async/io/tcp_socket.rb
CHANGED
@@ -28,6 +28,32 @@ module Async
|
|
28
28
|
class TCPSocket < IPSocket
|
29
29
|
wraps ::TCPSocket
|
30
30
|
|
31
|
+
class StreamWrapper
|
32
|
+
def initialize(io)
|
33
|
+
@io = io
|
34
|
+
end
|
35
|
+
|
36
|
+
def sync= value
|
37
|
+
@io.sync = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def close
|
41
|
+
@io.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def read(*args)
|
45
|
+
@io.sysread(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(*args)
|
49
|
+
@io.syswrite(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def flush
|
53
|
+
@io.flush
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
31
57
|
def initialize(remote_host, remote_port = nil, local_host = nil, local_port = nil)
|
32
58
|
if remote_host.is_a? ::TCPSocket
|
33
59
|
super(remote_host)
|
@@ -38,6 +64,7 @@ module Async
|
|
38
64
|
# We do this unusual dance to avoid leaking an "open" socket instance.
|
39
65
|
socket = Socket.connect(remote_address, local_address)
|
40
66
|
fd = socket.fcntl(Fcntl::F_DUPFD)
|
67
|
+
Async.logger.debug(self) {"Connected to #{remote_address.inspect}: #{fd}"}
|
41
68
|
socket.close
|
42
69
|
|
43
70
|
super(::TCPSocket.for_fd(fd))
|
@@ -46,7 +73,7 @@ module Async
|
|
46
73
|
# super(::TCPSocket.new(remote_host, remote_port, local_host, local_port))
|
47
74
|
end
|
48
75
|
|
49
|
-
@buffer = Stream.new(self)
|
76
|
+
@buffer = Stream.new(StreamWrapper.new(self))
|
50
77
|
end
|
51
78
|
|
52
79
|
class << self
|
@@ -58,6 +85,16 @@ module Async
|
|
58
85
|
attr :buffer
|
59
86
|
|
60
87
|
def_delegators :@buffer, :gets, :puts, :flush
|
88
|
+
|
89
|
+
def write(*)
|
90
|
+
@buffer.flush
|
91
|
+
|
92
|
+
super
|
93
|
+
end
|
94
|
+
|
95
|
+
def read(size)
|
96
|
+
@buffer.read_partial(size)
|
97
|
+
end
|
61
98
|
end
|
62
99
|
|
63
100
|
# Asynchronous TCP server wrappper.
|
data/lib/async/io/version.rb
CHANGED
@@ -39,6 +39,16 @@ RSpec.describe Async::IO::Socket do
|
|
39
39
|
Async::IO::Socket.connect(address)
|
40
40
|
end.to raise_error(Errno::ECONNREFUSED)
|
41
41
|
end
|
42
|
+
|
43
|
+
it "should close the socket when interrupted by a timeout" do
|
44
|
+
wrapper = double()
|
45
|
+
expect(Async::IO::Socket).to receive(:build).and_return(wrapper)
|
46
|
+
expect(wrapper).to receive(:connect).and_raise Async::TimeoutError
|
47
|
+
expect(wrapper).to receive(:close)
|
48
|
+
expect do
|
49
|
+
Async::IO::Socket.connect(address)
|
50
|
+
end.to raise_error(Async::TimeoutError)
|
51
|
+
end
|
42
52
|
end
|
43
53
|
|
44
54
|
describe '#bind' do
|
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.
|
4
|
+
version: 1.16.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-
|
11
|
+
date: 2018-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
168
|
version: '0'
|
169
169
|
requirements: []
|
170
170
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.7.
|
171
|
+
rubygems_version: 2.7.7
|
172
172
|
signing_key:
|
173
173
|
specification_version: 4
|
174
174
|
summary: Provides support for asynchonous TCP, UDP, UNIX and SSL sockets.
|