eventmachine 0.12.4 → 0.12.6

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.
Files changed (51) hide show
  1. data/.gitignore +13 -0
  2. data/Rakefile +66 -3
  3. data/docs/ChangeLog +38 -10
  4. data/eventmachine.gemspec +32 -0
  5. data/ext/cmain.cpp +45 -3
  6. data/ext/cplusplus.cpp +21 -0
  7. data/ext/ed.cpp +34 -1
  8. data/ext/ed.h +12 -0
  9. data/ext/em.cpp +23 -3
  10. data/ext/em.h +6 -2
  11. data/ext/eventmachine.h +9 -1
  12. data/ext/eventmachine_cpp.h +1 -0
  13. data/ext/extconf.rb +8 -29
  14. data/ext/fastfilereader/extconf.rb +50 -134
  15. data/ext/fastfilereader/mapper.cpp +12 -0
  16. data/ext/fastfilereader/mapper.h +1 -1
  17. data/ext/kb.cpp +0 -286
  18. data/ext/pipe.cpp +30 -13
  19. data/ext/rubymain.cpp +127 -12
  20. data/ext/ssl.cpp +15 -0
  21. data/ext/ssl.h +4 -0
  22. data/java/.classpath +8 -0
  23. data/java/.project +17 -0
  24. data/lib/em/processes.rb +45 -0
  25. data/lib/eventmachine.rb +260 -102
  26. data/lib/eventmachine_version.rb +1 -1
  27. data/lib/pr_eventmachine.rb +1 -1
  28. data/lib/protocols/httpcli2.rb +10 -1
  29. data/lib/protocols/httpclient.rb +2 -2
  30. data/lib/protocols/memcache.rb +293 -0
  31. data/lib/protocols/smtpserver.rb +1 -1
  32. data/setup.rb +1585 -0
  33. data/tasks/tests.rake +1 -0
  34. data/tests/test_attach.rb +19 -2
  35. data/tests/test_basic.rb +2 -2
  36. data/tests/test_connection_count.rb +45 -0
  37. data/tests/test_error_handler.rb +35 -0
  38. data/tests/test_errors.rb +3 -3
  39. data/tests/test_exc.rb +2 -2
  40. data/tests/test_handler_check.rb +37 -0
  41. data/tests/test_httpclient2.rb +1 -1
  42. data/tests/test_kb.rb +2 -2
  43. data/tests/test_next_tick.rb +7 -0
  44. data/tests/test_processes.rb +39 -0
  45. data/tests/test_pure.rb +2 -2
  46. data/tests/test_send_file.rb +1 -1
  47. data/tests/test_ssl_args.rb +3 -3
  48. data/tests/test_ssl_methods.rb +50 -0
  49. data/tests/test_timers.rb +3 -1
  50. data/web/whatis +7 -0
  51. metadata +88 -84
data/ext/kb.cpp CHANGED
@@ -80,289 +80,3 @@ void KeyboardDescriptor::Read()
80
80
  if (EventCallback)
81
81
  (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, &c, 1);
82
82
  }
