rev 0.2.2 → 0.2.3
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 +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)
|