eventmachine-eventmachine 0.12.7 → 0.12.8

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 (116) hide show
  1. data/{docs/README → README} +21 -13
  2. data/Rakefile +14 -4
  3. data/docs/DEFERRABLES +0 -5
  4. data/docs/INSTALL +2 -4
  5. data/docs/LEGAL +1 -1
  6. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
  7. data/docs/PURE_RUBY +0 -2
  8. data/docs/RELEASE_NOTES +0 -2
  9. data/docs/SMTP +0 -7
  10. data/docs/SPAWNED_PROCESSES +0 -4
  11. data/docs/TODO +0 -2
  12. data/eventmachine.gemspec +17 -8
  13. data/examples/ex_channel.rb +43 -0
  14. data/examples/ex_queue.rb +2 -0
  15. data/examples/helper.rb +2 -0
  16. data/ext/cmain.cpp +119 -20
  17. data/ext/cplusplus.cpp +15 -6
  18. data/ext/ed.cpp +303 -93
  19. data/ext/ed.h +49 -22
  20. data/ext/em.cpp +368 -42
  21. data/ext/em.h +43 -6
  22. data/ext/eventmachine.h +21 -8
  23. data/ext/eventmachine_cpp.h +1 -0
  24. data/ext/extconf.rb +4 -0
  25. data/ext/kb.cpp +1 -2
  26. data/ext/pipe.cpp +1 -3
  27. data/ext/project.h +21 -0
  28. data/ext/rubymain.cpp +232 -32
  29. data/ext/ssl.cpp +38 -1
  30. data/ext/ssl.h +5 -1
  31. data/java/src/com/rubyeventmachine/Application.java +7 -3
  32. data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
  33. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
  34. data/lib/{protocols → em}/buftok.rb +16 -5
  35. data/lib/em/callback.rb +26 -0
  36. data/lib/em/channel.rb +57 -0
  37. data/lib/em/connection.rb +505 -0
  38. data/lib/em/deferrable.rb +144 -165
  39. data/lib/em/file_watch.rb +54 -0
  40. data/lib/em/future.rb +24 -25
  41. data/lib/em/messages.rb +1 -1
  42. data/lib/em/process_watch.rb +44 -0
  43. data/lib/em/processes.rb +58 -52
  44. data/lib/em/protocols/header_and_content.rb +138 -0
  45. data/lib/em/protocols/httpclient.rb +263 -0
  46. data/lib/em/protocols/httpclient2.rb +582 -0
  47. data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
  48. data/lib/em/protocols/linetext2.rb +160 -0
  49. data/lib/{protocols → em/protocols}/memcache.rb +37 -7
  50. data/lib/em/protocols/object_protocol.rb +39 -0
  51. data/lib/em/protocols/postgres3.rb +247 -0
  52. data/lib/em/protocols/saslauth.rb +175 -0
  53. data/lib/em/protocols/smtpclient.rb +331 -0
  54. data/lib/em/protocols/smtpserver.rb +547 -0
  55. data/lib/em/protocols/stomp.rb +200 -0
  56. data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
  57. data/lib/em/protocols.rb +35 -0
  58. data/lib/em/queue.rb +61 -0
  59. data/lib/em/spawnable.rb +53 -56
  60. data/lib/em/streamer.rb +92 -74
  61. data/lib/em/timers.rb +55 -0
  62. data/lib/em/version.rb +3 -0
  63. data/lib/eventmachine.rb +1008 -1298
  64. data/lib/evma.rb +1 -1
  65. data/lib/jeventmachine.rb +106 -101
  66. data/lib/pr_eventmachine.rb +47 -36
  67. data/tasks/project.rake +2 -1
  68. data/tests/client.crt +31 -0
  69. data/tests/client.key +51 -0
  70. data/tests/test_attach.rb +18 -0
  71. data/tests/test_basic.rb +108 -54
  72. data/tests/test_channel.rb +63 -0
  73. data/tests/test_connection_count.rb +2 -2
  74. data/tests/test_epoll.rb +109 -110
  75. data/tests/test_errors.rb +36 -36
  76. data/tests/test_exc.rb +22 -25
  77. data/tests/test_file_watch.rb +49 -0
  78. data/tests/test_futures.rb +77 -93
  79. data/tests/test_hc.rb +2 -2
  80. data/tests/test_httpclient.rb +55 -52
  81. data/tests/test_httpclient2.rb +110 -112
  82. data/tests/test_inactivity_timeout.rb +30 -0
  83. data/tests/test_kb.rb +8 -9
  84. data/tests/test_ltp2.rb +274 -277
  85. data/tests/test_next_tick.rb +91 -65
  86. data/tests/test_object_protocol.rb +37 -0
  87. data/tests/test_process_watch.rb +48 -0
  88. data/tests/test_processes.rb +56 -23
  89. data/tests/test_proxy_connection.rb +92 -0
  90. data/tests/test_pure.rb +1 -5
  91. data/tests/test_queue.rb +44 -0
  92. data/tests/test_running.rb +9 -14
  93. data/tests/test_sasl.rb +32 -34
  94. data/tests/test_send_file.rb +175 -176
  95. data/tests/test_servers.rb +37 -41
  96. data/tests/test_smtpserver.rb +47 -55
  97. data/tests/test_spawn.rb +284 -291
  98. data/tests/test_ssl_args.rb +1 -1
  99. data/tests/test_ssl_methods.rb +1 -1
  100. data/tests/test_ssl_verify.rb +82 -0
  101. data/tests/test_timers.rb +81 -88
  102. data/tests/test_ud.rb +0 -7
  103. data/tests/testem.rb +1 -1
  104. metadata +53 -37
  105. data/lib/em/eventable.rb +0 -39
  106. data/lib/eventmachine_version.rb +0 -31
  107. data/lib/protocols/header_and_content.rb +0 -129
  108. data/lib/protocols/httpcli2.rb +0 -803
  109. data/lib/protocols/httpclient.rb +0 -270
  110. data/lib/protocols/linetext2.rb +0 -161
  111. data/lib/protocols/postgres.rb +0 -261
  112. data/lib/protocols/saslauth.rb +0 -179
  113. data/lib/protocols/smtpclient.rb +0 -308
  114. data/lib/protocols/smtpserver.rb +0 -556
  115. data/lib/protocols/stomp.rb +0 -153
  116. data/tests/test_eventables.rb +0 -77