83
-
84
-
85
-
86
-
87
- #if 0
88
- /******************************
89
- PipeDescriptor::PipeDescriptor
90
- ******************************/
91
-
92
- PipeDescriptor::PipeDescriptor (int fd, pid_t subpid, EventMachine_t *parent_em):
93
- EventableDescriptor (fd, parent_em),
94
- bReadAttemptedAfterClose (false),
95
- LastIo (gCurrentLoopTime),
96
- InactivityTimeout (0),
97
- OutboundDataSize (0),
98
- SubprocessPid (subpid)
99
- {
100
- #ifdef HAVE_EPOLL
101
- EpollEvent.events = EPOLLIN;
102
- #endif
103
- }
104
-
105
-
106
- /*******************************
107
- PipeDescriptor::~PipeDescriptor
108
- *******************************/
109
-
110
- PipeDescriptor::~PipeDescriptor()
111
- {
112
- // Run down any stranded outbound data.
113
- for (size_t i=0; i < OutboundPages.size(); i++)
114
- OutboundPages[i].Free();
115
-
116
- /* As a virtual destructor, we come here before the base-class
117
- * destructor that closes our file-descriptor.
118
- * We have to make sure the subprocess goes down (if it's not
119
- * already down) and we have to reap the zombie.
120
- *
121
- * This implementation is PROVISIONAL and will surely be improved.
122
- * The intention here is that we never block, hence the highly
123
- * undesirable sleeps. But if we can't reap the subprocess even
124
- * after sending it SIGKILL, then something is wrong and we
125
- * throw a fatal exception, which is also not something we should
126
- * be doing.
127
- *
128
- * Eventually the right thing to do will be to have the reactor
129
- * core respond to SIGCHLD by chaining a handler on top of the
130
- * one Ruby may have installed, and dealing with a list of dead
131
- * children that are pending cleanup.
132
- *
133
- * Since we want to have a signal processor integrated into the
134
- * client-visible API, let's wait until that is done before cleaning
135
- * this up.
136
- */
137
-
138
- struct timespec req = {0, 10000000};
139
- kill (SubprocessPid, SIGTERM);
140
- nanosleep (&req, NULL);
141
- if (waitpid (SubprocessPid, NULL, WNOHANG) == 0) {
142
- kill (SubprocessPid, SIGKILL);
143
- nanosleep (&req, NULL);
144
- if (waitpid (SubprocessPid, NULL, WNOHANG) == 0)
145
- throw std::runtime_error ("unable to reap subprocess");
146
- }
147
- }
148
-
149
-
150
-
151
- /********************
152
- PipeDescriptor::Read
153
- ********************/
154
-
155
- void PipeDescriptor::Read()
156
- {
157
- int sd = GetSocket();
158
- if (sd == INVALID_SOCKET) {
159
- assert (!bReadAttemptedAfterClose);
160
- bReadAttemptedAfterClose = true;
161
- return;
162
- }
163
-
164
- LastIo = gCurrentLoopTime;
165
-
166
- int total_bytes_read = 0;
167
- char readbuffer [16 * 1024];
168
-
169
- for (int i=0; i < 10; i++) {
170
- // Don't read just one buffer and then move on. This is faster
171
- // if there is a lot of incoming.
172
- // But don't read indefinitely. Give other sockets a chance to run.
173
- // NOTICE, we're reading one less than the buffer size.
174
- // That's so we can put a guard byte at the end of what we send
175
- // to user code.
176
- // Use read instead of recv, which on Linux gives a "socket operation
177
- // on nonsocket" error.
178
-
179
-
180
- int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
181
- //cerr << "<R:" << r << ">";
182
-
183
- if (r > 0) {
184
- total_bytes_read += r;
185
- LastRead = gCurrentLoopTime;
186
-
187
- // Add a null-terminator at the the end of the buffer
188
- // that we will send to the callback.
189
- // DO NOT EVER CHANGE THIS. We want to explicitly allow users
190
- // to be able to depend on this behavior, so they will have
191
- // the option to do some things faster. Additionally it's
192
- // a security guard against buffer overflows.
193
- readbuffer [r] = 0;
194
- if (EventCallback)
195
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, readbuffer, r);
196
- }
197
- else if (r == 0) {
198
- break;
199
- }
200
- else {
201
- // Basically a would-block, meaning we've read everything there is to read.
202
- break;
203
- }
204
-
205
- }
206
-
207
-
208
- if (total_bytes_read == 0) {
209
- // If we read no data on a socket that selected readable,
210
- // it generally means the other end closed the connection gracefully.
211
- ScheduleClose (false);
212
- //bCloseNow = true;
213
- }
214
-
215
- }
216
-
217
- /*********************
218
- PipeDescriptor::Write
219
- *********************/
220
-
221
- void PipeDescriptor::Write()
222
- {
223
- int sd = GetSocket();
224
- assert (sd != INVALID_SOCKET);
225
-
226
- LastIo = gCurrentLoopTime;
227
- char output_buffer [16 * 1024];
228
- size_t nbytes = 0;
229
-
230
- while ((OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
231
- OutboundPage *op = &(OutboundPages[0]);
232
- if ((nbytes + op->Length - op->Offset) < sizeof (output_buffer)) {
233
- memcpy (output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset);
234
- nbytes += (op->Length - op->Offset);
235
- op->Free();
236
- OutboundPages.pop_front();
237
- }
238
- else {
239
- int len = sizeof(output_buffer) - nbytes;
240
- memcpy (output_buffer + nbytes, op->Buffer + op->Offset, len);
241
- op->Offset += len;
242
- nbytes += len;
243
- }
244
- }
245
-
246
- // We should never have gotten here if there were no data to write,
247
- // so assert that as a sanity check.
248
- // Don't bother to make sure nbytes is less than output_buffer because
249
- // if it were we probably would have crashed already.
250
- assert (nbytes > 0);
251
-
252
- assert (GetSocket() != INVALID_SOCKET);
253
- int bytes_written = write (GetSocket(), output_buffer, nbytes);
254
-
255
- if (bytes_written > 0) {
256
- OutboundDataSize -= bytes_written;
257
- if ((size_t)bytes_written < nbytes) {
258
- int len = nbytes - bytes_written;
259
- char *buffer = (char*) malloc (len + 1);
260
- if (!buffer)
261
- throw std::runtime_error ("bad alloc throwing back data");
262
- memcpy (buffer, output_buffer + bytes_written, len);
263
- buffer [len] = 0;
264
- OutboundPages.push_front (OutboundPage (buffer, len));
265
- }
266
- #ifdef HAVE_EPOLL
267
- EpollEvent.events = (EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0));
268
- assert (MyEventMachine);
269
- MyEventMachine->Modify (this);
270
- #endif
271
- }
272
- else {
273
- #ifdef OS_UNIX
274
- if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK) && (errno != EINTR))
275
- #endif
276
- #ifdef OS_WIN32
277
- if ((errno != WSAEINPROGRESS) && (errno != WSAEWOULDBLOCK))
278
- #endif
279
- Close();
280
- }
281
- }
282
-
283
-
284
- /*************************
285
- PipeDescriptor::Heartbeat
286
- *************************/
287
-
288
- void PipeDescriptor::Heartbeat()
289
- {
290
- // If an inactivity timeout is defined, then check for it.
291
- if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout))
292
- ScheduleClose (false);
293
- //bCloseNow = true;
294
- }
295
-
296
-
297
- /*****************************
298
- PipeDescriptor::SelectForRead
299
- *****************************/
300
-
301
- bool PipeDescriptor::SelectForRead()
302
- {
303
- /* Pipe descriptors, being local by definition, don't have
304
- * a pending state, so this is simpler than for the
305
- * ConnectionDescriptor object.
306
- */
307
- return true;
308
- }
309
-
310
- /******************************
311
- PipeDescriptor::SelectForWrite
312
- ******************************/
313
-
314
- bool PipeDescriptor::SelectForWrite()
315
- {
316
- /* Pipe descriptors, being local by definition, don't have
317
- * a pending state, so this is simpler than for the
318
- * ConnectionDescriptor object.
319
- */
320
- return (GetOutboundDataSize() > 0);
321
- }
322
-
323
-
324
-
325
-
326
- /********************************
327
- PipeDescriptor::SendOutboundData
328
- ********************************/
329
-
330
- int PipeDescriptor::SendOutboundData (const char *data, int length)
331
- {
332
- //if (bCloseNow || bCloseAfterWriting)
333
- if (IsCloseScheduled())
334
- return 0;
335
-
336
- if (!data && (length > 0))
337
- throw std::runtime_error ("bad outbound data");
338
- char *buffer = (char *) malloc (length + 1);
339
- if (!buffer)
340
- throw std::runtime_error ("no allocation for outbound data");
341
- memcpy (buffer, data, length);
342
- buffer [length] = 0;
343
- OutboundPages.push_back (OutboundPage (buffer, length));
344
- OutboundDataSize += length;
345
- #ifdef HAVE_EPOLL
346
- EpollEvent.events = (EPOLLIN | EPOLLOUT);
347
- assert (MyEventMachine);
348
- MyEventMachine->Modify (this);
349
- #endif
350
- return length;
351
- }
352
-
353
- /********************************
354
- PipeDescriptor::GetSubprocessPid
355
- ********************************/
356
-
357
- bool PipeDescriptor::GetSubprocessPid (pid_t *pid)
358
- {
359
- bool ok = false;
360
- if (pid && (SubprocessPid > 0)) {
361
- *pid = SubprocessPid;
362
- ok = true;
363
- }
364
- return ok;
365
- }
366
-
367
- #endif
368
-
@@ -94,21 +94,38 @@ PipeDescriptor::~PipeDescriptor()
94
94
 
