eventmachine 0.10.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/DEFERRABLES +1 -1
- data/LIGHTWEIGHT_CONCURRENCY +1 -1
- data/PURE_RUBY +1 -1
- data/README +1 -1
- data/RELEASE_NOTES +1 -1
- data/SMTP +1 -1
- data/SPAWNED_PROCESSES +1 -1
- data/TODO +1 -1
- data/ext/binder.cpp +1 -1
- data/ext/binder.h +1 -1
- data/ext/cmain.cpp +29 -1
- data/ext/cplusplus.cpp +1 -1
- data/ext/ed.cpp +79 -1
- data/ext/ed.h +6 -1
- data/ext/em.cpp +343 -27
- data/ext/em.h +25 -1
- data/ext/emwin.cpp +1 -1
- data/ext/emwin.h +1 -1
- data/ext/epoll.cpp +1 -1
- data/ext/epoll.h +1 -1
- data/ext/eventmachine.h +3 -1
- data/ext/eventmachine_cpp.h +1 -1
- data/ext/extconf.rb +31 -1
- data/ext/files.cpp +1 -1
- data/ext/files.h +1 -1
- data/ext/kb.cpp +4 -1
- data/ext/page.cpp +1 -1
- data/ext/page.h +1 -1
- data/ext/pipe.cpp +4 -1
- data/ext/project.h +8 -2
- data/ext/rubymain.cpp +73 -2
- data/ext/sigs.cpp +1 -1
- data/ext/sigs.h +1 -1
- data/ext/ssl.cpp +4 -1
- data/ext/ssl.h +1 -1
- data/lib/em/deferrable.rb +1 -1
- data/lib/em/eventable.rb +1 -1
- data/lib/em/future.rb +1 -1
- data/lib/em/messages.rb +1 -1
- data/lib/em/processes.rb +68 -0
- data/lib/em/spawnable.rb +1 -1
- data/lib/em/streamer.rb +1 -1
- data/lib/eventmachine.rb +113 -66
- data/lib/eventmachine_version.rb +2 -2
- data/lib/evma.rb +1 -1
- data/lib/evma/callback.rb +1 -1
- data/lib/evma/container.rb +1 -1
- data/lib/evma/factory.rb +1 -1
- data/lib/evma/protocol.rb +1 -1
- data/lib/evma/reactor.rb +1 -1
- data/lib/jeventmachine.rb +1 -1
- data/lib/pr_eventmachine.rb +35 -8
- data/lib/protocols/header_and_content.rb +1 -1
- data/lib/protocols/httpcli2.rb +1 -1
- data/lib/protocols/httpclient.rb +1 -1
- data/lib/protocols/line_and_text.rb +1 -1
- data/lib/protocols/linetext2.rb +1 -1
- data/lib/protocols/saslauth.rb +59 -1
- data/lib/protocols/smtpclient.rb +4 -3
- data/lib/protocols/smtpserver.rb +3 -3
- data/lib/protocols/stomp.rb +1 -1
- data/lib/protocols/tcptest.rb +1 -1
- data/tests/test_basic.rb +2 -1
- data/tests/test_defer.rb +63 -0
- data/tests/test_epoll.rb +10 -5
- data/tests/test_errors.rb +13 -3
- data/tests/test_eventables.rb +1 -1
- data/tests/test_exc.rb +2 -1
- data/tests/test_futures.rb +2 -1
- data/tests/test_hc.rb +26 -2
- data/tests/test_httpclient.rb +2 -1
- data/tests/test_httpclient2.rb +2 -1
- data/tests/test_kb.rb +2 -1
- data/tests/test_ltp.rb +3 -1
- data/tests/test_ltp2.rb +2 -1
- data/tests/test_next_tick.rb +2 -1
- data/tests/test_processes.rb +56 -0
- data/tests/test_pure.rb +2 -1
- data/tests/test_running.rb +2 -1
- data/tests/test_sasl.rb +73 -0
- data/tests/test_send_file.rb +3 -1
- data/tests/test_servers.rb +4 -1
- data/tests/test_smtpclient.rb +2 -1
- data/tests/test_smtpserver.rb +3 -2
- data/tests/test_spawn.rb +2 -1
- data/tests/test_timers.rb +2 -2
- data/tests/test_ud.rb +2 -1
- data/tests/testem.rb +1 -1
- metadata +115 -104
data/lib/jeventmachine.rb
CHANGED
data/lib/pr_eventmachine.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: pr_eventmachine.rb
|
1
|
+
# $Id: pr_eventmachine.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -374,9 +374,24 @@ class Reactor
|
|
374
374
|
end
|
375
375
|
|
376
376
|
def open_loopbreaker
|
377
|
-
|
378
|
-
|
379
|
-
|
377
|
+
# Can't use an IO.pipe because they can't be set nonselectable in Windows.
|
378
|
+
# Pick a random localhost UDP port.
|
379
|
+
#@loopbreak_writer.close if @loopbreak_writer
|
380
|
+
#rd,@loopbreak_writer = IO.pipe
|
381
|
+
@loopbreak_reader = UDPSocket.new
|
382
|
+
@loopbreak_writer = UDPSocket.new
|
383
|
+
bound = false
|
384
|
+
100.times {
|
385
|
+
@loopbreak_port = rand(10000) + 40000
|
386
|
+
begin
|
387
|
+
@loopbreak_reader.bind "localhost", @loopbreak_port
|
388
|
+
bound = true
|
389
|
+
break
|
390
|
+
rescue
|
391
|
+
end
|
392
|
+
}
|
393
|
+
raise "Unable to bind Loopbreaker" unless bound
|
394
|
+
LoopbreakReader.new(@loopbreak_reader)
|
380
395
|
end
|
381
396
|
|
382
397
|
def close_loopbreaker
|
@@ -385,7 +400,8 @@ class Reactor
|
|
385
400
|
end
|
386
401
|
|
387
402
|
def signal_loopbreak
|
388
|
-
|
403
|
+
#@loopbreak_writer.write '+' if @loopbreak_writer
|
404
|
+
@loopbreak_writer.send('+',0,"localhost",@loopbreak_port) if @loopbreak_writer
|
389
405
|
end
|
390
406
|
|
391
407
|
def set_timer_quantum interval_in_seconds
|
@@ -428,8 +444,19 @@ module EventMachine
|
|
428
444
|
@io = io
|
429
445
|
@last_activity = Reactor.instance.current_loop_time
|
430
446
|
|
431
|
-
|
432
|
-
|
447
|
+
if defined?(Fcntl::F_GETFL)
|
448
|
+
m = @io.fcntl(Fcntl::F_GETFL, 0)
|
449
|
+
@io.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK | m)
|
450
|
+
else
|
451
|
+
# Windows doesn't define F_GETFL.
|
452
|
+
# It's not very reliable about setting descriptors nonblocking either.
|
453
|
+
begin
|
454
|
+
s = Socket.for_fd(@io.fileno)
|
455
|
+
s.fcntl( Fcntl::F_SETFL, Fcntl::O_NONBLOCK )
|
456
|
+
rescue Errno::EINVAL, Errno::EBADF
|
457
|
+
STDERR.puts "Serious error: unable to set descriptor non-blocking"
|
458
|
+
end
|
459
|
+
end
|
433
460
|
# TODO, should set CLOEXEC on Unix?
|
434
461
|
|
435
462
|
@close_scheduled = false
|
@@ -517,7 +544,7 @@ module EventMachine
|
|
517
544
|
data = io.sysread(4096)
|
518
545
|
EventMachine::event_callback uuid, ConnectionData, data
|
519
546
|
end
|
520
|
-
rescue Errno::EAGAIN
|
547
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
521
548
|
# no-op
|
522
549
|
rescue Errno::ECONNRESET, Errno::ECONNREFUSED, EOFError
|
523
550
|
@close_scheduled = true
|
data/lib/protocols/httpcli2.rb
CHANGED
data/lib/protocols/httpclient.rb
CHANGED
data/lib/protocols/linetext2.rb
CHANGED
data/lib/protocols/saslauth.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: saslauth.rb
|
1
|
+
# $Id: saslauth.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -107,6 +107,7 @@ module EventMachine
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
|
+
|
110
111
|
def validate username, psw, sysname, realm
|
111
112
|
p username
|
112
113
|
p psw
|
@@ -115,6 +116,63 @@ module EventMachine
|
|
115
116
|
true
|
116
117
|
end
|
117
118
|
end
|
119
|
+
|
120
|
+
# Implements the SASL authd client protocol.
|
121
|
+
# This is a very, very simple protocol that mimics the one used
|
122
|
+
# by saslauthd and pwcheck, two outboard daemons included in the
|
123
|
+
# standard SASL library distro.
|
124
|
+
# The only thing this is really suitable for is SASL PLAIN
|
125
|
+
# (user+password) authentication, but the SASL libs that are
|
126
|
+
# linked into standard servers (like imapd and sendmail) implement
|
127
|
+
# the other ones.
|
128
|
+
#
|
129
|
+
# You can use this module directly as a handler for EM Connections,
|
130
|
+
# or include it in a module or handler class of your own.
|
131
|
+
#
|
132
|
+
# First connect to a SASL server (it's probably a TCP server, or more
|
133
|
+
# likely a Unix-domain socket). Then call the #validate? method,
|
134
|
+
# passing at least a username and a password. #validate? returns
|
135
|
+
# a Deferrable which will either succeed or fail, depending
|
136
|
+
# on the status of the authentication operation.
|
137
|
+
#
|
138
|
+
module SASLauthclient
|
139
|
+
MaxFieldSize = 128*1024
|
140
|
+
|
141
|
+
def validate? username, psw, sysname=nil, realm=nil
|
142
|
+
|
143
|
+
str = [username, psw, sysname, realm].map {|m|
|
144
|
+
[(m || "").length, (m || "")]
|
145
|
+
}.flatten.pack( "nA*" * 4 )
|
146
|
+
send_data str
|
147
|
+
|
148
|
+
d = EM::DefaultDeferrable.new
|
149
|
+
@queries.unshift d
|
150
|
+
d
|
151
|
+
end
|
152
|
+
|
153
|
+
def post_init
|
154
|
+
@sasl_data = ""
|
155
|
+
@queries = []
|
156
|
+
end
|
157
|
+
|
158
|
+
def receive_data data
|
159
|
+
@sasl_data << data
|
160
|
+
|
161
|
+
while @sasl_data.length > 2
|
162
|
+
len = (@sasl_data[0,2].unpack("n")).first
|
163
|
+
raise "SASL Max Field Length exceeded" if len > MaxFieldSize
|
164
|
+
if @sasl_data.length >= (len + 2)
|
165
|
+
val = @sasl_data[2,len]
|
166
|
+
@sasl_data.slice!(0...(2+len))
|
167
|
+
q = @queries.pop
|
168
|
+
(val == "NO") ? q.fail : q.succeed
|
169
|
+
else
|
170
|
+
break
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
118
176
|
end
|
119
177
|
end
|
120
178
|
|
data/lib/protocols/smtpclient.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: smtpclient.rb
|
1
|
+
# $Id: smtpclient.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -24,7 +24,7 @@
|
|
24
24
|
#
|
25
25
|
|
26
26
|
|
27
|
-
require 'base64'
|
27
|
+
#require 'base64'
|
28
28
|
require 'ostruct'
|
29
29
|
|
30
30
|
module EventMachine
|
@@ -212,7 +212,8 @@ module Protocols
|
|
212
212
|
if psw.respond_to?(:call)
|
213
213
|
psw = psw.call
|
214
214
|
end
|
215
|
-
str = Base64::encode64("\0#{@args[:auth][:username]}\0#{psw}").chomp
|
215
|
+
#str = Base64::encode64("\0#{@args[:auth][:username]}\0#{psw}").chomp
|
216
|
+
str = ["\0#{@args[:auth][:username]}\0#{psw}"].pack("m").chomp
|
216
217
|
send_data "AUTH PLAIN #{str}\r\n"
|
217
218
|
@responder = :receive_auth_response
|
218
219
|
else
|
data/lib/protocols/smtpserver.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: smtpserver.rb
|
1
|
+
# $Id: smtpserver.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -24,7 +24,7 @@
|
|
24
24
|
#
|
25
25
|
|
26
26
|
|
27
|
-
require 'base64'
|
27
|
+
#require 'base64'
|
28
28
|
|
29
29
|
module EventMachine
|
30
30
|
module Protocols
|
@@ -254,7 +254,7 @@ module Protocols
|
|
254
254
|
if @state.include?(:auth)
|
255
255
|
send_data "503 auth already issued\r\n"
|
256
256
|
elsif str =~ /\APLAIN\s+/i
|
257
|
-
plain = Base64::decode64($'.dup)
|
257
|
+
plain = ($'.dup).unpack("m").first # Base64::decode64($'.dup)
|
258
258
|
discard,user,psw = plain.split("\000")
|
259
259
|
if receive_plain_auth user,psw
|
260
260
|
send_data "235 authentication ok\r\n"
|
data/lib/protocols/stomp.rb
CHANGED
data/lib/protocols/tcptest.rb
CHANGED
data/tests/test_basic.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_basic.rb
|
1
|
+
# $Id: test_basic.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -26,6 +26,7 @@
|
|
26
26
|
|
27
27
|
$:.unshift "../lib"
|
28
28
|
require 'eventmachine'
|
29
|
+
require 'test/unit'
|
29
30
|
|
30
31
|
class TestBasic < Test::Unit::TestCase
|
31
32
|
|
data/tests/test_defer.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# $Id: test_defer.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
|
+
#
|
3
|
+
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
+
# Homepage:: http://rubyeventmachine.com
|
5
|
+
# Date:: 8 April 2006
|
6
|
+
#
|
7
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
+
# usage examples.
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
+
# Gmail: blackhedd
|
14
|
+
#
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
16
|
+
# it under the terms of either: 1) the GNU General Public License
|
17
|
+
# as published by the Free Software Foundation; either version 2 of the
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
+
#
|
20
|
+
# See the file COPYING for complete licensing information.
|
21
|
+
#
|
22
|
+
#---------------------------------------------------------------------------
|
23
|
+
#
|
24
|
+
#
|
25
|
+
#
|
26
|
+
|
27
|
+
$:.unshift "../lib"
|
28
|
+
require 'eventmachine'
|
29
|
+
require 'test/unit'
|
30
|
+
|
31
|
+
class TestDeferUsage < Test::Unit::TestCase
|
32
|
+
|
33
|
+
def setup
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_em_with_defers
|
40
|
+
n = 0
|
41
|
+
n_times = 20
|
42
|
+
EM.run {
|
43
|
+
n_times.times {
|
44
|
+
EM.defer proc {
|
45
|
+
sleep 0.1
|
46
|
+
}, proc {
|
47
|
+
n += 1
|
48
|
+
EM.stop if n == n_times
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
assert_equal( n, n_times )
|
53
|
+
end
|
54
|
+
def test_defers
|
55
|
+
10.times {
|
56
|
+
run_em_with_defers {|n,ntimes|
|
57
|
+
assert_equal( n, ntimes )
|
58
|
+
}
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
data/tests/test_epoll.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_epoll.rb
|
1
|
+
# $Id: test_epoll.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -30,7 +30,7 @@
|
|
30
30
|
|
31
31
|
$:.unshift "../lib"
|
32
32
|
require 'eventmachine'
|
33
|
-
|
33
|
+
require 'test/unit'
|
34
34
|
|
35
35
|
|
36
36
|
class TestEpoll < Test::Unit::TestCase
|
@@ -148,12 +148,16 @@ class TestEpoll < Test::Unit::TestCase
|
|
148
148
|
# Pure Ruby also oddly won't let us make that many connections. This test used
|
149
149
|
# to run 100 times. Not sure where that lower connection-limit is coming from in
|
150
150
|
# pure Ruby.
|
151
|
-
|
152
|
-
|
151
|
+
# Let's not sweat the Unix-ness of the filename, since this test can't possibly
|
152
|
+
# work on Windows anyway.
|
153
|
+
#
|
154
|
+
fn = "/tmp/xxx.chain"
|
155
|
+
File.unlink(fn) if File.exist?(fn)
|
156
|
+
EM.start_unix_domain_server fn, TestEchoServer
|
153
157
|
$n = 0
|
154
158
|
$max = 0
|
155
159
|
50.times {
|
156
|
-
EM.connect_unix_domain(
|
160
|
+
EM.connect_unix_domain(fn, TestEchoClient) {$n += 1}
|
157
161
|
}
|
158
162
|
}
|
159
163
|
assert_equal(0, $n)
|
@@ -161,3 +165,4 @@ class TestEpoll < Test::Unit::TestCase
|
|
161
165
|
end
|
162
166
|
|
163
167
|
end
|
168
|
+
|
data/tests/test_errors.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_errors.rb
|
1
|
+
# $Id: test_errors.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -24,8 +24,15 @@
|
|
24
24
|
#
|
25
25
|
#
|
26
26
|
|
27
|
+
|
28
|
+
###### THIS TEST IS NOW OBSOLETE.
|
29
|
+
###### As of 27Dec07, the hookable error handling is obsolete because
|
30
|
+
###### of its performance impact.
|
31
|
+
|
32
|
+
|
27
33
|
$:.unshift "../lib"
|
28
34
|
require 'eventmachine'
|
35
|
+
require 'test/unit'
|
29
36
|
|
30
37
|
class TestErrors < Test::Unit::TestCase
|
31
38
|
|
@@ -42,13 +49,16 @@ class TestErrors < Test::Unit::TestCase
|
|
42
49
|
EM.set_runtime_error_hook
|
43
50
|
end
|
44
51
|
|
52
|
+
def test_a
|
53
|
+
end
|
54
|
+
|
45
55
|
# EM has a default handler for RuntimeErrors that are emitted from
|
46
56
|
# user written code. You can override the handler if you wish, but it's
|
47
57
|
# easier to call #set_runtime_error_hook.
|
48
58
|
# Ordinarily, an error in user code invoked by the reactor aborts the
|
49
59
|
# run.
|
50
60
|
#
|
51
|
-
def
|
61
|
+
def obsolete_test_unhandled_error
|
52
62
|
assert_raise( RuntimeError ) {
|
53
63
|
EM.run {
|
54
64
|
EM.add_timer(0) {raise "AAA"}
|
@@ -57,7 +67,7 @@ class TestErrors < Test::Unit::TestCase
|
|
57
67
|
|
58
68
|
end
|
59
69
|
|
60
|
-
def
|
70
|
+
def obsolete_test_handled_error
|
61
71
|
err = nil
|
62
72
|
EM.run {
|
63
73
|
EM.set_runtime_error_hook {
|
data/tests/test_eventables.rb
CHANGED
data/tests/test_exc.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_exc.rb
|
1
|
+
# $Id: test_exc.rb 668 2008-01-04 23:00:34Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -25,6 +25,7 @@
|
|
25
25
|
|
26
26
|
$:.unshift "../lib"
|
27
27
|
require 'eventmachine'
|
28
|
+
require 'test/unit'
|
28
29
|
|
29
30
|
class TestSomeExceptions < Test::Unit::TestCase
|
30
31
|
|