data/ext/eventmachine.h CHANGED
@@ -33,7 +33,9 @@ extern "C" {
33
33
  EM_LOOPBREAK_SIGNAL = 105,
34
34
  EM_CONNECTION_NOTIFY_READABLE = 106,
35
35
  EM_CONNECTION_NOTIFY_WRITABLE = 107,
36
- EM_SSL_HANDSHAKE_COMPLETED = 108
36
+ EM_SSL_HANDSHAKE_COMPLETED = 108,
37
+ EM_SSL_VERIFY = 109,
38
+ EM_PROXY_TARGET_UNBOUND = 110
37
39
 
38
40
  };
39
41
 
@@ -41,7 +43,7 @@ extern "C" {
41
43
  void evma_run_machine();
42
44
  void evma_release_library();
43
45
  const char *evma_install_oneshot_timer (int seconds);
44
- const char *evma_connect_to_server (const char *server, int port);
46
+ const char *evma_connect_to_server (const char *bind_addr, int bind_port, const char *server, int port);
45
47
  const char *evma_connect_to_unix_server (const char *server);
46
48
 
47
49
  const char *evma_attach_fd (int file_descriptor, int read_mode, int write_mode);
@@ -52,11 +54,12 @@ extern "C" {
52
54
  const char *evma_create_unix_domain_server (const char *filename);
53
55
  const char *evma_open_datagram_socket (const char *server, int port);
54
56
  const char *evma_open_keyboard();
55
- void evma_set_tls_parms (const char *binding, const char *privatekey_filename, const char *certchain_filenane);
57
+ void evma_set_tls_parms (const char *binding, const char *privatekey_filename, const char *certchain_filenane, int verify_peer);
56
58
  void evma_start_tls (const char *binding);
57
59
 
58
60
  #ifdef WITH_SSL
59
61
  X509 *evma_get_peer_cert (const char *binding);
62
+ void evma_accept_ssl_peer (const char *binding);
60
63
  #endif
61
64
 
62
65
  int evma_get_peername (const char *binding, struct sockaddr*);
@@ -66,8 +69,8 @@ extern "C" {
66
69
  int evma_get_connection_count();
67
70
  int evma_send_data_to_connection (const char *binding, const char *data, int data_length);
68
71
  int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port);
69
- int evma_get_comm_inactivity_timeout (const char *binding, /*out*/int *value);
70
- int evma_set_comm_inactivity_timeout (const char *binding, /*in,out*/int *value);
72
+ float evma_get_comm_inactivity_timeout (const char *binding);
73
+ int evma_set_comm_inactivity_timeout (const char *binding, float value);
71
74
  int evma_get_outbound_data_size (const char *binding);
72
75
  int evma_send_file_data_to_connection (const char *binding, const char *filename);
73
76
 
@@ -79,15 +82,25 @@ extern "C" {
79
82
  void evma_set_max_timer_count (int);
80
83
  void evma_setuid_string (const char *username);
81
84
  void evma_stop_machine();
85
+ float evma_get_heartbeat_interval();
86
+ int evma_set_heartbeat_interval(float);
82
87
 
83
88
  const char *evma__write_file (const char *filename);
84
89
  const char *evma_popen (char * const*cmd_strings);
85
90
 
91
+ const char *evma_watch_filename (const char *fname);
92
+ void evma_unwatch_filename (const char *sig);
93
+
94
+ const char *evma_watch_pid (int);
95
+ void evma_unwatch_pid (const char *sig);
96
+
97
+ void evma_start_proxy(const char*, const char*);
98
+ void evma_stop_proxy(const char*);
99
+
86
100
  int evma_set_rlimit_nofile (int n_files);
87
101
 
88
- // Temporary:
89
- void evma__epoll();
90
- void evma__kqueue();
102
+ void evma_set_epoll (int use);
103
+ void evma_set_kqueue (int use);
91
104
 
92
105
  #if __cplusplus
93
106
  }
@@ -63,6 +63,7 @@ namespace EM {
63
63
  virtual ~Connection() {}
64
64
 
65
65
  virtual void Connect (const char*, int);
66
+ virtual void BindConnect (const char *, int, const char*, int);
66
67
 
67
68
  void SendData (const char *data);
68
69
  void SendData (const char *data, int length);
data/ext/extconf.rb CHANGED
@@ -15,6 +15,9 @@ end
15
15
  add_define 'BUILD_FOR_RUBY'
16
16
  add_define 'HAVE_RBTRAP' if have_var('rb_trap_immediate', ['ruby.h', 'rubysig.h'])
17
17
  add_define "HAVE_TBR" if have_func('rb_thread_blocking_region')# and have_macro('RUBY_UBF_IO', 'ruby.h')
18
+ add_define "HAVE_INOTIFY" if inotify = have_func('inotify_init', 'sys/inotify.h')
19
+ add_define "HAVE_OLD_INOTIFY" if !inotify && have_macro('__NR_inotify_init', 'sys/syscall.h')
20
+ add_define 'HAVE_WRITEV' if have_func('writev', 'sys/uio.h')
18
21
 
19
22
  # Minor platform details between *nix and Windows:
20
23
 
@@ -59,6 +62,7 @@ when /solaris/
59
62
  # on Unix we need a g++ link, not gcc.
60
63
  CONFIG['LDSHARED'] = "$(CXX) -shared"
61
64
  end
65
+
62
66
  when /openbsd/
63
67
  # OpenBSD branch contributed by Guillaume Sellier.
64
68
 
data/ext/kb.cpp CHANGED
@@ -77,6 +77,5 @@ void KeyboardDescriptor::Read()
77
77
  {
78
78
  char c;
79
79
  read (GetSocket(), &c, 1);
80
- if (EventCallback)
81
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, &c, 1);
80
+ _GenericInboundDispatch(&c, 1);
82
81
  }
data/ext/pipe.cpp CHANGED
@@ -164,7 +164,6 @@ void PipeDescriptor::Read()
164
164
 
165
165
  if (r > 0) {
166
166
  total_bytes_read += r;
167
- LastRead = gCurrentLoopTime;
168
167
 
169
168
  // Add a null-terminator at the the end of the buffer
170
169
  // that we will send to the callback.
@@ -173,8 +172,7 @@ void PipeDescriptor::Read()
173
172
  // the option to do some things faster. Additionally it's
174
173
  // a security guard against buffer overflows.
175
174
  readbuffer [r] = 0;
176
- if (EventCallback)
177
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, readbuffer, r);
175
+ _GenericInboundDispatch(readbuffer, r);
178
176
  }
179
177
  else if (r == 0) {
180
178
  break;
data/ext/project.h CHANGED
@@ -102,6 +102,27 @@ using namespace std;
102
102
  #include <sys/queue.h>
103
103
  #endif
104
104
 
105
+ #ifdef HAVE_INOTIFY
106
+ #include <sys/inotify.h>
107
+ #endif
108
+
109
+ #ifdef HAVE_OLD_INOTIFY
110
+ #include <sys/syscall.h>
111
+ #include <linux/inotify.h>
112
+ static inline int inotify_init (void) { return syscall (__NR_inotify_init); }
113
+ static inline int inotify_add_watch (int fd, const char *name, __u32 mask) { return syscall (__NR_inotify_add_watch, fd, name, mask); }
114
+ static inline int inotify_rm_watch (int fd, __u32 wd) { return syscall (__NR_inotify_rm_watch, fd, wd); }
115
+ #define HAVE_INOTIFY 1
116
+ #endif
117
+
118
+ #ifdef HAVE_INOTIFY
119
+ #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
120
+ #endif
121
+
122
+ #ifdef HAVE_WRITEV
123
+ #include <sys/uio.h>
124
+ #endif
125
+
105
126
  #include "binder.h"
106
127
  #include "em.h"
107
128
  #include "epoll.h"
data/ext/rubymain.cpp CHANGED
@@ -21,7 +21,9 @@ See the file COPYING for complete licensing information.
21
21
  #include "eventmachine.h"
22
22
  #include <ruby.h>
23
23
 
24
-
24
+ #ifndef RFLOAT_VALUE
25
+ #define RFLOAT_VALUE(arg) RFLOAT(arg)->value
26
+ #endif
25
27
 
26
28
  /*******
27
29
  Statics
@@ -43,8 +45,10 @@ static VALUE Intern_delete;
43
45
  static VALUE Intern_call;
44
46
  static VALUE Intern_receive_data;
45
47
  static VALUE Intern_ssl_handshake_completed;
48
+ static VALUE Intern_ssl_verify_peer;
46
49
  static VALUE Intern_notify_readable;
47
50
  static VALUE Intern_notify_writable;
51
+ static VALUE Intern_proxy_target_unbound;
48
52
 
49
53
  static VALUE rb_cProcStatus;
50
54
 
@@ -93,10 +97,15 @@ static void event_callback (struct em_event* e)
93
97
  else if (a2 == EM_TIMER_FIRED) {
94
98
  VALUE t = rb_ivar_get (EmModule, Intern_at_timers);
95
99
  VALUE q = rb_funcall (t, Intern_delete, 1, rb_str_new(a3, a4));
96
- if (q == Qnil)
100
+ if (q == Qnil) {
97
101
  rb_raise (EM_eUnknownTimerFired, "no such timer: %s", a1);
98
- rb_funcall (q, Intern_call, 0);
102
+ } else if (q == Qfalse) {
103
+ /* Timer Canceled */
104
+ } else {
105
+ rb_funcall (q, Intern_call, 0);
106
+ }
99
107
  }