95
95
  assert (MyEventMachine);
96
96
 
97
- // check if the process is already dead
98
- if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) == 0) {
99
- kill (SubprocessPid, SIGTERM);
100
- // wait 0.25s for process to die
101
- struct timespec req = {0, 250000000};
97
+ /* Another hack to make the SubprocessPid available to get_subprocess_status */
98
+ MyEventMachine->SubprocessPid = SubprocessPid;
99
+
100
+ /* 01Mar09: Updated to use a small nanosleep in a loop. When nanosleep is interrupted by SIGCHLD,
101
+ * it resumes the system call after processing the signal (resulting in unnecessary latency).
102
+ * Calling nanosleep in a loop avoids this problem.
103
+ */
104
+ struct timespec req = {0, 50000000}; // 0.05s
105
+ int n;
106
+
107
+ // wait 0.25s for the process to die
108
+ for (n=0; n<5; n++) {
109
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
102
110
  nanosleep (&req, NULL);
103
- if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) == 0) {
104
- kill (SubprocessPid, SIGKILL);
105
- // wait 0.5s for process to die
106
- struct timespec req = {0, 500000000};
107
- nanosleep (&req, NULL);
108
- if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) == 0)
109
- throw std::runtime_error ("unable to reap subprocess");
110
- }
111
111
  }
