rev 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +11 -0
- data/README +10 -3
- data/Rakefile +2 -2
- data/examples/echo_client.rb +35 -0
- data/examples/google.rb +8 -0
- data/examples/httpclient.rb +35 -0
- data/ext/http11_client/Makefile +149 -0
- data/ext/http11_client/http11_client.bundle +0 -0
- data/ext/http11_client/http11_client.o +0 -0
- data/ext/http11_client/http11_parser.o +0 -0
- data/ext/http11_client/mkmf.log +12 -0
- data/ext/libev/Changes +114 -1
- data/ext/libev/ev.c +212 -97
- data/ext/libev/ev.h +13 -7
- data/ext/libev/ev_epoll.c +44 -11
- data/ext/libev/ev_kqueue.c +2 -2
- data/ext/libev/ev_poll.c +3 -1
- data/ext/libev/ev_port.c +4 -4
- data/ext/libev/ev_select.c +58 -19
- data/ext/libev/ev_vars.h +5 -1
- data/ext/libev/ev_win32.c +32 -3
- data/ext/libev/ev_wrap.h +4 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/ext/libev/update_ev_wrap +0 -0
- data/ext/rev/Makefile +149 -0
- data/ext/rev/ev_wrap.h +8 -0
- data/ext/rev/extconf.rb +17 -0
- data/ext/rev/libev.c +8 -0
- data/ext/rev/libev.o +0 -0
- data/ext/rev/mkmf.log +221 -0
- data/ext/rev/rev.h +8 -2
- data/ext/rev/rev_buffer.c +2 -3
- data/ext/rev/rev_buffer.o +0 -0
- data/ext/rev/rev_ext.bundle +0 -0
- data/ext/rev/rev_ext.c +4 -3
- data/ext/rev/rev_ext.o +0 -0
- data/ext/rev/rev_io_watcher.c +1 -2
- data/ext/rev/rev_io_watcher.o +0 -0
- data/ext/rev/rev_loop.c +4 -4
- data/ext/rev/rev_loop.o +0 -0
- data/ext/rev/rev_ssl.o +0 -0
- data/ext/rev/rev_timer_watcher.c +1 -2
- data/ext/rev/rev_timer_watcher.o +0 -0
- data/ext/rev/rev_utils.c +14 -0
- data/ext/rev/rev_utils.o +0 -0
- data/ext/rev/rev_watcher.c +7 -6
- data/ext/rev/rev_watcher.o +0 -0
- data/lib/http11_client.bundle +0 -0
- data/lib/rev.rb +1 -1
- data/lib/rev/dns_resolver.rb +29 -9
- data/lib/rev/io.rb +6 -4
- data/lib/rev/listener.rb +5 -1
- data/lib/rev/loop.rb +8 -4
- data/lib/rev/server.rb +3 -2
- data/lib/rev/socket.rb +14 -5
- data/lib/rev_ext.bundle +0 -0
- data/lib/revem.rb +210 -0
- data/rev.gemspec +2 -2
- metadata +29 -3
data/ext/rev/rev.h
CHANGED
@@ -10,10 +10,16 @@
|
|
10
10
|
#include "ruby.h"
|
11
11
|
#include "rubyio.h"
|
12
12
|
|
13
|
-
#
|
14
|
-
#define FPTR_TO_FD(fptr) fptr
|
13
|
+
#ifdef GetReadFile
|
14
|
+
#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
|
15
15
|
#else
|
16
|
+
|
17
|
+
#if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
|
16
18
|
#define FPTR_TO_FD(fptr) fileno(fptr->f)
|
19
|
+
#else
|
20
|
+
#define FPTR_TO_FD(fptr) fptr->fd
|
21
|
+
#endif
|
22
|
+
|
17
23
|
#endif
|
18
24
|
|
19
25
|
struct Rev_Event
|
data/ext/rev/rev_buffer.c
CHANGED
@@ -7,8 +7,7 @@
|
|
7
7
|
#include "ruby.h"
|
8
8
|
#include "rubyio.h"
|
9
9
|
|
10
|
-
#
|
11
|
-
#include "../libev/ev.h"
|
10
|
+
#include "ev_wrap.h"
|
12
11
|
|
13
12
|
#include "rev.h"
|
14
13
|
|
@@ -627,4 +626,4 @@ static int buffer_read_from(struct buffer *buf, int fd)
|
|
627
626
|
} while(bytes_read == nbytes);
|
628
627
|
|
629
628
|
return total_bytes_read;
|
630
|
-
}
|
629
|
+
}
|
Binary file
|
Binary file
|
data/ext/rev/rev_ext.c
CHANGED
@@ -4,10 +4,11 @@
|
|
4
4
|
* See LICENSE for details
|
5
5
|
*/
|
6
6
|
|
7
|
-
#include "ruby.h"
|
8
7
|
|
9
|
-
#
|
10
|
-
|
8
|
+
#include "ruby.h" // allow for an error "OpenFile redeclared" to not exist, somehow.
|
9
|
+
|
10
|
+
#include "ev_wrap.h"
|
11
|
+
|
11
12
|
|
12
13
|
#include "rev.h"
|
13
14
|
|
data/ext/rev/rev_ext.o
ADDED
Binary file
|
data/ext/rev/rev_io_watcher.c
CHANGED
Binary file
|
data/ext/rev/rev_loop.c
CHANGED
@@ -8,8 +8,7 @@
|
|
8
8
|
#include "ruby.h"
|
9
9
|
#include "rubysig.h"
|
10
10
|
|
11
|
-
#
|
12
|
-
#include "../libev/ev.h"
|
11
|
+
#include "ev_wrap.h"
|
13
12
|
|
14
13
|
#include "rev.h"
|
15
14
|
|
@@ -208,7 +207,7 @@ static VALUE Rev_Loop_ev_loop_oneshot_blocking(void *ptr)
|
|
208
207
|
static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
209
208
|
{
|
210
209
|
/* Use Ruby 1.9's rb_thread_blocking_region call to make a blocking system call */
|
211
|
-
rb_thread_blocking_region(Rev_Loop_ev_loop_oneshot_blocking, loop_data,
|
210
|
+
rb_thread_blocking_region(Rev_Loop_ev_loop_oneshot_blocking, loop_data, RUBY_UBF_IO, 0);
|
212
211
|
}
|
213
212
|
#endif
|
214
213
|
|
@@ -220,6 +219,7 @@ static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
|
220
219
|
/* Stub for scheduler's ev_timer callback */
|
221
220
|
static void timer_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents)
|
222
221
|
{
|
222
|
+
ev_timer_again (ev_loop, timer);
|
223
223
|
}
|
224
224
|
|
225
225
|
/* Run the event loop, calling rb_thread_schedule every 10ms */
|
@@ -284,4 +284,4 @@ static void Rev_Loop_dispatch_events(struct Rev_Loop *loop_data)
|
|
284
284
|
Data_Get_Struct(loop_data->eventbuf[i].watcher, struct Rev_Watcher, watcher_data);
|
285
285
|
watcher_data->dispatch_callback(loop_data->eventbuf[i].watcher, loop_data->eventbuf[i].revents);
|
286
286
|
}
|
287
|
-
}
|
287
|
+
}
|
data/ext/rev/rev_loop.o
ADDED
Binary file
|
data/ext/rev/rev_ssl.o
ADDED
Binary file
|
data/ext/rev/rev_timer_watcher.c
CHANGED
Binary file
|
data/ext/rev/rev_utils.c
CHANGED
@@ -6,7 +6,9 @@
|
|
6
6
|
|
7
7
|
#include "ruby.h"
|
8
8
|
|
9
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
9
10
|
#include <sys/resource.h>
|
11
|
+
#endif
|
10
12
|
|
11
13
|
#ifdef HAVE_SYS_SYSCTL_H
|
12
14
|
#include <sys/param.h>
|
@@ -80,12 +82,18 @@ static VALUE Rev_Utils_ncpus(VALUE self)
|
|
80
82
|
*/
|
81
83
|
static VALUE Rev_Utils_maxfds(VALUE self)
|
82
84
|
{
|
85
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
83
86
|
struct rlimit rlim;
|
84
87
|
|
85
88
|
if(getrlimit(RLIMIT_NOFILE, &rlim) < 0)
|
86
89
|
rb_sys_fail("getrlimit");
|
87
90
|
|
88
91
|
return INT2NUM(rlim.rlim_cur);
|
92
|
+
#endif
|
93
|
+
|
94
|
+
#ifndef HAVE_SYS_RESOURCE_H
|
95
|
+
rb_raise(rb_eRuntimeError, "operation not supported");
|
96
|
+
#endif
|
89
97
|
}
|
90
98
|
|
91
99
|
/**
|
@@ -97,6 +105,7 @@ static VALUE Rev_Utils_maxfds(VALUE self)
|
|
97
105
|
*/
|
98
106
|
static VALUE Rev_Utils_setmaxfds(VALUE self, VALUE max)
|
99
107
|
{
|
108
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
100
109
|
struct rlimit rlim;
|
101
110
|
|
102
111
|
rlim.rlim_cur = NUM2INT(max);
|
@@ -105,4 +114,9 @@ static VALUE Rev_Utils_setmaxfds(VALUE self, VALUE max)
|
|
105
114
|
rb_sys_fail("setrlimit");
|
106
115
|
|
107
116
|
return max;
|
117
|
+
#endif
|
118
|
+
|
119
|
+
#ifndef HAVE_SYS_RESOURCE_H
|
120
|
+
rb_raise(rb_eRuntimeError, "operation not supported");
|
121
|
+
#endif
|
108
122
|
}
|
data/ext/rev/rev_utils.o
ADDED
Binary file
|
data/ext/rev/rev_watcher.c
CHANGED
@@ -6,8 +6,7 @@
|
|
6
6
|
|
7
7
|
#include "ruby.h"
|
8
8
|
|
9
|
-
#
|
10
|
-
#include "../libev/ev.h"
|
9
|
+
#include "ev_wrap.h"
|
11
10
|
|
12
11
|
#include "rev.h"
|
13
12
|
|
@@ -99,7 +98,8 @@ static VALUE Rev_Watcher_attach(VALUE self, VALUE loop)
|
|
99
98
|
loop_watchers = rb_iv_get(loop, "@watchers");
|
100
99
|
|
101
100
|
if(loop_watchers == Qnil) {
|
102
|
-
|
101
|
+
/* we should never get here */
|
102
|
+
loop_watchers = rb_hash_new();
|
103
103
|
rb_iv_set(loop, "@watchers", loop_watchers);
|
104
104
|
}
|
105
105
|
|
@@ -108,7 +108,7 @@ static VALUE Rev_Watcher_attach(VALUE self, VALUE loop)
|
|
108
108
|
* with a loop (and also lets you see within Ruby which watchers are
|
109
109
|
* associated with a given loop), but isn't really necessary for any
|
110
110
|
* other reason */
|
111
|
-
|
111
|
+
rb_hash_aset(loop_watchers, self, Qtrue);
|
112
112
|
|
113
113
|
active_watchers = rb_iv_get(loop, "@active_watchers");
|
114
114
|
if(active_watchers == Qnil)
|
@@ -142,8 +142,9 @@ static VALUE Rev_Watcher_detach(VALUE self)
|
|
142
142
|
|
143
143
|
/* Remove us from the loop's array of active watchers. This likely
|
144
144
|
* has negative performance and scalability characteristics as this
|
145
|
-
* isn't an O(1) operation. Hopefully there's a better way...
|
146
|
-
|
145
|
+
* isn't an O(1) operation. Hopefully there's a better way...
|
146
|
+
* Trying a hash for now... */
|
147
|
+
rb_hash_delete(loop_watchers, self);
|
147
148
|
|
148
149
|
if(watcher_data->enabled) {
|
149
150
|
rb_iv_set(
|
Binary file
|
Binary file
|
data/lib/rev.rb
CHANGED
@@ -24,6 +24,6 @@ require File.dirname(__FILE__) + '/rev/server'
|
|
24
24
|
require File.dirname(__FILE__) + '/rev/http_client'
|
25
25
|
|
26
26
|
module Rev
|
27
|
-
Rev::VERSION = '0.2.
|
27
|
+
Rev::VERSION = '0.2.3' unless defined? Rev::VERSION
|
28
28
|
def self.version() VERSION end
|
29
29
|
end
|
data/lib/rev/dns_resolver.rb
CHANGED
@@ -11,7 +11,6 @@
|
|
11
11
|
#
|
12
12
|
# If you do know what you're doing with DNS, feel free to improve this!
|
13
13
|
#++
|
14
|
-
|
15
14
|
module Rev
|
16
15
|
# A non-blocking DNS resolver. It provides interfaces for querying both
|
17
16
|
# /etc/hosts and nameserves listed in /etc/resolv.conf, or nameservers of
|
@@ -25,12 +24,16 @@ module Rev
|
|
25
24
|
# automatically detach themselves from the event loop and cannot be used
|
26
25
|
# again.
|
27
26
|
class DNSResolver < IOWatcher
|
27
|
+
#--
|
28
|
+
# TODO check if it's caching right
|
28
29
|
RESOLV_CONF = '/etc/resolv.conf'
|
29
30
|
HOSTS = '/etc/hosts'
|
30
31
|
DNS_PORT = 53
|
31
32
|
DATAGRAM_SIZE = 512
|
32
33
|
TIMEOUT = 3 # Retry timeout for each datagram sent
|
33
34
|
RETRIES = 4 # Number of retries to attempt
|
35
|
+
# so currently total is 12s before it will err due to timeouts
|
36
|
+
# if it errs due to inability to reach the DNS server [Errno::EHOSTUNREACH], same
|
34
37
|
|
35
38
|
# Query /etc/hosts (or the specified hostfile) for the given host
|
36
39
|
def self.hosts(host, hostfile = HOSTS)
|
@@ -50,8 +53,8 @@ module Rev
|
|
50
53
|
# use nameservers listed in /etc/resolv.conf
|
51
54
|
def initialize(hostname, *nameservers)
|
52
55
|
if nameservers.empty?
|
53
|
-
nameservers = File.read(RESOLV_CONF).scan(/^\s*nameserver\s+([0-9.:]+)/).flatten
|
54
|
-
raise RuntimeError, "no nameservers found in #{RESOLV_CONF}" if nameservers.empty?
|
56
|
+
nameservers = File.read(RESOLV_CONF).scan(/^\s*nameserver\s+([0-9.:]+)/).flatten # TODO could optimize this to just read once
|
57
|
+
raise RuntimeError, "no nameservers found in #{RESOLV_CONF}" if nameservers.empty? # TODO just call resolve_failed, not raise [also handle Errno::ENOENT)]
|
55
58
|
end
|
56
59
|
|
57
60
|
@nameservers = nameservers
|
@@ -84,8 +87,10 @@ module Rev
|
|
84
87
|
def on_failure; end
|
85
88
|
event_callback :on_failure
|
86
89
|
|
87
|
-
# Called if we don't receive a response, defaults to on_failure
|
88
|
-
|
90
|
+
# Called if we don't receive a response, defaults to calling on_failure
|
91
|
+
def on_timeout
|
92
|
+
on_failure
|
93
|
+
end
|
89
94
|
|
90
95
|
#########
|
91
96
|
protected
|
@@ -93,13 +98,23 @@ module Rev
|
|
93
98
|
|
94
99
|
# Send a request to the DNS server
|
95
100
|
def send_request
|
101
|
+
nameserver = @nameservers.shift
|
102
|
+
@nameservers << nameserver # rotate them
|
96
103
|
@socket.connect @nameservers.first, DNS_PORT
|
97
|
-
|
104
|
+
begin
|
105
|
+
@socket.send request_message, 0
|
106
|
+
rescue Errno::EHOSTUNREACH # TODO figure out why it has to be wrapper here, when the other wrapper should be wrapping this one!
|
107
|
+
|
108
|
+
end
|
98
109
|
end
|
99
110
|
|
100
111
|
# Called by the subclass when the DNS response is available
|
101
112
|
def on_readable
|
102
|
-
datagram =
|
113
|
+
datagram = nil
|
114
|
+
begin
|
115
|
+
datagram = @socket.recvfrom_nonblock(DATAGRAM_SIZE).first
|
116
|
+
rescue Errno::ECONNREFUSED
|
117
|
+
end
|
103
118
|
address = response_address datagram rescue nil
|
104
119
|
address ? on_success(address) : on_failure
|
105
120
|
detach
|
@@ -184,8 +199,13 @@ module Rev
|
|
184
199
|
|
185
200
|
def on_timer
|
186
201
|
@attempts += 1
|
187
|
-
|
188
|
-
|
202
|
+
if @attempts <= RETRIES
|
203
|
+
begin
|
204
|
+
return @resolver.__send__(:send_request)
|
205
|
+
rescue Errno::EHOSTUNREACH # if the DNS is toast try again after the timeout occurs again
|
206
|
+
return nil
|
207
|
+
end
|
208
|
+
end
|
189
209
|
@resolver.__send__(:on_timeout)
|
190
210
|
@resolver.detach
|
191
211
|
end
|
data/lib/rev/io.rb
CHANGED
@@ -21,7 +21,7 @@ module Rev
|
|
21
21
|
|
22
22
|
def initialize(io)
|
23
23
|
@_io = io
|
24
|
-
@_write_buffer
|
24
|
+
@_write_buffer ||= Rev::Buffer.new
|
25
25
|
@_read_watcher = Watcher.new(io, self, :r)
|
26
26
|
@_write_watcher = Watcher.new(io, self, :w)
|
27
27
|
end
|
@@ -31,10 +31,10 @@ module Rev
|
|
31
31
|
#
|
32
32
|
|
33
33
|
# Attach to the event loop
|
34
|
-
def attach(loop); @_read_watcher.attach loop; self; end
|
34
|
+
def attach(loop); @_read_watcher.attach loop; schedule_write if !@_write_buffer.empty?; self; end
|
35
35
|
|
36
36
|
# Detach from the event loop
|
37
|
-
def detach; @_read_watcher.detach; self; end
|
37
|
+
def detach; @_read_watcher.detach; self; end # TODO should these detect write buffers, as well?
|
38
38
|
|
39
39
|
# Enable the watcher
|
40
40
|
def enable; @_read_watcher.enable; self; end
|
@@ -128,6 +128,8 @@ module Rev
|
|
128
128
|
|
129
129
|
# Schedule a write to be performed when the IO object becomes writable
|
130
130
|
def schedule_write
|
131
|
+
return unless @_io # this would mean 'we are still pre DNS here'
|
132
|
+
return unless attached? # this would mean 'currently unattached' -- ie still pre DNS, or just plain not attached, which is ok
|
131
133
|
begin
|
132
134
|
enable_write_watcher
|
133
135
|
rescue IOError
|
@@ -162,4 +164,4 @@ module Rev
|
|
162
164
|
def on_writable; @rev_io.__send__(:on_writable); end
|
163
165
|
end
|
164
166
|
end
|
165
|
-
end
|
167
|
+
end
|
data/lib/rev/listener.rb
CHANGED
@@ -32,7 +32,11 @@ module Rev
|
|
32
32
|
|
33
33
|
# Rev callback for handling new connections
|
34
34
|
def on_readable
|
35
|
-
|
35
|
+
begin
|
36
|
+
on_connection @listen_socket.accept_nonblock
|
37
|
+
rescue Errno::EAGAIN
|
38
|
+
STDERR.puts "warning: listener socket spuriously readable"
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
data/lib/rev/loop.rb
CHANGED
@@ -15,10 +15,8 @@ end
|
|
15
15
|
|
16
16
|
module Rev
|
17
17
|
class Loop
|
18
|
-
attr_reader :watchers
|
19
|
-
|
20
18
|
# In Ruby 1.9 we want a Rev::Loop per thread, but Ruby 1.8 is unithreaded
|
21
|
-
if RUBY_VERSION
|
19
|
+
if RUBY_VERSION >= "1.9.0"
|
22
20
|
# Retrieve the default event loop for the current thread
|
23
21
|
def self.default
|
24
22
|
Thread.current._rev_loop
|
@@ -49,7 +47,7 @@ module Rev
|
|
49
47
|
# :port (Solaris 10)
|
50
48
|
#
|
51
49
|
def initialize(options = {})
|
52
|
-
@watchers =
|
50
|
+
@watchers = {}
|
53
51
|
@active_watchers = 0
|
54
52
|
|
55
53
|
flags = 0
|
@@ -97,6 +95,7 @@ module Rev
|
|
97
95
|
while @running and not @active_watchers.zero?
|
98
96
|
run_once
|
99
97
|
end
|
98
|
+
@running = false
|
100
99
|
end
|
101
100
|
|
102
101
|
# Stop the event loop if it's running
|
@@ -110,6 +109,11 @@ module Rev
|
|
110
109
|
@active_watchers > 0
|
111
110
|
end
|
112
111
|
|
112
|
+
# All watchers attached to the current loop
|
113
|
+
def watchers
|
114
|
+
@watchers.keys
|
115
|
+
end
|
116
|
+
|
113
117
|
#######
|
114
118
|
private
|
115
119
|
#######
|
data/lib/rev/server.rb
CHANGED
@@ -39,7 +39,8 @@ module Rev
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# TCP server class. Listens on the specified host and port and creates
|
42
|
-
# new connection objects of the given class.
|
42
|
+
# new connection objects of the given class. This is the most common server class.
|
43
|
+
# Note that the new connection objects will be bound by default to the same event loop that the server is attached to.
|
43
44
|
class TCPServer < Server
|
44
45
|
def initialize(host, port, klass = TCPSocket, *args, &block)
|
45
46
|
listen_socket = ::TCPServer.new(host, port)
|
@@ -55,4 +56,4 @@ module Rev
|
|
55
56
|
super(::UNIXServer.new(*args), klass, *args, &block)
|
56
57
|
end
|
57
58
|
end
|
58
|
-
end
|
59
|
+
end
|
data/lib/rev/socket.rb
CHANGED
@@ -10,6 +10,7 @@ require 'resolv'
|
|
10
10
|
module Rev
|
11
11
|
class Socket < IO
|
12
12
|
def self.connect(socket, *args)
|
13
|
+
|
13
14
|
new(socket, *args).instance_eval do
|
14
15
|
@_connector = Connector.new(self, socket)
|
15
16
|
self
|
@@ -38,8 +39,10 @@ module Rev
|
|
38
39
|
event_callback :on_connect_failed
|
39
40
|
|
40
41
|
# Called if a hostname failed to resolve when connecting
|
41
|
-
# Defaults to
|
42
|
-
|
42
|
+
# Defaults to calling on_connect_failed
|
43
|
+
def on_resolve_failed
|
44
|
+
on_connect_failed
|
45
|
+
end
|
43
46
|
|
44
47
|
#########
|
45
48
|
protected
|
@@ -58,6 +61,9 @@ module Rev
|
|
58
61
|
if connect_successful?
|
59
62
|
@rev_socket.instance_eval { @_connector = nil }
|
60
63
|
@rev_socket.attach(evl)
|
64
|
+
@ruby_socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, [1].pack("l"))
|
65
|
+
@ruby_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true)
|
66
|
+
|
61
67
|
@rev_socket.__send__(:on_connect)
|
62
68
|
else
|
63
69
|
@rev_socket.instance_eval { @_failed = true }
|
@@ -93,6 +99,8 @@ module Rev
|
|
93
99
|
end
|
94
100
|
|
95
101
|
# Perform a non-blocking connect to the given host and port
|
102
|
+
# see examples/echo_client.rb
|
103
|
+
# addr is a string, can be an IP address or a hostname.
|
96
104
|
def self.connect(addr, port, *args)
|
97
105
|
family = nil
|
98
106
|
|
@@ -103,11 +111,11 @@ module Rev
|
|
103
111
|
end
|
104
112
|
|
105
113
|
if family
|
106
|
-
return super(TCPConnectSocket.new(family, addr, port), *args)
|
114
|
+
return super(TCPConnectSocket.new(family, addr, port), *args) # this creates a 'real' write buffer so we're ok there with regards to already having a write buffer from the get go
|
107
115
|
end
|
108
116
|
|
109
117
|
if host = Rev::DNSResolver.hosts(addr)
|
110
|
-
return connect(host, port, *args)
|
118
|
+
return connect(host, port, *args) # calls this same function
|
111
119
|
end
|
112
120
|
|
113
121
|
precreate(addr, port, *args)
|
@@ -115,6 +123,7 @@ module Rev
|
|
115
123
|
|
116
124
|
# Called by precreate during asyncronous DNS resolution
|
117
125
|
def preinitialize(addr, port, *args)
|
126
|
+
@_write_buffer = Rev::Buffer.new # allow for writing BEFORE the DNS has resolved
|
118
127
|
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
119
128
|
@_resolver = TCPConnectResolver.new(self, addr, port, *args)
|
120
129
|
end
|
@@ -141,7 +150,7 @@ module Rev
|
|
141
150
|
|
142
151
|
class TCPConnectSocket < ::Socket
|
143
152
|
def initialize(family, addr, port, host = addr)
|
144
|
-
@host,
|
153
|
+
@host, addr, @port = host, addr, port
|
145
154
|
@address_family = nil
|
146
155
|
|
147
156
|
@socket = super(family, ::Socket::SOCK_STREAM, 0)
|