108
+ #ifdef WITH_SSL
100
109
  else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) {
101
110
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
102
111
  VALUE q = rb_hash_aref (t, rb_str_new2(a1));
@@ -104,6 +113,23 @@ static void event_callback (struct em_event* e)
104
113
  rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
105
114
  rb_funcall (q, Intern_ssl_handshake_completed, 0);
106
115
  }
116
+ else if (a2 == EM_SSL_VERIFY) {
117
+ VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
118
+ VALUE q = rb_hash_aref (t, rb_str_new2(a1));
119
+ if (q == Qnil)
120
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
121
+ VALUE r = rb_funcall (q, Intern_ssl_verify_peer, 1, rb_str_new(a3, a4));
122
+ if (RTEST(r))
123
+ evma_accept_ssl_peer (a1);
124
+ }
125
+ #endif
126
+ else if (a2 == EM_PROXY_TARGET_UNBOUND) {
127
+ VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
128
+ VALUE q = rb_hash_aref (t, rb_str_new2(a1));
129
+ if (q == Qnil)
130
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
131
+ rb_funcall (q, Intern_proxy_target_unbound, 0);
132
+ }
107
133
  else
108
134
  rb_funcall (EmModule, Intern_event_callback, 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
109
135
  }
@@ -234,20 +260,20 @@ static VALUE t_start_tls (VALUE self, VALUE signature)
234
260
  t_set_tls_parms