112
+
113
+ // send SIGTERM and wait another 0.5s
114
+ kill (SubprocessPid, SIGTERM);
115
+ for (n=0; n<10; n++) {
116
+ nanosleep (&req, NULL);
117
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
118
+ }
119
+
120
+ // send SIGKILL and wait another 1s
121
+ kill (SubprocessPid, SIGKILL);
122
+ for (n=0; n<20; n++) {
123
+ nanosleep (&req, NULL);
124
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
125
+ }
126
+
127
+ // still not dead, give up!
128
+ throw std::runtime_error ("unable to reap subprocess");
112
129
  }
113
130
 
114
131
 
@@ -30,43 +30,61 @@ Statics
30
30
  static VALUE EmModule;
31
31
  static VALUE EmConnection;
32
32
 
33
+ static VALUE EM_eUnknownTimerFired;
34
+ static VALUE EM_eConnectionNotBound;
35
+
33
36
  static VALUE Intern_at_signature;
34
37
  static VALUE Intern_at_timers;
35
38
  static VALUE Intern_at_conns;
39
+ static VALUE Intern_at_error_handler;
36
40
  static VALUE Intern_event_callback;
37
41
  static VALUE Intern_run_deferred_callbacks;
38
42
  static VALUE Intern_delete;
39
43
  static VALUE Intern_call;
40
44
  static VALUE Intern_receive_data;
41
-
45
+ static VALUE Intern_ssl_handshake_completed;
42
46
  static VALUE Intern_notify_readable;
43
47
  static VALUE Intern_notify_writable;
44
48
 
49
+ static VALUE rb_cProcStatus;
50
+
51
+ struct em_event {
52
+ const char *a1;
53
+ int a2;
54
+ const char *a3;
55
+ int a4;
56
+ };
57
+
45
58
  /****************
46
59
  t_event_callback
47
60
  ****************/
48
61
 
