eventmachine 0.12.6-java → 0.12.8-java
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/{docs/README → README} +21 -13
- data/Rakefile +5 -3
- data/docs/DEFERRABLES +0 -5
- data/docs/INSTALL +2 -4
- data/docs/LEGAL +1 -1
- data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
- data/docs/PURE_RUBY +0 -2
- data/docs/RELEASE_NOTES +0 -2
- data/docs/SMTP +0 -7
- data/docs/SPAWNED_PROCESSES +0 -4
- data/docs/TODO +0 -2
- data/eventmachine.gemspec +17 -8
- data/examples/ex_channel.rb +43 -0
- data/examples/ex_queue.rb +2 -0
- data/examples/helper.rb +2 -0
- data/ext/cmain.cpp +119 -20
- data/ext/cplusplus.cpp +15 -6
- data/ext/ed.cpp +303 -93
- data/ext/ed.h +49 -22
- data/ext/em.cpp +368 -42
- data/ext/em.h +43 -6
- data/ext/eventmachine.h +21 -8
- data/ext/eventmachine_cpp.h +1 -0
- data/ext/extconf.rb +4 -0
- data/ext/kb.cpp +1 -2
- data/ext/pipe.cpp +1 -3
- data/ext/project.h +21 -0
- data/ext/rubymain.cpp +232 -32
- data/ext/ssl.cpp +38 -1
- data/ext/ssl.h +5 -1
- data/java/src/com/rubyeventmachine/Application.java +7 -3
- data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
- data/lib/{protocols → em}/buftok.rb +16 -5
- data/lib/em/callback.rb +26 -0
- data/lib/em/channel.rb +57 -0
- data/lib/em/connection.rb +505 -0
- data/lib/em/deferrable.rb +144 -165
- data/lib/em/file_watch.rb +54 -0
- data/lib/em/future.rb +24 -25
- data/lib/em/messages.rb +1 -1
- data/lib/em/process_watch.rb +44 -0
- data/lib/em/processes.rb +58 -52
- data/lib/em/protocols.rb +35 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +263 -0
- data/lib/em/protocols/httpclient2.rb +582 -0
- data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
- data/lib/em/protocols/linetext2.rb +160 -0
- data/lib/{protocols → em/protocols}/memcache.rb +37 -7
- data/lib/em/protocols/object_protocol.rb +39 -0
- data/lib/em/protocols/postgres3.rb +247 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +331 -0
- data/lib/em/protocols/smtpserver.rb +547 -0
- data/lib/em/protocols/stomp.rb +200 -0
- data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
- data/lib/em/queue.rb +61 -0
- data/lib/em/spawnable.rb +53 -56
- data/lib/em/streamer.rb +92 -74
- data/lib/em/timers.rb +55 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1008 -1298
- data/lib/evma.rb +1 -1
- data/lib/jeventmachine.rb +106 -101
- data/lib/pr_eventmachine.rb +47 -36
- data/tasks/project.rake +2 -1
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/test_attach.rb +18 -0
- data/tests/test_basic.rb +108 -54
- data/tests/test_channel.rb +63 -0
- data/tests/test_connection_count.rb +2 -2
- data/tests/test_epoll.rb +109 -110
- data/tests/test_errors.rb +36 -36
- data/tests/test_exc.rb +22 -25
- data/tests/test_file_watch.rb +49 -0
- data/tests/test_futures.rb +77 -93
- data/tests/test_hc.rb +2 -2
- data/tests/test_httpclient.rb +55 -52
- data/tests/test_httpclient2.rb +110 -112
- data/tests/test_inactivity_timeout.rb +30 -0
- data/tests/test_kb.rb +8 -9
- data/tests/test_ltp2.rb +274 -277
- data/tests/test_next_tick.rb +91 -65
- data/tests/test_object_protocol.rb +37 -0
- data/tests/test_process_watch.rb +48 -0
- data/tests/test_processes.rb +56 -23
- data/tests/test_proxy_connection.rb +92 -0
- data/tests/test_pure.rb +1 -5
- data/tests/test_queue.rb +44 -0
- data/tests/test_running.rb +9 -14
- data/tests/test_sasl.rb +32 -34
- data/tests/test_send_file.rb +175 -176
- data/tests/test_servers.rb +37 -41
- data/tests/test_smtpserver.rb +47 -55
- data/tests/test_spawn.rb +284 -291
- data/tests/test_ssl_args.rb +1 -1
- data/tests/test_ssl_methods.rb +1 -1
- data/tests/test_ssl_verify.rb +82 -0
- data/tests/test_timers.rb +81 -88
- data/tests/test_ud.rb +0 -7
- data/tests/testem.rb +1 -1
- metadata +52 -36
- data/lib/em/eventable.rb +0 -39
- data/lib/eventmachine_version.rb +0 -31
- data/lib/protocols/header_and_content.rb +0 -129
- data/lib/protocols/httpcli2.rb +0 -803
- data/lib/protocols/httpclient.rb +0 -270
- data/lib/protocols/linetext2.rb +0 -161
- data/lib/protocols/postgres.rb +0 -261
- data/lib/protocols/saslauth.rb +0 -179
- data/lib/protocols/smtpclient.rb +0 -308
- data/lib/protocols/smtpserver.rb +0 -556
- data/lib/protocols/stomp.rb +0 -153
- data/tests/test_eventables.rb +0 -77
data/lib/em/timers.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module EventMachine
|
|
2
|
+
# Creates a one-time timer
|
|
3
|
+
#
|
|
4
|
+
# timer = EventMachine::Timer.new(5) do
|
|
5
|
+
# # this will never fire because we cancel it
|
|
6
|
+
# end
|
|
7
|
+
# timer.cancel
|
|
8
|
+
#
|
|
9
|
+
class Timer
|
|
10
|
+
# Create a new timer that fires after a given number of seconds
|
|
11
|
+
def initialize interval, callback=nil, &block
|
|
12
|
+
@signature = EventMachine::add_timer(interval, callback || block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Cancel the timer
|
|
16
|
+
def cancel
|
|
17
|
+
EventMachine.send :cancel_timer, @signature
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Creates a periodic timer
|
|
22
|
+
#
|
|
23
|
+
# n = 0
|
|
24
|
+
# timer = EventMachine::PeriodicTimer.new(5) do
|
|
25
|
+
# puts "the time is #{Time.now}"
|
|
26
|
+
# timer.cancel if (n+=1) > 5
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
class PeriodicTimer
|
|
30
|
+
# Create a new periodic timer that executes every interval seconds
|
|
31
|
+
def initialize interval, callback=nil, &block
|
|
32
|
+
@interval = interval
|
|
33
|
+
@code = callback || block
|
|
34
|
+
schedule
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Cancel the periodic timer
|
|
38
|
+
def cancel
|
|
39
|
+
@cancelled = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Fire the timer every interval seconds
|
|
43
|
+
attr_accessor :interval
|
|
44
|
+
|
|
45
|
+
def schedule # :nodoc:
|
|
46
|
+
EventMachine::add_timer @interval, proc {self.fire}
|
|
47
|
+
end
|
|
48
|
+
def fire # :nodoc:
|
|
49
|
+
unless @cancelled
|
|
50
|
+
@code.call
|
|
51
|
+
schedule
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/em/version.rb
ADDED
data/lib/eventmachine.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
#--
|
|
2
2
|
#
|
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
|
@@ -73,21 +73,24 @@ else # :cascade
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
require "
|
|
76
|
+
require "em/version"
|
|
77
77
|
require 'em/deferrable'
|
|
78
78
|
require 'em/future'
|
|
79
|
-
require 'em/eventable'
|
|
80
|
-
require 'em/messages'
|
|
81
79
|
require 'em/streamer'
|
|
82
80
|
require 'em/spawnable'
|
|
81
|
+
require 'em/processes'
|
|
82
|
+
require 'em/buftok'
|
|
83
|
+
require 'em/timers'
|
|
84
|
+
require 'em/protocols'
|
|
85
|
+
require 'em/connection'
|
|
86
|
+
require 'em/callback'
|
|
87
|
+
require 'em/queue'
|
|
88
|
+
require 'em/channel'
|
|
89
|
+
require 'em/file_watch'
|
|
90
|
+
require 'em/process_watch'
|
|
83
91
|
|
|
84
92
|
require 'shellwords'
|
|
85
93
|
|
|
86
|
-
#-- Additional requires are at the BOTTOM of this file, because they
|
|
87
|
-
#-- depend on stuff defined in here. Refactor that someday.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
94
|
# == Introduction
|
|
92
95
|
# EventMachine provides a fast, lightweight framework for implementing
|
|
93
96
|
# Ruby programs that can use the network to communicate with other
|
|
@@ -114,21 +117,28 @@ require 'shellwords'
|
|
|
114
117
|
# == Usage example
|
|
115
118
|
#
|
|
116
119
|
# Here's a fully-functional echo server implemented in EventMachine:
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
120
|
+
#
|
|
121
|
+
# require 'eventmachine'
|
|
122
|
+
#
|
|
123
|
+
# module EchoServer
|
|
124
|
+
# def post_init
|
|
125
|
+
# puts "-- someone connected to the echo server!"
|
|
126
|
+
# end
|
|
127
|
+
#
|
|
128
|
+
# def receive_data data
|
|
129
|
+
# send_data ">>>you sent: #{data}"
|
|
130
|
+
# close_connection if data =~ /quit/i
|
|
131
|
+
# end
|
|
132
|
+
#
|
|
133
|
+
# def unbind
|
|
134
|
+
# puts "-- someone disconnected from the echo server!"
|
|
135
|
+
# end
|
|
136
|
+
# end
|
|
137
|
+
#
|
|
138
|
+
# EventMachine::run {
|
|
139
|
+
# EventMachine::start_server "127.0.0.1", 8081, EchoServer
|
|
140
|
+
# }
|
|
141
|
+
#
|
|
132
142
|
# What's going on here? Well, we have defined the module EchoServer to
|
|
133
143
|
# implement the semantics of the echo protocol (more about that shortly).
|
|
134
144
|
# The last three lines invoke the event-machine itself, which runs forever
|
|
@@ -164,144 +174,141 @@ require 'shellwords'
|
|
|
164
174
|
# (Notice that closing the connection doesn't terminate the processing loop,
|
|
165
175
|
# or change the fact that your echo server is still accepting connections!)
|
|
166
176
|
#
|
|
167
|
-
#
|
|
168
177
|
# == Questions and Futures
|
|
169
178
|
# Would it be useful for EventMachine to incorporate the Observer pattern
|
|
170
179
|
# and make use of the corresponding Ruby <tt>observer</tt> package?
|
|
171
180
|
# Interesting thought.
|
|
172
181
|
#
|
|
173
|
-
#
|
|
174
182
|
module EventMachine
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
# EventMachine::run initializes and runs an event loop.
|
|
184
|
+
# This method only returns if user-callback code calls stop_event_loop.
|
|
185
|
+
# Use the supplied block to define your clients and servers.
|
|
186
|
+
# The block is called by EventMachine::run immediately after initializing
|
|
187
|
+
# its internal event loop but <i>before</i> running the loop.
|
|
188
|
+
# Therefore this block is the right place to call start_server if you
|
|
189
|
+
# want to accept connections from remote clients.
|
|
190
|
+
#
|
|
191
|
+
# For programs that are structured as servers, it's usually appropriate
|
|
192
|
+
# to start an event loop by calling EventMachine::run, and let it
|
|
193
|
+
# run forever. It's also possible to use EventMachine::run to make a single
|
|
194
|
+
# client-connection to a remote server, process the data flow from that
|
|
195
|
+
# single connection, and then call stop_event_loop to force EventMachine::run
|
|
196
|
+
# to return. Your program will then continue from the point immediately
|
|
197
|
+
# following the call to EventMachine::run.
|
|
198
|
+
#
|
|
199
|
+
# You can of course do both client and servers simultaneously in the same program.
|
|
200
|
+
# One of the strengths of the event-driven programming model is that the
|
|
201
|
+
# handling of network events on many different connections will be interleaved,
|
|
202
|
+
# and scheduled according to the actual events themselves. This maximizes
|
|
203
|
+
# efficiency.
|
|
204
|
+
#
|
|
205
|
+
# === Server usage example
|
|
206
|
+
#
|
|
207
|
+
# See EventMachine.start_server
|
|
208
|
+
#
|
|
209
|
+
# === Client usage example
|
|
210
|
+
#
|
|
211
|
+
# See EventMachine.connect
|
|
212
|
+
#
|
|
213
|
+
#--
|
|
214
|
+
# Obsoleted the use_threads mechanism.
|
|
215
|
+
# 25Nov06: Added the begin/ensure block. We need to be sure that release_machine
|
|
216
|
+
# gets called even if an exception gets thrown within any of the user code
|
|
217
|
+
# that the event loop runs. The best way to see this is to run a unit
|
|
218
|
+
# test with two functions, each of which calls EventMachine#run and each of
|
|
219
|
+
# which throws something inside of #run. Without the ensure, the second test
|
|
220
|
+
# will start without release_machine being called and will immediately throw
|
|
221
|
+
# a C++ runtime error.
|
|
222
|
+
#
|
|
223
|
+
def self.run blk=nil, tail=nil, &block
|
|
224
|
+
@tails ||= []
|
|
225
|
+
tail and @tails.unshift(tail)
|
|
180
226
|
|
|
227
|
+
if reactor_running?
|
|
228
|
+
(b = blk || block) and b.call # next_tick(b)
|
|
229
|
+
else
|
|
230
|
+
@conns = {}
|
|
231
|
+
@acceptors = {}
|
|
232
|
+
@timers = {}
|
|
233
|
+
@wrapped_exception = nil
|
|
234
|
+
begin
|
|
235
|
+
@reactor_running = true
|
|
236
|
+
initialize_event_machine
|
|
237
|
+
(b = blk || block) and add_timer(0, b)
|
|
238
|
+
if @next_tick_queue && !@next_tick_queue.empty?
|
|
239
|
+
add_timer(0) { signal_loopbreak }
|
|
240
|
+
end
|
|
241
|
+
@reactor_thread = Thread.current
|
|
242
|
+
run_machine
|
|
243
|
+
ensure
|
|
244
|
+
begin
|
|
245
|
+
release_machine
|
|
246
|
+
ensure
|
|
247
|
+
if @threadpool
|
|
248
|
+
@threadpool.each { |t| t.exit }
|
|
249
|
+
@threadpool.each { |t| t.kill! if t.alive? }
|
|
250
|
+
@threadqueue = nil
|
|
251
|
+
@resultqueue = nil
|
|
252
|
+
end
|
|
253
|
+
@threadpool = nil
|
|
254
|
+
@next_tick_queue = nil
|
|
255
|
+
end
|
|
256
|
+
@reactor_running = false
|
|
257
|
+
@reactor_thread = nil
|
|
258
|
+
end
|
|
181
259
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# The block is called by EventMachine::run immediately after initializing
|
|
186
|
-
# its internal event loop but <i>before</i> running the loop.
|
|
187
|
-
# Therefore this block is the right place to call start_server if you
|
|
188
|
-
# want to accept connections from remote clients.
|
|
189
|
-
#
|
|
190
|
-
# For programs that are structured as servers, it's usually appropriate
|
|
191
|
-
# to start an event loop by calling EventMachine::run, and let it
|
|
192
|
-
# run forever. It's also possible to use EventMachine::run to make a single
|
|
193
|
-
# client-connection to a remote server, process the data flow from that
|
|
194
|
-
# single connection, and then call stop_event_loop to force EventMachine::run
|
|
195
|
-
# to return. Your program will then continue from the point immediately
|
|
196
|
-
# following the call to EventMachine::run.
|
|
197
|
-
#
|
|
198
|
-
# You can of course do both client and servers simultaneously in the same program.
|
|
199
|
-
# One of the strengths of the event-driven programming model is that the
|
|
200
|
-
# handling of network events on many different connections will be interleaved,
|
|
201
|
-
# and scheduled according to the actual events themselves. This maximizes
|
|
202
|
-
# efficiency.
|
|
203
|
-
#
|
|
204
|
-
# === Server usage example
|
|
205
|
-
#
|
|
206
|
-
# See the text at the top of this file for an example of an echo server.
|
|
207
|
-
#
|
|
208
|
-
# === Client usage example
|
|
209
|
-
#
|
|
210
|
-
# See the description of stop_event_loop for an extremely simple client example.
|
|
211
|
-
#
|
|
212
|
-
#--
|
|
213
|
-
# Obsoleted the use_threads mechanism.
|
|
214
|
-
# 25Nov06: Added the begin/ensure block. We need to be sure that release_machine
|
|
215
|
-
# gets called even if an exception gets thrown within any of the user code
|
|
216
|
-
# that the event loop runs. The best way to see this is to run a unit
|
|
217
|
-
# test with two functions, each of which calls EventMachine#run and each of
|
|
218
|
-
# which throws something inside of #run. Without the ensure, the second test
|
|
219
|
-
# will start without release_machine being called and will immediately throw
|
|
220
|
-
# a C++ runtime error.
|
|
221
|
-
#
|
|
222
|
-
def EventMachine::run blk=nil, tail=nil, &block
|
|
223
|
-
@tails ||= []
|
|
224
|
-
tail and @tails.unshift(tail)
|
|
225
|
-
|
|
226
|
-
if reactor_running?
|
|
227
|
-
(b = blk || block) and b.call # next_tick(b)
|
|
228
|
-
else
|
|
229
|
-
@conns = {}
|
|
230
|
-
@acceptors = {}
|
|
231
|
-
@timers = {}
|
|
232
|
-
@wrapped_exception = nil
|
|
233
|
-
begin
|
|
234
|
-
@reactor_running = true
|
|
235
|
-
initialize_event_machine
|
|
236
|
-
(b = blk || block) and add_timer(0, b)
|
|
237
|
-
if @next_tick_queue && !@next_tick_queue.empty?
|
|
238
|
-
add_timer(0) { signal_loopbreak }
|
|
239
|
-
end
|
|
240
|
-
run_machine
|
|
241
|
-
ensure
|
|
242
|
-
begin
|
|
243
|
-
release_machine
|
|
244
|
-
ensure
|
|
245
|
-
if @threadpool
|
|
246
|
-
@threadpool.each { |t| t.exit }
|
|
247
|
-
@threadpool.each { |t| t.kill! if t.alive? }
|
|
248
|
-
@threadqueue = nil
|
|
249
|
-
@resultqueue = nil
|
|
250
|
-
end
|
|
251
|
-
@threadpool = nil
|
|
252
|
-
end
|
|
253
|
-
@reactor_running = false
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
until @tails.empty?
|
|
257
|
-
@tails.pop.call
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
raise @wrapped_exception if @wrapped_exception
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
# Sugars a common use case. Will pass the given block to #run, but will terminate
|
|
266
|
-
# the reactor loop and exit the function as soon as the code in the block completes.
|
|
267
|
-
# (Normally, #run keeps running indefinitely, even after the block supplied to it
|
|
268
|
-
# finishes running, until user code calls #stop.)
|
|
269
|
-
#
|
|
270
|
-
def EventMachine::run_block &block
|
|
271
|
-
pr = proc {
|
|
272
|
-
block.call
|
|
273
|
-
EventMachine::stop
|
|
274
|
-
}
|
|
275
|
-
run(&pr)
|
|
276
|
-
end
|
|
260
|
+
until @tails.empty?
|
|
261
|
+
@tails.pop.call
|
|
262
|
+
end
|
|
277
263
|
|
|
278
|
-
|
|
279
|
-
#--
|
|
280
|
-
# This implementation is subject to change, especially if we clean up the relationship
|
|
281
|
-
# of EM#run to @reactor_running.
|
|
282
|
-
# Original patch by Aman Gupta.
|
|
283
|
-
#
|
|
284
|
-
def EventMachine::fork_reactor &block
|
|
285
|
-
Kernel.fork do
|
|
286
|
-
if self.reactor_running?
|
|
287
|
-
self.stop_event_loop
|
|
288
|
-
self.release_machine
|
|
289
|
-
self.instance_variable_set( '@reactor_running', false )
|
|
290
|
-
end
|
|
291
|
-
self.run block
|
|
292
|
-
end
|
|
264
|
+
raise @wrapped_exception if @wrapped_exception
|
|
293
265
|
end
|
|
266
|
+
end
|
|
294
267
|
|
|
268
|
+
# Sugars a common use case. Will pass the given block to #run, but will terminate
|
|
269
|
+
# the reactor loop and exit the function as soon as the code in the block completes.
|
|
270
|
+
# (Normally, #run keeps running indefinitely, even after the block supplied to it
|
|
271
|
+
# finishes running, until user code calls #stop.)
|
|
272
|
+
#
|
|
273
|
+
def self.run_block &block
|
|
274
|
+
pr = proc {
|
|
275
|
+
block.call
|
|
276
|
+
EventMachine::stop
|
|
277
|
+
}
|
|
278
|
+
run(&pr)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Returns true if the calling thread is the same thread as the reactor.
|
|
282
|
+
def self.reactor_thread?
|
|
283
|
+
Thread.current == @reactor_thread
|
|
284
|
+
end
|
|
295
285
|
|
|
296
|
-
#
|
|
286
|
+
# Runs the given callback on the reactor thread, or immediately if called
|
|
287
|
+
# from the reactor thread. Accepts the same arguments as EM::Callback
|
|
288
|
+
def self.schedule(*a, &b)
|
|
289
|
+
cb = Callback(*a, &b)
|
|
290
|
+
if reactor_running? && reactor_thread?
|
|
291
|
+
cb.call
|
|
292
|
+
else
|
|
293
|
+
next_tick { cb.call }
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# fork_reactor forks a new process and calls EM#run inside of it, passing your block.
|
|
297
298
|
#--
|
|
298
|
-
#
|
|
299
|
-
#
|
|
300
|
-
#
|
|
301
|
-
#
|
|
302
|
-
def
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
# This implementation is subject to change, especially if we clean up the relationship
|
|
300
|
+
# of EM#run to @reactor_running.
|
|
301
|
+
# Original patch by Aman Gupta.
|
|
302
|
+
#
|
|
303
|
+
def self.fork_reactor &block
|
|
304
|
+
Kernel.fork do
|
|
305
|
+
if self.reactor_running?
|
|
306
|
+
self.stop_event_loop
|
|
307
|
+
self.release_machine
|
|
308
|
+
self.instance_variable_set( '@reactor_running', false )
|
|
309
|
+
end
|
|
310
|
+
self.run block
|
|
311
|
+
end
|
|
305
312
|
end
|
|
306
313
|
|
|
307
314
|
# EventMachine#add_timer adds a one-shot timer to the event loop.
|
|
@@ -330,9 +337,6 @@ module EventMachine
|
|
|
330
337
|
# course, since no network clients or servers are defined. Stop the program
|
|
331
338
|
# with Ctrl-C.
|
|
332
339
|
#
|
|
333
|
-
# require 'rubygems'
|
|
334
|
-
# require 'eventmachine'
|
|
335
|
-
#
|
|
336
340
|
# EventMachine::run {
|
|
337
341
|
# puts "Starting the run now: #{Time.now}"
|
|
338
342
|
# EventMachine::add_timer 5, proc { puts "Executing timer event: #{Time.now}" }
|
|
@@ -340,15 +344,16 @@ module EventMachine
|
|
|
340
344
|
# }
|
|
341
345
|
#
|
|
342
346
|
#
|
|
347
|
+
# Also see EventMachine::Timer
|
|
343
348
|
#--
|
|
344
349
|
# Changed 04Oct06: We now pass the interval as an integer number of milliseconds.
|
|
345
350
|
#
|
|
346
|
-
def
|
|
351
|
+
def self.add_timer *args, &block
|
|
347
352
|
interval = args.shift
|
|
348
353
|
code = args.shift || block
|
|
349
354
|
if code
|
|
350
355
|
# check too many timers!
|
|
351
|
-
s = add_oneshot_timer((interval * 1000).to_i)
|
|
356
|
+
s = add_oneshot_timer((interval.to_f * 1000).to_i)
|
|
352
357
|
@timers[s] = code
|
|
353
358
|
s
|
|
354
359
|
end
|
|
@@ -370,7 +375,10 @@ module EventMachine
|
|
|
370
375
|
# EventMachine::add_periodic_timer( 5 ) { $stderr.write "$" }
|
|
371
376
|
# }
|
|
372
377
|
#
|
|
373
|
-
|
|
378
|
+
#
|
|
379
|
+
# Also see EventMachine::PeriodicTimer
|
|
380
|
+
#
|
|
381
|
+
def self.add_periodic_timer *args, &block
|
|
374
382
|
interval = args.shift
|
|
375
383
|
code = args.shift || block
|
|
376
384
|
if code
|
|
@@ -382,11 +390,11 @@ module EventMachine
|
|
|
382
390
|
end
|
|
383
391
|
end
|
|
384
392
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
393
|
+
# Cancel a timer using its signature. You can also use EventMachine::Timer#cancel
|
|
394
|
+
#
|
|
395
|
+
def self.cancel_timer signature
|
|
396
|
+
@timers[signature] = false if @timers.has_key?(signature)
|
|
397
|
+
end
|
|
390
398
|
|
|
391
399
|
|
|
392
400
|
# stop_event_loop may called from within a callback method
|
|
@@ -407,7 +415,6 @@ module EventMachine
|
|
|
407
415
|
# require 'eventmachine'
|
|
408
416
|
#
|
|
409
417
|
# module Redmond
|
|
410
|
-
#
|
|
411
418
|
# def post_init
|
|
412
419
|
# puts "We're sending a dumb HTTP request to the remote peer."
|
|
413
420
|
# send_data "GET / HTTP/1.1\r\nHost: www.microsoft.com\r\n\r\n"
|
|
@@ -422,7 +429,6 @@ module EventMachine
|
|
|
422
429
|
# def unbind
|
|
423
430
|
# puts "A connection has terminated."
|
|
424
431
|
# end
|
|
425
|
-
#
|
|
426
432
|
# end
|
|
427
433
|
#
|
|
428
434
|
# puts "We're starting the event loop now."
|
|
@@ -441,7 +447,7 @@ module EventMachine
|
|
|
441
447
|
# The event loop has stopped.
|
|
442
448
|
#
|
|
443
449
|
#
|
|
444
|
-
def
|
|
450
|
+
def self.stop_event_loop
|
|
445
451
|
EventMachine::stop
|
|
446
452
|
end
|
|
447
453
|
|
|
@@ -505,7 +511,6 @@ module EventMachine
|
|
|
505
511
|
# require 'eventmachine'
|
|
506
512
|
#
|
|
507
513
|
# module LineCounter
|
|
508
|
-
#
|
|
509
514
|
# MaxLinesPerConnection = 10
|
|
510
515
|
#
|
|
511
516
|
# def post_init
|
|
@@ -522,8 +527,7 @@ module EventMachine
|
|
|
522
527
|
# @line_count == MaxLinesPerConnection and close_connection_after_writing
|
|
523
528
|
# end
|
|
524
529
|
# end
|
|
525
|
-
#
|
|
526
|
-
# end # module LineCounter
|
|
530
|
+
# end
|
|
527
531
|
#
|
|
528
532
|
# EventMachine::run {
|
|
529
533
|
# host,port = "192.168.0.100", 8090
|
|
@@ -533,8 +537,7 @@ module EventMachine
|
|
|
533
537
|
# }
|
|
534
538
|
#
|
|
535
539
|
#
|
|
536
|
-
def
|
|
537
|
-
|
|
540
|
+
def self.start_server server, port=nil, handler=nil, *args, &block
|
|
538
541
|
begin
|
|
539
542
|
port = Integer(port)
|
|
540
543
|
rescue ArgumentError, TypeError
|
|
@@ -544,7 +547,7 @@ module EventMachine
|
|
|
544
547
|
handler = port
|
|
545
548
|
port = nil
|
|
546
549
|
end if port
|
|
547
|
-
|
|
550
|
+
|
|
548
551
|
klass = if (handler and handler.is_a?(Class))
|
|
549
552
|
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
550
553
|
handler
|
|
@@ -573,11 +576,15 @@ module EventMachine
|
|
|
573
576
|
# Requested by Kirk Haines. TODO, this isn't OOP enough. We ought somehow
|
|
574
577
|
# to have #start_server return an object that has a close or a stop method on it.
|
|
575
578
|
#
|
|
576
|
-
def
|
|
577
|
-
|
|
579
|
+
def self.stop_server signature
|
|
580
|
+
EventMachine::stop_tcp_server signature
|
|
578
581
|
end
|
|
579
582
|
|
|
580
|
-
|
|
583
|
+
# Start a Unix-domain server
|
|
584
|
+
#
|
|
585
|
+
# Note that this is an alias for EventMachine::start_server, which can be used to start both
|
|
586
|
+
# TCP and Unix-domain servers
|
|
587
|
+
def self.start_unix_domain_server filename, *args, &block
|
|
581
588
|
start_server filename, *args, &block
|
|
582
589
|
end
|
|
583
590
|
|
|
@@ -603,11 +610,7 @@ module EventMachine
|
|
|
603
610
|
# (antisocially) ends the event loop, which automatically drops the connection
|
|
604
611
|
# (and incidentally calls the connection's unbind method).
|
|
605
612
|
#
|
|
606
|
-
# require 'rubygems'
|
|
607
|
-
# require 'eventmachine'
|
|
608
|
-
#
|
|
609
613
|
# module DumbHttpClient
|
|
610
|
-
#
|
|
611
614
|
# def post_init
|
|
612
615
|
# send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
|
|
613
616
|
# @data = ""
|
|
@@ -627,9 +630,7 @@ module EventMachine
|
|
|
627
630
|
# def unbind
|
|
628
631
|
# puts "A connection has terminated"
|
|
629
632
|
# end
|
|
630
|
-
#
|
|
631
|
-
# end # DumbHttpClient
|
|
632
|
-
#
|
|
633
|
+
# end
|
|
633
634
|
#
|
|
634
635
|
# EventMachine::run {
|
|
635
636
|
# EventMachine::connect "www.bayshorenetworks.com", 80, DumbHttpClient
|
|
@@ -647,7 +648,7 @@ module EventMachine
|
|
|
647
648
|
# end
|
|
648
649
|
#
|
|
649
650
|
# #.......your other class code
|
|
650
|
-
# end
|
|
651
|
+
# end
|
|
651
652
|
#
|
|
652
653
|
# If you do this, then an instance of your class will be instantiated to handle
|
|
653
654
|
# every network connection created by your code or accepted by servers that you
|
|
@@ -678,7 +679,7 @@ module EventMachine
|
|
|
678
679
|
# to have them behave differently with respect to post_init
|
|
679
680
|
# if at all possible.
|
|
680
681
|
#
|
|
681
|
-
def
|
|
682
|
+
def self.bind_connect bind_addr, bind_port, server, port=nil, handler=nil, *args
|
|
682
683
|
begin
|
|
683
684
|
port = Integer(port)
|
|
684
685
|
rescue ArgumentError, TypeError
|
|
@@ -703,7 +704,11 @@ module EventMachine
|
|
|
703
704
|
end
|
|
704
705
|
|
|
705
706
|
s = if port
|
|
706
|
-
|
|
707
|
+
if bind_addr
|
|
708
|
+
bind_connect_server bind_addr, bind_port, server, port
|
|
709
|
+
else
|
|
710
|
+
connect_server server, port
|
|
711
|
+
end
|
|
707
712
|
else
|
|
708
713
|
connect_unix_server server
|
|
709
714
|
end
|
|
@@ -714,6 +719,10 @@ module EventMachine
|
|
|
714
719
|
c
|
|
715
720
|
end
|
|
716
721
|
|
|
722
|
+
def self.connect server, port=nil, handler=nil, *args, &blk
|
|
723
|
+
bind_connect nil, nil, server, port, handler, *args, &blk
|
|
724
|
+
end
|
|
725
|
+
|
|
717
726
|
# EventMachine::attach registers a given file descriptor or IO object with the eventloop
|
|
718
727
|
#
|
|
719
728
|
# If the handler provided has the functions notify_readable or notify_writable defined,
|
|
@@ -724,35 +733,35 @@ module EventMachine
|
|
|
724
733
|
#
|
|
725
734
|
# === Usage Example
|
|
726
735
|
#
|
|
727
|
-
#
|
|
728
|
-
#
|
|
729
|
-
#
|
|
730
|
-
#
|
|
736
|
+
# module SimpleHttpClient
|
|
737
|
+
# def initialize sock
|
|
738
|
+
# @sock = sock
|
|
739
|
+
# end
|
|
731
740
|
#
|
|
732
|
-
#
|
|
733
|
-
#
|
|
741
|
+
# def notify_readable
|
|
742
|
+
# header = @sock.readline
|
|
734
743
|
#
|
|
735
|
-
#
|
|
736
|
-
#
|
|
737
|
-
#
|
|
738
|
-
#
|
|
739
|
-
#
|
|
740
|
-
#
|
|
741
|
-
#
|
|
744
|
+
# if header == "\r\n"
|
|
745
|
+
# # detach returns the file descriptor number (fd == @sock.fileno)
|
|
746
|
+
# fd = detach
|
|
747
|
+
# end
|
|
748
|
+
# rescue EOFError
|
|
749
|
+
# detach
|
|
750
|
+
# end
|
|
742
751
|
#
|
|
743
|
-
#
|
|
744
|
-
#
|
|
745
|
-
#
|
|
746
|
-
#
|
|
747
|
-
#
|
|
748
|
-
#
|
|
749
|
-
#
|
|
752
|
+
# def unbind
|
|
753
|
+
# EM.next_tick do
|
|
754
|
+
# # socket is detached from the eventloop, but still open
|
|
755
|
+
# data = @sock.read
|
|
756
|
+
# end
|
|
757
|
+
# end
|
|
758
|
+
# end
|
|
750
759
|
#
|
|
751
|
-
#
|
|
752
|
-
#
|
|
753
|
-
#
|
|
754
|
-
#
|
|
755
|
-
#
|
|
760
|
+
# EM.run{
|
|
761
|
+
# $sock = TCPSocket.new('site.com', 80)
|
|
762
|
+
# $sock.write("GET / HTTP/1.0\r\n\r\n")
|
|
763
|
+
# EM.attach $sock, SimpleHttpClient, $sock
|
|
764
|
+
# }
|
|
756
765
|
#
|
|
757
766
|
#--
|
|
758
767
|
# Thanks to Riham Aldakkak (eSpace Technologies) for the initial patch
|
|
@@ -781,120 +790,122 @@ module EventMachine
|
|
|
781
790
|
c
|
|
782
791
|
end
|
|
783
792
|
|
|
784
|
-
#--
|
|
785
|
-
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO BE HERE IN THIS FORM, OR AT ALL.
|
|
786
|
-
# (03Nov06)
|
|
787
|
-
# Observe, the test for already-connected FAILS if we call a reconnect inside post_init,
|
|
788
|
-
# because we haven't set up the connection in @conns by that point.
|
|
789
|
-
# RESIST THE TEMPTATION to "fix" this problem by redefining the behavior of post_init.
|
|
790
|
-
#
|
|
791
|
-
# Changed 22Nov06: if called on an already-connected handler, just return the
|
|
792
|
-
# handler and do nothing more. Originally this condition raised an exception.
|
|
793
|
-
# We may want to change it yet again and call the block, if any.
|
|
794
|
-
#
|
|
795
|
-
def EventMachine::reconnect server, port, handler
|
|
796
|
-
raise "invalid handler" unless handler.respond_to?(:connection_completed)
|
|
797
|
-
#raise "still connected" if @conns.has_key?(handler.signature)
|
|
798
|
-
return handler if @conns.has_key?(handler.signature)
|
|
799
|
-
s = connect_server server, port
|
|
800
|
-
handler.signature = s
|
|
801
|
-
@conns[s] = handler
|
|
802
|
-
block_given? and yield handler
|
|
803
|
-
handler
|
|
804
|
-
end
|
|
805
793
|
|
|
794
|
+
# Connect to a given host/port and re-use the provided EventMachine::Connection instance
|
|
795
|
+
#--
|
|
796
|
+
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO BE HERE IN THIS FORM, OR AT ALL.
|
|
797
|
+
# (03Nov06)
|
|
798
|
+
# Observe, the test for already-connected FAILS if we call a reconnect inside post_init,
|
|
799
|
+
# because we haven't set up the connection in @conns by that point.
|
|
800
|
+
# RESIST THE TEMPTATION to "fix" this problem by redefining the behavior of post_init.
|
|
801
|
+
#
|
|
802
|
+
# Changed 22Nov06: if called on an already-connected handler, just return the
|
|
803
|
+
# handler and do nothing more. Originally this condition raised an exception.
|
|
804
|
+
# We may want to change it yet again and call the block, if any.
|
|
805
|
+
#
|
|
806
|
+
def self.reconnect server, port, handler # :nodoc:
|
|
807
|
+
raise "invalid handler" unless handler.respond_to?(:connection_completed)
|
|
808
|
+
#raise "still connected" if @conns.has_key?(handler.signature)
|
|
809
|
+
return handler if @conns.has_key?(handler.signature)
|
|
810
|
+
|
|
811
|
+
s = connect_server server, port
|
|
812
|
+
handler.signature = s
|
|
813
|
+
@conns[s] = handler
|
|
814
|
+
block_given? and yield handler
|
|
815
|
+
handler
|
|
816
|
+
end
|
|
806
817
|
|
|
807
818
|
|
|
819
|
+
# Make a connection to a Unix-domain socket. This is not implemented on Windows platforms.
|
|
820
|
+
# The parameter socketname is a String which identifies the Unix-domain socket you want
|
|
821
|
+
# to connect to. socketname is the name of a file on your local system, and in most cases
|
|
822
|
+
# is a fully-qualified path name. Make sure that your process has enough local permissions
|
|
823
|
+
# to open the Unix-domain socket.
|
|
824
|
+
# See also the documentation for #connect. This method behaves like #connect
|
|
825
|
+
# in all respects except for the fact that it connects to a local Unix-domain
|
|
826
|
+
# socket rather than a TCP socket.
|
|
827
|
+
#
|
|
828
|
+
# Note that this method is simply an alias for #connect, which can connect to both TCP
|
|
829
|
+
# and Unix-domain sockets
|
|
830
|
+
#--
|
|
831
|
+
# For making connections to Unix-domain sockets.
|
|
832
|
+
# Eventually this has to get properly documented and unified with the TCP-connect methods.
|
|
833
|
+
# Note how nearly identical this is to EventMachine#connect
|
|
834
|
+
def self.connect_unix_domain socketname, *args, &blk
|
|
835
|
+
connect socketname, *args, &blk
|
|
836
|
+
end
|
|
837
|
+
|
|
808
838
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
# then see Connection#send_datagram.
|
|
880
|
-
#
|
|
881
|
-
# DO NOT call send_data from a datagram socket
|
|
882
|
-
# outside of a #receive_data method. Use #send_datagram. If you do use #send_data
|
|
883
|
-
# outside of a #receive_data method, you'll get a confusing error
|
|
884
|
-
# because there is no "peer," as #send_data requires. (Inside of #receive_data,
|
|
885
|
-
# #send_data "fakes" the peer as described above.)
|
|
886
|
-
#
|
|
887
|
-
#--
|
|
888
|
-
# Replaced the implementation on 01Oct06. Thanks to Tobias Gustafsson for pointing
|
|
889
|
-
# out that this originally did not take a class but only a module.
|
|
890
|
-
#
|
|
891
|
-
def self::open_datagram_socket address, port, handler=nil, *args
|
|
892
|
-
klass = if (handler and handler.is_a?(Class))
|
|
893
|
-
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
894
|
-
handler
|
|
895
|
-
else
|
|
896
|
-
Class.new( Connection ) {handler and include handler}
|
|
897
|
-
end
|
|
839
|
+
# EventMachine#open_datagram_socket is for support of UDP-based
|
|
840
|
+
# protocols. Its usage is similar to that of EventMachine#start_server.
|
|
841
|
+
# It takes three parameters: an IP address (which must be valid
|
|
842
|
+
# on the machine which executes the method), a port number,
|
|
843
|
+
# and an optional Module name which will handle the data.
|
|
844
|
+
# This method will create a new UDP (datagram) socket and
|
|
845
|
+
# bind it to the address and port that you specify.
|
|
846
|
+
# The normal callbacks (see EventMachine#start_server) will
|
|
847
|
+
# be called as events of interest occur on the newly-created
|
|
848
|
+
# socket, but there are some differences in how they behave.
|
|
849
|
+
#
|
|
850
|
+
# Connection#receive_data will be called when a datagram packet
|
|
851
|
+
# is received on the socket, but unlike TCP sockets, the message
|
|
852
|
+
# boundaries of the received data will be respected. In other words,
|
|
853
|
+
# if the remote peer sent you a datagram of a particular size,
|
|
854
|
+
# you may rely on Connection#receive_data to give you the
|
|
855
|
+
# exact data in the packet, with the original data length.
|
|
856
|
+
# Also observe that Connection#receive_data may be called with a
|
|
857
|
+
# <i>zero-length</i> data payload, since empty datagrams are permitted
|
|
858
|
+
# in UDP.
|
|
859
|
+
#
|
|
860
|
+
# Connection#send_data is available with UDP packets as with TCP,
|
|
861
|
+
# but there is an important difference. Because UDP communications
|
|
862
|
+
# are <i>connectionless,</i> there is no implicit recipient for the packets you
|
|
863
|
+
# send. Ordinarily you must specify the recipient for each packet you send.
|
|
864
|
+
# However, EventMachine
|
|
865
|
+
# provides for the typical pattern of receiving a UDP datagram
|
|
866
|
+
# from a remote peer, performing some operation, and then sending
|
|
867
|
+
# one or more packets in response to the same remote peer.
|
|
868
|
+
# To support this model easily, just use Connection#send_data
|
|
869
|
+
# in the code that you supply for Connection:receive_data.
|
|
870
|
+
# EventMachine will
|
|
871
|
+
# provide an implicit return address for any messages sent to
|
|
872
|
+
# Connection#send_data within the context of a Connection#receive_data callback,
|
|
873
|
+
# and your response will automatically go to the correct remote peer.
|
|
874
|
+
# (TODO: Example-code needed!)
|
|
875
|
+
#
|
|
876
|
+
# Observe that the port number that you supply to EventMachine#open_datagram_socket
|
|
877
|
+
# may be zero. In this case, EventMachine will create a UDP socket
|
|
878
|
+
# that is bound to an <i>ephemeral</i> (not well-known) port.
|
|
879
|
+
# This is not appropriate for servers that must publish a well-known
|
|
880
|
+
# port to which remote peers may send datagrams. But it can be useful
|
|
881
|
+
# for clients that send datagrams to other servers.
|
|
882
|
+
# If you do this, you will receive any responses from the remote
|
|
883
|
+
# servers through the normal Connection#receive_data callback.
|
|
884
|
+
# Observe that you will probably have issues with firewalls blocking
|
|
885
|
+
# the ephemeral port numbers, so this technique is most appropriate for LANs.
|
|
886
|
+
# (TODO: Need an example!)
|
|
887
|
+
#
|
|
888
|
+
# If you wish to send datagrams to arbitrary remote peers (not
|
|
889
|
+
# necessarily ones that have sent data to which you are responding),
|
|
890
|
+
# then see Connection#send_datagram.
|
|
891
|
+
#
|
|
892
|
+
# DO NOT call send_data from a datagram socket
|
|
893
|
+
# outside of a #receive_data method. Use #send_datagram. If you do use #send_data
|
|
894
|
+
# outside of a #receive_data method, you'll get a confusing error
|
|
895
|
+
# because there is no "peer," as #send_data requires. (Inside of #receive_data,
|
|
896
|
+
# #send_data "fakes" the peer as described above.)
|
|
897
|
+
#
|
|
898
|
+
#--
|
|
899
|
+
# Replaced the implementation on 01Oct06. Thanks to Tobias Gustafsson for pointing
|
|
900
|
+
# out that this originally did not take a class but only a module.
|
|
901
|
+
#
|
|
902
|
+
def self.open_datagram_socket address, port, handler=nil, *args
|
|
903
|
+
klass = if (handler and handler.is_a?(Class))
|
|
904
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
905
|
+
handler
|
|
906
|
+
else
|
|
907
|
+
Class.new( Connection ) {handler and include handler}
|
|
908
|
+
end
|
|
898
909
|
|
|
899
910
|
arity = klass.instance_method(:initialize).arity
|
|
900
911
|
expected = arity >= 0 ? arity : -(arity + 1)
|
|
@@ -902,1025 +913,724 @@ module EventMachine
|
|
|
902
913
|
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
|
903
914
|
end
|
|
904
915
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
916
|
+
s = open_udp_socket address, port.to_i
|
|
917
|
+
c = klass.new s, *args
|
|
918
|
+
@conns[s] = c
|
|
919
|
+
block_given? and yield c
|
|
920
|
+
c
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
# For advanced users. This function sets the default timer granularity, which by default is
|
|
925
|
+
# slightly smaller than 100 milliseconds. Call this function to set a higher or lower granularity.
|
|
926
|
+
# The function affects the behavior of #add_timer and #add_periodic_timer. Most applications
|
|
927
|
+
# will not need to call this function.
|
|
928
|
+
#
|
|
929
|
+
# The argument is a number of milliseconds. Avoid setting the quantum to very low values because
|
|
930
|
+
# that may reduce performance under some extreme conditions. We recommend that you not set a quantum
|
|
931
|
+
# lower than 10.
|
|
932
|
+
#
|
|
933
|
+
# You may only call this function while an EventMachine loop is running (that is, after a call to
|
|
934
|
+
# EventMachine#run and before a subsequent call to EventMachine#stop).
|
|
935
|
+
#
|
|
936
|
+
def self.set_quantum mills
|
|
937
|
+
set_timer_quantum mills.to_i
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
# Sets the maximum number of timers and periodic timers that may be outstanding at any
|
|
941
|
+
# given time. You only need to call #set_max_timers if you need more than the default
|
|
942
|
+
# number of timers, which on most platforms is 1000.
|
|
943
|
+
# Call this method before calling EventMachine#run.
|
|
944
|
+
#
|
|
945
|
+
def self.set_max_timers ct
|
|
946
|
+
set_max_timer_count ct
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
# Gets the current maximum number of allowed timers
|
|
950
|
+
#
|
|
951
|
+
def self.get_max_timers
|
|
952
|
+
get_max_timer_count
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
# Returns the total number of connections (file descriptors) currently held by the reactor.
|
|
956
|
+
# Note that a tick must pass after the 'initiation' of a connection for this number to increment.
|
|
957
|
+
# It's usually accurate, but don't rely on the exact precision of this number unless you really know EM internals.
|
|
958
|
+
#
|
|
959
|
+
# For example, $count will be 0 in this case:
|
|
960
|
+
#
|
|
961
|
+
# EM.run {
|
|
962
|
+
# EM.connect("rubyeventmachine.com", 80)
|
|
963
|
+
# $count = EM.connection_count
|
|
964
|
+
# }
|
|
965
|
+
#
|
|
966
|
+
# In this example, $count will be 1 since the connection has been established in the next loop of the reactor.
|
|
967
|
+
#
|
|
968
|
+
# EM.run {
|
|
969
|
+
# EM.connect("rubyeventmachine.com", 80)
|
|
970
|
+
# EM.next_tick {
|
|
971
|
+
# $count = EM.connection_count
|
|
972
|
+
# }
|
|
973
|
+
# }
|
|
974
|
+
#
|
|
975
|
+
def self.connection_count
|
|
976
|
+
self.get_connection_count
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
#--
|
|
980
|
+
# The is the responder for the loopback-signalled event.
|
|
981
|
+
# It can be fired either by code running on a separate thread (EM#defer) or on
|
|
982
|
+
# the main thread (EM#next_tick).
|
|
983
|
+
# It will often happen that a next_tick handler will reschedule itself. We
|
|
984
|
+
# consume a copy of the tick queue so that tick events scheduled by tick events
|
|
985
|
+
# have to wait for the next pass through the reactor core.
|
|
986
|
+
#
|
|
987
|
+
def self.run_deferred_callbacks # :nodoc:
|
|
988
|
+
until (@resultqueue ||= []).empty?
|
|
989
|
+
result,cback = @resultqueue.pop
|
|
990
|
+
cback.call result if cback
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
@next_tick_queue ||= []
|
|
994
|
+
if (l = @next_tick_queue.length) > 0
|
|
995
|
+
l.times {|i| @next_tick_queue[i].call}
|
|
996
|
+
@next_tick_queue.slice!( 0...l )
|
|
997
|
+
end
|
|
986
998
|
|
|
987
999
|
=begin
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
=end
|
|
992
|
-
=begin
|
|
993
|
-
if (@next_tick_queue ||= []) and @next_tick_queue.length > 0
|
|
994
|
-
ary = @next_tick_queue.dup
|
|
995
|
-
@next_tick_queue.clear
|
|
996
|
-
until ary.empty?
|
|
997
|
-
cback=ary.pop and cback.call
|
|
998
|
-
end
|
|
999
|
-
end
|
|
1000
|
+
(@next_tick_queue ||= []).length.times {
|
|
1001
|
+
cback=@next_tick_queue.pop and cback.call
|
|
1002
|
+
}
|
|
1000
1003
|
=end
|
|
1001
|
-
end
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
# #defer is for integrating blocking operations into EventMachine's control flow.
|
|
1005
|
-
# Call #defer with one or two blocks, as shown below (the second block is <i>optional</i>):
|
|
1006
|
-
#
|
|
1007
|
-
# operation = proc {
|
|
1008
|
-
# # perform a long-running operation here, such as a database query.
|
|
1009
|
-
# "result" # as usual, the last expression evaluated in the block will be the return value.
|
|
1010
|
-
# }
|
|
1011
|
-
# callback = proc {|result|
|
|
1012
|
-
# # do something with result here, such as send it back to a network client.
|
|
1013
|
-
# }
|
|
1014
|
-
#
|
|
1015
|
-
# EventMachine.defer( operation, callback )
|
|
1016
|
-
#
|
|
1017
|
-
# The action of #defer is to take the block specified in the first parameter (the "operation")
|
|
1018
|
-
# and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
|
|
1019
|
-
# When the operation completes, it will pass the result computed by the block (if any)
|
|
1020
|
-
# back to the EventMachine reactor. Then, EventMachine calls the block specified in the
|
|
1021
|
-
# second parameter to #defer (the "callback"), as part of its normal, synchronous
|
|
1022
|
-
# event handling loop. The result computed by the operation block is passed as a parameter
|
|
1023
|
-
# to the callback. You may omit the callback parameter if you don't need to execute any code
|
|
1024
|
-
# after the operation completes.
|
|
1025
|
-
#
|
|
1026
|
-
# <i>Caveats:</i>
|
|
1027
|
-
# Note carefully that the code in your deferred operation will be executed on a separate
|
|
1028
|
-
# thread from the main EventMachine processing and all other Ruby threads that may exist in
|
|
1029
|
-
# your program. Also, multiple deferred operations may be running at once! Therefore, you
|
|
1030
|
-
# are responsible for ensuring that your operation code is threadsafe. [Need more explanation
|
|
1031
|
-
# and examples.]
|
|
1032
|
-
# Don't write a deferred operation that will block forever. If so, the current implementation will
|
|
1033
|
-
# not detect the problem, and the thread will never be returned to the pool. EventMachine limits
|
|
1034
|
-
# the number of threads in its pool, so if you do this enough times, your subsequent deferred
|
|
1035
|
-
# operations won't get a chance to run. [We might put in a timer to detect this problem.]
|
|
1036
|
-
#
|
|
1037
|
-
#--
|
|
1038
|
-
# OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
|
|
1039
|
-
# without syncing there.
|
|
1040
|
-
#
|
|
1041
|
-
# Running with $VERBOSE set to true gives a warning unless all ivars are defined when
|
|
1042
|
-
# they appear in rvalues. But we DON'T ever want to initialize @threadqueue unless we
|
|
1043
|
-
# need it, because the Ruby threads are so heavyweight. We end up with this bizarre
|
|
1044
|
-
# way of initializing @threadqueue because EventMachine is a Module, not a Class, and
|
|
1045
|
-
# has no constructor.
|
|
1046
|
-
#
|
|
1047
|
-
def self::defer op = nil, callback = nil, &blk
|
|
1048
|
-
unless @threadpool
|
|
1049
|
-
require 'thread'
|
|
1050
|
-
@threadpool = []
|
|
1051
|
-
@threadqueue = Queue.new
|
|
1052
|
-
@resultqueue = Queue.new
|
|
1053
|
-
spawn_threadpool
|
|
1054
|
-
end
|
|
1055
|
-
|
|
1056
|
-
@threadqueue << [op||blk,callback]
|
|
1057
|
-
end
|
|
1058
|
-
|
|
1059
|
-
def self.spawn_threadpool
|
|
1060
|
-
until @threadpool.size == 20
|
|
1061
|
-
thread = Thread.new do
|
|
1062
|
-
while true
|
|
1063
|
-
op, cback = *@threadqueue.pop
|
|
1064
|
-
result = op.call
|
|
1065
|
-
@resultqueue << [result, cback]
|
|
1066
|
-
EventMachine.signal_loopbreak
|
|
1067
|
-
end
|
|
1068
|
-
end
|
|
1069
|
-
@threadpool << thread
|
|
1070
|
-
end
|
|
1071
|
-
end
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
# Schedules a proc for execution immediately after the next "turn" through the reactor
|
|
1075
|
-
# core. An advanced technique, this can be useful for improving memory management and/or
|
|
1076
|
-
# application responsiveness, especially when scheduling large amounts of data for
|
|
1077
|
-
# writing to a network connection. TODO, we need a FAQ entry on this subject.
|
|
1078
|
-
#
|
|
1079
|
-
# #next_tick takes either a single argument (which must be a Proc) or a block.
|
|
1080
|
-
# And I'm taking suggestions for a better name for this method.
|
|
1081
|
-
#--
|
|
1082
|
-
# This works by adding to the @resultqueue that's used for #defer.
|
|
1083
|
-
# The general idea is that next_tick is used when we want to give the reactor a chance
|
|
1084
|
-
# to let other operations run, either to balance the load out more evenly, or to let
|
|
1085
|
-
# outbound network buffers drain, or both. So we probably do NOT want to block, and
|
|
1086
|
-
# we probably do NOT want to be spinning any threads. A program that uses next_tick
|
|
1087
|
-
# but not #defer shouldn't suffer the penalty of having Ruby threads running. They're
|
|
1088
|
-
# extremely expensive even if they're just sleeping.
|
|
1089
|
-
#
|
|
1090
|
-
def self::next_tick pr=nil, &block
|
|
1091
|
-
raise "no argument or block given" unless ((pr && pr.respond_to?(:call)) or block)
|
|
1092
|
-
(@next_tick_queue ||= []) << ( pr || block )
|
|
1093
|
-
signal_loopbreak if reactor_running?
|
|
1094
1004
|
=begin
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1005
|
+
if (@next_tick_queue ||= []) and @next_tick_queue.length > 0
|
|
1006
|
+
ary = @next_tick_queue.dup
|
|
1007
|
+
@next_tick_queue.clear
|
|
1008
|
+
until ary.empty?
|
|
1009
|
+
cback=ary.pop and cback.call
|
|
1010
|
+
end
|
|
1011
|
+
end
|
|
1102
1012
|
=end
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
# Run an external process. This does not currently work on Windows.
|
|
1143
|
-
#
|
|
1144
|
-
# module RubyCounter
|
|
1145
|
-
# def post_init
|
|
1146
|
-
# # count up to 5
|
|
1147
|
-
# send_data "5\n"
|
|
1148
|
-
# end
|
|
1149
|
-
# def receive_data data
|
|
1150
|
-
# puts "ruby sent me: #{data}"
|
|
1151
|
-
# end
|
|
1152
|
-
# def unbind
|
|
1153
|
-
# puts "ruby died with exit status: #{get_status.exitstatus}"
|
|
1154
|
-
# end
|
|
1155
|
-
# end
|
|
1156
|
-
#
|
|
1157
|
-
# EM.run{
|
|
1158
|
-
# EM.popen("ruby -e' $stdout.sync = true; gets.to_i.times{ |i| puts i+1; sleep 1 } '", RubyCounter)
|
|
1159
|
-
# }
|
|
1160
|
-
#
|
|
1161
|
-
# Also see EM::DeferrableChildProcess and EM::system
|
|
1162
|
-
#--
|
|
1163
|
-
# At this moment, it's only available on Unix.
|
|
1164
|
-
# Perhaps misnamed since the underlying function uses socketpair and is full-duplex.
|
|
1165
|
-
#
|
|
1166
|
-
def self::popen cmd, handler=nil, *args
|
|
1167
|
-
klass = if (handler and handler.is_a?(Class))
|
|
1168
|
-
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
1169
|
-
handler
|
|
1170
|
-
else
|
|
1171
|
-
Class.new( Connection ) {handler and include handler}
|
|
1172
|
-
end
|
|
1173
|
-
|
|
1174
|
-
w = Shellwords::shellwords( cmd )
|
|
1175
|
-
w.unshift( w.first ) if w.first
|
|
1176
|
-
s = invoke_popen( w )
|
|
1177
|
-
c = klass.new s, *args
|
|
1178
|
-
@conns[s] = c
|
|
1179
|
-
yield(c) if block_given?
|
|
1180
|
-
c
|
|
1181
|
-
end
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
# Tells you whether the EventMachine reactor loop is currently running. Returns true or
|
|
1185
|
-
# false. Useful when writing libraries that want to run event-driven code, but may
|
|
1186
|
-
# be running in programs that are already event-driven. In such cases, if EventMachine#reactor_running?
|
|
1187
|
-
# returns false, your code can invoke EventMachine#run and run your application code inside
|
|
1188
|
-
# the block passed to that method. If EventMachine#reactor_running? returns true, just
|
|
1189
|
-
# execute your event-aware code.
|
|
1190
|
-
#
|
|
1191
|
-
# This method is necessary because calling EventMachine#run inside of another call to
|
|
1192
|
-
# EventMachine#run generates a fatal error.
|
|
1193
|
-
#
|
|
1194
|
-
def self::reactor_running?
|
|
1195
|
-
(@reactor_running || false)
|
|
1196
|
-
end
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
# (Experimental)
|
|
1200
|
-
#
|
|
1201
|
-
#
|
|
1202
|
-
def EventMachine::open_keyboard handler=nil, *args
|
|
1203
|
-
klass = if (handler and handler.is_a?(Class))
|
|
1204
|
-
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
1205
|
-
handler
|
|
1206
|
-
else
|
|
1207
|
-
Class.new( Connection ) {handler and include handler}
|
|
1208
|
-
end
|
|
1209
|
-
|
|
1210
|
-
arity = klass.instance_method(:initialize).arity
|
|
1211
|
-
expected = arity >= 0 ? arity : -(arity + 1)
|
|
1212
|
-
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
|
1213
|
-
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
|
1214
|
-
end
|
|
1215
|
-
|
|
1216
|
-
s = read_keyboard
|
|
1217
|
-
c = klass.new s, *args
|
|
1218
|
-
@conns[s] = c
|
|
1219
|
-
block_given? and yield c
|
|
1220
|
-
c
|
|
1221
|
-
end
|
|
1222
|
-
|
|
1223
|
-
# Catch-all for errors raised during event loop callbacks.
|
|
1224
|
-
#
|
|
1225
|
-
# EM.error_handler{ |e|
|
|
1226
|
-
# puts "Error raised during event loop: #{e.message}"
|
|
1227
|
-
# }
|
|
1228
|
-
#
|
|
1229
|
-
def EventMachine::error_handler cb = nil, &blk
|
|
1230
|
-
if cb or blk
|
|
1231
|
-
@error_handler = cb || blk
|
|
1232
|
-
elsif instance_variable_defined? :@error_handler
|
|
1233
|
-
remove_instance_variable :@error_handler
|
|
1234
|
-
end
|
|
1235
|
-
end
|
|
1236
|
-
|
|
1237
|
-
private
|
|
1238
|
-
def EventMachine::event_callback conn_binding, opcode, data
|
|
1239
|
-
#
|
|
1240
|
-
# Changed 27Dec07: Eliminated the hookable error handling.
|
|
1241
|
-
# No one was using it, and it degraded performance significantly.
|
|
1242
|
-
# It's in original_event_callback, which is dead code.
|
|
1243
|
-
#
|
|
1244
|
-
# Changed 25Jul08: Added a partial solution to the problem of exceptions
|
|
1245
|
-
# raised in user-written event-handlers. If such exceptions are not caught,
|
|
1246
|
-
# we must cause the reactor to stop, and then re-raise the exception.
|
|
1247
|
-
# Otherwise, the reactor doesn't stop and it's left on the call stack.
|
|
1248
|
-
# This is partial because we only added it to #unbind, where it's critical
|
|
1249
|
-
# (to keep unbind handlers from being re-entered when a stopping reactor
|
|
1250
|
-
# runs down open connections). It should go on the other calls to user
|
|
1251
|
-
# code, but the performance impact may be too large.
|
|
1252
|
-
#
|
|
1253
|
-
if opcode == ConnectionUnbound
|
|
1254
|
-
if c = @conns.delete( conn_binding )
|
|
1255
|
-
begin
|
|
1256
|
-
c.unbind
|
|
1257
|
-
rescue
|
|
1258
|
-
@wrapped_exception = $!
|
|
1259
|
-
stop
|
|
1260
|
-
end
|
|
1261
|
-
elsif c = @acceptors.delete( conn_binding )
|
|
1262
|
-
# no-op
|
|
1263
|
-
else
|
|
1264
|
-
raise ConnectionNotBound, "recieved ConnectionUnbound for an unknown signature: #{conn_binding}"
|
|
1265
|
-
end
|
|
1266
|
-
elsif opcode == ConnectionAccepted
|
|
1267
|
-
accep,args,blk = @acceptors[conn_binding]
|
|
1268
|
-
raise NoHandlerForAcceptedConnection unless accep
|
|
1269
|
-
c = accep.new data, *args
|
|
1270
|
-
@conns[data] = c
|
|
1271
|
-
blk and blk.call(c)
|
|
1272
|
-
c # (needed?)
|
|
1273
|
-
elsif opcode == ConnectionCompleted
|
|
1274
|
-
c = @conns[conn_binding] or raise ConnectionNotBound, "received ConnectionCompleted for unknown signature: #{conn_binding}"
|
|
1275
|
-
c.connection_completed
|
|
1276
|
-
##
|
|
1277
|
-
# The remaining code is a fallback for the pure ruby reactor. Usually these events are handled in the C event_callback() in rubymain.cpp
|
|
1278
|
-
elsif opcode == TimerFired
|
|
1279
|
-
t = @timers.delete( data ) or raise UnknownTimerFired, "timer data: #{data}"
|
|
1280
|
-
t.call
|
|
1281
|
-
elsif opcode == ConnectionData
|
|
1282
|
-
c = @conns[conn_binding] or raise ConnectionNotBound, "received data #{data} for unknown signature: #{conn_binding}"
|
|
1283
|
-
c.receive_data data
|
|
1284
|
-
elsif opcode == LoopbreakSignalled
|
|
1285
|
-
run_deferred_callbacks
|
|
1286
|
-
elsif opcode == ConnectionNotifyReadable
|
|
1287
|
-
c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1288
|
-
c.notify_readable
|
|
1289
|
-
elsif opcode == ConnectionNotifyWritable
|
|
1290
|
-
c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1291
|
-
c.notify_writable
|
|
1292
|
-
end
|
|
1293
|
-
end
|
|
1294
|
-
|
|
1295
|
-
#--
|
|
1296
|
-
# The original event_callback below handled runtime errors in ruby and degraded performance significantly.
|
|
1297
|
-
# An optional C-based error handler is now available via EM::error_handler
|
|
1298
|
-
#
|
|
1299
|
-
# private
|
|
1300
|
-
# def EventMachine::original_event_callback conn_binding, opcode, data
|
|
1301
|
-
# #
|
|
1302
|
-
# # Added 03Oct07: Any code path that invokes user-written code must
|
|
1303
|
-
# # wrap itself in a begin/rescue for RuntimeErrors, that calls the
|
|
1304
|
-
# # user-overridable class method #handle_runtime_error.
|
|
1305
|
-
# #
|
|
1306
|
-
# if opcode == ConnectionData
|
|
1307
|
-
# c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1308
|
-
# begin
|
|
1309
|
-
# c.receive_data data
|
|
1310
|
-
# rescue
|
|
1311
|
-
# EventMachine.handle_runtime_error
|
|
1312
|
-
# end
|
|
1313
|
-
# elsif opcode == ConnectionUnbound
|
|
1314
|
-
# if c = @conns.delete( conn_binding )
|
|
1315
|
-
# begin
|
|
1316
|
-
# c.unbind
|
|
1317
|
-
# rescue
|
|
1318
|
-
# EventMachine.handle_runtime_error
|
|
1319
|
-
# end
|
|
1320
|
-
# elsif c = @acceptors.delete( conn_binding )
|
|
1321
|
-
# # no-op
|
|
1322
|
-
# else
|
|
1323
|
-
# raise ConnectionNotBound
|
|
1324
|
-
# end
|
|
1325
|
-
# elsif opcode == ConnectionAccepted
|
|
1326
|
-
# accep,args,blk = @acceptors[conn_binding]
|
|
1327
|
-
# raise NoHandlerForAcceptedConnection unless accep
|
|
1328
|
-
# c = accep.new data, *args
|
|
1329
|
-
# @conns[data] = c
|
|
1330
|
-
# begin
|
|
1331
|
-
# blk and blk.call(c)
|
|
1332
|
-
# rescue
|
|
1333
|
-
# EventMachine.handle_runtime_error
|
|
1334
|
-
# end
|
|
1335
|
-
# c # (needed?)
|
|
1336
|
-
# elsif opcode == TimerFired
|
|
1337
|
-
# t = @timers.delete( data ) or raise UnknownTimerFired
|
|
1338
|
-
# begin
|
|
1339
|
-
# t.call
|
|
1340
|
-
# rescue
|
|
1341
|
-
# EventMachine.handle_runtime_error
|
|
1342
|
-
# end
|
|
1343
|
-
# elsif opcode == ConnectionCompleted
|
|
1344
|
-
# c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1345
|
-
# begin
|
|
1346
|
-
# c.connection_completed
|
|
1347
|
-
# rescue
|
|
1348
|
-
# EventMachine.handle_runtime_error
|
|
1349
|
-
# end
|
|
1350
|
-
# elsif opcode == LoopbreakSignalled
|
|
1351
|
-
# begin
|
|
1352
|
-
# run_deferred_callbacks
|
|
1353
|
-
# rescue
|
|
1354
|
-
# EventMachine.handle_runtime_error
|
|
1355
|
-
# end
|
|
1356
|
-
# end
|
|
1357
|
-
# end
|
|
1358
|
-
#
|
|
1359
|
-
#
|
|
1360
|
-
# # Default handler for RuntimeErrors that are raised in user code.
|
|
1361
|
-
# # The default behavior is to re-raise the error, which ends your program.
|
|
1362
|
-
# # To override the default behavior, re-implement this method in your code.
|
|
1363
|
-
# # For example:
|
|
1364
|
-
# #
|
|
1365
|
-
# # module EventMachine
|
|
1366
|
-
# # def self.handle_runtime_error
|
|
1367
|
-
# # $>.puts $!
|
|
1368
|
-
# # end
|
|
1369
|
-
# # end
|
|
1370
|
-
# #
|
|
1371
|
-
# #--
|
|
1372
|
-
# # We need to ensure that any code path which invokes user code rescues RuntimeError
|
|
1373
|
-
# # and calls this method. The obvious place to do that is in #event_callback,
|
|
1374
|
-
# # but, scurrilously, it turns out that we need to be finer grained that that.
|
|
1375
|
-
# # Periodic timers, in particular, wrap their invocations of user code inside
|
|
1376
|
-
# # procs that do other stuff we can't not do, like schedule the next invocation.
|
|
1377
|
-
# # This is a potential non-robustness, since we need to remember to hook in the
|
|
1378
|
-
# # error handler whenever and wherever we change how user code is invoked.
|
|
1379
|
-
# #
|
|
1380
|
-
# def EventMachine::handle_runtime_error
|
|
1381
|
-
# @runtime_error_hook ? @runtime_error_hook.call : raise
|
|
1382
|
-
# end
|
|
1383
|
-
#
|
|
1384
|
-
# # Sets a handler for RuntimeErrors that are raised in user code.
|
|
1385
|
-
# # Pass a block with no parameters. You can also call this method without a block,
|
|
1386
|
-
# # which restores the default behavior (see #handle_runtime_error).
|
|
1387
|
-
# #
|
|
1388
|
-
# def EventMachine::set_runtime_error_hook &blk
|
|
1389
|
-
# @runtime_error_hook = blk
|
|
1390
|
-
# end
|
|
1391
|
-
|
|
1392
|
-
# Documentation stub
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
# #defer is for integrating blocking operations into EventMachine's control flow.
|
|
1017
|
+
# Call #defer with one or two blocks, as shown below (the second block is <i>optional</i>):
|
|
1018
|
+
#
|
|
1019
|
+
# operation = proc {
|
|
1020
|
+
# # perform a long-running operation here, such as a database query.
|
|
1021
|
+
# "result" # as usual, the last expression evaluated in the block will be the return value.
|
|
1022
|
+
# }
|
|
1023
|
+
# callback = proc {|result|
|
|
1024
|
+
# # do something with result here, such as send it back to a network client.
|
|
1025
|
+
# }
|
|
1026
|
+
#
|
|
1027
|
+
# EventMachine.defer( operation, callback )
|
|
1028
|
+
#
|
|
1029
|
+
# The action of #defer is to take the block specified in the first parameter (the "operation")
|
|
1030
|
+
# and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
|
|
1031
|
+
# When the operation completes, it will pass the result computed by the block (if any)
|
|
1032
|
+
# back to the EventMachine reactor. Then, EventMachine calls the block specified in the
|
|
1033
|
+
# second parameter to #defer (the "callback"), as part of its normal, synchronous
|
|
1034
|
+
# event handling loop. The result computed by the operation block is passed as a parameter
|
|
1035
|
+
# to the callback. You may omit the callback parameter if you don't need to execute any code
|
|
1036
|
+
# after the operation completes.
|
|
1037
|
+
#
|
|
1038
|
+
# == Caveats
|
|
1039
|
+
# Note carefully that the code in your deferred operation will be executed on a separate
|
|
1040
|
+
# thread from the main EventMachine processing and all other Ruby threads that may exist in
|
|
1041
|
+
# your program. Also, multiple deferred operations may be running at once! Therefore, you
|
|
1042
|
+
# are responsible for ensuring that your operation code is threadsafe. [Need more explanation
|
|
1043
|
+
# and examples.]
|
|
1044
|
+
# Don't write a deferred operation that will block forever. If so, the current implementation will
|
|
1045
|
+
# not detect the problem, and the thread will never be returned to the pool. EventMachine limits
|
|
1046
|
+
# the number of threads in its pool, so if you do this enough times, your subsequent deferred
|
|
1047
|
+
# operations won't get a chance to run. [We might put in a timer to detect this problem.]
|
|
1048
|
+
#
|
|
1393
1049
|
#--
|
|
1394
|
-
#
|
|
1395
|
-
#
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1050
|
+
# OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
|
|
1051
|
+
# without syncing there.
|
|
1052
|
+
#
|
|
1053
|
+
# Running with $VERBOSE set to true gives a warning unless all ivars are defined when
|
|
1054
|
+
# they appear in rvalues. But we DON'T ever want to initialize @threadqueue unless we
|
|
1055
|
+
# need it, because the Ruby threads are so heavyweight. We end up with this bizarre
|
|
1056
|
+
# way of initializing @threadqueue because EventMachine is a Module, not a Class, and
|
|
1057
|
+
# has no constructor.
|
|
1058
|
+
#
|
|
1059
|
+
def self.defer op = nil, callback = nil, &blk
|
|
1060
|
+
unless @threadpool
|
|
1061
|
+
require 'thread'
|
|
1062
|
+
@threadpool = []
|
|
1063
|
+
@threadqueue = ::Queue.new
|
|
1064
|
+
@resultqueue = ::Queue.new
|
|
1065
|
+
spawn_threadpool
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
@threadqueue << [op||blk,callback]
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
def self.spawn_threadpool # :nodoc:
|
|
1072
|
+
until @threadpool.size == @threadpool_size
|
|
1073
|
+
thread = Thread.new do
|
|
1074
|
+
while true
|
|
1075
|
+
op, cback = *@threadqueue.pop
|
|
1076
|
+
result = op.call
|
|
1077
|
+
@resultqueue << [result, cback]
|
|
1078
|
+
EventMachine.signal_loopbreak
|
|
1079
|
+
end
|
|
1403
1080
|
end
|
|
1081
|
+
@threadpool << thread
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
class << self
|
|
1086
|
+
attr_reader :threadpool # :nodoc:
|
|
1404
1087
|
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1088
|
+
# Size of the EventMachine.defer threadpool (defaults to 20)
|
|
1089
|
+
attr_accessor :threadpool_size
|
|
1090
|
+
EventMachine.threadpool_size = 20
|
|
1091
|
+
end
|
|
1092
|
+
|
|
1093
|
+
# Schedules a proc for execution immediately after the next "turn" through the reactor
|
|
1094
|
+
# core. An advanced technique, this can be useful for improving memory management and/or
|
|
1095
|
+
# application responsiveness, especially when scheduling large amounts of data for
|
|
1096
|
+
# writing to a network connection. TODO, we need a FAQ entry on this subject.
|
|
1097
|
+
#
|
|
1098
|
+
# #next_tick takes either a single argument (which must be a Proc) or a block.
|
|
1099
|
+
#--
|
|
1100
|
+
# This works by adding to the @resultqueue that's used for #defer.
|
|
1101
|
+
# The general idea is that next_tick is used when we want to give the reactor a chance
|
|
1102
|
+
# to let other operations run, either to balance the load out more evenly, or to let
|
|
1103
|
+
# outbound network buffers drain, or both. So we probably do NOT want to block, and
|
|
1104
|
+
# we probably do NOT want to be spinning any threads. A program that uses next_tick
|
|
1105
|
+
# but not #defer shouldn't suffer the penalty of having Ruby threads running. They're
|
|
1106
|
+
# extremely expensive even if they're just sleeping.
|
|
1107
|
+
#
|
|
1108
|
+
def self.next_tick pr=nil, &block
|
|
1109
|
+
raise "no argument or block given" unless ((pr && pr.respond_to?(:call)) or block)
|
|
1110
|
+
(@next_tick_queue ||= []) << ( pr || block )
|
|
1111
|
+
signal_loopbreak if reactor_running?
|
|
1112
|
+
=begin
|
|
1113
|
+
(@next_tick_procs ||= []) << (pr || block)
|
|
1114
|
+
if @next_tick_procs.length == 1
|
|
1115
|
+
add_timer(0) {
|
|
1116
|
+
@next_tick_procs.each {|t| t.call}
|
|
1117
|
+
@next_tick_procs.clear
|
|
1118
|
+
}
|
|
1410
1119
|
end
|
|
1120
|
+
=end
|
|
1411
1121
|
end
|
|
1412
1122
|
|
|
1123
|
+
# A wrapper over the setuid system call. Particularly useful when opening a network
|
|
1124
|
+
# server on a privileged port because you can use this call to drop privileges
|
|
1125
|
+
# after opening the port. Also very useful after a call to #set_descriptor_table_size,
|
|
1126
|
+
# which generally requires that you start your process with root privileges.
|
|
1127
|
+
#
|
|
1128
|
+
# This method has no effective implementation on Windows or in the pure-Ruby
|
|
1129
|
+
# implementation of EventMachine.
|
|
1130
|
+
# Call #set_effective_user by passing it a string containing the effective name
|
|
1131
|
+
# of the user whose privilege-level your process should attain.
|
|
1132
|
+
# This method is intended for use in enforcing security requirements, consequently
|
|
1133
|
+
# it will throw a fatal error and end your program if it fails.
|
|
1134
|
+
#
|
|
1135
|
+
def self.set_effective_user username
|
|
1136
|
+
EventMachine::setuid_string username
|
|
1137
|
+
end
|
|
1413
1138
|
|
|
1414
|
-
|
|
1415
|
-
#
|
|
1416
|
-
#
|
|
1417
|
-
#
|
|
1418
|
-
#
|
|
1419
|
-
# the
|
|
1420
|
-
#
|
|
1421
|
-
#
|
|
1422
|
-
#
|
|
1423
|
-
#
|
|
1424
|
-
#
|
|
1425
|
-
#
|
|
1426
|
-
#
|
|
1427
|
-
#
|
|
1428
|
-
#
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
#
|
|
1436
|
-
#
|
|
1437
|
-
#
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
#
|
|
1443
|
-
#
|
|
1444
|
-
#
|
|
1445
|
-
def
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1139
|
+
|
|
1140
|
+
# Sets the maximum number of file or socket descriptors that your process may open.
|
|
1141
|
+
# You can pass this method an integer specifying the new size of the descriptor table.
|
|
1142
|
+
# Returns the new descriptor-table size, which may be less than the number you
|
|
1143
|
+
# requested. If you call this method with no arguments, it will simply return
|
|
1144
|
+
# the current size of the descriptor table without attempting to change it.
|
|
1145
|
+
#
|
|
1146
|
+
# The new limit on open descriptors ONLY applies to sockets and other descriptors
|
|
1147
|
+
# that belong to EventMachine. It has NO EFFECT on the number of descriptors
|
|
1148
|
+
# you can create in ordinary Ruby code.
|
|
1149
|
+
#
|
|
1150
|
+
# Not available on all platforms. Increasing the number of descriptors beyond its
|
|
1151
|
+
# default limit usually requires superuser privileges. (See #set_effective_user
|
|
1152
|
+
# for a way to drop superuser privileges while your program is running.)
|
|
1153
|
+
#
|
|
1154
|
+
def self.set_descriptor_table_size n_descriptors=nil
|
|
1155
|
+
EventMachine::set_rlimit_nofile n_descriptors
|
|
1156
|
+
end
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
# Run an external process. This does not currently work on Windows.
|
|
1161
|
+
#
|
|
1162
|
+
# module RubyCounter
|
|
1163
|
+
# def post_init
|
|
1164
|
+
# # count up to 5
|
|
1165
|
+
# send_data "5\n"
|
|
1166
|
+
# end
|
|
1167
|
+
# def receive_data data
|
|
1168
|
+
# puts "ruby sent me: #{data}"
|
|
1169
|
+
# end
|
|
1170
|
+
# def unbind
|
|
1171
|
+
# puts "ruby died with exit status: #{get_status.exitstatus}"
|
|
1172
|
+
# end
|
|
1173
|
+
# end
|
|
1174
|
+
#
|
|
1175
|
+
# EM.run{
|
|
1176
|
+
# EM.popen("ruby -e' $stdout.sync = true; gets.to_i.times{ |i| puts i+1; sleep 1 } '", RubyCounter)
|
|
1177
|
+
# }
|
|
1178
|
+
#
|
|
1179
|
+
# Also see EventMachine::DeferrableChildProcess and EventMachine.system
|
|
1180
|
+
#--
|
|
1181
|
+
# At this moment, it's only available on Unix.
|
|
1182
|
+
# Perhaps misnamed since the underlying function uses socketpair and is full-duplex.
|
|
1183
|
+
#
|
|
1184
|
+
def self.popen cmd, handler=nil, *args
|
|
1185
|
+
klass = if (handler and handler.is_a?(Class))
|
|
1186
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
1187
|
+
handler
|
|
1188
|
+
else
|
|
1189
|
+
Class.new( Connection ) {handler and include handler}
|
|
1456
1190
|
end
|
|
1191
|
+
|
|
1192
|
+
w = Shellwords::shellwords( cmd )
|
|
1193
|
+
w.unshift( w.first ) if w.first
|
|
1194
|
+
s = invoke_popen( w )
|
|
1195
|
+
c = klass.new s, *args
|
|
1196
|
+
@conns[s] = c
|
|
1197
|
+
yield(c) if block_given?
|
|
1198
|
+
c
|
|
1457
1199
|
end
|
|
1458
1200
|
|
|
1459
|
-
|
|
1201
|
+
|
|
1202
|
+
# Tells you whether the EventMachine reactor loop is currently running. Returns true or
|
|
1203
|
+
# false. Useful when writing libraries that want to run event-driven code, but may
|
|
1204
|
+
# be running in programs that are already event-driven. In such cases, if EventMachine#reactor_running?
|
|
1205
|
+
# returns false, your code can invoke EventMachine#run and run your application code inside
|
|
1206
|
+
# the block passed to that method. If EventMachine#reactor_running? returns true, just
|
|
1207
|
+
# execute your event-aware code.
|
|
1208
|
+
#
|
|
1209
|
+
# This method is necessary because calling EventMachine#run inside of another call to
|
|
1210
|
+
# EventMachine#run generates a fatal error.
|
|
1460
1211
|
#
|
|
1461
|
-
|
|
1212
|
+
def self.reactor_running?
|
|
1213
|
+
(@reactor_running || false)
|
|
1462
1214
|
end
|
|
1463
1215
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
# be used throughout the lifetime of the network connection.
|
|
1475
|
-
#
|
|
1476
|
-
def post_init
|
|
1477
|
-
end
|
|
1478
|
-
|
|
1479
|
-
# EventMachine::Connection#receive_data is called by the event loop
|
|
1480
|
-
# whenever data has been received by the network connection.
|
|
1481
|
-
# It is never called by user code.
|
|
1482
|
-
# receive_data is called with a single parameter, a String containing
|
|
1483
|
-
# the network protocol data, which may of course be binary. You will
|
|
1484
|
-
# generally redefine this method to perform your own processing of the incoming data.
|
|
1485
|
-
#
|
|
1486
|
-
# Here's a key point which is essential to understanding the event-driven
|
|
1487
|
-
# programming model: <i>EventMachine knows absolutely nothing about the protocol
|
|
1488
|
-
# which your code implements.</i> You must not make any assumptions about
|
|
1489
|
-
# the size of the incoming data packets, or about their alignment on any
|
|
1490
|
-
# particular intra-message or PDU boundaries (such as line breaks).
|
|
1491
|
-
# receive_data can and will send you arbitrary chunks of data, with the
|
|
1492
|
-
# only guarantee being that the data is presented to your code in the order
|
|
1493
|
-
# it was collected from the network. Don't even assume that the chunks of
|
|
1494
|
-
# data will correspond to network packets, as EventMachine can and will coalesce
|
|
1495
|
-
# several incoming packets into one, to improve performance. The implication for your
|
|
1496
|
-
# code is that you generally will need to implement some kind of a state machine
|
|
1497
|
-
# in your redefined implementation of receive_data. For a better understanding
|
|
1498
|
-
# of this, read through the examples of specific protocol handlers given
|
|
1499
|
-
# elsewhere in this package. (STUB, WE MUST ADD THESE!)
|
|
1500
|
-
#
|
|
1501
|
-
# The base-class implementation of receive_data (which will be invoked if
|
|
1502
|
-
# you don't redefine it) simply prints the size of each incoming data packet
|
|
1503
|
-
# to stdout.
|
|
1504
|
-
#
|
|
1505
|
-
def receive_data data
|
|
1506
|
-
puts "............>>>#{data.length}"
|
|
1507
|
-
end
|
|
1508
|
-
|
|
1509
|
-
# #ssl_handshake_completed is called by EventMachine when the SSL/TLS handshake has
|
|
1510
|
-
# been completed, as a result of calling #start_tls to initiate SSL/TLS on the connection.
|
|
1511
|
-
#
|
|
1512
|
-
# This callback exists because #post_init and #connection_completed are <b>not</b> reliable
|
|
1513
|
-
# for indicating when an SSL/TLS connection is ready to have it's certificate queried for.
|
|
1514
|
-
#
|
|
1515
|
-
# See #get_peer_cert for application and example.
|
|
1516
|
-
def ssl_handshake_completed
|
|
1517
|
-
end
|
|
1518
|
-
|
|
1519
|
-
# EventMachine::Connection#unbind is called by the framework whenever a connection
|
|
1520
|
-
# (either a server or client connection) is closed. The close can occur because
|
|
1521
|
-
# your code intentionally closes it (see close_connection and close_connection_after_writing),
|
|
1522
|
-
# because the remote peer closed the connection, or because of a network error.
|
|
1523
|
-
# You may not assume that the network connection is still open and able to send or
|
|
1524
|
-
# receive data when the callback to unbind is made. This is intended only to give
|
|
1525
|
-
# you a chance to clean up associations your code may have made to the connection
|
|
1526
|
-
# object while it was open.
|
|
1527
|
-
#
|
|
1528
|
-
def unbind
|
|
1529
|
-
end
|
|
1530
|
-
|
|
1531
|
-
# EventMachine::Connection#close_connection is called only by user code, and never
|
|
1532
|
-
# by the event loop. You may call this method against a connection object in any
|
|
1533
|
-
# callback handler, whether or not the callback was made against the connection
|
|
1534
|
-
# you want to close. close_connection <i>schedules</i> the connection to be closed
|
|
1535
|
-
# at the next available opportunity within the event loop. You may not assume that
|
|
1536
|
-
# the connection is closed when close_connection returns. In particular, the framework
|
|
1537
|
-
# will callback the unbind method for the particular connection at a point shortly
|
|
1538
|
-
# after you call close_connection. You may assume that the unbind callback will
|
|
1539
|
-
# take place sometime after your call to close_connection completes. In other words,
|
|
1540
|
-
# the unbind callback will not re-enter your code "inside" of your call to close_connection.
|
|
1541
|
-
# However, it's not guaranteed that a future version of EventMachine will not change
|
|
1542
|
-
# this behavior.
|
|
1543
|
-
#
|
|
1544
|
-
# close_connection will <i>silently discard</i> any outbound data which you have
|
|
1545
|
-
# sent to the connection using EventMachine::Connection#send_data but which has not
|
|
1546
|
-
# yet been sent across the network. If you want to avoid this behavior, use
|
|
1547
|
-
# EventMachine::Connection#close_connection_after_writing.
|
|
1548
|
-
#
|
|
1549
|
-
def close_connection after_writing = false
|
|
1550
|
-
EventMachine::close_connection @signature, after_writing
|
|
1551
|
-
end
|
|
1552
|
-
|
|
1553
|
-
# EventMachine::Connection#detach will remove the given connection from the event loop.
|
|
1554
|
-
# The connection's socket remains open and its file descriptor number is returned
|
|
1555
|
-
def detach
|
|
1556
|
-
EventMachine::detach_fd @signature
|
|
1557
|
-
end
|
|
1558
|
-
|
|
1559
|
-
# EventMachine::Connection#close_connection_after_writing is a variant of close_connection.
|
|
1560
|
-
# All of the descriptive comments given for close_connection also apply to
|
|
1561
|
-
# close_connection_after_writing, <i>with one exception:</i> If the connection has
|
|
1562
|
-
# outbound data sent using send_dat but which has not yet been sent across the network,
|
|
1563
|
-
# close_connection_after_writing will schedule the connection to be closed <i>after</i>
|
|
1564
|
-
# all of the outbound data has been safely written to the remote peer.
|
|
1565
|
-
#
|
|
1566
|
-
# Depending on the amount of outgoing data and the speed of the network,
|
|
1567
|
-
# considerable time may elapse between your call to close_connection_after_writing
|
|
1568
|
-
# and the actual closing of the socket (at which time the unbind callback will be called
|
|
1569
|
-
# by the event loop). During this time, you <i>may not</i> call send_data to transmit
|
|
1570
|
-
# additional data (that is, the connection is closed for further writes). In very
|
|
1571
|
-
# rare cases, you may experience a receive_data callback after your call to close_connection_after_writing,
|
|
1572
|
-
# depending on whether incoming data was in the process of being received on the connection
|
|
1573
|
-
# at the moment when you called close_connection_after_writing. Your protocol handler must
|
|
1574
|
-
# be prepared to properly deal with such data (probably by ignoring it).
|
|
1575
|
-
#
|
|
1576
|
-
def close_connection_after_writing
|
|
1577
|
-
close_connection true
|
|
1578
|
-
end
|
|
1579
|
-
|
|
1580
|
-
# EventMachine::Connection#send_data is only called by user code, never by
|
|
1581
|
-
# the event loop. You call this method to send data to the remote end of the
|
|
1582
|
-
# network connection. send_data is called with a single String argument, which
|
|
1583
|
-
# may of course contain binary data. You can call send_data any number of times.
|
|
1584
|
-
# send_data is an instance method of an object derived from EventMachine::Connection
|
|
1585
|
-
# and containing your mixed-in handler code), so if you call it without qualification
|
|
1586
|
-
# within a callback function, the data will be sent to the same network connection
|
|
1587
|
-
# that generated the callback. Calling self.send_data is exactly equivalent.
|
|
1588
|
-
#
|
|
1589
|
-
# You can also call send_data to write to a connection <i>other than the one
|
|
1590
|
-
# whose callback you are calling send_data from.</i> This is done by recording
|
|
1591
|
-
# the value of the connection in any callback function (the value self), in any
|
|
1592
|
-
# variable visible to other callback invocations on the same or different
|
|
1593
|
-
# connection objects. (Need an example to make that clear.)
|
|
1594
|
-
#
|
|
1595
|
-
def send_data data
|
|
1596
|
-
size = data.bytesize if data.respond_to?(:bytesize)
|
|
1597
|
-
size ||= data.size
|
|
1598
|
-
EventMachine::send_data @signature, data, size
|
|
1599
|
-
end
|
|
1600
|
-
|
|
1601
|
-
# Returns true if the connection is in an error state, false otherwise.
|
|
1602
|
-
# In general, you can detect the occurrence of communication errors or unexpected
|
|
1603
|
-
# disconnection by the remote peer by handing the #unbind method. In some cases, however,
|
|
1604
|
-
# it's useful to check the status of the connection using #error? before attempting to send data.
|
|
1605
|
-
# This function is synchronous: it will return immediately without blocking.
|
|
1606
|
-
#
|
|
1607
|
-
#
|
|
1608
|
-
def error?
|
|
1609
|
-
EventMachine::report_connection_error_status(@signature) != 0
|
|
1610
|
-
end
|
|
1611
|
-
|
|
1612
|
-
# #connection_completed is called by the event loop when a remote TCP connection
|
|
1613
|
-
# attempt completes successfully. You can expect to get this notification after calls
|
|
1614
|
-
# to EventMachine#connect. Remember that EventMachine makes remote connections
|
|
1615
|
-
# asynchronously, just as with any other kind of network event. #connection_completed
|
|
1616
|
-
# is intended primarily to assist with network diagnostics. For normal protocol
|
|
1617
|
-
# handling, use #post_init to perform initial work on a new connection (such as
|
|
1618
|
-
# send an initial set of data).
|
|
1619
|
-
# #post_init will always be called. #connection_completed will only be called in case
|
|
1620
|
-
# of a successful completion. A connection-attempt which fails will receive a call
|
|
1621
|
-
# to #unbind after the failure.
|
|
1622
|
-
def connection_completed
|
|
1623
|
-
end
|
|
1624
|
-
|
|
1625
|
-
# Call #start_tls at any point to initiate TLS encryption on connected streams.
|
|
1626
|
-
# The method is smart enough to know whether it should perform a server-side
|
|
1627
|
-
# or a client-side handshake. An appropriate place to call #start_tls is in
|
|
1628
|
-
# your redefined #post_init method, or in the #connection_completed handler for
|
|
1629
|
-
# an outbound connection.
|
|
1630
|
-
#
|
|
1631
|
-
# #start_tls takes an optional parameter hash that allows you to specify certificate
|
|
1632
|
-
# and other options to be used with this Connection object. Here are the currently-supported
|
|
1633
|
-
# options:
|
|
1634
|
-
# :cert_chain_file : takes a String, which is interpreted as the name of a readable file in the
|
|
1635
|
-
# local filesystem. The file is expected to contain a chain of X509 certificates in
|
|
1636
|
-
# PEM format, with the most-resolved certificate at the top of the file, successive
|
|
1637
|
-
# intermediate certs in the middle, and the root (or CA) cert at the bottom.
|
|
1638
|
-
#
|
|
1639
|
-
# :private_key_file : tales a String, which is interpreted as the name of a readable file in the
|
|
1640
|
-
# local filesystem. The file must contain a private key in PEM format.
|
|
1641
|
-
#
|
|
1642
|
-
#--
|
|
1643
|
-
# TODO: support passing an encryption parameter, which can be string or Proc, to get a passphrase
|
|
1644
|
-
# for encrypted private keys.
|
|
1645
|
-
# TODO: support passing key material via raw strings or Procs that return strings instead of
|
|
1646
|
-
# just filenames.
|
|
1647
|
-
# What will get nasty is whether we have to define a location for storing this stuff as files.
|
|
1648
|
-
# In general, the OpenSSL interfaces for dealing with certs and keys in files are much better
|
|
1649
|
-
# behaved than the ones for raw chunks of memory.
|
|
1650
|
-
#
|
|
1651
|
-
def start_tls args={}
|
|
1652
|
-
priv_key, cert_chain = args.values_at(:private_key_file, :cert_chain_file)
|
|
1653
|
-
|
|
1654
|
-
[priv_key, cert_chain].each do |file|
|
|
1655
|
-
next if file.nil? or file.empty?
|
|
1656
|
-
raise FileNotFoundException,
|
|
1657
|
-
"Could not find #{file} for start_tls" unless File.exists? file
|
|
1216
|
+
|
|
1217
|
+
# (Experimental)
|
|
1218
|
+
#
|
|
1219
|
+
#
|
|
1220
|
+
def self.open_keyboard handler=nil, *args
|
|
1221
|
+
klass = if (handler and handler.is_a?(Class))
|
|
1222
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
1223
|
+
handler
|
|
1224
|
+
else
|
|
1225
|
+
Class.new( Connection ) {handler and include handler}
|
|
1658
1226
|
end
|
|
1659
|
-
|
|
1660
|
-
EventMachine::set_tls_parms(@signature, priv_key || '', cert_chain || '')
|
|
1661
|
-
|
|
1662
|
-
EventMachine::start_tls @signature
|
|
1663
|
-
end
|
|
1664
1227
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1228
|
+
arity = klass.instance_method(:initialize).arity
|
|
1229
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
|
1230
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
|
1231
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
s = read_keyboard
|
|
1235
|
+
c = klass.new s, *args
|
|
1236
|
+
@conns[s] = c
|
|
1237
|
+
block_given? and yield c
|
|
1238
|
+
c
|
|
1239
|
+
end
|
|
1240
|
+
|
|
1241
|
+
# EventMachine's file monitoring API. Currently supported are the following events
|
|
1242
|
+
# on individual files, using inotify on Linux systems, and kqueue for OSX/BSD:
|
|
1668
1243
|
#
|
|
1669
|
-
#
|
|
1670
|
-
#
|
|
1671
|
-
#
|
|
1672
|
-
# not adequate, because the SSL handshake may still be taking place.
|
|
1244
|
+
# * File modified (written to)
|
|
1245
|
+
# * File moved/renamed
|
|
1246
|
+
# * File deleted
|
|
1673
1247
|
#
|
|
1674
|
-
#
|
|
1248
|
+
# EventMachine::watch_file takes a filename and a handler Module containing your custom callback methods.
|
|
1249
|
+
# This will setup the low level monitoring on the specified file, and create a new EventMachine::FileWatch
|
|
1250
|
+
# object with your Module mixed in. FileWatch is a subclass of EM::Connection, so callbacks on this object
|
|
1251
|
+
# work in the familiar way. The callbacks that will be fired by EventMachine are:
|
|
1675
1252
|
#
|
|
1676
|
-
# *
|
|
1677
|
-
# *
|
|
1678
|
-
# *
|
|
1679
|
-
# * Remote peer for any other reason has not presented a certificate
|
|
1253
|
+
# * file_modified
|
|
1254
|
+
# * file_moved
|
|
1255
|
+
# * file_deleted
|
|
1680
1256
|
#
|
|
1681
|
-
#
|
|
1257
|
+
# You can access the filename being monitored from within this object using FileWatch#path.
|
|
1682
1258
|
#
|
|
1683
|
-
#
|
|
1259
|
+
# When a file is deleted, FileWatch#stop_watching will be called after your file_deleted callback,
|
|
1260
|
+
# to clean up the underlying monitoring and remove EventMachine's reference to the now-useless FileWatch.
|
|
1261
|
+
# This will in turn call unbind, if you wish to use it.
|
|
1684
1262
|
#
|
|
1685
|
-
#
|
|
1686
|
-
#
|
|
1687
|
-
# start_tls
|
|
1688
|
-
# end
|
|
1263
|
+
# The corresponding system-level Errno will be raised when attempting to monitor non-existent files,
|
|
1264
|
+
# files with wrong permissions, or if an error occurs dealing with inotify/kqueue.
|
|
1689
1265
|
#
|
|
1690
|
-
#
|
|
1691
|
-
# puts get_peer_cert
|
|
1692
|
-
# close_connection
|
|
1693
|
-
# end
|
|
1266
|
+
# === Usage example:
|
|
1694
1267
|
#
|
|
1695
|
-
#
|
|
1696
|
-
#
|
|
1697
|
-
#
|
|
1268
|
+
# Make sure we have a file to monitor:
|
|
1269
|
+
# $ echo "bar" > /tmp/foo
|
|
1270
|
+
#
|
|
1271
|
+
# module Handler
|
|
1272
|
+
# def file_modified
|
|
1273
|
+
# puts "#{path} modified"
|
|
1274
|
+
# end
|
|
1698
1275
|
#
|
|
1276
|
+
# def file_moved
|
|
1277
|
+
# puts "#{path} moved"
|
|
1278
|
+
# end
|
|
1279
|
+
#
|
|
1280
|
+
# def file_deleted
|
|
1281
|
+
# puts "#{path} deleted"
|
|
1282
|
+
# end
|
|
1283
|
+
#
|
|
1284
|
+
# def unbind
|
|
1285
|
+
# puts "#{path} monitoring ceased"
|
|
1286
|
+
# end
|
|
1699
1287
|
# end
|
|
1700
1288
|
#
|
|
1701
1289
|
# EM.run {
|
|
1702
|
-
#
|
|
1290
|
+
# EM.watch_file("/tmp/foo", Handler)
|
|
1703
1291
|
# }
|
|
1704
1292
|
#
|
|
1705
|
-
#
|
|
1706
|
-
#
|
|
1707
|
-
#
|
|
1708
|
-
#
|
|
1709
|
-
#
|
|
1710
|
-
#
|
|
1711
|
-
#
|
|
1712
|
-
#
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
# b3J5L1RoYXd0ZV9TR0NfQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEF
|
|
1721
|
-
# BQADgYEAsRwpLg1dgCR1gYDK185MFGukXMeQFUvhGqF8eT/CjpdvezyKVuz84gSu
|
|
1722
|
-
# 6ccMXgcPQZGQN/F4Xug+Q01eccJjRSVfdvR5qwpqCj+6BFl5oiKDBsveSkrmL5dz
|
|
1723
|
-
# s2bn7TdTSYKcLeBkjXxDLHGBqLJ6TNCJ3c4/cbbG5JhGvoema94=
|
|
1724
|
-
# -----END CERTIFICATE-----
|
|
1725
|
-
#
|
|
1726
|
-
# You can do whatever you want with the certificate String, such as load it
|
|
1727
|
-
# as a certificate object using the OpenSSL library, and check it's fields.
|
|
1728
|
-
def get_peer_cert
|
|
1729
|
-
EventMachine::get_peer_cert @signature
|
|
1730
|
-
end
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
# send_datagram is for sending UDP messages.
|
|
1734
|
-
# This method may be called from any Connection object that refers
|
|
1735
|
-
# to an open datagram socket (see EventMachine#open_datagram_socket).
|
|
1736
|
-
# The method sends a UDP (datagram) packet containing the data you specify,
|
|
1737
|
-
# to a remote peer specified by the IP address and port that you give
|
|
1738
|
-
# as parameters to the method.
|
|
1739
|
-
# Observe that you may send a zero-length packet (empty string).
|
|
1740
|
-
# However, you may not send an arbitrarily-large data packet because
|
|
1741
|
-
# your operating system will enforce a platform-specific limit on
|
|
1742
|
-
# the size of the outbound packet. (Your kernel
|
|
1743
|
-
# will respond in a platform-specific way if you send an overlarge
|
|
1744
|
-
# packet: some will send a truncated packet, some will complain, and
|
|
1745
|
-
# some will silently drop your request).
|
|
1746
|
-
# On LANs, it's usually OK to send datagrams up to about 4000 bytes in length,
|
|
1747
|
-
# but to be really safe, send messages smaller than the Ethernet-packet
|
|
1748
|
-
# size (typically about 1400 bytes). Some very restrictive WANs
|
|
1749
|
-
# will either drop or truncate packets larger than about 500 bytes.
|
|
1750
|
-
#--
|
|
1751
|
-
# Added the Integer wrapper around the port parameter per suggestion by
|
|
1752
|
-
# Matthieu Riou, after he passed a String and spent hours tearing his hair out.
|
|
1753
|
-
#
|
|
1754
|
-
def send_datagram data, recipient_address, recipient_port
|
|
1755
|
-
data = data.to_s
|
|
1756
|
-
EventMachine::send_datagram @signature, data, data.length, recipient_address, Integer(recipient_port)
|
|
1757
|
-
end
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
# #get_peername is used with stream-connections to obtain the identity
|
|
1761
|
-
# of the remotely-connected peer. If a peername is available, this method
|
|
1762
|
-
# returns a sockaddr structure. The method returns nil if no peername is available.
|
|
1763
|
-
# You can use Socket#unpack_sockaddr_in and its variants to obtain the
|
|
1764
|
-
# values contained in the peername structure returned from #get_peername.
|
|
1765
|
-
def get_peername
|
|
1766
|
-
EventMachine::get_peername @signature
|
|
1767
|
-
end
|
|
1768
|
-
|
|
1769
|
-
# #get_sockname is used with stream-connections to obtain the identity
|
|
1770
|
-
# of the local side of the connection. If a local name is available, this method
|
|
1771
|
-
# returns a sockaddr structure. The method returns nil if no local name is available.
|
|
1772
|
-
# You can use Socket#unpack_sockaddr_in and its variants to obtain the
|
|
1773
|
-
# values contained in the local-name structure returned from #get_sockname.
|
|
1774
|
-
def get_sockname
|
|
1775
|
-
EventMachine::get_sockname @signature
|
|
1776
|
-
end
|
|
1777
|
-
|
|
1778
|
-
# Returns the PID (kernel process identifier) of a subprocess
|
|
1779
|
-
# associated with this Connection object. For use with EventMachine#popen
|
|
1780
|
-
# and similar methods. Returns nil when there is no meaningful subprocess.
|
|
1781
|
-
#--
|
|
1782
|
-
#
|
|
1783
|
-
def get_pid
|
|
1784
|
-
EventMachine::get_subprocess_pid @signature
|
|
1785
|
-
end
|
|
1786
|
-
|
|
1787
|
-
# Returns a subprocess exit status. Only useful for #popen. Call it in your
|
|
1788
|
-
# #unbind handler.
|
|
1789
|
-
#
|
|
1790
|
-
def get_status
|
|
1791
|
-
EventMachine::get_subprocess_status @signature
|
|
1792
|
-
end
|
|
1793
|
-
|
|
1794
|
-
# comm_inactivity_timeout returns the current value (in seconds) of the inactivity-timeout
|
|
1795
|
-
# property of network-connection and datagram-socket objects. A nonzero value
|
|
1796
|
-
# indicates that the connection or socket will automatically be closed if no read or write
|
|
1797
|
-
# activity takes place for at least that number of seconds.
|
|
1798
|
-
# A zero value (the default) specifies that no automatic timeout will take place.
|
|
1799
|
-
def comm_inactivity_timeout
|
|
1800
|
-
EventMachine::get_comm_inactivity_timeout @signature
|
|
1801
|
-
end
|
|
1802
|
-
|
|
1803
|
-
# Alias for #set_comm_inactivity_timeout.
|
|
1804
|
-
def comm_inactivity_timeout= value
|
|
1805
|
-
self.send :set_comm_inactivity_timeout, value
|
|
1806
|
-
end
|
|
1807
|
-
|
|
1808
|
-
# comm_inactivity_timeout= allows you to set the inactivity-timeout property for
|
|
1809
|
-
# a network connection or datagram socket. Specify a non-negative numeric value in seconds.
|
|
1810
|
-
# If the value is greater than zero, the connection or socket will automatically be closed
|
|
1811
|
-
# if no read or write activity takes place for at least that number of seconds.
|
|
1812
|
-
# Specify a value of zero to indicate that no automatic timeout should take place.
|
|
1813
|
-
# Zero is the default value.
|
|
1814
|
-
def set_comm_inactivity_timeout value
|
|
1815
|
-
EventMachine::set_comm_inactivity_timeout @signature, value
|
|
1816
|
-
end
|
|
1817
|
-
|
|
1818
|
-
#--
|
|
1819
|
-
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO REMAIN SUPPORTED.
|
|
1820
|
-
# (03Nov06)
|
|
1821
|
-
def reconnect server, port
|
|
1822
|
-
EventMachine::reconnect server, port, self
|
|
1823
|
-
end
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
# Like EventMachine::Connection#send_data, this sends data to the remote end of
|
|
1827
|
-
# the network connection. EventMachine::Connection@send_file_data takes a
|
|
1828
|
-
# filename as an argument, though, and sends the contents of the file, in one
|
|
1829
|
-
# chunk. Contributed by Kirk Haines.
|
|
1830
|
-
#
|
|
1831
|
-
def send_file_data filename
|
|
1832
|
-
EventMachine::send_file_data @signature, filename
|
|
1833
|
-
end
|
|
1834
|
-
|
|
1835
|
-
# Open a file on the filesystem and send it to the remote peer. This returns an
|
|
1836
|
-
# object of type EventMachine::Deferrable. The object's callbacks will be executed
|
|
1837
|
-
# on the reactor main thread when the file has been completely scheduled for
|
|
1838
|
-
# transmission to the remote peer. Its errbacks will be called in case of an error
|
|
1839
|
-
# (such as file-not-found). #stream_file_data employs various strategems to achieve
|
|
1840
|
-
# the fastest possible performance, balanced against minimum consumption of memory.
|
|
1841
|
-
#
|
|
1842
|
-
# You can control the behavior of #stream_file_data with the optional arguments parameter.
|
|
1843
|
-
# Currently-supported arguments are:
|
|
1844
|
-
# :http_chunks, a boolean flag which defaults false. If true, this flag streams the
|
|
1845
|
-
# file data in a format compatible with the HTTP chunked-transfer encoding.
|
|
1846
|
-
#
|
|
1847
|
-
# Warning: this feature has an implicit dependency on an outboard extension,
|
|
1848
|
-
# evma_fastfilereader. You must install this extension in order to use #stream_file_data
|
|
1849
|
-
# with files larger than a certain size (currently 8192 bytes).
|
|
1850
|
-
#
|
|
1851
|
-
def stream_file_data filename, args={}
|
|
1852
|
-
EventMachine::FileStreamer.new( self, filename, args )
|
|
1853
|
-
end
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
# TODO, document this
|
|
1857
|
-
#
|
|
1858
|
-
#
|
|
1859
|
-
class EventMachine::PeriodicTimer
|
|
1860
|
-
attr_accessor :interval
|
|
1861
|
-
def initialize *args, &block
|
|
1862
|
-
@interval = args.shift
|
|
1863
|
-
@code = args.shift || block
|
|
1864
|
-
schedule
|
|
1865
|
-
end
|
|
1866
|
-
def schedule
|
|
1867
|
-
EventMachine::add_timer @interval, proc {self.fire}
|
|
1868
|
-
end
|
|
1869
|
-
def fire
|
|
1870
|
-
unless @cancelled
|
|
1871
|
-
@code.call
|
|
1872
|
-
schedule
|
|
1873
|
-
end
|
|
1874
|
-
end
|
|
1875
|
-
def cancel
|
|
1876
|
-
@cancelled = true
|
|
1877
|
-
end
|
|
1878
|
-
end
|
|
1879
|
-
|
|
1880
|
-
# TODO, document this
|
|
1881
|
-
#
|
|
1882
|
-
#
|
|
1883
|
-
class EventMachine::Timer
|
|
1884
|
-
def initialize *args, &block
|
|
1885
|
-
@signature = EventMachine::add_timer(*args, &block)
|
|
1886
|
-
end
|
|
1887
|
-
def cancel
|
|
1888
|
-
EventMachine.send :cancel_timer, @signature
|
|
1889
|
-
end
|
|
1890
|
-
end
|
|
1293
|
+
# $ echo "baz" >> /tmp/foo => "/tmp/foo modified"
|
|
1294
|
+
# $ mv /tmp/foo /tmp/oof => "/tmp/foo moved"
|
|
1295
|
+
# $ rm /tmp/oof => "/tmp/foo deleted"
|
|
1296
|
+
# => "/tmp/foo monitoring ceased"
|
|
1297
|
+
#
|
|
1298
|
+
# Note that we have not implemented the ability to pick up on the new filename after a rename.
|
|
1299
|
+
# Calling #path will always return the filename you originally used.
|
|
1300
|
+
#
|
|
1301
|
+
def self.watch_file(filename, handler=nil, *args)
|
|
1302
|
+
klass = if (handler and handler.is_a?(Class))
|
|
1303
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::FileWatch' unless FileWatch > handler
|
|
1304
|
+
handler
|
|
1305
|
+
else
|
|
1306
|
+
Class.new( FileWatch ) {handler and include handler}
|
|
1307
|
+
end
|
|
1891
1308
|
|
|
1892
|
-
|
|
1309
|
+
arity = klass.instance_method(:initialize).arity
|
|
1310
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
|
1311
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
|
1312
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
|
1313
|
+
end
|
|
1893
1314
|
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
# A good citizen would use eventmachine/protocols/tcptest.
|
|
1903
|
-
# TODO : various autotools are completely useless with the lack of naming
|
|
1904
|
-
# convention, we need to correct that!
|
|
1905
|
-
autoload :TcpConnectTester, 'protocols/tcptest'
|
|
1906
|
-
autoload :HttpClient, 'protocols/httpclient'
|
|
1907
|
-
autoload :LineAndTextProtocol, 'protocols/line_and_text'
|
|
1908
|
-
autoload :HeaderAndContentProtocol, 'protocols/header_and_content'
|
|
1909
|
-
autoload :LineText2, 'protocols/linetext2'
|
|
1910
|
-
autoload :HttpClient2, 'protocols/httpcli2'
|
|
1911
|
-
autoload :Stomp, 'protocols/stomp'
|
|
1912
|
-
autoload :SmtpClient, 'protocols/smtpclient'
|
|
1913
|
-
autoload :SmtpServer, 'protocols/smtpserver'
|
|
1914
|
-
autoload :SASLauth, 'protocols/saslauth'
|
|
1915
|
-
autoload :Memcache, 'protocols/memcache'
|
|
1916
|
-
|
|
1917
|
-
#require 'protocols/postgres' UNCOMMENT THIS LINE WHEN THE POSTGRES CODE IS READY FOR PRIME TIME.
|
|
1918
|
-
end
|
|
1315
|
+
s = EM::watch_filename(filename)
|
|
1316
|
+
c = klass.new s, *args
|
|
1317
|
+
# we have to set the path like this because of how Connection.new works
|
|
1318
|
+
c.instance_variable_set("@path", filename)
|
|
1319
|
+
@conns[s] = c
|
|
1320
|
+
block_given? and yield c
|
|
1321
|
+
c
|
|
1322
|
+
end
|
|
1919
1323
|
|
|
1324
|
+
# EventMachine's process monitoring API. Currently supported using kqueue for OSX/BSD.
|
|
1325
|
+
#
|
|
1326
|
+
# === Usage example:
|
|
1327
|
+
#
|
|
1328
|
+
# module ProcessWatcher
|
|
1329
|
+
# def process_exited
|
|
1330
|
+
# put 'the forked child died!'
|
|
1331
|
+
# end
|
|
1332
|
+
# end
|
|
1333
|
+
#
|
|
1334
|
+
# pid = fork{ sleep }
|
|
1335
|
+
#
|
|
1336
|
+
# EM.run{
|
|
1337
|
+
# EM.watch_process(pid, ProcessWatcher)
|
|
1338
|
+
# EM.add_timer(1){ Process.kill('TERM', pid) }
|
|
1339
|
+
# }
|
|
1340
|
+
#
|
|
1341
|
+
def self.watch_process(pid, handler=nil, *args)
|
|
1342
|
+
pid = pid.to_i
|
|
1343
|
+
|
|
1344
|
+
klass = if (handler and handler.is_a?(Class))
|
|
1345
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::ProcessWatch' unless ProcessWatch > handler
|
|
1346
|
+
handler
|
|
1347
|
+
else
|
|
1348
|
+
Class.new( ProcessWatch ) {handler and include handler}
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
arity = klass.instance_method(:initialize).arity
|
|
1352
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
|
1353
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
|
1354
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
|
1355
|
+
end
|
|
1356
|
+
|
|
1357
|
+
s = EM::watch_pid(pid)
|
|
1358
|
+
c = klass.new s, *args
|
|
1359
|
+
# we have to set the path like this because of how Connection.new works
|
|
1360
|
+
c.instance_variable_set("@pid", pid)
|
|
1361
|
+
@conns[s] = c
|
|
1362
|
+
block_given? and yield c
|
|
1363
|
+
c
|
|
1364
|
+
end
|
|
1365
|
+
|
|
1366
|
+
# Catch-all for errors raised during event loop callbacks.
|
|
1367
|
+
#
|
|
1368
|
+
# EM.error_handler{ |e|
|
|
1369
|
+
# puts "Error raised during event loop: #{e.message}"
|
|
1370
|
+
# }
|
|
1371
|
+
#
|
|
1372
|
+
def self.error_handler cb = nil, &blk
|
|
1373
|
+
if cb or blk
|
|
1374
|
+
@error_handler = cb || blk
|
|
1375
|
+
elsif instance_variable_defined? :@error_handler
|
|
1376
|
+
remove_instance_variable :@error_handler
|
|
1377
|
+
end
|
|
1378
|
+
end
|
|
1379
|
+
|
|
1380
|
+
# enable_proxy allows for direct writing of incoming data back out to another descriptor, at the C++ level in the reactor.
|
|
1381
|
+
# This is especially useful for proxies where high performance is required. Propogating data from a server response
|
|
1382
|
+
# all the way up to Ruby, and then back down to the reactor to be sent back to the client, is often unnecessary and
|
|
1383
|
+
# incurs a significant performance decrease.
|
|
1384
|
+
#
|
|
1385
|
+
# The two arguments are Connections, 'from' and 'to'. 'from' is the connection whose inbound data you want
|
|
1386
|
+
# relayed back out. 'to' is the connection to write it to.
|
|
1387
|
+
#
|
|
1388
|
+
# Once you call this method, the 'from' connection will no longer get receive_data callbacks from the reactor,
|
|
1389
|
+
# except in the case that 'to' connection has already closed when attempting to write to it. You can see
|
|
1390
|
+
# in the example, that proxy_target_unbound will be called when this occurs. After that, further incoming
|
|
1391
|
+
# data will be passed into receive_data as normal.
|
|
1392
|
+
#
|
|
1393
|
+
# Note also that this feature supports different types of descriptors - TCP, UDP, and pipes. You can relay
|
|
1394
|
+
# data from one kind to another.
|
|
1395
|
+
#
|
|
1396
|
+
# Example:
|
|
1397
|
+
#
|
|
1398
|
+
# module ProxyConnection
|
|
1399
|
+
# def initialize(client, request)
|
|
1400
|
+
# @client, @request = client, request
|
|
1401
|
+
# end
|
|
1402
|
+
#
|
|
1403
|
+
# def post_init
|
|
1404
|
+
# EM::enable_proxy(self, @client)
|
|
1405
|
+
# end
|
|
1406
|
+
#
|
|
1407
|
+
# def connection_completed
|
|
1408
|
+
# send_data @request
|
|
1409
|
+
# end
|
|
1410
|
+
#
|
|
1411
|
+
# def proxy_target_unbound
|
|
1412
|
+
# close_connection
|
|
1413
|
+
# end
|
|
1414
|
+
#
|
|
1415
|
+
# def unbind
|
|
1416
|
+
# @client.close_connection_after_writing
|
|
1417
|
+
# end
|
|
1418
|
+
# end
|
|
1419
|
+
#
|
|
1420
|
+
# module ProxyServer
|
|
1421
|
+
# def receive_data(data)
|
|
1422
|
+
# (@buf ||= "") << data
|
|
1423
|
+
# if @buf =~ /\r\n\r\n/ # all http headers received
|
|
1424
|
+
# EM.connect("10.0.0.15", 80, ProxyConnection, self, data)
|
|
1425
|
+
# end
|
|
1426
|
+
# end
|
|
1427
|
+
# end
|
|
1428
|
+
#
|
|
1429
|
+
# EM.run {
|
|
1430
|
+
# EM.start_server("127.0.0.1", 8080, ProxyServer)
|
|
1431
|
+
# }
|
|
1432
|
+
def self.enable_proxy(from, to)
|
|
1433
|
+
EM::start_proxy(from.signature, to.signature)
|
|
1434
|
+
end
|
|
1435
|
+
|
|
1436
|
+
# disable_proxy takes just one argument, a Connection that has proxying enabled via enable_proxy.
|
|
1437
|
+
# Calling this method will remove that functionality and your connection will begin receiving
|
|
1438
|
+
# data via receive_data again.
|
|
1439
|
+
def self.disable_proxy(from)
|
|
1440
|
+
EM::stop_proxy(from.signature)
|
|
1441
|
+
end
|
|
1442
|
+
|
|
1443
|
+
# Retrieve the heartbeat interval. This is how often EventMachine will check for dead connections
|
|
1444
|
+
# that have had an InactivityTimeout set via Connection#set_comm_inactivity_timeout.
|
|
1445
|
+
# Default is 2 seconds.
|
|
1446
|
+
def self.heartbeat_interval
|
|
1447
|
+
EM::get_heartbeat_interval
|
|
1448
|
+
end
|
|
1449
|
+
|
|
1450
|
+
# Set the heartbeat interval. This is how often EventMachine will check for dead connections
|
|
1451
|
+
# that have had an InactivityTimeout set via Connection#set_comm_inactivity_timeout.
|
|
1452
|
+
# Takes a Numeric number of seconds. Default is 2.
|
|
1453
|
+
def self.heartbeat_interval= (time)
|
|
1454
|
+
EM::set_heartbeat_interval time.to_f
|
|
1455
|
+
end
|
|
1456
|
+
|
|
1457
|
+
private
|
|
1458
|
+
|
|
1459
|
+
def self.event_callback conn_binding, opcode, data # :nodoc:
|
|
1460
|
+
#
|
|
1461
|
+
# Changed 27Dec07: Eliminated the hookable error handling.
|
|
1462
|
+
# No one was using it, and it degraded performance significantly.
|
|
1463
|
+
# It's in original_event_callback, which is dead code.
|
|
1464
|
+
#
|
|
1465
|
+
# Changed 25Jul08: Added a partial solution to the problem of exceptions
|
|
1466
|
+
# raised in user-written event-handlers. If such exceptions are not caught,
|
|
1467
|
+
# we must cause the reactor to stop, and then re-raise the exception.
|
|
1468
|
+
# Otherwise, the reactor doesn't stop and it's left on the call stack.
|
|
1469
|
+
# This is partial because we only added it to #unbind, where it's critical
|
|
1470
|
+
# (to keep unbind handlers from being re-entered when a stopping reactor
|
|
1471
|
+
# runs down open connections). It should go on the other calls to user
|
|
1472
|
+
# code, but the performance impact may be too large.
|
|
1473
|
+
#
|
|
1474
|
+
if opcode == ConnectionUnbound
|
|
1475
|
+
if c = @conns.delete( conn_binding )
|
|
1476
|
+
begin
|
|
1477
|
+
c.unbind
|
|
1478
|
+
rescue
|
|
1479
|
+
@wrapped_exception = $!
|
|
1480
|
+
stop
|
|
1481
|
+
end
|
|
1482
|
+
elsif c = @acceptors.delete( conn_binding )
|
|
1483
|
+
# no-op
|
|
1484
|
+
else
|
|
1485
|
+
raise ConnectionNotBound, "recieved ConnectionUnbound for an unknown signature: #{conn_binding}"
|
|
1486
|
+
end
|
|
1487
|
+
elsif opcode == ConnectionAccepted
|
|
1488
|
+
accep,args,blk = @acceptors[conn_binding]
|
|
1489
|
+
raise NoHandlerForAcceptedConnection unless accep
|
|
1490
|
+
c = accep.new data, *args
|
|
1491
|
+
@conns[data] = c
|
|
1492
|
+
blk and blk.call(c)
|
|
1493
|
+
c # (needed?)
|
|
1494
|
+
elsif opcode == ConnectionCompleted
|
|
1495
|
+
c = @conns[conn_binding] or raise ConnectionNotBound, "received ConnectionCompleted for unknown signature: #{conn_binding}"
|
|
1496
|
+
c.connection_completed
|
|
1497
|
+
##
|
|
1498
|
+
# The remaining code is a fallback for the pure ruby reactor. Usually these events are handled in the C event_callback() in rubymain.cpp
|
|
1499
|
+
elsif opcode == TimerFired
|
|
1500
|
+
t = @timers.delete( data )
|
|
1501
|
+
return if t == false # timer cancelled
|
|
1502
|
+
t or raise UnknownTimerFired, "timer data: #{data}"
|
|
1503
|
+
t.call
|
|
1504
|
+
elsif opcode == ConnectionData
|
|
1505
|
+
c = @conns[conn_binding] or raise ConnectionNotBound, "received data #{data} for unknown signature: #{conn_binding}"
|
|
1506
|
+
c.receive_data data
|
|
1507
|
+
elsif opcode == LoopbreakSignalled
|
|
1508
|
+
run_deferred_callbacks
|
|
1509
|
+
elsif opcode == ConnectionNotifyReadable
|
|
1510
|
+
c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1511
|
+
c.notify_readable
|
|
1512
|
+
elsif opcode == ConnectionNotifyWritable
|
|
1513
|
+
c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1514
|
+
c.notify_writable
|
|
1515
|
+
end
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
#--
|
|
1519
|
+
# The original event_callback below handled runtime errors in ruby and degraded performance significantly.
|
|
1520
|
+
# An optional C-based error handler is now available via EM::error_handler
|
|
1521
|
+
#
|
|
1522
|
+
# private
|
|
1523
|
+
# def EventMachine::original_event_callback conn_binding, opcode, data
|
|
1524
|
+
# #
|
|
1525
|
+
# # Added 03Oct07: Any code path that invokes user-written code must
|
|
1526
|
+
# # wrap itself in a begin/rescue for RuntimeErrors, that calls the
|
|
1527
|
+
# # user-overridable class method #handle_runtime_error.
|
|
1528
|
+
# #
|
|
1529
|
+
# if opcode == ConnectionData
|
|
1530
|
+
# c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1531
|
+
# begin
|
|
1532
|
+
# c.receive_data data
|
|
1533
|
+
# rescue
|
|
1534
|
+
# EventMachine.handle_runtime_error
|
|
1535
|
+
# end
|
|
1536
|
+
# elsif opcode == ConnectionUnbound
|
|
1537
|
+
# if c = @conns.delete( conn_binding )
|
|
1538
|
+
# begin
|
|
1539
|
+
# c.unbind
|
|
1540
|
+
# rescue
|
|
1541
|
+
# EventMachine.handle_runtime_error
|
|
1542
|
+
# end
|
|
1543
|
+
# elsif c = @acceptors.delete( conn_binding )
|
|
1544
|
+
# # no-op
|
|
1545
|
+
# else
|
|
1546
|
+
# raise ConnectionNotBound
|
|
1547
|
+
# end
|
|
1548
|
+
# elsif opcode == ConnectionAccepted
|
|
1549
|
+
# accep,args,blk = @acceptors[conn_binding]
|
|
1550
|
+
# raise NoHandlerForAcceptedConnection unless accep
|
|
1551
|
+
# c = accep.new data, *args
|
|
1552
|
+
# @conns[data] = c
|
|
1553
|
+
# begin
|
|
1554
|
+
# blk and blk.call(c)
|
|
1555
|
+
# rescue
|
|
1556
|
+
# EventMachine.handle_runtime_error
|
|
1557
|
+
# end
|
|
1558
|
+
# c # (needed?)
|
|
1559
|
+
# elsif opcode == TimerFired
|
|
1560
|
+
# t = @timers.delete( data ) or raise UnknownTimerFired
|
|
1561
|
+
# begin
|
|
1562
|
+
# t.call
|
|
1563
|
+
# rescue
|
|
1564
|
+
# EventMachine.handle_runtime_error
|
|
1565
|
+
# end
|
|
1566
|
+
# elsif opcode == ConnectionCompleted
|
|
1567
|
+
# c = @conns[conn_binding] or raise ConnectionNotBound
|
|
1568
|
+
# begin
|
|
1569
|
+
# c.connection_completed
|
|
1570
|
+
# rescue
|
|
1571
|
+
# EventMachine.handle_runtime_error
|
|
1572
|
+
# end
|
|
1573
|
+
# elsif opcode == LoopbreakSignalled
|
|
1574
|
+
# begin
|
|
1575
|
+
# run_deferred_callbacks
|
|
1576
|
+
# rescue
|
|
1577
|
+
# EventMachine.handle_runtime_error
|
|
1578
|
+
# end
|
|
1579
|
+
# end
|
|
1580
|
+
# end
|
|
1581
|
+
#
|
|
1582
|
+
#
|
|
1583
|
+
# # Default handler for RuntimeErrors that are raised in user code.
|
|
1584
|
+
# # The default behavior is to re-raise the error, which ends your program.
|
|
1585
|
+
# # To override the default behavior, re-implement this method in your code.
|
|
1586
|
+
# # For example:
|
|
1587
|
+
# #
|
|
1588
|
+
# # module EventMachine
|
|
1589
|
+
# # def self.handle_runtime_error
|
|
1590
|
+
# # $>.puts $!
|
|
1591
|
+
# # end
|
|
1592
|
+
# # end
|
|
1593
|
+
# #
|
|
1594
|
+
# #--
|
|
1595
|
+
# # We need to ensure that any code path which invokes user code rescues RuntimeError
|
|
1596
|
+
# # and calls this method. The obvious place to do that is in #event_callback,
|
|
1597
|
+
# # but, scurrilously, it turns out that we need to be finer grained that that.
|
|
1598
|
+
# # Periodic timers, in particular, wrap their invocations of user code inside
|
|
1599
|
+
# # procs that do other stuff we can't not do, like schedule the next invocation.
|
|
1600
|
+
# # This is a potential non-robustness, since we need to remember to hook in the
|
|
1601
|
+
# # error handler whenever and wherever we change how user code is invoked.
|
|
1602
|
+
# #
|
|
1603
|
+
# def EventMachine::handle_runtime_error
|
|
1604
|
+
# @runtime_error_hook ? @runtime_error_hook.call : raise
|
|
1605
|
+
# end
|
|
1606
|
+
#
|
|
1607
|
+
# # Sets a handler for RuntimeErrors that are raised in user code.
|
|
1608
|
+
# # Pass a block with no parameters. You can also call this method without a block,
|
|
1609
|
+
# # which restores the default behavior (see #handle_runtime_error).
|
|
1610
|
+
# #
|
|
1611
|
+
# def EventMachine::set_runtime_error_hook &blk
|
|
1612
|
+
# @runtime_error_hook = blk
|
|
1613
|
+
# end
|
|
1614
|
+
|
|
1615
|
+
#--
|
|
1616
|
+
# This is a provisional implementation of a stream-oriented file access object.
|
|
1617
|
+
# We also experiment with wrapping up some better exception reporting.
|
|
1618
|
+
def self._open_file_for_writing filename, handler=nil # :nodoc:
|
|
1619
|
+
klass = if (handler and handler.is_a?(Class))
|
|
1620
|
+
raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
|
|
1621
|
+
handler
|
|
1622
|
+
else
|
|
1623
|
+
Class.new( Connection ) {handler and include handler}
|
|
1624
|
+
end
|
|
1625
|
+
|
|
1626
|
+
s = _write_file filename
|
|
1627
|
+
c = klass.new s
|
|
1628
|
+
@conns[s] = c
|
|
1629
|
+
block_given? and yield c
|
|
1630
|
+
c
|
|
1631
|
+
end
|
|
1920
1632
|
end # module EventMachine
|
|
1921
1633
|
|
|
1922
1634
|
# Save everyone some typing.
|
|
1923
1635
|
EM = EventMachine
|
|
1924
|
-
EM::P = EventMachine::Protocols
|
|
1925
|
-
|
|
1926
|
-
require 'em/processes'
|
|
1636
|
+
EM::P = EventMachine::Protocols
|