235
261
  ***************/
236
262
 
237
- static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VALUE certchainfile)
263
+ static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VALUE certchainfile, VALUE verify_peer)
238
264
  {
239
265
  /* set_tls_parms takes a series of positional arguments for specifying such things
240
266
  * as private keys and certificate chains.
241
267
  * It's expected that the parameter list will grow as we add more supported features.
242
268
  * ALL of these parameters are optional, and can be specified as empty or NULL strings.
243
269
  */
244
- evma_set_tls_parms (StringValuePtr (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile) );
270
+ evma_set_tls_parms (StringValuePtr (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile), (verify_peer == Qtrue ? 1 : 0));
245
271
  return Qnil;
246
272
  }
247
273
 
248
- /***********
274
+ /***************
249
275
  t_get_peer_cert
250
- ***********/
276
+ ***************/
251
277
 
252
278
  static VALUE t_get_peer_cert (VALUE self, VALUE signature)
253
279
  {
@@ -352,10 +378,7 @@ t_get_comm_inactivity_timeout
352
378
 
353
379
  static VALUE t_get_comm_inactivity_timeout (VALUE self, VALUE signature)
354
380
  {
355
- int timeout;
356
- if (evma_get_comm_inactivity_timeout (StringValuePtr (signature), &timeout))
357
- return INT2FIX (timeout);
358
- return Qnil;
381
+ return rb_float_new(evma_get_comm_inactivity_timeout(StringValuePtr(signature)));
359
382
  }
360
383
 
361
384
  /*****************************
@@ -364,10 +387,10 @@ t_set_comm_inactivity_timeout
364
387
 
365
388
  static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout)
366
389
  {
367
- int ti = FIX2INT (timeout);
368
- if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), &ti));
390
+ float ti = RFLOAT_VALUE(timeout);
391
+ if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), ti));
369
392
  return Qtrue;
370
- return Qnil;
393
+ return Qfalse;
371
394
  }
372
395
 
373
396
 
@@ -414,12 +437,33 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
414
437
  // Specifically, if the value of port comes in as a string rather than an integer,
415
438
  // NUM2INT will throw a type error, but FIX2INT will generate garbage.
416
439
 
417
- const char *f = evma_connect_to_server (StringValuePtr(server), NUM2INT(port));
440
+ const char *f = evma_connect_to_server (NULL, 0, StringValuePtr(server), NUM2INT(port));
418
441
  if (!f || !*f)
419
442
  rb_raise (rb_eRuntimeError, "no connection");
420
443
  return rb_str_new2 (f);
421
444
  }
422
445
 
446
+ /*********************
447
+ t_bind_connect_server
448
+ *********************/
449
+
450
+ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port, VALUE server, VALUE port)
451
+ {
452
+ // Avoid FIX2INT in this case, because it doesn't deal with type errors properly.
453
+ // Specifically, if the value of port comes in as a string rather than an integer,
454
+ // NUM2INT will throw a type error, but FIX2INT will generate garbage.
455
+
456
+ const char *f;
457
+ try {
458
+ f = evma_connect_to_server (StringValuePtr(bind_addr), NUM2INT(bind_port), StringValuePtr(server), NUM2INT(port));
459
+ if (!f || !*f)
460
+ rb_raise (rb_eRuntimeError, "no connection");
461
+ } catch (std::runtime_error e) {
462
+ rb_sys_fail(e.what());
463
+ }
464
+ return rb_str_new2 (f);
465
+ }
466
+
423
467
  /*********************
424
468
  t_connect_unix_server
425
469
  *********************/
