rev 0.2.0 → 0.2.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.
- data/CHANGES +16 -0
- data/README +1 -0
- data/Rakefile +10 -0
- data/ext/http11_client/http11_parser.c +563 -502
- data/ext/http11_client/http11_parser.rl +1 -1
- data/ext/libev/Changes +39 -1
- data/ext/libev/ev.c +286 -105
- data/ext/libev/ev.h +102 -34
- data/ext/libev/ev_poll.c +17 -14
- data/ext/libev/ev_select.c +4 -4
- data/ext/libev/ev_vars.h +14 -1
- data/ext/libev/ev_wrap.h +14 -0
- data/ext/rev/extconf.rb +15 -11
- data/ext/rev/rev_loop.c +35 -34
- data/ext/rev/rev_ssl.c +90 -3
- data/lib/rev.rb +8 -2
- data/lib/rev/http_client.rb +6 -6
- data/lib/rev/io.rb +53 -29
- data/lib/rev/io_watcher.rb +2 -1
- data/lib/rev/{watcher.rb → meta.rb} +3 -3
- data/lib/rev/server.rb +2 -2
- data/lib/rev/socket.rb +27 -21
- data/lib/rev/ssl.rb +35 -49
- data/lib/rev/timer_watcher.rb +1 -0
- data/rev.gemspec +2 -2
- metadata +3 -3
data/ext/rev/rev_ssl.c
CHANGED
@@ -38,6 +38,44 @@ static VALUE Rev_SSL_IO_start_ssl(VALUE self, int (*func)(), const char *funcnam
|
|
38
38
|
static VALUE Rev_SSL_IO_read_nonblock(int argc, VALUE *argv, VALUE self);
|
39
39
|
static VALUE Rev_SSL_IO_write_nonblock(VALUE self, VALUE str);
|
40
40
|
|
41
|
+
/*
|
42
|
+
* Time to monkey patch some C code!
|
43
|
+
*/
|
44
|
+
|
45
|
+
/* Ruby 1.8 leaves us no recourse but to commonly couple to the OpenSSL native
|
46
|
+
extension through externs. Ugh */
|
47
|
+
#if RUBY_VERSION_CODE < 190
|
48
|
+
|
49
|
+
/* Externs from Ruby's OpenSSL native extension , in ossl_ssl.c*/
|
50
|
+
extern int ossl_ssl_ex_vcb_idx;
|
51
|
+
extern int ossl_ssl_ex_store_p;
|
52
|
+
extern int ossl_ssl_ex_ptr_idx;
|
53
|
+
extern int ossl_ssl_ex_client_cert_cb_idx;
|
54
|
+
extern int ossl_ssl_ex_tmp_dh_callback_idx;
|
55
|
+
|
56
|
+
/* #defines shamelessly copied and pasted from ossl_ssl.c */
|
57
|
+
#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
|
58
|
+
#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
|
59
|
+
#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
|
60
|
+
#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
|
61
|
+
#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
|
62
|
+
|
63
|
+
#ifdef _WIN32
|
64
|
+
# define TO_SOCKET(s) _get_osfhandle(s)
|
65
|
+
#else
|
66
|
+
# define TO_SOCKET(s) s
|
67
|
+
#endif
|
68
|
+
|
69
|
+
#endif
|
70
|
+
|
71
|
+
#ifndef HAVE_RB_STR_SET_LEN
|
72
|
+
static void rb_str_set_len(VALUE str, long len)
|
73
|
+
{
|
74
|
+
RSTRING(str)->len = len;
|
75
|
+
RSTRING(str)->ptr[len] = '\0';
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
|
41
79
|
void Init_rev_ssl()
|
42
80
|
{
|
43
81
|
rb_require("openssl");
|
@@ -63,6 +101,47 @@ void Init_rev_ssl()
|
|
63
101
|
rb_define_method(cRev_SSL_IO, "write_nonblock", Rev_SSL_IO_write_nonblock, 1);
|
64
102
|
}
|
65
103
|
|
104
|
+
#if RUBY_VERSION_CODE < 190
|
105
|
+
/* SSL initialization for Ruby 1.8 */
|
106
|
+
static VALUE
|
107
|
+
Rev_SSL_IO_ssl_setup(VALUE self)
|
108
|
+
{
|
109
|
+
VALUE io, v_ctx, cb;
|
110
|
+
SSL_CTX *ctx;
|
111
|
+
SSL *ssl;
|
112
|
+
OpenFile *fptr;
|
113
|
+
|
114
|
+
Data_Get_Struct(self, SSL, ssl);
|
115
|
+
if(!ssl) {
|
116
|
+
v_ctx = ossl_ssl_get_ctx(self);
|
117
|
+
Data_Get_Struct(v_ctx, SSL_CTX, ctx);
|
118
|
+
|
119
|
+
ssl = SSL_new(ctx);
|
120
|
+
if (!ssl) {
|
121
|
+
ossl_raise(eSSLError, "SSL_new:");
|
122
|
+
}
|
123
|
+
DATA_PTR(self) = ssl;
|
124
|
+
|
125
|
+
io = ossl_ssl_get_io(self);
|
126
|
+
GetOpenFile(io, fptr);
|
127
|
+
rb_io_check_readable(fptr);
|
128
|
+
rb_io_check_writable(fptr);
|
129
|
+
SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
|
130
|
+
SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
|
131
|
+
cb = ossl_sslctx_get_verify_cb(v_ctx);
|
132
|
+
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
|
133
|
+
cb = ossl_sslctx_get_client_cert_cb(v_ctx);
|
134
|
+
SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
|
135
|
+
cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
|
136
|
+
SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
|
137
|
+
}
|
138
|
+
|
139
|
+
return Qtrue;
|
140
|
+
}
|
141
|
+
#endif
|
142
|
+
|
143
|
+
#if RUBY_VERSION_CODE >= 190
|
144
|
+
/* Slightly less insane SSL setup for Ruby 1.9 */
|
66
145
|
static VALUE
|
67
146
|
Rev_SSL_IO_ssl_setup(VALUE self)
|
68
147
|
{
|
@@ -95,15 +174,13 @@ Rev_SSL_IO_ssl_setup(VALUE self)
|
|
95
174
|
*/
|
96
175
|
rb_funcall(self, rb_intern("session="), 1, Qnil);
|
97
176
|
}
|
177
|
+
#endif
|
98
178
|
|
99
179
|
/* Ensure the error raised by calling #session= with a dummy argument is
|
100
180
|
* the one we were expecting */
|
101
181
|
static VALUE
|
102
182
|
Rev_SSL_IO_ssl_setup_check(VALUE dummy, VALUE err)
|
103
183
|
{
|
104
|
-
if(!rb_obj_is_kind_of(err, rb_eTypeError))
|
105
|
-
rb_raise(rb_eRuntimeError, "Rev::SSL not supported in this Ruby version, sorry");
|
106
|
-
|
107
184
|
return Qnil;
|
108
185
|
}
|
109
186
|
|
@@ -114,7 +191,12 @@ Rev_SSL_IO_ssl_setup_check(VALUE dummy, VALUE err)
|
|
114
191
|
static VALUE
|
115
192
|
Rev_SSL_IO_connect_nonblock(VALUE self)
|
116
193
|
{
|
194
|
+
#if RUBY_VERSION_CODE >= 190
|
117
195
|
rb_rescue(Rev_SSL_IO_ssl_setup, self, Rev_SSL_IO_ssl_setup_check, Qnil);
|
196
|
+
#else
|
197
|
+
Rev_SSL_IO_ssl_setup(self);
|
198
|
+
#endif
|
199
|
+
|
118
200
|
return Rev_SSL_IO_start_ssl(self, SSL_connect, "SSL_connect");
|
119
201
|
}
|
120
202
|
|
@@ -125,7 +207,12 @@ Rev_SSL_IO_connect_nonblock(VALUE self)
|
|
125
207
|
static VALUE
|
126
208
|
Rev_SSL_IO_accept_nonblock(VALUE self)
|
127
209
|
{
|
210
|
+
#if RUBY_VERSION_CODE >= 190
|
128
211
|
rb_rescue(Rev_SSL_IO_ssl_setup, self, 0, 0);
|
212
|
+
#else
|
213
|
+
Rev_SSL_IO_ssl_setup(self);
|
214
|
+
#endif
|
215
|
+
|
129
216
|
return Rev_SSL_IO_start_ssl(self, SSL_accept, "SSL_accept");
|
130
217
|
}
|
131
218
|
|
data/lib/rev.rb
CHANGED
@@ -4,9 +4,15 @@
|
|
4
4
|
# See file LICENSE for details
|
5
5
|
#++
|
6
6
|
|
7
|
+
# Pull in the OpenSSL extension if available
|
8
|
+
begin
|
9
|
+
require 'openssl'
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
7
13
|
require File.dirname(__FILE__) + '/rev_ext'
|
8
14
|
require File.dirname(__FILE__) + '/rev/loop'
|
9
|
-
require File.dirname(__FILE__) + '/rev/
|
15
|
+
require File.dirname(__FILE__) + '/rev/meta'
|
10
16
|
require File.dirname(__FILE__) + '/rev/io_watcher'
|
11
17
|
require File.dirname(__FILE__) + '/rev/timer_watcher'
|
12
18
|
require File.dirname(__FILE__) + '/rev/async_watcher'
|
@@ -18,6 +24,6 @@ require File.dirname(__FILE__) + '/rev/server'
|
|
18
24
|
require File.dirname(__FILE__) + '/rev/http_client'
|
19
25
|
|
20
26
|
module Rev
|
21
|
-
Rev::VERSION = '0.2.
|
27
|
+
Rev::VERSION = '0.2.1' unless defined? Rev::VERSION
|
22
28
|
def self.version() VERSION end
|
23
29
|
end
|
data/lib/rev/http_client.rb
CHANGED
@@ -68,7 +68,7 @@ module Rev
|
|
68
68
|
|
69
69
|
# Map all header keys to a downcased string version
|
70
70
|
def munge_header_keys(head)
|
71
|
-
head.
|
71
|
+
head.inject({}) { |h, (k, v)| h[k.to_s.downcase] = v; h }
|
72
72
|
end
|
73
73
|
|
74
74
|
# HTTP is kind of retarded that you have to specify
|
@@ -98,15 +98,15 @@ module Rev
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def encode_headers(head)
|
101
|
-
head.
|
101
|
+
head.inject('') do |result, (key, value)|
|
102
102
|
# Munge keys from foo-bar-baz to Foo-Bar-Baz
|
103
|
-
|
104
|
-
result << encode_field(
|
103
|
+
key = key.split('-').map { |k| k.capitalize }.join('-')
|
104
|
+
result << encode_field(key, value)
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
108
|
def encode_cookies(cookies)
|
109
|
-
cookies.
|
109
|
+
cookies.inject('') { |result, (k, v)| result << encode_field('Cookie', encode_param(k, v)) }
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
@@ -167,7 +167,7 @@ module Rev
|
|
167
167
|
# Specify the request body (you must encode it for now)
|
168
168
|
#
|
169
169
|
def request(method, path, options = {})
|
170
|
-
raise ArgumentError, "invalid request path" unless
|
170
|
+
raise ArgumentError, "invalid request path" unless /^\// === path
|
171
171
|
raise RuntimeError, "request already sent" if @requested
|
172
172
|
|
173
173
|
@method, @path, @options = method, path, options
|
data/lib/rev/io.rb
CHANGED
@@ -13,16 +13,44 @@ module Rev
|
|
13
13
|
# This class is primarily meant as a base class for other streams
|
14
14
|
# which need non-blocking writing, and is used to implement Rev's
|
15
15
|
# Socket class and its associated subclasses.
|
16
|
-
class IO
|
16
|
+
class IO
|
17
|
+
extend Meta
|
18
|
+
|
17
19
|
# Maximum number of bytes to consume at once
|
18
20
|
INPUT_SIZE = 16384
|
19
21
|
|
20
22
|
def initialize(io)
|
21
|
-
@
|
22
|
-
@
|
23
|
-
|
23
|
+
@_io = io
|
24
|
+
@_write_buffer = Rev::Buffer.new
|
25
|
+
@_read_watcher = Watcher.new(io, self, :r)
|
26
|
+
@_write_watcher = Watcher.new(io, self, :w)
|
24
27
|
end
|
25
28
|
|
29
|
+
#
|
30
|
+
# Watcher methods, delegated to @_read_watcher
|
31
|
+
#
|
32
|
+
|
33
|
+
# Attach to the event loop
|
34
|
+
def attach(loop); @_read_watcher.attach loop; self; end
|
35
|
+
|
36
|
+
# Detach from the event loop
|
37
|
+
def detach; @_read_watcher.detach; self; end
|
38
|
+
|
39
|
+
# Enable the watcher
|
40
|
+
def enable; @_read_watcher.enable; self; end
|
41
|
+
|
42
|
+
# Disable the watcher
|
43
|
+
def disable; @_read_watcher.disable; self; end
|
44
|
+
|
45
|
+
# Is the watcher attached?
|
46
|
+
def attached?; @_read_watcher.attached?; end
|
47
|
+
|
48
|
+
# Is the watcher enabled?
|
49
|
+
def enabled?; @_read_watcher.enabled?; end
|
50
|
+
|
51
|
+
# Obtain the event loop associated with this object
|
52
|
+
def evloop; @_read_watcher.evloop; end
|
53
|
+
|
26
54
|
#
|
27
55
|
# Callbacks for asynchronous events
|
28
56
|
#
|
@@ -45,21 +73,21 @@ module Rev
|
|
45
73
|
|
46
74
|
# Write data in a buffered, non-blocking manner
|
47
75
|
def write(data)
|
48
|
-
@
|
76
|
+
@_write_buffer << data
|
49
77
|
schedule_write
|
50
78
|
data.size
|
51
79
|
end
|
52
80
|
|
53
81
|
# Number of bytes are currently in the output buffer
|
54
82
|
def output_buffer_size
|
55
|
-
@
|
83
|
+
@_write_buffer.size
|
56
84
|
end
|
57
85
|
|
58
86
|
# Close the IO stream
|
59
87
|
def close
|
60
88
|
detach if attached?
|
61
89
|
detach_write_watcher
|
62
|
-
@
|
90
|
+
@_io.close unless @_io.closed?
|
63
91
|
|
64
92
|
on_close
|
65
93
|
nil
|
@@ -67,7 +95,7 @@ module Rev
|
|
67
95
|
|
68
96
|
# Is the IO object closed?
|
69
97
|
def closed?
|
70
|
-
@
|
98
|
+
@_io.closed?
|
71
99
|
end
|
72
100
|
|
73
101
|
#########
|
@@ -77,7 +105,8 @@ module Rev
|
|
77
105
|
# Read from the input buffer and dispatch to on_read
|
78
106
|
def on_readable
|
79
107
|
begin
|
80
|
-
on_read @
|
108
|
+
on_read @_io.read_nonblock(INPUT_SIZE)
|
109
|
+
rescue Errno::EAGAIN
|
81
110
|
rescue Errno::ECONNRESET, EOFError
|
82
111
|
close
|
83
112
|
end
|
@@ -86,12 +115,12 @@ module Rev
|
|
86
115
|
# Write the contents of the output buffer
|
87
116
|
def on_writable
|
88
117
|
begin
|
89
|
-
@
|
118
|
+
@_write_buffer.write_to(@_io)
|
90
119
|
rescue Errno::EPIPE, Errno::ECONNRESET
|
91
120
|
return close
|
92
121
|
end
|
93
122
|
|
94
|
-
if @
|
123
|
+
if @_write_buffer.empty?
|
95
124
|
disable_write_watcher
|
96
125
|
on_write_complete
|
97
126
|
end
|
@@ -105,37 +134,32 @@ module Rev
|
|
105
134
|
end
|
106
135
|
end
|
107
136
|
|
108
|
-
# Return a handle to the writing IOWatcher
|
109
|
-
def write_watcher
|
110
|
-
@write_watcher ||= WriteWatcher.new(@io, self)
|
111
|
-
end
|
112
|
-
|
113
137
|
def enable_write_watcher
|
114
|
-
if
|
115
|
-
|
138
|
+
if @_write_watcher.attached?
|
139
|
+
@_write_watcher.enable unless @_write_watcher.enabled?
|
116
140
|
else
|
117
|
-
|
141
|
+
@_write_watcher.attach(evloop)
|
118
142
|
end
|
119
143
|
end
|
120
144
|
|
121
145
|
def disable_write_watcher
|
122
|
-
@
|
146
|
+
@_write_watcher.disable if @_write_watcher and @_write_watcher.enabled?
|
123
147
|
end
|
124
148
|
|
125
149
|
def detach_write_watcher
|
126
|
-
@
|
150
|
+
@_write_watcher.detach if @_write_watcher and @_write_watcher.attached?
|
127
151
|
end
|
128
|
-
|
129
|
-
class
|
130
|
-
|
152
|
+
|
153
|
+
# Internal class implementing watchers used by Rev::IO
|
154
|
+
class Watcher < IOWatcher
|
155
|
+
def initialize(ruby_io, rev_io, flags)
|
131
156
|
@rev_io = rev_io
|
132
|
-
super(ruby_io,
|
157
|
+
super(ruby_io, flags)
|
133
158
|
end
|
134
159
|
|
135
|
-
#
|
136
|
-
def
|
137
|
-
|
138
|
-
end
|
160
|
+
# Configure IOWatcher event callbacks to call the method passed to #initialize
|
161
|
+
def on_readable; @rev_io.__send__(:on_readable); end
|
162
|
+
def on_writable; @rev_io.__send__(:on_writable); end
|
139
163
|
end
|
140
164
|
end
|
141
165
|
end
|
data/lib/rev/io_watcher.rb
CHANGED
@@ -5,12 +5,13 @@
|
|
5
5
|
#++
|
6
6
|
|
7
7
|
module Rev
|
8
|
-
class IOWatcher
|
8
|
+
class IOWatcher
|
9
9
|
# The actual implementation of this class resides in the C extension
|
10
10
|
# Here we metaprogram proper event_callbacks for the callback methods
|
11
11
|
# These can take a block and store it to be called when the event
|
12
12
|
# is actually fired.
|
13
13
|
|
14
|
+
extend Meta
|
14
15
|
event_callback :on_readable, :on_writable
|
15
16
|
end
|
16
17
|
end
|
@@ -5,12 +5,12 @@
|
|
5
5
|
#++
|
6
6
|
|
7
7
|
module Rev
|
8
|
-
|
8
|
+
module Meta
|
9
9
|
# Use an alternate watcher with the attach/detach/enable/disable methods
|
10
10
|
# if it is presently assigned. This is useful if you are waiting for
|
11
11
|
# an event to occur before the current watcher can be used in earnest,
|
12
12
|
# such as making an outgoing TCP connection.
|
13
|
-
def
|
13
|
+
def watcher_delegate(proxy_var)
|
14
14
|
%w{attach detach enable disable}.each do |method|
|
15
15
|
module_eval <<-EOD
|
16
16
|
def #{method}(*args)
|
@@ -29,7 +29,7 @@ module Rev
|
|
29
29
|
# This is done by giving a block to the callback method, which is captured
|
30
30
|
# as a proc and stored for later. If the method is called without a block,
|
31
31
|
# the stored block is executed if present, otherwise it's a noop.
|
32
|
-
def
|
32
|
+
def event_callback(*methods)
|
33
33
|
methods.each do |method|
|
34
34
|
module_eval <<-EOD
|
35
35
|
def #{method}(*args, &block)
|
data/lib/rev/server.rb
CHANGED
@@ -11,8 +11,8 @@ module Rev
|
|
11
11
|
# connections is a Socket, but any subclass of IOWatcher is acceptable.
|
12
12
|
def initialize(listen_socket, klass = Socket, *args, &block)
|
13
13
|
# Ensure the provided class responds to attach
|
14
|
-
unless klass.allocate.is_a?
|
15
|
-
raise ArgumentError, "
|
14
|
+
unless klass.allocate.is_a? IO
|
15
|
+
raise ArgumentError, "can't convert #{klass} to Rev::IO"
|
16
16
|
end
|
17
17
|
|
18
18
|
# Verify the arity of the provided arguments
|
data/lib/rev/socket.rb
CHANGED
@@ -10,19 +10,19 @@ require 'resolv'
|
|
10
10
|
module Rev
|
11
11
|
class Socket < IO
|
12
12
|
def self.connect(socket, *args)
|
13
|
-
new(socket, *args).instance_eval
|
14
|
-
@
|
13
|
+
new(socket, *args).instance_eval do
|
14
|
+
@_connector = Connector.new(self, socket)
|
15
15
|
self
|
16
|
-
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
|
-
watcher_delegate :@
|
19
|
+
watcher_delegate :@_connector
|
20
20
|
|
21
21
|
def attach(evloop)
|
22
|
-
raise RuntimeError, "connection failed" if @
|
22
|
+
raise RuntimeError, "connection failed" if @_failed
|
23
23
|
|
24
|
-
if @
|
25
|
-
@
|
24
|
+
if @_connector
|
25
|
+
@_connector.attach(evloop)
|
26
26
|
return self
|
27
27
|
end
|
28
28
|
|
@@ -56,11 +56,11 @@ module Rev
|
|
56
56
|
detach
|
57
57
|
|
58
58
|
if connect_successful?
|
59
|
-
@rev_socket.instance_eval { @
|
59
|
+
@rev_socket.instance_eval { @_connector = nil }
|
60
60
|
@rev_socket.attach(evl)
|
61
61
|
@rev_socket.__send__(:on_connect)
|
62
62
|
else
|
63
|
-
@rev_socket.instance_eval { @
|
63
|
+
@rev_socket.instance_eval { @_failed = true }
|
64
64
|
@rev_socket.__send__(:on_connect_failed)
|
65
65
|
end
|
66
66
|
end
|
@@ -77,7 +77,7 @@ module Rev
|
|
77
77
|
|
78
78
|
class TCPSocket < Socket
|
79
79
|
attr_reader :remote_host, :remote_addr, :remote_port, :address_family
|
80
|
-
watcher_delegate :@
|
80
|
+
watcher_delegate :@_resolver
|
81
81
|
|
82
82
|
# Similar to .new, but used in cases where the resulting object is in a
|
83
83
|
# "half-open" state. This is primarily used for when asynchronous
|
@@ -114,7 +114,7 @@ module Rev
|
|
114
114
|
# Called by precreate during asyncronous DNS resolution
|
115
115
|
def preinitialize(addr, port, *args)
|
116
116
|
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
117
|
-
@
|
117
|
+
@_resolver = TCPConnectResolver.new(self, addr, port, *args)
|
118
118
|
end
|
119
119
|
|
120
120
|
private :preinitialize
|
@@ -168,22 +168,28 @@ module Rev
|
|
168
168
|
def on_success(addr)
|
169
169
|
host, port, args = @host, @port, @args
|
170
170
|
|
171
|
-
@sock.instance_eval
|
172
|
-
# DNSResolver only supports IPv4 so we can safely assume
|
173
|
-
|
171
|
+
@sock.instance_eval do
|
172
|
+
# DNSResolver only supports IPv4 so we can safely assume IPv4 address
|
173
|
+
begin
|
174
|
+
socket = TCPConnectSocket.new(::Socket::AF_INET, addr, port, host)
|
175
|
+
rescue Errno::ENETUNREACH
|
176
|
+
on_connect_failed
|
177
|
+
return
|
178
|
+
end
|
179
|
+
|
174
180
|
initialize(socket, *args)
|
175
|
-
@
|
176
|
-
@
|
177
|
-
|
181
|
+
@_connector = Socket::Connector.new(self, socket)
|
182
|
+
@_resolver = nil
|
183
|
+
end
|
178
184
|
@sock.attach(evloop)
|
179
185
|
end
|
180
186
|
|
181
187
|
def on_failure
|
182
188
|
@sock.__send__(:on_resolve_failed)
|
183
|
-
@sock.instance_eval
|
184
|
-
@
|
185
|
-
@
|
186
|
-
|
189
|
+
@sock.instance_eval do
|
190
|
+
@_resolver = nil
|
191
|
+
@_failed = true
|
192
|
+
end
|
187
193
|
return
|
188
194
|
end
|
189
195
|
end
|