eventmachine 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: pipe.cpp 494 2007-08-15 06:23:09Z blackhedd $
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
- if (waitpid (SubprocessPid, NULL, WNOHANG) == 0) {
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, NULL, WNOHANG) == 0)
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
 
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: rubymain.cpp 502 2007-08-24 09:29:53Z blackhedd $
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);
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: ssl.cpp 498 2007-08-15 14:03:32Z blackhedd $
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
- e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey);
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
- e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
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
 
@@ -1,4 +1,4 @@
1
- # $Id: streamer.rb 476 2007-07-27 03:32:51Z blackhedd $
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
@@ -1,4 +1,4 @@
1
- # $Id: eventmachine.rb 521 2007-09-04 18:22:07Z blackhedd $
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
- require 'rubyeventmachine'
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
- c.receive_data data
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
- c.unbind
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
- blk and blk.call(c)
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
- t.call
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
- c.connection_completed
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
- def initialize sig #:nodoc:
1091
- @signature = sig
1092
- post_init
1093
- end
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
- @code.call
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