@@ -609,17 +653,56 @@ static VALUE t_read_keyboard (VALUE self)
609
653
  }
610
654
 
611
655
 
612
- /********
613
- t__epoll
614
- ********/
656
+ /****************
657
+ t_watch_filename
658
+ ****************/
615
659
 
616
- static VALUE t__epoll (VALUE self)
660
+ static VALUE t_watch_filename (VALUE self, VALUE fname)
661
+ {
662
+ try {
663
+ return rb_str_new2(evma_watch_filename(StringValuePtr(fname)));
664
+ } catch (std::runtime_error e) {
665
+ rb_sys_fail(e.what());
666
+ }
667
+ }
668
+
669
+
670
+ /******************
671
+ t_unwatch_filename
672
+ ******************/
673
+
674
+ static VALUE t_unwatch_filename (VALUE self, VALUE sig)
617
675
  {
618
- // Temporary.
619
- evma__epoll();
676
+ evma_unwatch_filename(StringValuePtr(sig));
620
677
  return Qnil;
621
678
  }
622
679
 
680
+
681
+ /***********
682
+ t_watch_pid
683
+ ***********/
684
+
685
+ static VALUE t_watch_pid (VALUE self, VALUE pid)
686
+ {
687
+ try {
688
+ return rb_str_new2(evma_watch_pid(NUM2INT(pid)));
689
+ } catch (std::runtime_error e) {
690
+ rb_sys_fail(e.what());
691
+ }
692
+ }
693
+
694
+
695
+ /*************
696
+ t_unwatch_pid
697
+ *************/
698
+
699
+ static VALUE t_unwatch_pid (VALUE self, VALUE sig)
700
+ {
701
+ evma_unwatch_pid(StringValuePtr(sig));
702
+ return Qnil;
703
+ }
704
+
705
+
623
706
  /**********
624
707
  t__epoll_p
625
708
  **********/
@@ -633,18 +716,33 @@ static VALUE t__epoll_p (VALUE self)
633
716
  #endif
634
717
  }
635
718
 
719
+ /********
720
+ t__epoll
721
+ ********/
636
722
 
