eventmachine 0.12.8 → 0.12.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +2 -1
  2. data/Rakefile +155 -45
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +13 -14
  5. data/ext/binder.h +5 -7
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +20 -20
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +4 -4
  15. data/ext/extconf.rb +28 -13
  16. data/ext/fastfilereader/extconf.rb +11 -5
  17. data/ext/project.h +12 -1
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +3 -3
  20. data/ext/ssl.h +2 -2
  21. data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +5 -0
  38. data/lib/em/protocols.rb +1 -0
  39. data/lib/em/protocols/httpclient2.rb +8 -0
  40. data/lib/em/protocols/line_and_text.rb +0 -1
  41. data/lib/em/protocols/linetext2.rb +1 -0
  42. data/lib/em/protocols/object_protocol.rb +8 -2
  43. data/lib/em/protocols/smtpclient.rb +42 -16
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +1 -1
  46. data/lib/em/timers.rb +2 -1
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +124 -9
  50. data/tasks/{cpp.rake → cpp.rake_example} +0 -0
  51. data/tests/test_attach.rb +29 -4
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +10 -20
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +0 -6
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +16 -5
  63. data/tests/test_timers.rb +22 -1
  64. metadata +14 -12
  65. data/tasks/project.rake +0 -79
  66. 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 String signature;
41
+ public long signature;
42
42
 
43
43
  public void postInit() {}
44
44
  public void connectionCompleted() {}
@@ -28,7 +28,7 @@
28
28
 
29
29
 
30
30
 
31
- package com.rubyeventmachine;
31
+ package com.rubyeventmachine.application;
32
32
 
33
33
  //import com.rubyeventmachine.*;
34
34
 
@@ -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
 
@@ -27,7 +27,7 @@
27
27
  */
28
28
 
29
29
 
30
- package com.rubyeventmachine;
30
+ package com.rubyeventmachine.application;
31
31
 
32
32
  public class PeriodicTimer extends Timer {
33
33
 
@@ -27,7 +27,7 @@
27
27
  */
28
28
 
29
29
 
30
- package com.rubyeventmachine;
30
+ package com.rubyeventmachine.application;
31
31
 
32
32
  public class Timer {
33
33
  /**
@@ -42,6 +42,7 @@ import java.io.*;
42
42
  import java.nio.*;
43
43
 
44
44
  import com.rubyeventmachine.*;
45
+ import com.rubyeventmachine.application.*;
45
46
 
46
47
  public class ApplicationTest {
47
48
 
@@ -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 Server());
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
 
@@ -1,6 +1,6 @@
1
1
  package com.rubyeventmachine.tests;
2
2
 
3
- import com.rubyeventmachine.*;
3
+ import com.rubyeventmachine.application.*;
4
4
  import java.net.*;
5
5
  import java.nio.*;
6
6
 
@@ -31,6 +31,7 @@ package com.rubyeventmachine.tests;
31
31
 
32
32
 
33
33
  import com.rubyeventmachine.*;
34
+ import com.rubyeventmachine.application.*;
34
35
  import java.net.*;
35
36
  import org.junit.After;
36
37
  import org.junit.AfterClass;
@@ -30,6 +30,7 @@
30
30
  package com.rubyeventmachine.tests;
31
31
 
32
32
  import com.rubyeventmachine.*;
33
+ import com.rubyeventmachine.application.*;
33
34
  import java.io.*;
34
35
 
35
36
  import org.junit.Assert;
@@ -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
- # Store signature and run #post_init
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
- # no-op for the time being, to match similar no-op in rubymain.cpp
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.send :set_comm_inactivity_timeout, value
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
@@ -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
@@ -31,5 +31,6 @@ module EventMachine
31
31
  autoload :Memcache, 'em/protocols/memcache'
32
32
  autoload :Postgres3, 'em/protocols/postgres3'
33
33
  autoload :ObjectProtocol, 'em/protocols/object_protocol'
34
+ autoload :Socks4, 'em/protocols/socks4'
34
35
  end
35
36
  end
@@ -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
@@ -23,7 +23,6 @@
23
23
  #
24
24
  #
25
25
  #
26
- require File.dirname(__FILE__) + '/../buftok'
27
26
 
28
27
  module EventMachine
29
28
  module Protocols
@@ -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 Marshal.load(@buf.slice!(0,size))
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 = Marshal.dump(obj)
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
- # 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
- # }
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