eventmachine-eventmachine 0.12.7 → 0.12.8

Sign up to get free protection for your applications and to get access to all the features.
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);