49
- static void event_callback (const char *a1, int a2, const char *a3, int a4)
62
+ static void event_callback (struct em_event* e)
50
63
  {
64
+ const char *a1 = e->a1;
65
+ int a2 = e->a2;
66
+ const char *a3 = e->a3;
67
+ int a4 = e->a4;
68
+
51
69
  if (a2 == EM_CONNECTION_READ) {
52
70
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
53
71
  VALUE q = rb_hash_aref (t, rb_str_new2(a1));
54
72
  if (q == Qnil)
55
- rb_raise (rb_eRuntimeError, "no connection");
73
+ rb_raise (EM_eConnectionNotBound, "received %d bytes of data for unknown signature: %s", a4, a1);
56
74
  rb_funcall (q, Intern_receive_data, 1, rb_str_new (a3, a4));
57
75
  }
58
76
  else if (a2 == EM_CONNECTION_NOTIFY_READABLE) {
59
77
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
60
78
  VALUE q = rb_hash_aref (t, rb_str_new2(a1));
61
79
  if (q == Qnil)
62
- rb_raise (rb_eRuntimeError, "no connection");
80
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
63
81
  rb_funcall (q, Intern_notify_readable, 0);
64
82
  }
65
83
  else if (a2 == EM_CONNECTION_NOTIFY_WRITABLE) {
66
84
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
67
85
  VALUE q = rb_hash_aref (t, rb_str_new2(a1));
68
86
  if (q == Qnil)
69
- rb_raise (rb_eRuntimeError, "no connection");
87
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
70
88
  rb_funcall (q, Intern_notify_writable, 0);
71
89
  }
72
90
  else if (a2 == EM_LOOPBREAK_SIGNAL) {
@@ -76,14 +94,47 @@ static void event_callback (const char *a1, int a2, const char *a3, int a4)
76
94
  VALUE t = rb_ivar_get (EmModule, Intern_at_timers);
77
95
  VALUE q = rb_funcall (t, Intern_delete, 1, rb_str_new(a3, a4));
78
96
  if (q == Qnil)
79
- rb_raise (rb_eRuntimeError, "no timer");
97
+ rb_raise (EM_eUnknownTimerFired, "no such timer: %s", a1);
80
98
  rb_funcall (q, Intern_call, 0);
81
99
  }
100
+ else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) {
101
+ VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
102
+ VALUE q = rb_hash_aref (t, rb_str_new2(a1));
103
+ if (q == Qnil)
104
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
105
+ rb_funcall (q, Intern_ssl_handshake_completed, 0);
106
+ }
82
107
  else
83
108
  rb_funcall (EmModule, Intern_event_callback, 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
84
109
  }
85
110
 
111
+ /*******************
112
+ event_error_handler
113
+ *******************/
114
+
115
+ static void event_error_handler(VALUE unused, VALUE err)
116
+ {
117
+ VALUE error_handler = rb_ivar_get(EmModule, Intern_at_error_handler);
118
+ rb_funcall (error_handler, Intern_call, 1, err);
119
+ }
120
+
121
+ /**********************
122
+ event_callback_wrapper
123
+ **********************/
86
124
 
125
+ static void event_callback_wrapper (const char *a1, int a2, const char *a3, int a4)
126
+ {
127
+ struct em_event e;
128
+ e.a1 = a1;
129
+ e.a2 = a2;
130
+ e.a3 = a3;
131
+ e.a4 = a4;
132
+
133
+ if (!rb_ivar_defined(EmModule, Intern_at_error_handler))
134
+ event_callback(&e);
135
+ else
136
+ rb_rescue((VALUE (*)(ANYARGS))event_callback, (VALUE)&e, (VALUE (*)(ANYARGS))event_error_handler, Qnil);
137
+ }
87
138
 
