ione 1.2.0.pre1 → 1.2.0.pre2
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 +4 -4
- data/lib/ione/future.rb +44 -24
- data/lib/ione/io.rb +3 -0
- data/lib/ione/io/acceptor.rb +25 -11
- data/lib/ione/io/base_connection.rb +4 -1
- data/lib/ione/io/connection.rb +1 -4
- data/lib/ione/io/io_reactor.rb +46 -5
- data/lib/ione/io/server_connection.rb +1 -4
- data/lib/ione/io/ssl_acceptor.rb +21 -0
- data/lib/ione/io/ssl_connection.rb +79 -0
- data/lib/ione/io/ssl_server_connection.rb +43 -0
- data/lib/ione/version.rb +1 -1
- data/spec/integration/ssl_spec.rb +97 -0
- data/spec/ione/future_spec.rb +145 -30
- data/spec/ione/io/acceptor_spec.rb +7 -0
- data/spec/ione/io/connection_common.rb +28 -26
- data/spec/ione/io/io_reactor_spec.rb +50 -2
- data/spec/ione/io/ssl_acceptor_spec.rb +116 -0
- data/spec/ione/io/ssl_connection_spec.rb +165 -0
- data/spec/ione/io/ssl_server_connection_spec.rb +108 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 571332add4f394d8de9adbe6b371de13c84e3a09
|
4
|
+
data.tar.gz: 006892c0ffe2f9fdb489ba5848d28be6e45ad27c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f41e94213226b72a09487b4ff615ab01b3be84ffe351f5dcd78ef2e350a0bcc17b117395fdcf35944d8ab78f4ae9383821140fa43cfb15866f9e78af9cc970ec
|
7
|
+
data.tar.gz: 91778d76c5ef9fdf87ec0d51a29abb495056d0e3843badaec6ca6eeb86683f4aa82948a6e0a68d93ddf0dc012e54eafe4d84ba91d4d38224de3eb658297f1c2e
|
data/lib/ione/future.rb
CHANGED
@@ -44,7 +44,7 @@ module Ione
|
|
44
44
|
#
|
45
45
|
# @param [Ione::Future] future the future to observe
|
46
46
|
def observe(future)
|
47
|
-
future.on_complete do |
|
47
|
+
future.on_complete do |v, e|
|
48
48
|
if e
|
49
49
|
fail(e)
|
50
50
|
else
|
@@ -215,7 +215,7 @@ module Ione
|
|
215
215
|
# @return [Ione::Future] a new future representing the transformed value
|
216
216
|
def map(value=nil, &block)
|
217
217
|
f = CompletableFuture.new
|
218
|
-
on_complete do |
|
218
|
+
on_complete do |v, e|
|
219
219
|
if e
|
220
220
|
f.fail(e)
|
221
221
|
else
|
@@ -242,13 +242,13 @@ module Ione
|
|
242
242
|
# @return [Ione::Future] a new future representing the transformed value
|
243
243
|
def flat_map(&block)
|
244
244
|
f = CompletableFuture.new
|
245
|
-
on_complete do |
|
245
|
+
on_complete do |v, e|
|
246
246
|
if e
|
247
247
|
f.fail(e)
|
248
248
|
else
|
249
249
|
begin
|
250
250
|
ff = block.call(v)
|
251
|
-
ff.on_complete do |
|
251
|
+
ff.on_complete do |vv, ee|
|
252
252
|
if ee
|
253
253
|
f.fail(ee)
|
254
254
|
else
|
@@ -288,14 +288,14 @@ module Ione
|
|
288
288
|
# @return [Ione::Future] a new future representing the transformed value
|
289
289
|
def then(&block)
|
290
290
|
f = CompletableFuture.new
|
291
|
-
on_complete do |
|
291
|
+
on_complete do |v, e|
|
292
292
|
if e
|
293
293
|
f.fail(e)
|
294
294
|
else
|
295
295
|
begin
|
296
296
|
fv = block.call(v)
|
297
297
|
if fv.respond_to?(:on_complete)
|
298
|
-
fv.on_complete do |
|
298
|
+
fv.on_complete do |vv, ee|
|
299
299
|
if ee
|
300
300
|
f.fail(ee)
|
301
301
|
else
|
@@ -334,7 +334,7 @@ module Ione
|
|
334
334
|
# @return [Ione::Future] a new future representing a value recovered from the error
|
335
335
|
def recover(value=nil, &block)
|
336
336
|
f = CompletableFuture.new
|
337
|
-
on_complete do |
|
337
|
+
on_complete do |v, e|
|
338
338
|
if e
|
339
339
|
begin
|
340
340
|
f.resolve(block ? block.call(e) : value)
|
@@ -372,11 +372,11 @@ module Ione
|
|
372
372
|
# error
|
373
373
|
def fallback(&block)
|
374
374
|
f = CompletableFuture.new
|
375
|
-
on_complete do |
|
375
|
+
on_complete do |v, e|
|
376
376
|
if e
|
377
377
|
begin
|
378
378
|
ff = block.call(e)
|
379
|
-
ff.on_complete do |
|
379
|
+
ff.on_complete do |vv, ee|
|
380
380
|
if ee
|
381
381
|
f.fail(ee)
|
382
382
|
else
|
@@ -401,8 +401,8 @@ module Ione
|
|
401
401
|
#
|
402
402
|
# @yieldparam [Object] value the value of the resolved future
|
403
403
|
def on_value(&listener)
|
404
|
-
on_complete do |
|
405
|
-
listener.call(value)
|
404
|
+
on_complete do |value, error|
|
405
|
+
listener.call(value) unless error
|
406
406
|
end
|
407
407
|
nil
|
408
408
|
end
|
@@ -413,8 +413,8 @@ module Ione
|
|
413
413
|
#
|
414
414
|
# @yieldparam [Error] error the error that failed the future
|
415
415
|
def on_failure(&listener)
|
416
|
-
on_complete do |
|
417
|
-
listener.call(error) if
|
416
|
+
on_complete do |_, error|
|
417
|
+
listener.call(error) if error
|
418
418
|
end
|
419
419
|
nil
|
420
420
|
end
|
@@ -456,7 +456,7 @@ module Ione
|
|
456
456
|
end
|
457
457
|
end
|
458
458
|
if run_immediately
|
459
|
-
listener
|
459
|
+
call_listener(listener)
|
460
460
|
end
|
461
461
|
nil
|
462
462
|
end
|
@@ -493,6 +493,7 @@ module Ione
|
|
493
493
|
semaphore.pop
|
494
494
|
end
|
495
495
|
end
|
496
|
+
alias_method :get, :value
|
496
497
|
|
497
498
|
# Returns true if this future is resolved or failed
|
498
499
|
def completed?
|
@@ -526,6 +527,25 @@ module Ione
|
|
526
527
|
@lock.unlock
|
527
528
|
end
|
528
529
|
end
|
530
|
+
|
531
|
+
private
|
532
|
+
|
533
|
+
def call_listener(listener)
|
534
|
+
begin
|
535
|
+
n = listener.arity
|
536
|
+
if n == 1
|
537
|
+
listener.call(self)
|
538
|
+
elsif n == 2 || n == -3
|
539
|
+
listener.call(@value, @error)
|
540
|
+
elsif n == 0
|
541
|
+
listener.call
|
542
|
+
else
|
543
|
+
listener.call(@value, @error, self)
|
544
|
+
end
|
545
|
+
rescue
|
546
|
+
# swallowed
|
547
|
+
end
|
548
|
+
end
|
529
549
|
end
|
530
550
|
|
531
551
|
# @private
|
@@ -543,7 +563,7 @@ module Ione
|
|
543
563
|
@lock.unlock
|
544
564
|
end
|
545
565
|
listeners.each do |listener|
|
546
|
-
listener
|
566
|
+
call_listener(listener)
|
547
567
|
end
|
548
568
|
nil
|
549
569
|
end
|
@@ -561,7 +581,7 @@ module Ione
|
|
561
581
|
@lock.unlock
|
562
582
|
end
|
563
583
|
listeners.each do |listener|
|
564
|
-
listener
|
584
|
+
call_listener(listener)
|
565
585
|
end
|
566
586
|
nil
|
567
587
|
end
|
@@ -574,7 +594,7 @@ module Ione
|
|
574
594
|
remaining = futures.count
|
575
595
|
values = Array.new(remaining)
|
576
596
|
futures.each_with_index do |f, i|
|
577
|
-
f.on_complete do |
|
597
|
+
f.on_complete do |v, e|
|
578
598
|
unless failed?
|
579
599
|
if e
|
580
600
|
fail(e)
|
@@ -651,7 +671,7 @@ module Ione
|
|
651
671
|
private
|
652
672
|
|
653
673
|
def reduce_next(i)
|
654
|
-
@futures[i].on_complete do |
|
674
|
+
@futures[i].on_complete do |v, e|
|
655
675
|
unless failed?
|
656
676
|
if e
|
657
677
|
fail(e)
|
@@ -669,7 +689,7 @@ module Ione
|
|
669
689
|
super
|
670
690
|
if @remaining > 0
|
671
691
|
futures.each do |f|
|
672
|
-
f.on_complete do |
|
692
|
+
f.on_complete do |v, e|
|
673
693
|
unless failed?
|
674
694
|
if e
|
675
695
|
fail(e)
|
@@ -690,7 +710,7 @@ module Ione
|
|
690
710
|
def initialize(futures)
|
691
711
|
super()
|
692
712
|
futures.each do |f|
|
693
|
-
f.on_complete do |
|
713
|
+
f.on_complete do |v, e|
|
694
714
|
unless completed?
|
695
715
|
if e
|
696
716
|
if futures.all?(&:failed?)
|
@@ -721,7 +741,7 @@ module Ione
|
|
721
741
|
true
|
722
742
|
end
|
723
743
|
|
724
|
-
def
|
744
|
+
def resolvesd?
|
725
745
|
true
|
726
746
|
end
|
727
747
|
|
@@ -730,7 +750,7 @@ module Ione
|
|
730
750
|
end
|
731
751
|
|
732
752
|
def on_complete(&listener)
|
733
|
-
listener
|
753
|
+
call_listener(listener)
|
734
754
|
end
|
735
755
|
|
736
756
|
def on_value(&listener)
|
@@ -768,7 +788,7 @@ module Ione
|
|
768
788
|
end
|
769
789
|
|
770
790
|
def on_complete(&listener)
|
771
|
-
listener
|
791
|
+
call_listener(listener)
|
772
792
|
end
|
773
793
|
|
774
794
|
def on_value
|
@@ -778,4 +798,4 @@ module Ione
|
|
778
798
|
listener.call(@error) rescue nil
|
779
799
|
end
|
780
800
|
end
|
781
|
-
end
|
801
|
+
end
|
data/lib/ione/io.rb
CHANGED
data/lib/ione/io/acceptor.rb
CHANGED
@@ -6,6 +6,8 @@ module Ione
|
|
6
6
|
class Acceptor
|
7
7
|
ServerSocket = RUBY_ENGINE == 'jruby' ? ::ServerSocket : Socket
|
8
8
|
|
9
|
+
attr_reader :backlog
|
10
|
+
|
9
11
|
def initialize(host, port, backlog, unblocker, reactor, socket_impl=nil)
|
10
12
|
@host = host
|
11
13
|
@port = port
|
@@ -27,8 +29,8 @@ module Ione
|
|
27
29
|
addrinfos = @socket_impl.getaddrinfo(@host, @port, nil, Socket::SOCK_STREAM)
|
28
30
|
begin
|
29
31
|
_, port, _, ip, address_family, socket_type = addrinfos.shift
|
30
|
-
@
|
31
|
-
bind_socket(@
|
32
|
+
@io = @socket_impl.new(address_family, socket_type, 0)
|
33
|
+
bind_socket(@io, @socket_impl.sockaddr_in(port, ip), @backlog)
|
32
34
|
rescue Errno::EADDRNOTAVAIL => e
|
33
35
|
if addrinfos.empty?
|
34
36
|
raise
|
@@ -38,26 +40,27 @@ module Ione
|
|
38
40
|
end
|
39
41
|
Future.resolved(self)
|
40
42
|
rescue => e
|
43
|
+
close
|
41
44
|
Future.failed(e)
|
42
45
|
end
|
43
46
|
|
44
47
|
def close
|
45
|
-
return false unless @
|
48
|
+
return false unless @io
|
46
49
|
begin
|
47
|
-
@
|
50
|
+
@io.close
|
48
51
|
rescue SystemCallError, IOError
|
49
52
|
# nothing to do, the socket was most likely already closed
|
50
53
|
end
|
51
|
-
@
|
54
|
+
@io = nil
|
52
55
|
true
|
53
56
|
end
|
54
57
|
|
55
58
|
def to_io
|
56
|
-
@
|
59
|
+
@io
|
57
60
|
end
|
58
61
|
|
59
62
|
def closed?
|
60
|
-
@
|
63
|
+
@io.nil?
|
61
64
|
end
|
62
65
|
|
63
66
|
def connected?
|
@@ -73,12 +76,10 @@ module Ione
|
|
73
76
|
end
|
74
77
|
|
75
78
|
def read
|
76
|
-
client_socket,
|
77
|
-
port, host = @socket_impl.unpack_sockaddr_in(client_sockaddr)
|
79
|
+
client_socket, host, port = accept
|
78
80
|
connection = ServerConnection.new(client_socket, host, port, @unblocker)
|
79
81
|
@reactor.accept(connection)
|
80
|
-
|
81
|
-
listeners.each { |l| l.call(connection) rescue nil }
|
82
|
+
notify_accept_listeners(connection)
|
82
83
|
end
|
83
84
|
|
84
85
|
if RUBY_ENGINE == 'jruby'
|
@@ -91,6 +92,19 @@ module Ione
|
|
91
92
|
socket.listen(backlog)
|
92
93
|
end
|
93
94
|
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def accept
|
99
|
+
client_socket, client_sockaddr = @io.accept_nonblock
|
100
|
+
port, host = @socket_impl.unpack_sockaddr_in(client_sockaddr)
|
101
|
+
return client_socket, host, port
|
102
|
+
end
|
103
|
+
|
104
|
+
def notify_accept_listeners(connection)
|
105
|
+
listeners = @lock.synchronize { @accept_listeners }
|
106
|
+
listeners.each { |l| l.call(connection) rescue nil }
|
107
|
+
end
|
94
108
|
end
|
95
109
|
end
|
96
110
|
end
|
@@ -5,10 +5,13 @@ module Ione
|
|
5
5
|
class BaseConnection
|
6
6
|
attr_reader :host, :port
|
7
7
|
|
8
|
-
def initialize(host, port)
|
8
|
+
def initialize(host, port, unblocker)
|
9
9
|
@host = host
|
10
10
|
@port = port
|
11
|
+
@unblocker = unblocker
|
11
12
|
@state = :connecting
|
13
|
+
@lock = Mutex.new
|
14
|
+
@write_buffer = ByteBuffer.new
|
12
15
|
@closed_promise = Promise.new
|
13
16
|
end
|
14
17
|
|
data/lib/ione/io/connection.rb
CHANGED
@@ -9,13 +9,10 @@ module Ione
|
|
9
9
|
|
10
10
|
# @private
|
11
11
|
def initialize(host, port, connection_timeout, unblocker, clock, socket_impl=Socket)
|
12
|
-
super(host, port)
|
12
|
+
super(host, port, unblocker)
|
13
13
|
@connection_timeout = connection_timeout
|
14
|
-
@unblocker = unblocker
|
15
14
|
@clock = clock
|
16
15
|
@socket_impl = socket_impl
|
17
|
-
@lock = Mutex.new
|
18
|
-
@write_buffer = ByteBuffer.new
|
19
16
|
@connected_promise = Promise.new
|
20
17
|
on_closed(&method(:cleanup_on_close))
|
21
18
|
end
|
data/lib/ione/io/io_reactor.rb
CHANGED
@@ -156,23 +156,57 @@ module Ione
|
|
156
156
|
#
|
157
157
|
# @param host [String] the host to connect to
|
158
158
|
# @param port [Integer] the port to connect to
|
159
|
-
# @param
|
160
|
-
#
|
159
|
+
# @param options_or_timeout [Hash, Numeric] a hash of options (see below)
|
160
|
+
# or the connection timeout (equivalent to using the `:timeout` option).
|
161
|
+
# @option options_or_timeout [Numeric] :timeout (5) the number of seconds
|
162
|
+
# to wait for a connection before failing
|
163
|
+
# @option options_or_timeout [Boolean, OpenSSL::SSL::SSLContext] :ssl (false)
|
164
|
+
# pass an `OpenSSL::SSL::SSLContext` to upgrade the connection to SSL,
|
165
|
+
# or true to upgrade the connection and create a new context.
|
161
166
|
# @yieldparam [Ione::Io::Connection] connection the newly opened connection
|
162
167
|
# @return [Ione::Future] a future that will resolve when the connection is
|
163
168
|
# open. The value will be the connection, or when a block is given to
|
164
169
|
# what the block returns
|
165
|
-
def connect(host, port,
|
170
|
+
def connect(host, port, options=nil, &block)
|
171
|
+
if options.is_a?(Numeric) || options.nil?
|
172
|
+
timeout = options || 5
|
173
|
+
ssl = false
|
174
|
+
elsif options
|
175
|
+
timeout = options[:timeout] || 5
|
176
|
+
ssl = options[:ssl]
|
177
|
+
end
|
166
178
|
connection = Connection.new(host, port, timeout, @unblocker, @clock)
|
167
179
|
f = connection.connect
|
168
180
|
@io_loop.add_socket(connection)
|
169
181
|
@unblocker.unblock!
|
182
|
+
if ssl
|
183
|
+
f = f.flat_map do
|
184
|
+
ssl_context = ssl == true ? nil : ssl
|
185
|
+
upgraded_connection = SslConnection.new(host, port, connection.to_io, @unblocker, ssl_context)
|
186
|
+
ff = upgraded_connection.connect
|
187
|
+
@io_loop.remove_socket(connection)
|
188
|
+
@io_loop.add_socket(upgraded_connection)
|
189
|
+
@unblocker.unblock!
|
190
|
+
ff
|
191
|
+
end
|
192
|
+
end
|
170
193
|
f = f.map(&block) if block_given?
|
171
194
|
f
|
172
195
|
end
|
173
196
|
|
174
|
-
def bind(host, port,
|
175
|
-
|
197
|
+
def bind(host, port, options=nil, &block)
|
198
|
+
if options.is_a?(Integer) || options.nil?
|
199
|
+
backlog = options || 5
|
200
|
+
ssl_context = nil
|
201
|
+
elsif options
|
202
|
+
backlog = options[:backlog] || 5
|
203
|
+
ssl_context = options[:ssl]
|
204
|
+
end
|
205
|
+
if ssl_context
|
206
|
+
server = SslAcceptor.new(host, port, backlog, @unblocker, self, ssl_context)
|
207
|
+
else
|
208
|
+
server = Acceptor.new(host, port, backlog, @unblocker, self)
|
209
|
+
end
|
176
210
|
f = server.bind
|
177
211
|
@io_loop.add_socket(server)
|
178
212
|
@unblocker.unblock!
|
@@ -261,6 +295,7 @@ module Ione
|
|
261
295
|
private
|
262
296
|
|
263
297
|
PING_BYTE = "\0".freeze
|
298
|
+
DEFAULT_CONNECT_OPTIONS = {:timeout => 5}.freeze
|
264
299
|
end
|
265
300
|
|
266
301
|
# @private
|
@@ -282,6 +317,12 @@ module Ione
|
|
282
317
|
@lock.unlock
|
283
318
|
end
|
284
319
|
|
320
|
+
def remove_socket(socket)
|
321
|
+
@lock.synchronize do
|
322
|
+
@sockets = @sockets.reject { |s| s == socket || s.closed? }
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
285
326
|
def schedule_timer(timeout, promise=Promise.new)
|
286
327
|
@lock.lock
|
287
328
|
timers = @timers.reject { |pair| pair[1].nil? }
|
@@ -5,11 +5,8 @@ module Ione
|
|
5
5
|
class ServerConnection < BaseConnection
|
6
6
|
# @private
|
7
7
|
def initialize(socket, host, port, unblocker)
|
8
|
-
super(host, port)
|
8
|
+
super(host, port, unblocker)
|
9
9
|
@io = socket
|
10
|
-
@unblocker = unblocker
|
11
|
-
@lock = Mutex.new
|
12
|
-
@write_buffer = ByteBuffer.new
|
13
10
|
@state = :connected
|
14
11
|
end
|
15
12
|
end
|