eventmachine 1.0.0.beta.2-x86-mswin32-60 → 1.0.0.beta.3-x86-mswin32-60
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/.yardopts +3 -0
- data/Gemfile +1 -0
- data/eventmachine.gemspec +1 -3
- data/ext/cmain.cpp +4 -4
- data/ext/ed.cpp +13 -16
- data/ext/ed.h +9 -10
- data/ext/em.cpp +14 -24
- data/ext/eventmachine.h +2 -2
- data/ext/extconf.rb +1 -1
- data/ext/rubymain.cpp +8 -6
- data/lib/em/connection.rb +3 -1
- data/lib/em/pure_ruby.rb +17 -17
- data/lib/em/resolver.rb +186 -0
- data/lib/em/spawnable.rb +3 -7
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +6 -4
- data/lib/jeventmachine.rb +1 -1
- data/tasks/package.rake +4 -1
- data/tasks/test.rake +1 -0
- data/tests/em_test_helper.rb +55 -0
- data/tests/test_attach.rb +46 -56
- data/tests/test_basic.rb +74 -96
- data/tests/test_channel.rb +2 -4
- data/tests/test_connection_count.rb +1 -3
- data/tests/test_defer.rb +13 -44
- data/tests/test_deferrable.rb +19 -19
- data/tests/test_epoll.rb +25 -55
- data/tests/test_error_handler.rb +10 -7
- data/tests/test_exc.rb +6 -33
- data/tests/test_file_watch.rb +51 -35
- data/tests/test_futures.rb +9 -37
- data/tests/test_get_sock_opt.rb +27 -20
- data/tests/test_handler_check.rb +1 -3
- data/tests/test_hc.rb +24 -59
- data/tests/test_httpclient.rb +27 -64
- data/tests/test_httpclient2.rb +1 -29
- data/tests/test_inactivity_timeout.rb +44 -40
- data/tests/test_kb.rb +26 -52
- data/tests/test_ltp.rb +23 -67
- data/tests/test_ltp2.rb +1 -30
- data/tests/test_next_tick.rb +1 -30
- data/tests/test_object_protocol.rb +8 -9
- data/tests/test_pause.rb +45 -37
- data/tests/test_pending_connect_timeout.rb +42 -38
- data/tests/test_process_watch.rb +1 -3
- data/tests/test_processes.rb +92 -110
- data/tests/test_proxy_connection.rb +128 -104
- data/tests/test_pure.rb +29 -75
- data/tests/test_queue.rb +2 -4
- data/tests/test_resolver.rb +55 -0
- data/tests/test_running.rb +1 -29
- data/tests/test_sasl.rb +7 -32
- data/tests/test_send_file.rb +162 -196
- data/tests/test_servers.rb +13 -56
- data/tests/test_smtpclient.rb +1 -29
- data/tests/test_smtpserver.rb +1 -29
- data/tests/test_spawn.rb +2 -31
- data/tests/test_ssl_args.rb +9 -10
- data/tests/test_ssl_methods.rb +1 -3
- data/tests/test_ssl_verify.rb +63 -63
- data/tests/test_tick_loop.rb +1 -1
- data/tests/test_timers.rb +52 -89
- data/tests/test_ud.rb +1 -29
- metadata +20 -10
- data/setup.rb +0 -1585
- data/tests/test_errors.rb +0 -82
- data/tests/testem.rb +0 -31
data/lib/em/resolver.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module DNS
|
3
|
+
class Resolver
|
4
|
+
|
5
|
+
def self.resolve(hostname)
|
6
|
+
Request.new(socket, hostname)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.socket
|
10
|
+
if !@socket || (@socket && @socket.error?)
|
11
|
+
@socket = Socket.open
|
12
|
+
|
13
|
+
@hosts = {}
|
14
|
+
IO.readlines('/etc/hosts').each do |line|
|
15
|
+
next if line =~ /^#/
|
16
|
+
addr, host = line.split(/\s+/)
|
17
|
+
|
18
|
+
if @hosts[host]
|
19
|
+
@hosts[host] << addr
|
20
|
+
else
|
21
|
+
@hosts[host] = [addr]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
@socket
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.nameservers=(ns)
|
30
|
+
@nameservers = ns
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.nameservers
|
34
|
+
if !@nameservers
|
35
|
+
@nameservers = []
|
36
|
+
IO.readlines('/etc/resolv.conf').each do |line|
|
37
|
+
if line =~ /^nameserver (.+)$/
|
38
|
+
@nameservers << $1.split(/\s+/).first
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@nameservers
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.nameserver
|
46
|
+
nameservers.shuffle.first
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.hosts
|
50
|
+
@hosts
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class RequestIdAlreadyUsed < RuntimeError; end
|
55
|
+
|
56
|
+
class Socket < EventMachine::Connection
|
57
|
+
def self.open
|
58
|
+
EventMachine::open_datagram_socket('0.0.0.0', 0, self)
|
59
|
+
end
|
60
|
+
|
61
|
+
def post_init
|
62
|
+
@requests = {}
|
63
|
+
EM.add_periodic_timer(0.1, &method(:tick))
|
64
|
+
end
|
65
|
+
|
66
|
+
def unbind
|
67
|
+
end
|
68
|
+
|
69
|
+
def tick
|
70
|
+
@requests.each do |id,req|
|
71
|
+
req.tick
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def register_request(id, req)
|
76
|
+
if @requests.has_key?(id)
|
77
|
+
raise RequestIdAlreadyUsed
|
78
|
+
else
|
79
|
+
@requests[id] = req
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def send_packet(pkt)
|
84
|
+
send_datagram(pkt, nameserver, 53)
|
85
|
+
end
|
86
|
+
|
87
|
+
def nameserver=(ns)
|
88
|
+
@nameserver = ns
|
89
|
+
end
|
90
|
+
|
91
|
+
def nameserver
|
92
|
+
@nameserver || Resolver.nameserver
|
93
|
+
end
|
94
|
+
|
95
|
+
# Decodes the packet, looks for the request and passes the
|
96
|
+
# response over to the requester
|
97
|
+
def receive_data(data)
|
98
|
+
msg = nil
|
99
|
+
begin
|
100
|
+
msg = Resolv::DNS::Message.decode data
|
101
|
+
rescue
|
102
|
+
else
|
103
|
+
req = @requests[msg.id]
|
104
|
+
if req
|
105
|
+
@requests.delete(msg.id)
|
106
|
+
req.receive_answer(msg)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Request
|
113
|
+
include Deferrable
|
114
|
+
attr_accessor :retry_interval, :max_tries
|
115
|
+
|
116
|
+
def initialize(socket, hostname)
|
117
|
+
@socket = socket
|
118
|
+
@hostname = hostname
|
119
|
+
@tries = 0
|
120
|
+
@last_send = Time.at(0)
|
121
|
+
@retry_interval = 3
|
122
|
+
@max_tries = 5
|
123
|
+
|
124
|
+
if addrs = Resolver.hosts[hostname]
|
125
|
+
succeed addrs
|
126
|
+
else
|
127
|
+
EM.next_tick { tick }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def tick
|
132
|
+
# Break early if nothing to do
|
133
|
+
return if @last_send + @retry_interval > Time.now
|
134
|
+
if @tries < @max_tries
|
135
|
+
send
|
136
|
+
else
|
137
|
+
fail 'retries exceeded'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def receive_answer(msg)
|
142
|
+
addrs = []
|
143
|
+
msg.each_answer do |name,ttl,data|
|
144
|
+
if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
|
145
|
+
data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
|
146
|
+
addrs << data.address.to_s
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if addrs.empty?
|
151
|
+
fail "rcode=#{msg.rcode}"
|
152
|
+
else
|
153
|
+
succeed addrs
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def send
|
160
|
+
@tries += 1
|
161
|
+
@last_send = Time.now
|
162
|
+
@socket.send_packet(packet.encode)
|
163
|
+
end
|
164
|
+
|
165
|
+
def id
|
166
|
+
begin
|
167
|
+
@id = rand(65535)
|
168
|
+
@socket.register_request(@id, self)
|
169
|
+
rescue RequestIdAlreadyUsed
|
170
|
+
retry
|
171
|
+
end unless defined?(@id)
|
172
|
+
|
173
|
+
@id
|
174
|
+
end
|
175
|
+
|
176
|
+
def packet
|
177
|
+
msg = Resolv::DNS::Message.new
|
178
|
+
msg.id = id
|
179
|
+
msg.rd = 1
|
180
|
+
msg.add_question @hostname, Resolv::DNS::Resource::IN::A
|
181
|
+
msg
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/em/spawnable.rb
CHANGED
@@ -45,15 +45,11 @@ module EventMachine
|
|
45
45
|
end
|
46
46
|
alias_method :resume, :notify
|
47
47
|
alias_method :run, :notify # for formulations like (EM.spawn {xxx}).run
|
48
|
-
#attr_accessor :receiver
|
49
48
|
|
50
|
-
#--
|
51
|
-
# I know I'm missing something stupid, but the inside of class << s
|
52
|
-
# can't see locally-bound values. It can see globals, though.
|
53
49
|
def set_receiver blk
|
54
|
-
|
55
|
-
|
56
|
-
define_method :call,
|
50
|
+
(class << self ; self ; end).class_eval do
|
51
|
+
remove_method :call if method_defined? :call
|
52
|
+
define_method :call, blk
|
57
53
|
end
|
58
54
|
end
|
59
55
|
|
data/lib/em/version.rb
CHANGED
data/lib/eventmachine.rb
CHANGED
@@ -12,7 +12,7 @@ else
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
require
|
15
|
+
require 'em/version'
|
16
16
|
require 'em/deferrable'
|
17
17
|
require 'em/future'
|
18
18
|
require 'em/streamer'
|
@@ -29,9 +29,11 @@ require 'em/channel'
|
|
29
29
|
require 'em/file_watch'
|
30
30
|
require 'em/process_watch'
|
31
31
|
require 'em/tick_loop'
|
32
|
+
require 'em/resolver'
|
32
33
|
|
33
34
|
require 'shellwords'
|
34
35
|
require 'thread'
|
36
|
+
require 'resolv'
|
35
37
|
|
36
38
|
# == Introduction
|
37
39
|
# EventMachine provides a fast, lightweight framework for implementing
|
@@ -122,7 +124,7 @@ require 'thread'
|
|
122
124
|
# Interesting thought.
|
123
125
|
#
|
124
126
|
module EventMachine
|
125
|
-
class <<self
|
127
|
+
class << self
|
126
128
|
# Exposed to allow joining on the thread, when run in a multithreaded
|
127
129
|
# environment. Performing other actions on the thread has undefined
|
128
130
|
# semantics.
|
@@ -1373,7 +1375,7 @@ module EventMachine
|
|
1373
1375
|
@wrapped_exception = $!
|
1374
1376
|
EM.stop
|
1375
1377
|
else
|
1376
|
-
raise ConnectionNotBound, "
|
1378
|
+
raise ConnectionNotBound, "received ConnectionUnbound for an unknown signature: #{conn_binding}"
|
1377
1379
|
end
|
1378
1380
|
end
|
1379
1381
|
elsif opcode == ConnectionAccepted
|
@@ -1545,4 +1547,4 @@ end # module EventMachine
|
|
1545
1547
|
|
1546
1548
|
# Save everyone some typing.
|
1547
1549
|
EM = EventMachine
|
1548
|
-
EM::P = EventMachine::Protocols
|
1550
|
+
EM::P = EventMachine::Protocols
|
data/lib/jeventmachine.rb
CHANGED
data/tasks/package.rake
CHANGED
@@ -24,10 +24,12 @@ else
|
|
24
24
|
|
25
25
|
Rake::ExtensionTask.new("rubyeventmachine", GEMSPEC) do |ext|
|
26
26
|
ext.ext_dir = 'ext'
|
27
|
+
ext.source_pattern = '*.{h,c,cpp}'
|
27
28
|
setup_cross_compilation(ext)
|
28
29
|
end
|
29
30
|
Rake::ExtensionTask.new("fastfilereaderext", GEMSPEC) do |ext|
|
30
31
|
ext.ext_dir = 'ext/fastfilereader'
|
32
|
+
ext.source_pattern = '*.{h,c,cpp}'
|
31
33
|
setup_cross_compilation(ext)
|
32
34
|
end
|
33
35
|
end
|
@@ -47,7 +49,8 @@ end
|
|
47
49
|
|
48
50
|
task :cross_cxx do
|
49
51
|
ENV['CROSS_COMPILING'] = 'yes'
|
50
|
-
|
52
|
+
require 'rake/extensioncompiler'
|
53
|
+
ENV['CXX'] = "#{Rake::ExtensionCompiler.mingw_host}-g++"
|
51
54
|
end
|
52
55
|
|
53
56
|
if Rake::Task.task_defined?(:cross)
|
data/tasks/test.rake
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'lib/eventmachine'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
Test::Unit::TestCase.class_eval do
|
7
|
+
class EMTestTimeout < StandardError ; end
|
8
|
+
|
9
|
+
def setup_timeout(timeout = TIMEOUT_INTERVAL)
|
10
|
+
EM.schedule {
|
11
|
+
EM.add_timer(timeout) {
|
12
|
+
raise EMTestTimeout, "Test was cancelled after #{timeout} seconds."
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def port_in_use?(port, host="127.0.0.1")
|
18
|
+
s = TCPSocket.new(host, port)
|
19
|
+
s.close
|
20
|
+
s
|
21
|
+
rescue Errno::ECONNREFUSED
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def next_port
|
26
|
+
@@port ||= 9000
|
27
|
+
begin
|
28
|
+
@@port += 1
|
29
|
+
end while port_in_use?(@@port)
|
30
|
+
|
31
|
+
@@port
|
32
|
+
end
|
33
|
+
|
34
|
+
def exception_class
|
35
|
+
jruby? ? NativeException : RuntimeError
|
36
|
+
end
|
37
|
+
|
38
|
+
module PlatformHelper
|
39
|
+
# http://blog.emptyway.com/2009/11/03/proper-way-to-detect-windows-platform-in-ruby/
|
40
|
+
def windows?
|
41
|
+
Config::CONFIG['host_os'] =~ /mswin|mingw/
|
42
|
+
end
|
43
|
+
|
44
|
+
# http://stackoverflow.com/questions/1342535/how-can-i-tell-if-im-running-from-jruby-vs-ruby/1685970#1685970
|
45
|
+
def jruby?
|
46
|
+
defined? JRUBY_VERSION
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
include PlatformHelper
|
51
|
+
extend PlatformHelper
|
52
|
+
|
53
|
+
# Tests run significantly slower on windows. YMMV
|
54
|
+
TIMEOUT_INTERVAL = windows? ? 1 : 0.25
|
55
|
+
end
|
data/tests/test_attach.rb
CHANGED
@@ -1,31 +1,7 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#----------------------------------------------------------------------------
|
4
|
-
#
|
5
|
-
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
6
|
-
# Gmail: blackhedd
|
7
|
-
#
|
8
|
-
# This program is free software; you can redistribute it and/or modify
|
9
|
-
# it under the terms of either: 1) the GNU General Public License
|
10
|
-
# as published by the Free Software Foundation; either version 2 of the
|
11
|
-
# License, or (at your option) any later version; or 2) Ruby's License.
|
12
|
-
#
|
13
|
-
# See the file COPYING for complete licensing information.
|
14
|
-
#
|
15
|
-
#---------------------------------------------------------------------------
|
16
|
-
#
|
17
|
-
|
18
|
-
$:.unshift "../lib"
|
19
|
-
require 'eventmachine'
|
1
|
+
require 'em_test_helper'
|
20
2
|
require 'socket'
|
21
|
-
require 'test/unit'
|
22
|
-
|
23
3
|
|
24
4
|
class TestAttach < Test::Unit::TestCase
|
25
|
-
|
26
|
-
Host = "127.0.0.1"
|
27
|
-
Port = 9550
|
28
|
-
|
29
5
|
class EchoServer < EM::Connection
|
30
6
|
def receive_data data
|
31
7
|
send_data data
|
@@ -33,47 +9,51 @@ class TestAttach < Test::Unit::TestCase
|
|
33
9
|
end
|
34
10
|
|
35
11
|
class EchoClient < EM::Connection
|
36
|
-
def initialize
|
12
|
+
def initialize socket
|
37
13
|
self.notify_readable = true
|
38
|
-
|
14
|
+
@socket = socket
|
15
|
+
@socket.write("abc\n")
|
39
16
|
end
|
40
17
|
|
41
18
|
def notify_readable
|
42
|
-
$read =
|
19
|
+
$read = @socket.readline
|
43
20
|
$fd = detach
|
44
21
|
end
|
45
22
|
|
46
23
|
def unbind
|
47
24
|
EM.next_tick do
|
48
|
-
|
49
|
-
EM.add_timer(0.1){ EM.stop }
|
25
|
+
@socket.write("def\n")
|
26
|
+
EM.add_timer(0.1) { EM.stop }
|
50
27
|
end
|
51
28
|
end
|
52
29
|
end
|
53
30
|
|
54
31
|
def setup
|
55
|
-
|
32
|
+
@port = next_port
|
33
|
+
$read, $r, $w, $fd = nil
|
56
34
|
end
|
57
35
|
|
58
36
|
def teardown
|
59
|
-
[$
|
37
|
+
[$r, $w].each do |io|
|
60
38
|
io.close rescue nil
|
61
39
|
end
|
62
40
|
end
|
63
41
|
|
64
42
|
def test_attach
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
EM.
|
43
|
+
socket = nil
|
44
|
+
|
45
|
+
EM.run {
|
46
|
+
EM.start_server "127.0.0.1", @port, EchoServer
|
47
|
+
socket = TCPSocket.new "127.0.0.1", @port
|
48
|
+
EM.watch socket, EchoClient, socket
|
69
49
|
}
|
70
50
|
|
71
51
|
assert_equal $read, "abc\n"
|
72
|
-
unless
|
73
|
-
assert_equal $fd,
|
52
|
+
unless jruby? # jruby filenos are not real
|
53
|
+
assert_equal $fd, socket.fileno
|
74
54
|
end
|
75
|
-
assert_equal false,
|
76
|
-
assert_equal
|
55
|
+
assert_equal false, socket.closed?
|
56
|
+
assert_equal socket.readline, "def\n"
|
77
57
|
end
|
78
58
|
|
79
59
|
module PipeWatch
|
@@ -96,6 +76,8 @@ class TestAttach < Test::Unit::TestCase
|
|
96
76
|
end
|
97
77
|
|
98
78
|
def test_set_readable
|
79
|
+
before, after = nil
|
80
|
+
|
99
81
|
EM.run{
|
100
82
|
$r, $w = IO.pipe
|
101
83
|
c = EM.watch $r, PipeWatch do |con|
|
@@ -103,34 +85,42 @@ class TestAttach < Test::Unit::TestCase
|
|
103
85
|
end
|
104
86
|
|
105
87
|
EM.next_tick{
|
106
|
-
|
88
|
+
before = c.notify_readable?
|
107
89
|
c.notify_readable = true
|
108
|
-
|
90
|
+
after = c.notify_readable?
|
109
91
|
}
|
110
92
|
|
111
93
|
$w.write("jkl\n")
|
112
94
|
}
|
113
95
|
|
114
|
-
assert
|
115
|
-
assert
|
96
|
+
assert !before
|
97
|
+
assert after
|
116
98
|
assert_equal $read, "jkl\n"
|
117
99
|
end
|
118
100
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
101
|
+
def test_read_write_pipe
|
102
|
+
result = nil
|
103
|
+
|
104
|
+
pipe_reader = Module.new do
|
105
|
+
define_method :receive_data do |data|
|
106
|
+
result = data
|
107
|
+
EM.stop
|
108
|
+
end
|
123
109
|
end
|
124
|
-
end
|
125
110
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
EM.attach
|
130
|
-
writer = EM.attach(
|
111
|
+
r,w = IO.pipe
|
112
|
+
|
113
|
+
EM.run {
|
114
|
+
EM.attach r, pipe_reader
|
115
|
+
writer = EM.attach(w)
|
131
116
|
writer.send_data 'ghi'
|
117
|
+
|
118
|
+
# XXX: Process will hang in Windows without this line
|
119
|
+
writer.close_connection_after_writing
|
132
120
|
}
|
133
121
|
|
134
|
-
assert_equal
|
122
|
+
assert_equal "ghi", result
|
123
|
+
ensure
|
124
|
+
[r,w].each {|io| io.close rescue nil }
|
135
125
|
end
|
136
|
-
end
|
126
|
+
end
|