88
139
  /**************************
89
140
  t_initialize_event_machine
@@ -91,7 +142,7 @@ t_initialize_event_machine
91
142
 
92
143
  static VALUE t_initialize_event_machine (VALUE self)
93
144
  {
94
- evma_initialize_library (event_callback);
145
+ evma_initialize_library (event_callback_wrapper);
95
146
  return Qnil;
96
147
  }
97
148
 
@@ -194,6 +245,34 @@ static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VA
194
245
  return Qnil;
195
246
  }
196
247
 
248
+ /***********
249
+ t_get_peer_cert
250
+ ***********/
251
+
252
+ static VALUE t_get_peer_cert (VALUE self, VALUE signature)
253
+ {
254
+ VALUE ret = Qnil;
255
+
256
+ #ifdef WITH_SSL
257
+ X509 *cert = NULL;
258
+ BUF_MEM *buf;
259
+ BIO *out;
260
+
261
+ cert = evma_get_peer_cert (StringValuePtr (signature));
262
+
263
+ if (cert != NULL) {
264
+ out = BIO_new(BIO_s_mem());
265
+ PEM_write_bio_X509(out, cert);
266
+ BIO_get_mem_ptr(out, &buf);
267
+ ret = rb_str_new(buf->data, buf->length);
268
+ X509_free(cert);
269
+ BUF_MEM_free(buf);
270
+ }
271
+ #endif
272
+
273
+ return ret;
274
+ }
275
+
197
276
  /**************
198
277
  t_get_peername
199
278
  **************/
@@ -242,12 +321,29 @@ t_get_subprocess_status
242
321
 
243
322
  static VALUE t_get_subprocess_status (VALUE self, VALUE signature)
244
323
  {
324
+ VALUE proc_status = Qnil;
325
+
245
326
  int status;
327
+ pid_t pid;
328
+
246
329
  if (evma_get_subprocess_status (StringValuePtr (signature), &status)) {
247
- return INT2NUM (status);
330
+ if (evma_get_subprocess_pid (StringValuePtr (signature), &pid)) {
331
+ proc_status = rb_obj_alloc(rb_cProcStatus);
332
+ rb_iv_set(proc_status, "status", INT2FIX(status));
333
+ rb_iv_set(proc_status, "pid", INT2FIX(pid));
334
+ }
248
335
  }
249
336
 
250
- return Qnil;
337
+ return proc_status;
338
+ }
339
+
340
+ /**********************
341
+ t_get_connection_count
342
+ **********************/
343
+
344
+ static VALUE t_get_connection_count (VALUE self)
345
+ {
346
+ return INT2NUM(evma_get_connection_count());
251
347
  }
252
348
 
253
349
  /*****************************
@@ -423,6 +519,15 @@ static VALUE t_set_timer_quantum (VALUE self, VALUE interval)
423
519
  return Qnil;
424
520
  }
425
521
 
522
+ /********************
523
+ t_get_max_timer_count
524
+ ********************/
525
+
526
+ static VALUE t_get_max_timer_count (VALUE self)
527
+ {
528
+ return INT2FIX (evma_get_max_timer_count());
529
+ }
530
+
426
531
  /********************
427
532
  t_set_max_timer_count
428
533
  ********************/
@@ -640,17 +745,22 @@ Init_rubyeventmachine
640
745
 
641
746
  extern "C" void Init_rubyeventmachine()