637
- /*********
638
- t__kqueue
639
- *********/
723
+ static VALUE t__epoll (VALUE self)
724
+ {
725
+ if (t__epoll_p(self) == Qfalse)
726
+ return Qfalse;
640
727
 
641
- static VALUE t__kqueue (VALUE self)
728
+ evma_set_epoll (1);
729
+ return Qtrue;
730
+ }
731
+
732
+ /***********
733
+ t__epoll_set
734
+ ***********/
735
+
736
+ static VALUE t__epoll_set (VALUE self, VALUE val)
642
737
  {
643
- // Temporary.
644
- evma__kqueue();
645
- return Qnil;
738
+ if (t__epoll_p(self) == Qfalse)
739
+ return Qfalse;
740
+
741
+ evma_set_epoll (val == Qtrue ? 1 : 0);
742
+ return val;
646
743
  }
647
744
 
745
+
648
746
  /***********
649
747
  t__kqueue_p
650
748
  ***********/
@@ -658,6 +756,46 @@ static VALUE t__kqueue_p (VALUE self)
658
756
  #endif
659
757
  }
660
758
 
759
+ /*********
760
+ t__kqueue
761
+ *********/
762
+
763
+ static VALUE t__kqueue (VALUE self)
764
+ {
765
+ if (t__kqueue_p(self) == Qfalse)
766
+ return Qfalse;
767
+
768
+ evma_set_kqueue (1);
769
+ return Qtrue;
770
+ }
771
+
772
+ /*************
773
+ t__kqueue_set
774
+ *************/
775
+
776
+ static VALUE t__kqueue_set (VALUE self, VALUE val)
777
+ {
778
+ if (t__kqueue_p(self) == Qfalse)
779
+ return Qfalse;
780
+
781
+ evma_set_kqueue (val == Qtrue ? 1 : 0);
782
+ return val;
783
+ }
784
+
785
+
786
+ /********
787
+ t__ssl_p
788
+ ********/
789
+
790
+ static VALUE t__ssl_p (VALUE self)
791
+ {
792
+ #ifdef WITH_SSL
793
+ return Qtrue;
794
+ #else
795
+ return Qfalse;
796
+ #endif
797
+ }
798
+
661
799
 
662
800
  /****************
663
801
  t_send_file_data
@@ -739,6 +877,51 @@ static VALUE t_get_loop_time (VALUE self)
739
877
  }
740
878
 
741
879
 
880
+ /*************
881
+ t_start_proxy
882
+ **************/
883
+
884
+ static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to)
885
+ {
886
+ evma_start_proxy(StringValuePtr(from), StringValuePtr(to));
887
+ return Qnil;
888
+ }
889
+
890
+
891
+ /************
892
+ t_stop_proxy
893
+ *************/
894
+
895
+ static VALUE t_stop_proxy (VALUE self, VALUE from)
896
+ {
897
+ evma_stop_proxy(StringValuePtr(from));
898
+ return Qnil;
899
+ }
900
+
901
+
902
+ /************************
903
+ t_get_heartbeat_interval
904
+ *************************/
905
+
906
+ static VALUE t_get_heartbeat_interval (VALUE self)
907
+ {
908
+ return rb_float_new(evma_get_heartbeat_interval());
909
+ }
910
+
911
+
912
+ /************************
913
+ t_set_heartbeat_interval
914
+ *************************/
915
+
916
+ static VALUE t_set_heartbeat_interval (VALUE self, VALUE interval)
917
+ {
918
+ float iv = RFLOAT_VALUE(interval);
919
+ if (evma_set_heartbeat_interval(iv))
920
+ return Qtrue;
921
+ return Qfalse;
922
+ }
923
+
924
+
742
925
  /*********************
743
926
  Init_rubyeventmachine
744
927
  *********************/
@@ -761,8 +944,10 @@ extern "C" void Init_rubyeventmachine()
761
944
  Intern_call = rb_intern ("call");
762
945
  Intern_receive_data = rb_intern ("receive_data");
763
946
  Intern_ssl_handshake_completed = rb_intern ("ssl_handshake_completed");
947
+ Intern_ssl_verify_peer = rb_intern ("ssl_verify_peer");
764
948
  Intern_notify_readable = rb_intern ("notify_readable");
765
949
  Intern_notify_writable = rb_intern ("notify_writable");
950
+ Intern_proxy_target_unbound = rb_intern ("proxy_target_unbound");
766
951
 
767
952
  // INCOMPLETE, we need to define class Connections inside module EventMachine
768
953
  // run_machine and run_machine_without_threads are now identical.
@@ -781,7 +966,7 @@ extern "C" void Init_rubyeventmachine()
781
966
  rb_define_module_function (EmModule, "start_tcp_server", (VALUE(*)(...))t_start_server, 2);
782
967
  rb_define_module_function (EmModule, "stop_tcp_server", (VALUE(*)(...))t_stop_server, 1);
783
968
  rb_define_module_function (EmModule, "start_unix_server", (VALUE(*)(...))t_start_unix_server, 1);
