eventmachine 0.12.8 → 0.12.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/Rakefile +155 -45
- data/eventmachine.gemspec +4 -5
- data/ext/binder.cpp +13 -14
- data/ext/binder.h +5 -7
- data/ext/cmain.cpp +184 -42
- data/ext/cplusplus.cpp +20 -20
- data/ext/ed.cpp +242 -81
- data/ext/ed.h +39 -22
- data/ext/em.cpp +127 -108
- data/ext/em.h +27 -18
- data/ext/emwin.cpp +3 -3
- data/ext/eventmachine.h +49 -38
- data/ext/eventmachine_cpp.h +4 -4
- data/ext/extconf.rb +28 -13
- data/ext/fastfilereader/extconf.rb +11 -5
- data/ext/project.h +12 -1
- data/ext/rubymain.cpp +222 -103
- data/ext/ssl.cpp +3 -3
- data/ext/ssl.h +2 -2
- data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
- data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
- data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
- data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
- data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
- data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
- data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
- data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
- data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
- data/lib/em/connection.rb +71 -12
- data/lib/em/deferrable.rb +5 -0
- data/lib/em/protocols.rb +1 -0
- data/lib/em/protocols/httpclient2.rb +8 -0
- data/lib/em/protocols/line_and_text.rb +0 -1
- data/lib/em/protocols/linetext2.rb +1 -0
- data/lib/em/protocols/object_protocol.rb +8 -2
- data/lib/em/protocols/smtpclient.rb +42 -16
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/queue.rb +1 -1
- data/lib/em/timers.rb +2 -1
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +125 -169
- data/lib/jeventmachine.rb +124 -9
- data/tasks/{cpp.rake → cpp.rake_example} +0 -0
- data/tests/test_attach.rb +29 -4
- data/tests/test_basic.rb +1 -2
- data/tests/test_connection_count.rb +10 -20
- data/tests/test_epoll.rb +0 -2
- data/tests/test_get_sock_opt.rb +30 -0
- data/tests/test_httpclient2.rb +3 -3
- data/tests/test_inactivity_timeout.rb +21 -1
- data/tests/test_ltp.rb +0 -6
- data/tests/test_next_tick.rb +0 -2
- data/tests/test_pause.rb +70 -0
- data/tests/test_pending_connect_timeout.rb +48 -0
- data/tests/test_ssl_args.rb +16 -5
- data/tests/test_timers.rb +22 -1
- metadata +14 -12
- data/tasks/project.rake +0 -79
- data/tasks/tests.rake +0 -193
@@ -28,7 +28,7 @@
|
|
28
28
|
|
29
29
|
|
30
30
|
|
31
|
-
package com.rubyeventmachine;
|
31
|
+
package com.rubyeventmachine.application;
|
32
32
|
|
33
33
|
//import java.io.*;
|
34
34
|
import java.nio.*;
|
@@ -38,7 +38,7 @@ import java.net.*;
|
|
38
38
|
public class Connection {
|
39
39
|
|
40
40
|
public Application application;
|
41
|
-
public
|
41
|
+
public long signature;
|
42
42
|
|
43
43
|
public void postInit() {}
|
44
44
|
public void connectionCompleted() {}
|
@@ -28,9 +28,9 @@
|
|
28
28
|
|
29
29
|
|
30
30
|
|
31
|
-
package com.rubyeventmachine;
|
31
|
+
package com.rubyeventmachine.application;
|
32
32
|
|
33
|
-
import com.rubyeventmachine.ConnectionFactory;
|
33
|
+
import com.rubyeventmachine.application.ConnectionFactory;
|
34
34
|
|
35
35
|
public class DefaultConnectionFactory implements ConnectionFactory {
|
36
36
|
|
@@ -35,11 +35,13 @@ import org.junit.AfterClass;
|
|
35
35
|
import org.junit.Before;
|
36
36
|
import org.junit.BeforeClass;
|
37
37
|
import org.junit.Test;
|
38
|
+
import java.net.*;
|
38
39
|
import java.io.*;
|
39
40
|
import java.nio.*;
|
40
41
|
import java.nio.channels.*;
|
41
42
|
|
42
43
|
import com.rubyeventmachine.*;
|
44
|
+
import com.rubyeventmachine.application.*;
|
43
45
|
|
44
46
|
public class ConnectTest {
|
45
47
|
|
@@ -110,12 +112,12 @@ public class ConnectTest {
|
|
110
112
|
Application a = new Application();
|
111
113
|
a.addTimer(0, new Timer() {
|
112
114
|
public void fire() {
|
113
|
-
application.startServer(new InetSocketAddress("localhost", 20000), new
|
115
|
+
application.startServer(new InetSocketAddress("localhost", 20000), new DefaultConnectionFactory());
|
114
116
|
}
|
115
117
|
});
|
116
118
|
a.addTimer(500, new Timer() {
|
117
119
|
public void fire() {
|
118
|
-
application.bindConnect("localhost", 33333, "localhost", 20000);
|
120
|
+
application.bindConnect("localhost", 33333, "localhost", 20000, new Connection());
|
119
121
|
}
|
120
122
|
});
|
121
123
|
|
data/lib/em/connection.rb
CHANGED
@@ -34,12 +34,14 @@ module EventMachine
|
|
34
34
|
#
|
35
35
|
def self.new(sig, *args) #:nodoc:
|
36
36
|
allocate.instance_eval do
|
37
|
+
# Store signature
|
38
|
+
@signature = sig
|
39
|
+
associate_callback_target sig
|
40
|
+
|
37
41
|
# Call a superclass's #initialize if it has one
|
38
42
|
initialize(*args)
|
39
43
|
|
40
|
-
#
|
41
|
-
@signature = sig
|
42
|
-
associate_callback_target sig
|
44
|
+
# post initialize callback
|
43
45
|
post_init
|
44
46
|
|
45
47
|
self
|
@@ -51,9 +53,9 @@ module EventMachine
|
|
51
53
|
def initialize(*args) #:nodoc:
|
52
54
|
end
|
53
55
|
|
54
|
-
def associate_callback_target(sig) #:nodoc:
|
55
|
-
|
56
|
-
end
|
56
|
+
# def associate_callback_target(sig) #:nodoc:
|
57
|
+
# # no-op for the time being, to match similar no-op in rubymain.cpp
|
58
|
+
# end
|
57
59
|
|
58
60
|
# EventMachine::Connection#post_init is called by the event loop
|
59
61
|
# immediately after the network connection has been established,
|
@@ -136,8 +138,8 @@ module EventMachine
|
|
136
138
|
# a low-level proxy relay for all data inbound for this connection, to the connection given
|
137
139
|
# as the argument. This is essentially just a helper method for enable_proxy.
|
138
140
|
# See EventMachine::enable_proxy documentation for details.
|
139
|
-
def proxy_incoming_to(conn)
|
140
|
-
EventMachine::enable_proxy(self, conn)
|
141
|
+
def proxy_incoming_to(conn,bufsize=0)
|
142
|
+
EventMachine::enable_proxy(self, conn, bufsize)
|
141
143
|
end
|
142
144
|
|
143
145
|
# Helper method for EventMachine::disable_proxy(self)
|
@@ -173,6 +175,10 @@ module EventMachine
|
|
173
175
|
EventMachine::detach_fd @signature
|
174
176
|
end
|
175
177
|
|
178
|
+
def get_sock_opt level, option
|
179
|
+
EventMachine::get_sock_opt @signature, level, option
|
180
|
+
end
|
181
|
+
|
176
182
|
# EventMachine::Connection#close_connection_after_writing is a variant of close_connection.
|
177
183
|
# All of the descriptive comments given for close_connection also apply to
|
178
184
|
# close_connection_after_writing, <i>with one exception:</i> If the connection has
|
@@ -451,7 +457,7 @@ module EventMachine
|
|
451
457
|
|
452
458
|
# Alias for #set_comm_inactivity_timeout.
|
453
459
|
def comm_inactivity_timeout= value
|
454
|
-
self.
|
460
|
+
self.set_comm_inactivity_timeout value
|
455
461
|
end
|
456
462
|
|
457
463
|
# comm_inactivity_timeout= allows you to set the inactivity-timeout property for
|
@@ -464,10 +470,26 @@ module EventMachine
|
|
464
470
|
EventMachine::set_comm_inactivity_timeout @signature, value.to_f
|
465
471
|
end
|
466
472
|
|
473
|
+
# pending_connect_timeout is the duration after which a TCP connection in the connecting
|
474
|
+
# state will fail. It is important to distinguish this value from comm_inactivity_timeout,
|
475
|
+
# which looks at how long since data was passed on an already established connection.
|
476
|
+
# The value is a float in seconds.
|
477
|
+
def pending_connect_timeout
|
478
|
+
EventMachine::get_pending_connect_timeout @signature
|
479
|
+
end
|
480
|
+
|
481
|
+
# Alias for #set_pending_connect_timeout.
|
482
|
+
def pending_connect_timeout= value
|
483
|
+
self.set_pending_connect_timeout value
|
484
|
+
end
|
485
|
+
|
486
|
+
# set_pending_connect_timeout sets the duration after which a TCP connection in a
|
487
|
+
# connecting state will fail. Takes a float in seconds.
|
488
|
+
def set_pending_connect_timeout value
|
489
|
+
EventMachine::set_pending_connect_timeout @signature, value.to_f
|
490
|
+
end
|
491
|
+
|
467
492
|
# Reconnect to a given host/port with the current EventMachine::Connection instance
|
468
|
-
#--
|
469
|
-
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO REMAIN SUPPORTED.
|
470
|
-
# (03Nov06)
|
471
493
|
def reconnect server, port
|
472
494
|
EventMachine::reconnect server, port, self
|
473
495
|
end
|
@@ -501,5 +523,42 @@ module EventMachine
|
|
501
523
|
def stream_file_data filename, args={}
|
502
524
|
EventMachine::FileStreamer.new( self, filename, args )
|
503
525
|
end
|
526
|
+
|
527
|
+
# Enable notify_readable callbacks on this connection. Only possible if the connection was created
|
528
|
+
# using EM.attach and had notify_readable/notify_writable defined on the handler.
|
529
|
+
def notify_readable= mode
|
530
|
+
EventMachine::set_notify_readable @signature, mode
|
531
|
+
end
|
532
|
+
|
533
|
+
# Returns true if the connection is being watched for readability.
|
534
|
+
def notify_readable?
|
535
|
+
EventMachine::is_notify_readable @signature
|
536
|
+
end
|
537
|
+
|
538
|
+
# Enable notify_writable callbacks on this connection. Only possible if the connection was created
|
539
|
+
# using EM.attach and had notify_readable/notify_writable defined on the handler.
|
540
|
+
def notify_writable= mode
|
541
|
+
EventMachine::set_notify_writable @signature, mode
|
542
|
+
end
|
543
|
+
|
544
|
+
# Returns true if the connection is being watched for writability.
|
545
|
+
def notify_writable?
|
546
|
+
EventMachine::is_notify_writable @signature
|
547
|
+
end
|
548
|
+
|
549
|
+
# Pause a connection so that #send_data and #receive_data events are not fired until #resume is called.
|
550
|
+
def pause
|
551
|
+
EventMachine::pause_connection @signature
|
552
|
+
end
|
553
|
+
|
554
|
+
# Resume a connection's #send_data and #receive_data events.
|
555
|
+
def resume
|
556
|
+
EventMachine::resume_connection @signature
|
557
|
+
end
|
558
|
+
|
559
|
+
# True if the connect was paused using #pause.
|
560
|
+
def paused?
|
561
|
+
EventMachine::connection_paused? @signature
|
562
|
+
end
|
504
563
|
end
|
505
564
|
end
|
data/lib/em/deferrable.rb
CHANGED
@@ -42,6 +42,7 @@ module EventMachine
|
|
42
42
|
#
|
43
43
|
def callback &block
|
44
44
|
return unless block
|
45
|
+
@deferred_status ||= :unknown
|
45
46
|
if @deferred_status == :succeeded
|
46
47
|
block.call(*@deferred_args)
|
47
48
|
elsif @deferred_status != :failed
|
@@ -59,6 +60,7 @@ module EventMachine
|
|
59
60
|
#
|
60
61
|
def errback &block
|
61
62
|
return unless block
|
63
|
+
@deferred_status ||= :unknown
|
62
64
|
if @deferred_status == :failed
|
63
65
|
block.call(*@deferred_args)
|
64
66
|
elsif @deferred_status != :succeeded
|
@@ -121,6 +123,8 @@ module EventMachine
|
|
121
123
|
#
|
122
124
|
def set_deferred_status status, *args
|
123
125
|
cancel_timeout
|
126
|
+
@errbacks ||= nil
|
127
|
+
@callbacks ||= nil
|
124
128
|
@deferred_status = status
|
125
129
|
@deferred_args = args
|
126
130
|
case @deferred_status
|
@@ -155,6 +159,7 @@ module EventMachine
|
|
155
159
|
# Cancels an outstanding timeout if any. Undoes the action of #timeout.
|
156
160
|
#
|
157
161
|
def cancel_timeout
|
162
|
+
@deferred_timeout ||= nil
|
158
163
|
if @deferred_timeout
|
159
164
|
@deferred_timeout.cancel
|
160
165
|
@deferred_timeout = nil
|
data/lib/em/protocols.rb
CHANGED
@@ -40,6 +40,12 @@ module EventMachine
|
|
40
40
|
# }
|
41
41
|
class HttpClient2 < Connection
|
42
42
|
include LineText2
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
@authorization = nil
|
46
|
+
@closed = nil
|
47
|
+
@requests = nil
|
48
|
+
end
|
43
49
|
|
44
50
|
class Request # :nodoc:
|
45
51
|
include Deferrable
|
@@ -57,6 +63,8 @@ module EventMachine
|
|
57
63
|
@header_lines = []
|
58
64
|
@headers = {}
|
59
65
|
@blanks = 0
|
66
|
+
@chunk_trailer = nil
|
67
|
+
@chunking = nil
|
60
68
|
end
|
61
69
|
|
62
70
|
def send_request
|
@@ -132,6 +132,7 @@ module EventMachine
|
|
132
132
|
# when in sized text mode. User overrides of #receive_binary_data need to
|
133
133
|
# be aware that they may get a short buffer.
|
134
134
|
def unbind
|
135
|
+
@lt2_mode ||= nil
|
135
136
|
if @lt2_mode == :text and @lt2_textpos > 0
|
136
137
|
receive_binary_data @lt2_textbuffer.join
|
137
138
|
end
|
@@ -11,13 +11,19 @@ module EventMachine
|
|
11
11
|
# end
|
12
12
|
#
|
13
13
|
module ObjectProtocol
|
14
|
+
# By default returns Marshal, override to return JSON or YAML, or any
|
15
|
+
# other serializer/deserializer responding to #dump and #load.
|
16
|
+
def serializer
|
17
|
+
Marshal
|
18
|
+
end
|
19
|
+
|
14
20
|
def receive_data data # :nodoc:
|
15
21
|
(@buf ||= '') << data
|
16
22
|
|
17
23
|
while @buf.size >= 4
|
18
24
|
if @buf.size >= 4+(size=@buf.unpack('N').first)
|
19
25
|
@buf.slice!(0,4)
|
20
|
-
receive_object
|
26
|
+
receive_object serializer.load(@buf.slice!(0,size))
|
21
27
|
else
|
22
28
|
break
|
23
29
|
end
|
@@ -31,7 +37,7 @@ module EventMachine
|
|
31
37
|
|
32
38
|
# Sends a ruby object over the network
|
33
39
|
def send_object obj
|
34
|
-
data =
|
40
|
+
data = serializer.dump(obj)
|
35
41
|
send_data [data.respond_to?(:bytesize) ? data.bytesize : data.size, data].pack('Na*')
|
36
42
|
end
|
37
43
|
end
|
@@ -30,26 +30,49 @@ module EventMachine
|
|
30
30
|
|
31
31
|
# Simple SMTP client
|
32
32
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
33
|
+
# email = EM::Protocols::SmtpClient.send(
|
34
|
+
# :domain=>"example.com",
|
35
|
+
# :host=>'localhost',
|
36
|
+
# :port=>25, # optional, defaults 25
|
37
|
+
# :starttls=>true, # use ssl
|
38
|
+
# :from=>"sender@example.com",
|
39
|
+
# :to=> ["to_1@example.com", "to_2@example.com"],
|
40
|
+
# :header=> {"Subject" => "This is a subject line"},
|
41
|
+
# :body=> "This is the body of the email"
|
42
|
+
# )
|
43
|
+
# email.callback{
|
44
|
+
# puts 'Email sent!'
|
45
|
+
# }
|
46
|
+
# email.errback{ |e|
|
47
|
+
# puts 'Email failed!'
|
48
|
+
# }
|
49
|
+
#
|
50
|
+
# Sending generated emails (using mailfactory)
|
51
|
+
#
|
52
|
+
# mail = MailFactory.new
|
53
|
+
# mail.to = 'someone@site.co'
|
54
|
+
# mail.from = 'me@site.com'
|
55
|
+
# mail.subject = 'hi!'
|
56
|
+
# mail.text = 'hello world'
|
57
|
+
# mail.html = '<h1>hello world</h1>'
|
58
|
+
#
|
59
|
+
# email = EM::P::SmtpClient.send(
|
60
|
+
# :domain=>'site.com',
|
61
|
+
# :from=>mail.from,
|
62
|
+
# :to=>mail.to,
|
63
|
+
# :content=>"#{mail.to_s}\r\n.\r\n"
|
64
|
+
# )
|
49
65
|
#
|
50
66
|
class SmtpClient < Connection
|
51
67
|
include EventMachine::Deferrable
|
52
68
|
include EventMachine::Protocols::LineText2
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@succeeded = nil
|
72
|
+
@responder = nil
|
73
|
+
@code = nil
|
74
|
+
@msg = nil
|
75
|
+
end
|
53
76
|
|
54
77
|
# :host => required String
|
55
78
|
# a string containing the IP address or host name of the SMTP server to connect to.
|
@@ -95,6 +118,9 @@ module EventMachine
|
|
95
118
|
# correct line-breaks to text data. I think the :body parameter should remain as it is, and we
|
96
119
|
# should add a :content parameter that contains autoconversions and/or conversion parameters.
|
97
120
|
# Then we can check if either :body or :content is present and do the right thing.
|
121
|
+
# :content => Optional array or string
|
122
|
+
# Alternative to providing header and body, an array or string of raw data which MUST be in
|
123
|
+
# correct SMTP body format, including a trailing dot line
|
98
124
|
# :verbose => Optional.
|
99
125
|
# If true, will cause a lot of information (including the server-side of the
|
100
126
|
# conversation) to be dumped to $>.
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module Protocols
|
3
|
+
# Basic SOCKS v4 client implementation
|
4
|
+
#
|
5
|
+
# Use as you would any regular connection:
|
6
|
+
#
|
7
|
+
# class MyConn < EM::P::Socks4
|
8
|
+
# def post_init
|
9
|
+
# send_data("sup")
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# def receive_data(data)
|
13
|
+
# send_data("you said: #{data}")
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# EM.connect socks_host, socks_port, MyConn, host, port
|
18
|
+
#
|
19
|
+
class Socks4 < Connection
|
20
|
+
def initialize(host, port)
|
21
|
+
@host = Socket.gethostbyname(host).last
|
22
|
+
@port = port
|
23
|
+
@socks_error_code = nil
|
24
|
+
@buffer = ''
|
25
|
+
setup_methods
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup_methods
|
29
|
+
class << self
|
30
|
+
def post_init; socks_post_init; end
|
31
|
+
def receive_data(*a); socks_receive_data(*a); end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def restore_methods
|
36
|
+
class << self
|
37
|
+
remove_method :post_init
|
38
|
+
remove_method :receive_data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def socks_post_init
|
43
|
+
header = [4, 1, @port, @host, 0].flatten.pack("CCnA4C")
|
44
|
+
send_data(header)
|
45
|
+
end
|
46
|
+
|
47
|
+
def socks_receive_data(data)
|
48
|
+
@buffer << data
|
49
|
+
return if @buffer.size < 8
|
50
|
+
|
51
|
+
header_resp = @buffer.slice! 0, 8
|
52
|
+
_, r = header_resp.unpack("cc")
|
53
|
+
if r != 90
|
54
|
+
@socks_error_code = r
|
55
|
+
close_connection
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
restore_methods
|
60
|
+
|
61
|
+
post_init
|
62
|
+
receive_data(@buffer) unless @buffer.empty?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|