642
747
  {
748
+ // Lookup Process::Status for get_subprocess_status
749
+ VALUE rb_mProcess = rb_const_get(rb_cObject, rb_intern("Process"));
750
+ rb_cProcStatus = rb_const_get(rb_mProcess, rb_intern("Status"));
751
+
643
752
  // Tuck away some symbol values so we don't have to look 'em up every time we need 'em.
644
753
  Intern_at_signature = rb_intern ("@signature");
645
754
  Intern_at_timers = rb_intern ("@timers");
646
755
  Intern_at_conns = rb_intern ("@conns");
756
+ Intern_at_error_handler = rb_intern("@error_handler");
647
757
 
648
758
  Intern_event_callback = rb_intern ("event_callback");
649
759
  Intern_run_deferred_callbacks = rb_intern ("run_deferred_callbacks");
650
760
  Intern_delete = rb_intern ("delete");
651
761
  Intern_call = rb_intern ("call");
652
762
  Intern_receive_data = rb_intern ("receive_data");
653
-
763
+ Intern_ssl_handshake_completed = rb_intern ("ssl_handshake_completed");
654
764
  Intern_notify_readable = rb_intern ("notify_readable");
655
765
  Intern_notify_writable = rb_intern ("notify_writable");
656
766
 
@@ -660,9 +770,9 @@ extern "C" void Init_rubyeventmachine()
660
770
  EmModule = rb_define_module ("EventMachine");
661
771
  EmConnection = rb_define_class_under (EmModule, "Connection", rb_cObject);
662
772
 
663
- rb_define_class_under (EmModule, "ConnectionNotBound", rb_eException);
664
773
  rb_define_class_under (EmModule, "NoHandlerForAcceptedConnection", rb_eException);
665
- rb_define_class_under (EmModule, "UnknownTimerFired", rb_eException);
774
+ EM_eConnectionNotBound = rb_define_class_under (EmModule, "ConnectionNotBound", rb_eRuntimeError);
775
+ EM_eUnknownTimerFired = rb_define_class_under (EmModule, "UnknownTimerFired", rb_eRuntimeError);
666
776
 
667
777
  rb_define_module_function (EmModule, "initialize_event_machine", (VALUE(*)(...))t_initialize_event_machine, 0);
668
778
  rb_define_module_function (EmModule, "run_machine", (VALUE(*)(...))t_run_machine_without_threads, 0);
@@ -673,6 +783,7 @@ extern "C" void Init_rubyeventmachine()
673
783
  rb_define_module_function (EmModule, "start_unix_server", (VALUE(*)(...))t_start_unix_server, 1);
674
784
  rb_define_module_function (EmModule, "set_tls_parms", (VALUE(*)(...))t_set_tls_parms, 3);
675
785
  rb_define_module_function (EmModule, "start_tls", (VALUE(*)(...))t_start_tls, 1);
786
+ rb_define_module_function (EmModule, "get_peer_cert", (VALUE(*)(...))t_get_peer_cert, 1);
676
787
  rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3);
677
788
  rb_define_module_function (EmModule, "send_datagram", (VALUE(*)(...))t_send_datagram, 5);
678
789
  rb_define_module_function (EmModule, "close_connection", (VALUE(*)(...))t_close_connection, 2);
@@ -692,6 +803,7 @@ extern "C" void Init_rubyeventmachine()
692
803
  rb_define_module_function (EmModule, "signal_loopbreak", (VALUE(*)(...))t_signal_loopbreak, 0);
693
804
  rb_define_module_function (EmModule, "library_type", (VALUE(*)(...))t_library_type, 0);
694
805
  rb_define_module_function (EmModule, "set_timer_quantum", (VALUE(*)(...))t_set_timer_quantum, 1);
806
+ rb_define_module_function (EmModule, "get_max_timer_count", (VALUE(*)(...))t_get_max_timer_count, 0);
695
807
  rb_define_module_function (EmModule, "set_max_timer_count", (VALUE(*)(...))t_set_max_timer_count, 1);
696
808
  rb_define_module_function (EmModule, "setuid_string", (VALUE(*)(...))t_setuid_string, 1);
697
809
  rb_define_module_function (EmModule, "invoke_popen", (VALUE(*)(...))t_invoke_popen, 1);
@@ -707,6 +819,7 @@ extern "C" void Init_rubyeventmachine()
707
819
  rb_define_module_function (EmModule, "get_comm_inactivity_timeout", (VALUE(*)(...))t_get_comm_inactivity_timeout, 1);
708
820
  rb_define_module_function (EmModule, "set_comm_inactivity_timeout", (VALUE(*)(...))t_set_comm_inactivity_timeout, 2);
709
821
  rb_define_module_function (EmModule, "set_rlimit_nofile", (VALUE(*)(...))t_set_rlimit_nofile, 1);
822
+ rb_define_module_function (EmModule, "get_connection_count", (VALUE(*)(...))t_get_connection_count, 0);
710
823
 
711
824
  // Temporary:
712
825
  rb_define_module_function (EmModule, "epoll", (VALUE(*)(...))t__epoll, 0);
@@ -728,5 +841,7 @@ extern "C" void Init_rubyeventmachine()
728
841
  rb_define_const (EmModule, "ConnectionNotifyReadable", INT2NUM(106));
729
842
  rb_define_const (EmModule, "ConnectionNotifyWritable", INT2NUM(107));
730
843
 
844
+ rb_define_const (EmModule, "SslHandshakeCompleted", INT2NUM(108));
845
+
731
846
  }
732
847