eventmachine 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/DEFERRABLES +3 -3
- data/PURE_RUBY +77 -0
- data/ext/cmain.cpp +41 -2
- data/ext/ed.cpp +67 -3
- data/ext/ed.h +4 -1
- data/ext/em.cpp +33 -10
- data/ext/em.h +6 -14
- data/ext/eventmachine.h +4 -1
- data/ext/pipe.cpp +21 -3
- data/ext/rubymain.cpp +38 -1
- data/ext/ssl.cpp +9 -3
- data/lib/em/streamer.rb +1 -3
- data/lib/eventmachine.rb +190 -38
- data/lib/eventmachine_version.rb +2 -2
- data/lib/pr_eventmachine.rb +309 -28
- data/lib/protocols/httpcli2.rb +784 -0
- data/lib/protocols/saslauth.rb +121 -0
- data/lib/protocols/smtpclient.rb +41 -10
- data/lib/protocols/smtpserver.rb +30 -1
- data/tests/test_basic.rb +33 -2
- data/tests/test_epoll.rb +9 -3
- data/tests/test_errors.rb +72 -0
- data/tests/test_httpclient2.rb +132 -0
- data/tests/test_pure.rb +127 -0
- data/tests/test_timers.rb +30 -1
- metadata +37 -32
- data/ext/eee +0 -173
- data/lib/svn-commit.tmp +0 -4
data/ext/pipe.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: pipe.cpp
|
3
|
+
$Id: pipe.cpp 585 2007-11-27 14:29:34Z blackhedd $
|
4
4
|
|
5
5
|
File: pipe.cpp
|
6
6
|
Date: 30May07
|
@@ -71,15 +71,32 @@ PipeDescriptor::~PipeDescriptor()
|
|
71
71
|
* Since we want to have a signal processor integrated into the
|
72
72
|
* client-visible API, let's wait until that is done before cleaning
|
73
73
|
* this up.
|
74
|
+
*
|
75
|
+
* Added a very ugly hack to support passing the subprocess's exit
|
76
|
+
* status to the user. It only makes logical sense for user code to access
|
77
|
+
* the subprocess exit status in the unbind callback. But unbind is called
|
78
|
+
* back during the EventableDescriptor destructor. So by that time there's
|
79
|
+
* no way to call back this object through an object binding, because it's
|
80
|
+
* already been cleaned up. We might have added a parameter to the unbind
|
81
|
+
* callback, but that would probably break a huge amount of existing code.
|
82
|
+
* So the hack-solution is to define an instance variable in the EventMachine
|
83
|
+
* object and stick the exit status in there, where it can easily be accessed
|
84
|
+
* with an accessor visible to user code.
|
85
|
+
* User code should ONLY access the exit status from within the unbind callback.
|
86
|
+
* Otherwise there's no guarantee it'll be valid.
|
87
|
+
* This hack won't make it impossible to run multiple EventMachines in a single
|
88
|
+
* process, but it will make it impossible to reliably nest unbind calls
|
89
|
+
* within other unbind calls. (Not sure if that's even possible.)
|
74
90
|
*/
|
75
91
|
|
76
92
|
struct timespec req = {0, 10000000};
|
77
93
|
kill (SubprocessPid, SIGTERM);
|
78
94
|
nanosleep (&req, NULL);
|
79
|
-
|
95
|
+
assert (MyEventMachine);
|
96
|
+
if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) == 0) {
|
80
97
|
kill (SubprocessPid, SIGKILL);
|
81
98
|
nanosleep (&req, NULL);
|
82
|
-
if (waitpid (SubprocessPid,
|
99
|
+
if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) == 0)
|
83
100
|
throw std::runtime_error ("unable to reap subprocess");
|
84
101
|
}
|
85
102
|
}
|
@@ -302,5 +319,6 @@ bool PipeDescriptor::GetSubprocessPid (pid_t *pid)
|
|
302
319
|
return ok;
|
303
320
|
}
|
304
321
|
|
322
|
+
|
305
323
|
#endif // OS_UNIX
|
306
324
|
|
data/ext/rubymain.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: rubymain.cpp
|
3
|
+
$Id: rubymain.cpp 584 2007-11-27 07:27:32Z blackhedd $
|
4
4
|
|
5
5
|
File: rubymain.cpp
|
6
6
|
Date: 06Apr06
|
@@ -181,6 +181,20 @@ static VALUE t_get_subprocess_pid (VALUE self, VALUE signature)
|
|
181
181
|
return Qnil;
|
182
182
|
}
|
183
183
|
|
184
|
+
/***********************
|
185
|
+
t_get_subprocess_status
|
186
|
+
***********************/
|
187
|
+
|
188
|
+
static VALUE t_get_subprocess_status (VALUE self, VALUE signature)
|
189
|
+
{
|
190
|
+
int status;
|
191
|
+
if (evma_get_subprocess_status (StringValuePtr (signature), &status)) {
|
192
|
+
return INT2NUM (status);
|
193
|
+
}
|
194
|
+
|
195
|
+
return Qnil;
|
196
|
+
}
|
197
|
+
|
184
198
|
/*****************************
|
185
199
|
t_get_comm_inactivity_timeout
|
186
200
|
*****************************/
|
@@ -227,6 +241,16 @@ static VALUE t_close_connection (VALUE self, VALUE signature, VALUE after_writin
|
|
227
241
|
return Qnil;
|
228
242
|
}
|
229
243
|
|
244
|
+
/********************************
|
245
|
+
t_report_connection_error_status
|
246
|
+
********************************/
|
247
|
+
|
248
|
+
static VALUE t_report_connection_error_status (VALUE self, VALUE signature)
|
249
|
+
{
|
250
|
+
int b = evma_report_connection_error_status (StringValuePtr (signature));
|
251
|
+
return INT2NUM (b);
|
252
|
+
}
|
253
|
+
|
230
254
|
|
231
255
|
|
232
256
|
/****************
|
@@ -323,6 +347,16 @@ static VALUE t_set_timer_quantum (VALUE self, VALUE interval)
|
|
323
347
|
return Qnil;
|
324
348
|
}
|
325
349
|
|
350
|
+
/********************
|
351
|
+
t_set_max_timer_count
|
352
|
+
********************/
|
353
|
+
|
354
|
+
static VALUE t_set_max_timer_count (VALUE self, VALUE ct)
|
355
|
+
{
|
356
|
+
evma_set_max_timer_count (FIX2INT (ct));
|
357
|
+
return Qnil;
|
358
|
+
}
|
359
|
+
|
326
360
|
/***************
|
327
361
|
t_setuid_string
|
328
362
|
***************/
|
@@ -485,6 +519,7 @@ extern "C" void Init_rubyeventmachine()
|
|
485
519
|
rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3);
|
486
520
|
rb_define_module_function (EmModule, "send_datagram", (VALUE(*)(...))t_send_datagram, 5);
|
487
521
|
rb_define_module_function (EmModule, "close_connection", (VALUE(*)(...))t_close_connection, 2);
|
522
|
+
rb_define_module_function (EmModule, "report_connection_error_status", (VALUE(*)(...))t_report_connection_error_status, 1);
|
488
523
|
rb_define_module_function (EmModule, "connect_server", (VALUE(*)(...))t_connect_server, 2);
|
489
524
|
rb_define_module_function (EmModule, "connect_unix_server", (VALUE(*)(...))t_connect_unix_server, 1);
|
490
525
|
rb_define_module_function (EmModule, "open_udp_socket", (VALUE(*)(...))t_open_udp_socket, 2);
|
@@ -494,6 +529,7 @@ extern "C" void Init_rubyeventmachine()
|
|
494
529
|
rb_define_module_function (EmModule, "signal_loopbreak", (VALUE(*)(...))t_signal_loopbreak, 0);
|
495
530
|
rb_define_module_function (EmModule, "library_type", (VALUE(*)(...))t_library_type, 0);
|
496
531
|
rb_define_module_function (EmModule, "set_timer_quantum", (VALUE(*)(...))t_set_timer_quantum, 1);
|
532
|
+
rb_define_module_function (EmModule, "set_max_timer_count", (VALUE(*)(...))t_set_max_timer_count, 1);
|
497
533
|
rb_define_module_function (EmModule, "setuid_string", (VALUE(*)(...))t_setuid_string, 1);
|
498
534
|
rb_define_module_function (EmModule, "invoke_popen", (VALUE(*)(...))t_invoke_popen, 1);
|
499
535
|
rb_define_module_function (EmModule, "send_file_data", (VALUE(*)(...))t_send_file_data, 2);
|
@@ -503,6 +539,7 @@ extern "C" void Init_rubyeventmachine()
|
|
503
539
|
|
504
540
|
rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1);
|
505
541
|
rb_define_module_function (EmModule, "get_subprocess_pid", (VALUE(*)(...))t_get_subprocess_pid, 1);
|
542
|
+
rb_define_module_function (EmModule, "get_subprocess_status", (VALUE(*)(...))t_get_subprocess_status, 1);
|
506
543
|
rb_define_module_function (EmModule, "get_comm_inactivity_timeout", (VALUE(*)(...))t_get_comm_inactivity_timeout, 1);
|
507
544
|
rb_define_module_function (EmModule, "set_comm_inactivity_timeout", (VALUE(*)(...))t_set_comm_inactivity_timeout, 2);
|
508
545
|
rb_define_module_function (EmModule, "set_rlimit_nofile", (VALUE(*)(...))t_set_rlimit_nofile, 1);
|
data/ext/ssl.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*****************************************************************************
|
2
2
|
|
3
|
-
$Id: ssl.cpp
|
3
|
+
$Id: ssl.cpp 574 2007-11-19 23:36:04Z blackhedd $
|
4
4
|
|
5
5
|
File: ssl.cpp
|
6
6
|
Date: 30Apr06
|
@@ -155,9 +155,15 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
155
155
|
if (is_server) {
|
156
156
|
// The SSL_CTX calls here do NOT allocate memory.
|
157
157
|
int e;
|
158
|
-
|
158
|
+
if (privkeyfile.length() > 0)
|
159
|
+
e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM);
|
160
|
+
else
|
161
|
+
e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey);
|
159
162
|
assert (e > 0);
|
160
|
-
|
163
|
+
if (certchainfile.length() > 0)
|
164
|
+
e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str());
|
165
|
+
else
|
166
|
+
e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
|
161
167
|
assert (e > 0);
|
162
168
|
}
|
163
169
|
|
data/lib/em/streamer.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: streamer.rb
|
1
|
+
# $Id: streamer.rb 599 2007-12-05 14:24:11Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -49,7 +49,6 @@ module EventMachine
|
|
49
49
|
|
50
50
|
def stream_without_mapping filename
|
51
51
|
if @http_chunks
|
52
|
-
#@connection.send_data "#{format("%x",@size)}\r\n"
|
53
52
|
@connection.send_data "#{@size.to_s(16)}\r\n"
|
54
53
|
@connection.send_file_data filename
|
55
54
|
@connection.send_data "\r\n0\r\n\r\n"
|
@@ -79,7 +78,6 @@ module EventMachine
|
|
79
78
|
len = @size - @position
|
80
79
|
len = ChunkSize if (len > ChunkSize)
|
81
80
|
|
82
|
-
#@connection.send_data( "#{format("%x",len)}\r\n" ) if @http_chunks
|
83
81
|
@connection.send_data( "#{len.to_s(16)}\r\n" ) if @http_chunks
|
84
82
|
@connection.send_data( @mapping.get_chunk( @position, len ))
|
85
83
|
@connection.send_data("\r\n") if @http_chunks
|
data/lib/eventmachine.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: eventmachine.rb
|
1
|
+
# $Id: eventmachine.rb 594 2007-12-05 11:41:39Z blackhedd $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -32,6 +32,14 @@
|
|
32
32
|
# till now. The reason I'm disabling it is because the pure-Ruby
|
33
33
|
# code will have problems of its own, and it's not nearly as fast
|
34
34
|
# anyway. Suggested by a problem report from Moshe Litvin. 05Jun07.
|
35
|
+
#
|
36
|
+
# 05Dec07: Re-enabled the pure-ruby mechanism, but without the automatic
|
37
|
+
# fallback feature that tripped up Moshe Litvin. We shouldn't fail over to
|
38
|
+
# the pure Ruby version because it's possible that the user intended to
|
39
|
+
# run the extension but failed to do so because of a compilation or
|
40
|
+
# similar error. So we require either a global variable or an environment
|
41
|
+
# string be set in order to select the pure-Ruby version.
|
42
|
+
#
|
35
43
|
|
36
44
|
=begin
|
37
45
|
$eventmachine_library ||= nil
|
@@ -56,7 +64,11 @@ if RUBY_PLATFORM =~ /java/
|
|
56
64
|
require 'java'
|
57
65
|
require 'jeventmachine'
|
58
66
|
else
|
59
|
-
|
67
|
+
if $eventmachine_library == :pure_ruby or ENV['EVENTMACHINE_LIBRARY'] == "pure_ruby"
|
68
|
+
require 'pr_eventmachine'
|
69
|
+
else
|
70
|
+
require 'rubyeventmachine'
|
71
|
+
end
|
60
72
|
end
|
61
73
|
|
62
74
|
|
@@ -153,17 +165,6 @@ require 'shellwords'
|
|
153
165
|
#
|
154
166
|
#
|
155
167
|
# == Questions and Futures
|
156
|
-
# Encryption: EventMachine needs the capability to run SSL/TLS on any
|
157
|
-
# of its clients and servers. Coming soon.
|
158
|
-
#
|
159
|
-
# <tt>epoll(4):</tt> EventMachine currently is based on the <tt>select(2)</tt>
|
160
|
-
# system call in order to be compatible with the widest variety of platforms,
|
161
|
-
# but it would be interesting to re-base it on <tt>epoll(4).</tt>
|
162
|
-
# While requiring a Linux 2.6 kernel, this might possibly give much better
|
163
|
-
# performance and scalability. EventMachine's C++ antecedents already work
|
164
|
-
# with <tt>kqueue</tt> from the BSD world, but it's not yet clear that this
|
165
|
-
# is worth doing. Depends on how many people ask for it.
|
166
|
-
#
|
167
168
|
# Would it be useful for EventMachine to incorporate the Observer pattern
|
168
169
|
# and make use of the corresponding Ruby <tt>observer</tt> package?
|
169
170
|
# Interesting thought.
|
@@ -483,15 +484,21 @@ module EventMachine
|
|
483
484
|
# }
|
484
485
|
#
|
485
486
|
#
|
486
|
-
def EventMachine::start_server server, port, handler=nil, &block
|
487
|
+
def EventMachine::start_server server, port, handler=nil, *args, &block
|
487
488
|
klass = if (handler and handler.is_a?(Class))
|
488
489
|
handler
|
489
490
|
else
|
490
491
|
Class.new( Connection ) {handler and include handler}
|
491
492
|
end
|
492
493
|
|
494
|
+
arity = klass.instance_method(:initialize).arity
|
495
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
496
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
497
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
498
|
+
end
|
499
|
+
|
493
500
|
s = start_tcp_server server, port
|
494
|
-
@acceptors[s] = [klass,block]
|
501
|
+
@acceptors[s] = [klass,args,block]
|
495
502
|
s
|
496
503
|
end
|
497
504
|
|
@@ -505,15 +512,21 @@ module EventMachine
|
|
505
512
|
EventMachine::stop_tcp_server signature
|
506
513
|
end
|
507
514
|
|
508
|
-
def EventMachine::start_unix_domain_server filename, handler=nil, &block
|
515
|
+
def EventMachine::start_unix_domain_server filename, handler=nil, *args, &block
|
509
516
|
klass = if (handler and handler.is_a?(Class))
|
510
517
|
handler
|
511
518
|
else
|
512
519
|
Class.new( Connection ) {handler and include handler}
|
513
520
|
end
|
514
521
|
|
522
|
+
arity = klass.instance_method(:initialize).arity
|
523
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
524
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
525
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
526
|
+
end
|
527
|
+
|
515
528
|
s = start_unix_server filename
|
516
|
-
@acceptors[s] = [klass,block]
|
529
|
+
@acceptors[s] = [klass,args,block]
|
517
530
|
end
|
518
531
|
|
519
532
|
# EventMachine#connect initiates a TCP connection to a remote
|
@@ -613,16 +626,21 @@ module EventMachine
|
|
613
626
|
# to have them behave differently with respect to post_init
|
614
627
|
# if at all possible.
|
615
628
|
#
|
616
|
-
def EventMachine::connect server, port, handler=nil
|
617
|
-
|
629
|
+
def EventMachine::connect server, port, handler=nil, *args
|
618
630
|
klass = if (handler and handler.is_a?(Class))
|
619
631
|
handler
|
620
632
|
else
|
621
633
|
Class.new( Connection ) {handler and include handler}
|
622
634
|
end
|
623
635
|
|
636
|
+
arity = klass.instance_method(:initialize).arity
|
637
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
638
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
639
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
640
|
+
end
|
641
|
+
|
624
642
|
s = connect_server server, port
|
625
|
-
c = klass.new s
|
643
|
+
c = klass.new s, *args
|
626
644
|
@conns[s] = c
|
627
645
|
block_given? and yield c
|
628
646
|
c
|
@@ -668,15 +686,21 @@ module EventMachine
|
|
668
686
|
# For making connections to Unix-domain sockets.
|
669
687
|
# Eventually this has to get properly documented and unified with the TCP-connect methods.
|
670
688
|
# Note how nearly identical this is to EventMachine#connect
|
671
|
-
def EventMachine::connect_unix_domain socketname, handler=nil
|
689
|
+
def EventMachine::connect_unix_domain socketname, handler=nil, *args
|
672
690
|
klass = if (handler and handler.is_a?(Class))
|
673
691
|
handler
|
674
692
|
else
|
675
693
|
Class.new( Connection ) {handler and include handler}
|
676
694
|
end
|
677
695
|
|
696
|
+
arity = klass.instance_method(:initialize).arity
|
697
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
698
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
699
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
700
|
+
end
|
701
|
+
|
678
702
|
s = connect_unix_server socketname
|
679
|
-
c = klass.new s
|
703
|
+
c = klass.new s, *args
|
680
704
|
@conns[s] = c
|
681
705
|
block_given? and yield c
|
682
706
|
c
|
@@ -746,15 +770,21 @@ module EventMachine
|
|
746
770
|
# Replaced the implementation on 01Oct06. Thanks to Tobias Gustafsson for pointing
|
747
771
|
# out that this originally did not take a class but only a module.
|
748
772
|
#
|
749
|
-
def self::open_datagram_socket address, port, handler=nil
|
773
|
+
def self::open_datagram_socket address, port, handler=nil, *args
|
750
774
|
klass = if (handler and handler.is_a?(Class))
|
751
775
|
handler
|
752
776
|
else
|
753
777
|
Class.new( Connection ) {handler and include handler}
|
754
778
|
end
|
755
779
|
|
780
|
+
arity = klass.instance_method(:initialize).arity
|
781
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
782
|
+
if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
|
783
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
|
784
|
+
end
|
785
|
+
|
756
786
|
s = open_udp_socket address, port
|
757
|
-
c = klass.new s
|
787
|
+
c = klass.new s, *args
|
758
788
|
@conns[s] = c
|
759
789
|
block_given? and yield c
|
760
790
|
c
|
@@ -777,6 +807,14 @@ module EventMachine
|
|
777
807
|
set_timer_quantum mills.to_i
|
778
808
|
end
|
779
809
|
|
810
|
+
# Sets the maximum number of timers and periodic timers that may be outstanding at any
|
811
|
+
# given time. You only need to call #set_max_timers if you need more than the default
|
812
|
+
# number of timers, which on most platforms is 1000.
|
813
|
+
# Call this method before calling EventMachine#run.
|
814
|
+
#
|
815
|
+
def self::set_max_timers ct
|
816
|
+
set_max_timer_count ct
|
817
|
+
end
|
780
818
|
|
781
819
|
#--
|
782
820
|
# The is the responder for the loopback-signalled event.
|
@@ -1007,36 +1045,97 @@ module EventMachine
|
|
1007
1045
|
|
1008
1046
|
private
|
1009
1047
|
def EventMachine::event_callback conn_binding, opcode, data
|
1048
|
+
#
|
1049
|
+
# Added 03Oct07: Any code path that invokes user-written code must
|
1050
|
+
# wrap itself in a begin/rescue for RuntimeErrors, that calls the
|
1051
|
+
# user-overridable class method #handle_runtime_error.
|
1052
|
+
#
|
1010
1053
|
if opcode == ConnectionData
|
1011
1054
|
c = @conns[conn_binding] or raise ConnectionNotBound
|
1012
|
-
|
1055
|
+
begin
|
1056
|
+
c.receive_data data
|
1057
|
+
rescue
|
1058
|
+
EventMachine.handle_runtime_error
|
1059
|
+
end
|
1013
1060
|
elsif opcode == ConnectionUnbound
|
1014
1061
|
if c = @conns.delete( conn_binding )
|
1015
|
-
|
1062
|
+
begin
|
1063
|
+
c.unbind
|
1064
|
+
rescue
|
1065
|
+
EventMachine.handle_runtime_error
|
1066
|
+
end
|
1016
1067
|
elsif c = @acceptors.delete( conn_binding )
|
1017
1068
|
# no-op
|
1018
1069
|
else
|
1019
1070
|
raise ConnectionNotBound
|
1020
1071
|
end
|
1021
1072
|
elsif opcode == ConnectionAccepted
|
1022
|
-
accep,blk = @acceptors[conn_binding]
|
1073
|
+
accep,args,blk = @acceptors[conn_binding]
|
1023
1074
|
raise NoHandlerForAcceptedConnection unless accep
|
1024
|
-
c = accep.new data
|
1075
|
+
c = accep.new data, *args
|
1025
1076
|
@conns[data] = c
|
1026
|
-
|
1077
|
+
begin
|
1078
|
+
blk and blk.call(c)
|
1079
|
+
rescue
|
1080
|
+
EventMachine.handle_runtime_error
|
1081
|
+
end
|
1027
1082
|
c # (needed?)
|
1028
1083
|
elsif opcode == TimerFired
|
1029
1084
|
t = @timers.delete( data ) or raise UnknownTimerFired
|
1030
|
-
|
1085
|
+
begin
|
1086
|
+
t.call
|
1087
|
+
rescue
|
1088
|
+
EventMachine.handle_runtime_error
|
1089
|
+
end
|
1031
1090
|
elsif opcode == ConnectionCompleted
|
1032
1091
|
c = @conns[conn_binding] or raise ConnectionNotBound
|
1033
|
-
|
1092
|
+
begin
|
1093
|
+
c.connection_completed
|
1094
|
+
rescue
|
1095
|
+
EventMachine.handle_runtime_error
|
1096
|
+
end
|
1034
1097
|
elsif opcode == LoopbreakSignalled
|
1098
|
+
begin
|
1035
1099
|
run_deferred_callbacks
|
1100
|
+
rescue
|
1101
|
+
EventMachine.handle_runtime_error
|
1102
|
+
end
|
1036
1103
|
end
|
1037
1104
|
end
|
1038
1105
|
|
1039
1106
|
|
1107
|
+
# Default handler for RuntimeErrors that are raised in user code.
|
1108
|
+
# The default behavior is to re-raise the error, which ends your program.
|
1109
|
+
# To override the default behavior, re-implement this method in your code.
|
1110
|
+
# For example:
|
1111
|
+
#
|
1112
|
+
# module EventMachine
|
1113
|
+
# def self.handle_runtime_error
|
1114
|
+
# $>.puts $!
|
1115
|
+
# end
|
1116
|
+
# end
|
1117
|
+
#
|
1118
|
+
#--
|
1119
|
+
# We need to ensure that any code path which invokes user code rescues RuntimeError
|
1120
|
+
# and calls this method. The obvious place to do that is in #event_callback,
|
1121
|
+
# but, scurrilously, it turns out that we need to be finer grained that that.
|
1122
|
+
# Periodic timers, in particular, wrap their invocations of user code inside
|
1123
|
+
# procs that do other stuff we can't not do, like schedule the next invocation.
|
1124
|
+
# This is a potential non-robustness, since we need to remember to hook in the
|
1125
|
+
# error handler whenever and wherever we change how user code is invoked.
|
1126
|
+
#
|
1127
|
+
def EventMachine::handle_runtime_error
|
1128
|
+
@runtime_error_hook ? @runtime_error_hook.call : raise
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
# Sets a handler for RuntimeErrors that are raised in user code.
|
1132
|
+
# Pass a block with no parameters. You can also call this method without a block,
|
1133
|
+
# which restores the default behavior (see #handle_runtime_error).
|
1134
|
+
#
|
1135
|
+
def EventMachine::set_runtime_error_hook &blk
|
1136
|
+
@runtime_error_hook = blk
|
1137
|
+
end
|
1138
|
+
|
1040
1139
|
# Documentation stub
|
1041
1140
|
#--
|
1042
1141
|
# This is a provisional implementation of a stream-oriented file access object.
|
@@ -1083,14 +1182,33 @@ module EventMachine
|
|
1083
1182
|
# only by user code.
|
1084
1183
|
#
|
1085
1184
|
class Connection
|
1086
|
-
|
1087
1185
|
# EXPERIMENTAL. Added the reconnect methods, which may go away.
|
1088
1186
|
attr_accessor :signature
|
1089
1187
|
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1188
|
+
# Override .new so subclasses don't have to call super and can ignore
|
1189
|
+
# connection-specific arguments
|
1190
|
+
#
|
1191
|
+
def self.new sig, *args #:nodoc:
|
1192
|
+
allocate.instance_eval do
|
1193
|
+
# Call a superclass's #initialize if it has one
|
1194
|
+
initialize *args
|
1195
|
+
|
1196
|
+
# Store signature and run #post_init
|
1197
|
+
@signature = sig
|
1198
|
+
begin
|
1199
|
+
post_init
|
1200
|
+
rescue
|
1201
|
+
EventMachine::handle_runtime_error
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
self
|
1205
|
+
end
|
1206
|
+
end
|
1207
|
+
|
1208
|
+
# Stubbed initialize so legacy superclasses can safely call super
|
1209
|
+
#
|
1210
|
+
def initialize(*args) #:nodoc:
|
1211
|
+
end
|
1094
1212
|
|
1095
1213
|
# EventMachine::Connection#post_init is called by the event loop
|
1096
1214
|
# immediately after the network connection has been established,
|
@@ -1207,6 +1325,17 @@ class Connection
|
|
1207
1325
|
EventMachine::send_data @signature, data, data.length
|
1208
1326
|
end
|
1209
1327
|
|
1328
|
+
# Returns true if the connection is in an error state, false otherwise.
|
1329
|
+
# In general, you can detect the occurrence of communication errors or unexpected
|
1330
|
+
# disconnection by the remote peer by handing the #unbind method. In some cases, however,
|
1331
|
+
# it's useful to check the status of the connection using #error? before attempting to send data.
|
1332
|
+
# This function is synchronous: it will return immediately without blocking.
|
1333
|
+
#
|
1334
|
+
#
|
1335
|
+
def error?
|
1336
|
+
EventMachine::report_connection_error_status(@signature) != 0
|
1337
|
+
end
|
1338
|
+
|
1210
1339
|
# #connection_completed is called by the event loop when a remote TCP connection
|
1211
1340
|
# attempt completes successfully. You can expect to get this notification after calls
|
1212
1341
|
# to EventMachine#connect. Remember that EventMachine makes remote connections
|
@@ -1273,10 +1402,13 @@ class Connection
|
|
1273
1402
|
# but to be really safe, send messages smaller than the Ethernet-packet
|
1274
1403
|
# size (typically about 1400 bytes). Some very restrictive WANs
|
1275
1404
|
# will either drop or truncate packets larger than about 500 bytes.
|
1405
|
+
#--
|
1406
|
+
# Added the Integer wrapper around the port parameter per suggestion by
|
1407
|
+
# Matthieu Riou, after he passed a String and spent hours tearing his hair out.
|
1276
1408
|
#
|
1277
1409
|
def send_datagram data, recipient_address, recipient_port
|
1278
1410
|
data = data.to_s
|
1279
|
-
EventMachine::send_datagram @signature, data, data.length, recipient_address, recipient_port
|
1411
|
+
EventMachine::send_datagram @signature, data, data.length, recipient_address, Integer(recipient_port)
|
1280
1412
|
end
|
1281
1413
|
|
1282
1414
|
|
@@ -1298,6 +1430,13 @@ class Connection
|
|
1298
1430
|
EventMachine::get_subprocess_pid @signature
|
1299
1431
|
end
|
1300
1432
|
|
1433
|
+
# Returns a subprocess exit status. Only useful for #popen. Call it in your
|
1434
|
+
# #unbind handler.
|
1435
|
+
#
|
1436
|
+
def get_status
|
1437
|
+
EventMachine::get_subprocess_status @signature
|
1438
|
+
end
|
1439
|
+
|
1301
1440
|
# comm_inactivity_timeout returns the current value (in seconds) of the inactivity-timeout
|
1302
1441
|
# property of network-connection and datagram-socket objects. A nonzero value
|
1303
1442
|
# indicates that the connection or socket will automatically be closed if no read or write
|
@@ -1373,7 +1512,11 @@ class Connection
|
|
1373
1512
|
EventMachine::add_timer @interval, proc {self.fire}
|
1374
1513
|
end
|
1375
1514
|
def fire
|
1376
|
-
|
1515
|
+
begin
|
1516
|
+
@code.call
|
1517
|
+
rescue
|
1518
|
+
EventMachine::handle_runtime_error
|
1519
|
+
end
|
1377
1520
|
schedule unless @cancelled
|
1378
1521
|
end
|
1379
1522
|
def cancel
|
@@ -1398,6 +1541,10 @@ class Connection
|
|
1398
1541
|
|
1399
1542
|
end
|
1400
1543
|
|
1544
|
+
module Protocols
|
1545
|
+
# In this module, we define standard protocol implementations.
|
1546
|
+
# They get included from separate source files.
|
1547
|
+
end
|
1401
1548
|
|
1402
1549
|
end # module EventMachine
|
1403
1550
|
|
@@ -1405,6 +1552,7 @@ end # module EventMachine
|
|
1405
1552
|
|
1406
1553
|
# Save everyone some typing.
|
1407
1554
|
EM = EventMachine
|
1555
|
+
EM::P = EventMachine::Protocols
|
1408
1556
|
|
1409
1557
|
|
1410
1558
|
# At the bottom of this module, we load up protocol handlers that depend on some
|
@@ -1417,7 +1565,11 @@ require 'protocols/httpclient'
|
|
1417
1565
|
require 'protocols/line_and_text'
|
1418
1566
|
require 'protocols/header_and_content'
|
1419
1567
|
require 'protocols/linetext2'
|
1568
|
+
require 'protocols/httpcli2'
|
1420
1569
|
require 'protocols/stomp'
|
1421
1570
|
require 'protocols/smtpclient'
|
1422
1571
|
require 'protocols/smtpserver'
|
1572
|
+
require 'protocols/saslauth'
|
1573
|
+
|
1574
|
+
|
1423
1575
|
|