784
- rb_define_module_function (EmModule, "set_tls_parms", (VALUE(*)(...))t_set_tls_parms, 3);
969
+ rb_define_module_function (EmModule, "set_tls_parms", (VALUE(*)(...))t_set_tls_parms, 4);
785
970
  rb_define_module_function (EmModule, "start_tls", (VALUE(*)(...))t_start_tls, 1);
786
971
  rb_define_module_function (EmModule, "get_peer_cert", (VALUE(*)(...))t_get_peer_cert, 1);
787
972
  rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3);
@@ -789,11 +974,21 @@ extern "C" void Init_rubyeventmachine()
789
974
  rb_define_module_function (EmModule, "close_connection", (VALUE(*)(...))t_close_connection, 2);
790
975
  rb_define_module_function (EmModule, "report_connection_error_status", (VALUE(*)(...))t_report_connection_error_status, 1);
791
976
  rb_define_module_function (EmModule, "connect_server", (VALUE(*)(...))t_connect_server, 2);
977
+ rb_define_module_function (EmModule, "bind_connect_server", (VALUE(*)(...))t_bind_connect_server, 4);
792
978
  rb_define_module_function (EmModule, "connect_unix_server", (VALUE(*)(...))t_connect_unix_server, 1);
793
979
 
794
980
  rb_define_module_function (EmModule, "attach_fd", (VALUE (*)(...))t_attach_fd, 3);
795
981
  rb_define_module_function (EmModule, "detach_fd", (VALUE (*)(...))t_detach_fd, 1);
796
982
 
983
+ rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 2);
984
+ rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1);
985
+
986
+ rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1);
987
+ rb_define_module_function (EmModule, "unwatch_filename", (VALUE (*)(...))t_unwatch_filename, 1);
988
+
989
+ rb_define_module_function (EmModule, "watch_pid", (VALUE (*)(...))t_watch_pid, 1);
990
+ rb_define_module_function (EmModule, "unwatch_pid", (VALUE (*)(...))t_unwatch_pid, 1);
991
+
797
992
  rb_define_module_function (EmModule, "current_time", (VALUE(*)(...))t_get_loop_time, 0);
798
993
 
799
994
  rb_define_module_function (EmModule, "open_udp_socket", (VALUE(*)(...))t_open_udp_socket, 2);
@@ -808,6 +1003,8 @@ extern "C" void Init_rubyeventmachine()
808
1003
  rb_define_module_function (EmModule, "setuid_string", (VALUE(*)(...))t_setuid_string, 1);
809
1004
  rb_define_module_function (EmModule, "invoke_popen", (VALUE(*)(...))t_invoke_popen, 1);
810
1005
  rb_define_module_function (EmModule, "send_file_data", (VALUE(*)(...))t_send_file_data, 2);
1006
+ rb_define_module_function (EmModule, "get_heartbeat_interval", (VALUE(*)(...))t_get_heartbeat_interval, 0);
1007
+ rb_define_module_function (EmModule, "set_heartbeat_interval", (VALUE(*)(...))t_set_heartbeat_interval, 1);
811
1008
 
812
1009
  // Provisional:
813
1010
  rb_define_module_function (EmModule, "_write_file", (VALUE(*)(...))t__write_file, 1);
@@ -821,13 +1018,16 @@ extern "C" void Init_rubyeventmachine()
821
1018
  rb_define_module_function (EmModule, "set_rlimit_nofile", (VALUE(*)(...))t_set_rlimit_nofile, 1);
822
1019
  rb_define_module_function (EmModule, "get_connection_count", (VALUE(*)(...))t_get_connection_count, 0);
823
1020
 
824
- // Temporary:
825
1021
  rb_define_module_function (EmModule, "epoll", (VALUE(*)(...))t__epoll, 0);
826
- rb_define_module_function (EmModule, "kqueue", (VALUE(*)(...))t__kqueue, 0);
827
-
1022
+ rb_define_module_function (EmModule, "epoll=", (VALUE(*)(...))t__epoll_set, 1);
828
1023
  rb_define_module_function (EmModule, "epoll?", (VALUE(*)(...))t__epoll_p, 0);
1024
+
1025
+ rb_define_module_function (EmModule, "kqueue", (VALUE(*)(...))t__kqueue, 0);
1026
+ rb_define_module_function (EmModule, "kqueue=", (VALUE(*)(...))t__kqueue_set, 1);
829
1027
  rb_define_module_function (EmModule, "kqueue?", (VALUE(*)(...))t__kqueue_p, 0);
830
1028
 
