cool.io 1.0.0 → 1.9.0
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 +7 -0
- data/.github/workflows/test.yaml +54 -0
- data/.gitignore +30 -0
- data/.rspec +3 -0
- data/{CHANGES → CHANGES.md} +175 -79
- data/{README.markdown → README.md} +43 -49
- data/Rakefile +44 -69
- data/appveyor.yml +18 -0
- data/cool.io.gemspec +18 -131
- data/examples/callbacked_echo_server.rb +24 -0
- data/ext/cool.io/buffer.c +781 -0
- data/ext/cool.io/cool.io.h +13 -0
- data/ext/cool.io/cool.io_ext.c +1 -0
- data/ext/cool.io/ev_wrap.h +4 -2
- data/ext/cool.io/extconf.rb +27 -16
- data/ext/cool.io/iowatcher.c +17 -8
- data/ext/cool.io/loop.c +36 -84
- data/ext/cool.io/stat_watcher.c +103 -25
- data/ext/cool.io/timer_watcher.c +3 -3
- data/ext/cool.io/utils.c +5 -0
- data/ext/cool.io/watcher.h +1 -1
- data/ext/libev/Changes +152 -3
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +8 -8
- data/ext/libev/ev.c +1719 -348
- data/ext/libev/ev.h +146 -118
- data/ext/libev/ev_epoll.c +71 -20
- data/ext/libev/ev_kqueue.c +36 -16
- data/ext/libev/ev_poll.c +14 -11
- data/ext/libev/ev_port.c +43 -18
- data/ext/libev/ev_select.c +82 -25
- data/ext/libev/ev_vars.h +28 -21
- data/ext/libev/ev_win32.c +19 -10
- data/ext/libev/ev_wrap.h +166 -152
- data/ext/libev/test_libev_win32.c +1 -1
- data/gems.rb +9 -0
- data/lib/cool.io/async_watcher.rb +1 -1
- data/lib/cool.io/custom_require.rb +9 -0
- data/lib/cool.io/dns_resolver.rb +30 -22
- data/lib/cool.io/dsl.rb +32 -28
- data/lib/cool.io/io.rb +55 -35
- data/lib/cool.io/iowatcher.rb +1 -1
- data/lib/cool.io/listener.rb +35 -17
- data/lib/cool.io/loop.rb +17 -25
- data/lib/cool.io/meta.rb +6 -5
- data/lib/cool.io/server.rb +5 -4
- data/lib/cool.io/socket.rb +41 -30
- data/lib/cool.io/timer_watcher.rb +1 -1
- data/lib/cool.io/version.rb +7 -0
- data/lib/cool.io.rb +11 -10
- data/lib/coolio.rb +1 -1
- data/libev_ruby_gil.diff +175 -0
- data/libev_win_select.diff +130 -0
- data/spec/async_watcher_spec.rb +5 -5
- data/spec/dns_spec.rb +27 -8
- data/spec/iobuffer_spec.rb +147 -0
- data/spec/spec_helper.rb +15 -1
- data/spec/stat_watcher_spec.rb +81 -0
- data/spec/tcp_server_spec.rb +225 -0
- data/spec/tcp_socket_spec.rb +185 -0
- data/spec/timer_watcher_spec.rb +23 -19
- data/spec/udp_socket_spec.rb +58 -0
- data/spec/unix_listener_spec.rb +8 -8
- data/spec/unix_server_spec.rb +10 -8
- metadata +109 -112
- data/VERSION +0 -1
- data/examples/httpclient.rb +0 -38
- data/ext/http11_client/.gitignore +0 -5
- data/ext/http11_client/LICENSE +0 -31
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -300
- data/ext/http11_client/http11_parser.c +0 -403
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -173
- data/lib/cool.io/eventmachine.rb +0 -234
- data/lib/cool.io/http_client.rb +0 -419
- data/lib/rev.rb +0 -4
- data/spec/possible_tests/schedules_other_threads.rb +0 -48
- data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
- data/spec/possible_tests/test_resolves.rb +0 -27
- data/spec/possible_tests/test_write_during_resolve.rb +0 -27
- data/spec/possible_tests/works_straight.rb +0 -71
data/lib/cool.io/io.rb
CHANGED
|
@@ -15,13 +15,13 @@ module Coolio
|
|
|
15
15
|
# Socket class and its associated subclasses.
|
|
16
16
|
class IO
|
|
17
17
|
extend Meta
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
# Maximum number of bytes to consume at once
|
|
20
20
|
INPUT_SIZE = 16384
|
|
21
21
|
|
|
22
22
|
def initialize(io)
|
|
23
23
|
@_io = io
|
|
24
|
-
@_write_buffer ||= ::
|
|
24
|
+
@_write_buffer ||= ::Coolio::Buffer.new
|
|
25
25
|
@_read_watcher = Watcher.new(io, self, :r)
|
|
26
26
|
@_write_watcher = Watcher.new(io, self, :w)
|
|
27
27
|
end
|
|
@@ -29,32 +29,52 @@ module Coolio
|
|
|
29
29
|
#
|
|
30
30
|
# Watcher methods, delegated to @_read_watcher
|
|
31
31
|
#
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
# Attach to the event loop
|
|
34
|
-
def attach(loop)
|
|
35
|
-
|
|
34
|
+
def attach(loop)
|
|
35
|
+
@_read_watcher.attach(loop)
|
|
36
|
+
schedule_write if !@_write_buffer.empty?
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
36
40
|
# Detach from the event loop
|
|
37
|
-
def detach
|
|
38
|
-
|
|
41
|
+
def detach
|
|
42
|
+
# TODO should these detect write buffers, as well?
|
|
43
|
+
@_read_watcher.detach
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
|
|
39
47
|
# Enable the watcher
|
|
40
|
-
def enable
|
|
41
|
-
|
|
48
|
+
def enable
|
|
49
|
+
@_read_watcher.enable
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
42
53
|
# Disable the watcher
|
|
43
|
-
def disable
|
|
44
|
-
|
|
54
|
+
def disable
|
|
55
|
+
@_read_watcher.disable
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
45
59
|
# Is the watcher attached?
|
|
46
|
-
def attached
|
|
47
|
-
|
|
60
|
+
def attached?
|
|
61
|
+
@_read_watcher.attached?
|
|
62
|
+
end
|
|
63
|
+
|
|
48
64
|
# Is the watcher enabled?
|
|
49
|
-
def enabled
|
|
50
|
-
|
|
65
|
+
def enabled?
|
|
66
|
+
@_read_watcher.enabled?
|
|
67
|
+
end
|
|
68
|
+
|
|
51
69
|
# Obtain the event loop associated with this object
|
|
52
|
-
def evloop
|
|
53
|
-
|
|
70
|
+
def evloop
|
|
71
|
+
@_read_watcher.evloop
|
|
72
|
+
end
|
|
73
|
+
|
|
54
74
|
#
|
|
55
75
|
# Callbacks for asynchronous events
|
|
56
76
|
#
|
|
57
|
-
|
|
77
|
+
|
|
58
78
|
# Called whenever the IO object receives data
|
|
59
79
|
def on_read(data); end
|
|
60
80
|
event_callback :on_read
|
|
@@ -78,16 +98,11 @@ module Coolio
|
|
|
78
98
|
data.size
|
|
79
99
|
end
|
|
80
100
|
|
|
81
|
-
# Number of bytes are currently in the output buffer
|
|
82
|
-
def output_buffer_size
|
|
83
|
-
@_write_buffer.size
|
|
84
|
-
end
|
|
85
|
-
|
|
86
101
|
# Close the IO stream
|
|
87
102
|
def close
|
|
88
103
|
detach if attached?
|
|
89
104
|
detach_write_watcher
|
|
90
|
-
@_io.close unless
|
|
105
|
+
@_io.close unless closed?
|
|
91
106
|
|
|
92
107
|
on_close
|
|
93
108
|
nil
|
|
@@ -114,7 +129,7 @@ module Coolio
|
|
|
114
129
|
close
|
|
115
130
|
end
|
|
116
131
|
end
|
|
117
|
-
|
|
132
|
+
|
|
118
133
|
# Write the contents of the output buffer
|
|
119
134
|
def on_writable
|
|
120
135
|
begin
|
|
@@ -126,23 +141,23 @@ module Coolio
|
|
|
126
141
|
rescue SystemCallError, IOError, SocketError
|
|
127
142
|
return close
|
|
128
143
|
end
|
|
129
|
-
|
|
144
|
+
|
|
130
145
|
if @_write_buffer.empty?
|
|
131
146
|
disable_write_watcher
|
|
132
147
|
on_write_complete
|
|
133
148
|
end
|
|
134
149
|
end
|
|
135
150
|
|
|
136
|
-
# Schedule a write to be performed when the IO object becomes writable
|
|
151
|
+
# Schedule a write to be performed when the IO object becomes writable
|
|
137
152
|
def schedule_write
|
|
138
153
|
return unless @_io # this would mean 'we are still pre DNS here'
|
|
139
|
-
return unless attached? # this would mean 'currently unattached' -- ie still pre DNS, or just plain not attached, which is ok
|
|
154
|
+
return unless @_read_watcher.attached? # this would mean 'currently unattached' -- ie still pre DNS, or just plain not attached, which is ok
|
|
140
155
|
begin
|
|
141
|
-
enable_write_watcher
|
|
156
|
+
enable_write_watcher
|
|
142
157
|
rescue IOError
|
|
143
158
|
end
|
|
144
159
|
end
|
|
145
|
-
|
|
160
|
+
|
|
146
161
|
def enable_write_watcher
|
|
147
162
|
if @_write_watcher.attached?
|
|
148
163
|
@_write_watcher.enable unless @_write_watcher.enabled?
|
|
@@ -150,15 +165,15 @@ module Coolio
|
|
|
150
165
|
@_write_watcher.attach(evloop)
|
|
151
166
|
end
|
|
152
167
|
end
|
|
153
|
-
|
|
168
|
+
|
|
154
169
|
def disable_write_watcher
|
|
155
170
|
@_write_watcher.disable if @_write_watcher and @_write_watcher.enabled?
|
|
156
171
|
end
|
|
157
|
-
|
|
172
|
+
|
|
158
173
|
def detach_write_watcher
|
|
159
174
|
@_write_watcher.detach if @_write_watcher and @_write_watcher.attached?
|
|
160
175
|
end
|
|
161
|
-
|
|
176
|
+
|
|
162
177
|
# Internal class implementing watchers used by Coolio::IO
|
|
163
178
|
class Watcher < IOWatcher
|
|
164
179
|
def initialize(ruby_io, coolio_io, flags)
|
|
@@ -167,8 +182,13 @@ module Coolio
|
|
|
167
182
|
end
|
|
168
183
|
|
|
169
184
|
# Configure IOWatcher event callbacks to call the method passed to #initialize
|
|
170
|
-
def on_readable
|
|
171
|
-
|
|
185
|
+
def on_readable
|
|
186
|
+
@coolio_io.__send__(:on_readable)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def on_writable
|
|
190
|
+
@coolio_io.__send__(:on_writable)
|
|
191
|
+
end
|
|
172
192
|
end
|
|
173
193
|
end
|
|
174
194
|
end
|
data/lib/cool.io/iowatcher.rb
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#++
|
|
6
6
|
|
|
7
7
|
module Coolio
|
|
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
|
data/lib/cool.io/listener.rb
CHANGED
|
@@ -21,6 +21,10 @@ module Coolio
|
|
|
21
21
|
@listen_socket.fileno
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def listen(backlog)
|
|
25
|
+
@listen_socket.listen(backlog)
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
# Close the listener
|
|
25
29
|
def close
|
|
26
30
|
detach if attached?
|
|
@@ -36,26 +40,38 @@ module Coolio
|
|
|
36
40
|
#########
|
|
37
41
|
|
|
38
42
|
# Coolio callback for handling new connections
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
unless RUBY_PLATFORM =~ /mingw|mswin/
|
|
44
|
+
def on_readable
|
|
45
|
+
begin
|
|
46
|
+
on_connection @listen_socket.accept_nonblock
|
|
47
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
|
48
|
+
# EAGAIN can be triggered here if the socket is shared between
|
|
49
|
+
# multiple processes and a thundering herd is woken up to accept
|
|
50
|
+
# one connection, only one process will get the connection and
|
|
51
|
+
# the others will be awoken.
|
|
52
|
+
# ECONNABORTED is documented in accept() manpages but modern TCP
|
|
53
|
+
# stacks with syncookies and/or accept()-filtering for DoS
|
|
54
|
+
# protection do not see it. In any case this error is harmless
|
|
55
|
+
# and we should instead spend our time with clients that follow
|
|
56
|
+
# through on connection attempts.
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
def on_readable
|
|
61
|
+
begin
|
|
62
|
+
# In Windows, accept_nonblock() with multiple processes
|
|
63
|
+
# causes thundering herd problem.
|
|
64
|
+
# To avoid this, we need to use accept().
|
|
65
|
+
on_connection @listen_socket.accept
|
|
66
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
|
67
|
+
end
|
|
52
68
|
end
|
|
53
69
|
end
|
|
54
70
|
end
|
|
55
71
|
|
|
72
|
+
DEFAULT_BACKLOG = 1024
|
|
73
|
+
|
|
56
74
|
class TCPListener < Listener
|
|
57
|
-
DEFAULT_BACKLOG = 1024
|
|
58
|
-
|
|
59
75
|
# Create a new Coolio::TCPListener on the specified address and port.
|
|
60
76
|
# Accepts the following options:
|
|
61
77
|
#
|
|
@@ -68,7 +84,7 @@ module Coolio
|
|
|
68
84
|
def initialize(addr, port = nil, options = {})
|
|
69
85
|
BasicSocket.do_not_reverse_lookup = true unless options[:reverse_lookup]
|
|
70
86
|
options[:backlog] ||= DEFAULT_BACKLOG
|
|
71
|
-
|
|
87
|
+
|
|
72
88
|
listen_socket = if ::TCPServer === addr
|
|
73
89
|
addr
|
|
74
90
|
else
|
|
@@ -87,7 +103,9 @@ module Coolio
|
|
|
87
103
|
# Optionally, it can also take anyn existing UNIXServer object
|
|
88
104
|
# and create a Coolio::UNIXListener out of it.
|
|
89
105
|
def initialize(*args)
|
|
90
|
-
|
|
106
|
+
s = ::UNIXServer === args.first ? args.first : ::UNIXServer.new(*args)
|
|
107
|
+
s.instance_eval { listen(DEFAULT_BACKLOG) }
|
|
108
|
+
super(s)
|
|
91
109
|
end
|
|
92
110
|
end
|
|
93
111
|
end
|
data/lib/cool.io/loop.rb
CHANGED
|
@@ -15,17 +15,9 @@ end
|
|
|
15
15
|
|
|
16
16
|
module Coolio
|
|
17
17
|
class Loop
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def self.default
|
|
22
|
-
Thread.current._coolio_loop
|
|
23
|
-
end
|
|
24
|
-
else
|
|
25
|
-
# Retrieve the default event loop
|
|
26
|
-
def self.default
|
|
27
|
-
@@_coolio_loop ||= Coolio::Loop.new
|
|
28
|
-
end
|
|
18
|
+
# Retrieve the default event loop for the current thread
|
|
19
|
+
def self.default
|
|
20
|
+
Thread.current._coolio_loop
|
|
29
21
|
end
|
|
30
22
|
|
|
31
23
|
# Create a new Coolio::Loop
|
|
@@ -35,7 +27,7 @@ module Coolio
|
|
|
35
27
|
# :skip_environment (boolean)
|
|
36
28
|
# Ignore the $LIBEV_FLAGS environment variable
|
|
37
29
|
#
|
|
38
|
-
# :fork_check (boolean)
|
|
30
|
+
# :fork_check (boolean)
|
|
39
31
|
# Enable autodetection of forks
|
|
40
32
|
#
|
|
41
33
|
# :backend
|
|
@@ -49,7 +41,7 @@ module Coolio
|
|
|
49
41
|
def initialize(options = {})
|
|
50
42
|
@watchers = {}
|
|
51
43
|
@active_watchers = 0
|
|
52
|
-
|
|
44
|
+
|
|
53
45
|
flags = 0
|
|
54
46
|
|
|
55
47
|
options.each do |option, value|
|
|
@@ -76,7 +68,7 @@ module Coolio
|
|
|
76
68
|
|
|
77
69
|
@loop = ev_loop_new(flags)
|
|
78
70
|
end
|
|
79
|
-
|
|
71
|
+
|
|
80
72
|
# Attach a watcher to the loop
|
|
81
73
|
def attach(watcher)
|
|
82
74
|
watcher.attach self
|
|
@@ -86,14 +78,14 @@ module Coolio
|
|
|
86
78
|
# are no watchers associated with the event loop it will return
|
|
87
79
|
# immediately. Otherwise, run will continue blocking and making
|
|
88
80
|
# event callbacks to watchers until all watchers associated with
|
|
89
|
-
# the loop have been disabled or detached. The loop may be
|
|
81
|
+
# the loop have been disabled or detached. The loop may be
|
|
90
82
|
# explicitly stopped by calling the stop method on the loop object.
|
|
91
|
-
def run
|
|
83
|
+
def run(timeout = nil)
|
|
92
84
|
raise RuntimeError, "no watchers for this loop" if @watchers.empty?
|
|
93
85
|
|
|
94
86
|
@running = true
|
|
95
87
|
while @running and not @active_watchers.zero?
|
|
96
|
-
run_once
|
|
88
|
+
run_once(timeout)
|
|
97
89
|
end
|
|
98
90
|
@running = false
|
|
99
91
|
end
|
|
@@ -103,28 +95,28 @@ module Coolio
|
|
|
103
95
|
raise RuntimeError, "loop not running" unless @running
|
|
104
96
|
@running = false
|
|
105
97
|
end
|
|
106
|
-
|
|
98
|
+
|
|
107
99
|
# Does the loop have any active watchers?
|
|
108
100
|
def has_active_watchers?
|
|
109
101
|
@active_watchers > 0
|
|
110
102
|
end
|
|
111
|
-
|
|
103
|
+
|
|
112
104
|
# All watchers attached to the current loop
|
|
113
105
|
def watchers
|
|
114
106
|
@watchers.keys
|
|
115
107
|
end
|
|
116
|
-
|
|
108
|
+
|
|
117
109
|
#######
|
|
118
110
|
private
|
|
119
111
|
#######
|
|
120
|
-
|
|
112
|
+
|
|
121
113
|
EVFLAG_NOENV = 0x1000000 # do NOT consult environment
|
|
122
114
|
EVFLAG_FORKCHECK = 0x2000000 # check for a fork in each iteration
|
|
123
115
|
|
|
124
|
-
EVBACKEND_SELECT = 0x00000001 # supported about anywhere
|
|
125
|
-
EVBACKEND_POLL = 0x00000002 # !win
|
|
126
|
-
EVBACKEND_EPOLL = 0x00000004 # linux
|
|
127
|
-
EVBACKEND_KQUEUE = 0x00000008 # bsd
|
|
116
|
+
EVBACKEND_SELECT = 0x00000001 # supported about anywhere
|
|
117
|
+
EVBACKEND_POLL = 0x00000002 # !win
|
|
118
|
+
EVBACKEND_EPOLL = 0x00000004 # linux
|
|
119
|
+
EVBACKEND_KQUEUE = 0x00000008 # bsd
|
|
128
120
|
EVBACKEND_PORT = 0x00000020 # solaris 10
|
|
129
121
|
end
|
|
130
122
|
end
|
data/lib/cool.io/meta.rb
CHANGED
|
@@ -11,10 +11,10 @@ module Coolio
|
|
|
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
13
|
def watcher_delegate(proxy_var)
|
|
14
|
-
%w{attach detach enable disable}.each do |method|
|
|
14
|
+
%w{attach attached? detach enable disable}.each do |method|
|
|
15
15
|
module_eval <<-EOD
|
|
16
16
|
def #{method}(*args)
|
|
17
|
-
if #{proxy_var}
|
|
17
|
+
if defined? #{proxy_var} and #{proxy_var}
|
|
18
18
|
#{proxy_var}.#{method}(*args)
|
|
19
19
|
return self
|
|
20
20
|
end
|
|
@@ -32,14 +32,15 @@ module Coolio
|
|
|
32
32
|
def event_callback(*methods)
|
|
33
33
|
methods.each do |method|
|
|
34
34
|
module_eval <<-EOD
|
|
35
|
+
remove_method "#{method}"
|
|
35
36
|
def #{method}(*args, &block)
|
|
36
37
|
if block
|
|
37
38
|
@#{method}_callback = block
|
|
38
39
|
return
|
|
39
40
|
end
|
|
40
|
-
|
|
41
|
-
if @#{method}_callback
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
if defined? @#{method}_callback and @#{method}_callback
|
|
43
|
+
@#{method}_callback.call(*args)
|
|
43
44
|
end
|
|
44
45
|
end
|
|
45
46
|
EOD
|
data/lib/cool.io/server.rb
CHANGED
|
@@ -20,9 +20,9 @@ module Coolio
|
|
|
20
20
|
expected = arity >= 0 ? arity : -(arity + 1)
|
|
21
21
|
|
|
22
22
|
if (arity >= 0 and args.size + 1 != expected) or (arity < 0 and args.size + 1 < expected)
|
|
23
|
-
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size+1} for #{expected})"
|
|
23
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size+1} for #{expected})"
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
@klass, @args, @block = klass, args, block
|
|
27
27
|
super(listen_socket)
|
|
28
28
|
end
|
|
@@ -35,7 +35,7 @@ module Coolio
|
|
|
35
35
|
#########
|
|
36
36
|
protected
|
|
37
37
|
#########
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
def on_connection(socket)
|
|
40
40
|
connection = @klass.new(socket, *@args).attach(evloop)
|
|
41
41
|
connection.__send__(:on_connect)
|
|
@@ -56,7 +56,7 @@ module Coolio
|
|
|
56
56
|
raise ArgumentError, "port must be an integer" if nil == port
|
|
57
57
|
::TCPServer.new(host, port)
|
|
58
58
|
end
|
|
59
|
-
listen_socket.instance_eval { listen(
|
|
59
|
+
listen_socket.instance_eval { listen(DEFAULT_BACKLOG) } # Change listen backlog to 1024
|
|
60
60
|
super(listen_socket, klass, *args, &block)
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -68,6 +68,7 @@ module Coolio
|
|
|
68
68
|
class UNIXServer < Server
|
|
69
69
|
def initialize(path, klass = UNIXSocket, *args, &block)
|
|
70
70
|
s = ::UNIXServer === path ? path : ::UNIXServer.new(path)
|
|
71
|
+
s.instance_eval { listen(DEFAULT_BACKLOG) }
|
|
71
72
|
super(s, klass, *args, &block)
|
|
72
73
|
end
|
|
73
74
|
end
|
data/lib/cool.io/socket.rb
CHANGED
|
@@ -8,7 +8,7 @@ require 'socket'
|
|
|
8
8
|
require 'resolv'
|
|
9
9
|
|
|
10
10
|
module Coolio
|
|
11
|
-
class Socket < IO
|
|
11
|
+
class Socket < IO
|
|
12
12
|
def self.connect(socket, *args)
|
|
13
13
|
|
|
14
14
|
new(socket, *args).instance_eval do
|
|
@@ -16,42 +16,51 @@ module Coolio
|
|
|
16
16
|
self
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# Just initializes some instance variables to avoid
|
|
21
|
+
# warnings and calls super().
|
|
22
|
+
def initialize *args
|
|
23
|
+
@_failed = nil
|
|
24
|
+
@_connector = nil
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
|
|
20
28
|
watcher_delegate :@_connector
|
|
21
29
|
|
|
30
|
+
remove_method :attach
|
|
22
31
|
def attach(evloop)
|
|
23
32
|
raise RuntimeError, "connection failed" if @_failed
|
|
24
|
-
|
|
33
|
+
|
|
25
34
|
if @_connector
|
|
26
35
|
@_connector.attach(evloop)
|
|
27
36
|
return self
|
|
28
37
|
end
|
|
29
|
-
|
|
38
|
+
|
|
30
39
|
super
|
|
31
40
|
end
|
|
32
41
|
|
|
33
42
|
# Called upon completion of a socket connection
|
|
34
43
|
def on_connect; end
|
|
35
44
|
event_callback :on_connect
|
|
36
|
-
|
|
45
|
+
|
|
37
46
|
# Called if a socket connection failed to complete
|
|
38
47
|
def on_connect_failed; end
|
|
39
48
|
event_callback :on_connect_failed
|
|
40
|
-
|
|
49
|
+
|
|
41
50
|
# Called if a hostname failed to resolve when connecting
|
|
42
51
|
# Defaults to calling on_connect_failed
|
|
43
52
|
alias_method :on_resolve_failed, :on_connect_failed
|
|
44
|
-
|
|
53
|
+
|
|
45
54
|
#########
|
|
46
55
|
protected
|
|
47
56
|
#########
|
|
48
|
-
|
|
57
|
+
|
|
49
58
|
class Connector < IOWatcher
|
|
50
59
|
def initialize(coolio_socket, ruby_socket)
|
|
51
60
|
@coolio_socket, @ruby_socket = coolio_socket, ruby_socket
|
|
52
61
|
super(ruby_socket, :w)
|
|
53
62
|
end
|
|
54
|
-
|
|
63
|
+
|
|
55
64
|
def on_writable
|
|
56
65
|
evl = evloop
|
|
57
66
|
detach
|
|
@@ -67,7 +76,7 @@ module Coolio
|
|
|
67
76
|
@coolio_socket.instance_eval { @_failed = true }
|
|
68
77
|
@coolio_socket.__send__(:on_connect_failed)
|
|
69
78
|
end
|
|
70
|
-
end
|
|
79
|
+
end
|
|
71
80
|
|
|
72
81
|
#######
|
|
73
82
|
private
|
|
@@ -80,11 +89,11 @@ module Coolio
|
|
|
80
89
|
end
|
|
81
90
|
end
|
|
82
91
|
end
|
|
83
|
-
|
|
92
|
+
|
|
84
93
|
class TCPSocket < Socket
|
|
85
94
|
attr_reader :remote_host, :remote_addr, :remote_port, :address_family
|
|
86
95
|
watcher_delegate :@_resolver
|
|
87
|
-
|
|
96
|
+
|
|
88
97
|
# Similar to .new, but used in cases where the resulting object is in a
|
|
89
98
|
# "half-open" state. This is primarily used for when asynchronous
|
|
90
99
|
# DNS resolution is taking place. We don't actually have a handle to
|
|
@@ -95,7 +104,7 @@ module Coolio
|
|
|
95
104
|
obj.__send__(:preinitialize, *args, &block)
|
|
96
105
|
obj
|
|
97
106
|
end
|
|
98
|
-
|
|
107
|
+
|
|
99
108
|
# Perform a non-blocking connect to the given host and port
|
|
100
109
|
# see examples/echo_client.rb
|
|
101
110
|
# addr is a string, can be an IP address or a hostname.
|
|
@@ -107,7 +116,7 @@ module Coolio
|
|
|
107
116
|
elsif(Resolv::IPv6.create(addr) rescue nil)
|
|
108
117
|
family = ::Socket::AF_INET6
|
|
109
118
|
end
|
|
110
|
-
|
|
119
|
+
|
|
111
120
|
if family
|
|
112
121
|
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
|
|
113
122
|
end
|
|
@@ -118,37 +127,39 @@ module Coolio
|
|
|
118
127
|
|
|
119
128
|
precreate(addr, port, *args)
|
|
120
129
|
end
|
|
121
|
-
|
|
130
|
+
|
|
122
131
|
# Called by precreate during asyncronous DNS resolution
|
|
123
132
|
def preinitialize(addr, port, *args)
|
|
124
|
-
@_write_buffer = ::
|
|
133
|
+
@_write_buffer = ::Coolio::Buffer.new # allow for writing BEFORE DNS has resolved
|
|
125
134
|
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
|
126
135
|
@_resolver = TCPConnectResolver.new(self, addr, port, *args)
|
|
127
136
|
end
|
|
128
|
-
|
|
137
|
+
|
|
129
138
|
private :preinitialize
|
|
130
|
-
|
|
139
|
+
|
|
140
|
+
PEERADDR_FAILED = ["?", 0, "name resolusion failed", "?"]
|
|
141
|
+
|
|
131
142
|
def initialize(socket)
|
|
132
143
|
unless socket.is_a?(::TCPSocket) or socket.is_a?(TCPConnectSocket)
|
|
133
144
|
raise TypeError, "socket must be a TCPSocket"
|
|
134
145
|
end
|
|
135
|
-
|
|
146
|
+
|
|
136
147
|
super
|
|
137
|
-
|
|
138
|
-
@address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
|
|
148
|
+
|
|
149
|
+
@address_family, @remote_port, @remote_host, @remote_addr = (socket.peeraddr rescue PEERADDR_FAILED)
|
|
139
150
|
end
|
|
140
|
-
|
|
151
|
+
|
|
141
152
|
def peeraddr
|
|
142
153
|
[@address_family, @remote_port, @remote_host, @remote_addr]
|
|
143
154
|
end
|
|
144
|
-
|
|
155
|
+
|
|
145
156
|
#########
|
|
146
157
|
protected
|
|
147
158
|
#########
|
|
148
159
|
|
|
149
160
|
class TCPConnectSocket < ::Socket
|
|
150
161
|
def initialize(family, addr, port, host = addr)
|
|
151
|
-
@host,
|
|
162
|
+
@host, @addr, @port = host, addr, port
|
|
152
163
|
@address_family = nil
|
|
153
164
|
|
|
154
165
|
super(family, ::Socket::SOCK_STREAM, 0)
|
|
@@ -195,26 +206,26 @@ module Coolio
|
|
|
195
206
|
|
|
196
207
|
def on_failure
|
|
197
208
|
@sock.__send__(:on_resolve_failed)
|
|
198
|
-
@sock.instance_eval do
|
|
199
|
-
@_resolver = nil
|
|
209
|
+
@sock.instance_eval do
|
|
210
|
+
@_resolver = nil
|
|
200
211
|
@_failed = true
|
|
201
212
|
end
|
|
202
213
|
return
|
|
203
214
|
end
|
|
204
215
|
end
|
|
205
216
|
end
|
|
206
|
-
|
|
217
|
+
|
|
207
218
|
class UNIXSocket < Socket
|
|
208
219
|
attr_reader :path, :address_family
|
|
209
|
-
|
|
220
|
+
|
|
210
221
|
# Connect to the given UNIX domain socket
|
|
211
222
|
def self.connect(path, *args)
|
|
212
223
|
new(::UNIXSocket.new(path), *args)
|
|
213
224
|
end
|
|
214
|
-
|
|
225
|
+
|
|
215
226
|
def initialize(socket)
|
|
216
227
|
raise ArgumentError, "socket must be a UNIXSocket" unless socket.is_a? ::UNIXSocket
|
|
217
|
-
|
|
228
|
+
|
|
218
229
|
super
|
|
219
230
|
@address_family, @path = socket.peeraddr
|
|
220
231
|
end
|
data/lib/cool.io.rb
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (C)
|
|
2
|
+
# Copyright (C)2011 Tony Arcieri
|
|
3
3
|
# You can redistribute this under the terms of the Ruby license
|
|
4
4
|
# See file LICENSE for details
|
|
5
5
|
#++
|
|
6
6
|
|
|
7
|
-
require
|
|
7
|
+
require "cool.io/version"
|
|
8
|
+
require "cool.io/custom_require"
|
|
9
|
+
cool_require "cool.io_ext"
|
|
8
10
|
|
|
9
|
-
require "cool.io_ext"
|
|
10
11
|
require "cool.io/loop"
|
|
11
12
|
require "cool.io/meta"
|
|
12
13
|
require "cool.io/io"
|
|
@@ -17,16 +18,16 @@ require "cool.io/listener"
|
|
|
17
18
|
require "cool.io/dns_resolver"
|
|
18
19
|
require "cool.io/socket"
|
|
19
20
|
require "cool.io/server"
|
|
20
|
-
require "cool.io/http_client"
|
|
21
|
-
require "cool.io/dsl"
|
|
22
21
|
|
|
23
22
|
module Coolio
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
def self.inspect
|
|
24
|
+
"Cool.io"
|
|
25
|
+
end
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
module Cool
|
|
30
29
|
# Allow Coolio module to be referenced as Cool.io
|
|
31
|
-
def self.io
|
|
32
|
-
|
|
30
|
+
def self.io
|
|
31
|
+
Coolio
|
|
32
|
+
end
|
|
33
|
+
end
|