1029
+ rb_define_module_function (EmModule, "ssl?", (VALUE(*)(...))t__ssl_p, 0);
1030
+
831
1031
  rb_define_method (EmConnection, "get_outbound_data_size", (VALUE(*)(...))conn_get_outbound_data_size, 0);
832
1032
  rb_define_method (EmConnection, "associate_callback_target", (VALUE(*)(...))conn_associate_callback_target, 1);
833
1033
 
data/ext/ssl.cpp CHANGED
@@ -208,9 +208,10 @@ SslContext_t::~SslContext_t()
208
208
  SslBox_t::SslBox_t
209
209
  ******************/
210
210
 
211
- SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile):
211
+ SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const char *binding):
212
212
  bIsServer (is_server),
213
213
  bHandshakeCompleted (false),
214
+ bVerifyPeer (verify_peer),
214
215
  pSSL (NULL),
215
216
  pbioRead (NULL),
216
217
  pbioWrite (NULL)
@@ -232,6 +233,12 @@ SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &cer
232
233
  assert (pSSL);
233
234
  SSL_set_bio (pSSL, pbioRead, pbioWrite);
234
235
 
236
+ // Store a pointer to the binding signature in the SSL object so we can retrieve it later
237
+ SSL_set_ex_data(pSSL, 0, (void*) binding);
238
+
239
+ if (bVerifyPeer)
240
+ SSL_set_verify(pSSL, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, ssl_verify_wrapper);
241
+
235
242
  if (!bIsServer)
236
243
  SSL_connect (pSSL);
237
244
  }
@@ -419,5 +426,35 @@ X509 *SslBox_t::GetPeerCert()
419
426
  return cert;
420
427
  }
421
428
 
429
+
430
+ /******************
431
+ ssl_verify_wrapper
432
+ *******************/
433
+
434
+ extern "C" int ssl_verify_wrapper(int preverify_ok, X509_STORE_CTX *ctx)
435
+ {
436
+ const char *binding;
437
+ X509 *cert;
438
+ SSL *ssl;
439
+ BUF_MEM *buf;
440
+ BIO *out;
441
+ int result;
442
+
443
+ cert = X509_STORE_CTX_get_current_cert(ctx);
444
+ ssl = (SSL*) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
445
+ binding = (const char*) SSL_get_ex_data(ssl, 0);
446
+
447
+ out = BIO_new(BIO_s_mem());
448
+ PEM_write_bio_X509(out, cert);
449
+ BIO_write(out, "\0", 1);
450
+ BIO_get_mem_ptr(out, &buf);
451
+
452
+ ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject(binding));
453
+ result = (cd->VerifySslPeer(buf->data) == true ? 1 : 0);
454
+ BUF_MEM_free(buf);
455
+
456
+ return result;
457
+ }
458
+
422
459
  #endif // WITH_SSL
423
460
 
data/ext/ssl.h CHANGED
@@ -57,7 +57,7 @@ class SslBox_t
57
57
  class SslBox_t
58
58
  {
59
59
  public:
60
- SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile);
60
+ SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const char *binding);
61
61
  virtual ~SslBox_t();
62
62
 
63
63
  int PutPlaintext (const char*, int);
@@ -75,6 +75,7 @@ class SslBox_t
75
75
  protected:
76
76
  SslContext_t *Context;
77
77
 
78
+ bool bVerifyPeer;
78
79
  bool bIsServer;
79
80
  bool bHandshakeCompleted;
80
81
  SSL *pSSL;
@@ -83,6 +84,9 @@ class SslBox_t
83
84
 
84
85
  PageList OutboundQ;
85
86
  };
87
+
88
+ extern "C" int ssl_verify_wrapper(int, X509_STORE_CTX*);
89
+
86
90
  #endif // WITH_SSL
87
91
 
88
92
 
@@ -128,16 +128,20 @@ public class Application {
128
128
  reactor.timers.put(s, t);
129
129
 
130
130
  }
131
-
132
- public void connect (String host, int port, Connection c) {
131
+
132
+ public void bindConnect (String bindAddr, int bindPort, String host, int port, Connection c) {
133
133
  try {
134
- String s = reactor.connectTcpServer(host, port);
134
+ String s = reactor.connectTcpServer(bindAddr, bindPort, host, port);
135
135
  c.application = this;
136
136
  c.signature = s;
137
137
  reactor.connections.put(s, c);
138
138
  c.postInit();
139
139
  } catch (ClosedChannelException e) {}
140
140
  }
141
+
142
+ public void connect (String host, int port, Connection c) {
143
+ bindConnect(null, 0, host, port, c);
144
+ }
141
145
 
142
146
  public void startServer (SocketAddress sa, ConnectionFactory f) throws EmReactorException {
143
147
  String s = reactor.startTcpServer(sa);