eventmachine 0.12.6 → 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.rb +35 -0
  45. data/lib/em/protocols/header_and_content.rb +138 -0
  46. data/lib/em/protocols/httpclient.rb +263 -0
  47. data/lib/em/protocols/httpclient2.rb +582 -0
  48. data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
  49. data/lib/em/protocols/linetext2.rb +160 -0
  50. data/lib/{protocols → em/protocols}/memcache.rb +37 -7
  51. data/lib/em/protocols/object_protocol.rb +39 -0
  52. data/lib/em/protocols/postgres3.rb +247 -0
  53. data/lib/em/protocols/saslauth.rb +175 -0
  54. data/lib/em/protocols/smtpclient.rb +331 -0
  55. data/lib/em/protocols/smtpserver.rb +547 -0
  56. data/lib/em/protocols/stomp.rb +200 -0
  57. data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
  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 +68 -39
  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/em.h CHANGED
@@ -57,9 +57,10 @@ typedef long long Int64;
57
57
  typedef __int64 Int64;
58
58
  #endif
59
59
 
60
- extern time_t gCurrentLoopTime;
60
+ extern Int64 gCurrentLoopTime;
61
61
 
62
62
  class EventableDescriptor;
63
+ class InotifyDescriptor;
63
64
 
64
65
 
65
66
  /********************
@@ -80,9 +81,8 @@ class EventMachine_t
80
81
  void ScheduleHalt();
81
82
  void SignalLoopBreaker();
82
83
  const char *InstallOneshotTimer (int);
83
- const char *ConnectToServer (const char *, int);
84
+ const char *ConnectToServer (const char *, int, const char *, int);
84
85
  const char *ConnectToUnixServer (const char *);
85
- const char *AttachFD (int, bool, bool);
86
86
 
87
87
  const char *CreateTcpServer (const char *, int);
88
88
  const char *OpenDatagramSocket (const char *, int);
@@ -94,7 +94,10 @@ class EventMachine_t
94
94
 
95
95
  void Add (EventableDescriptor*);
96
96
  void Modify (EventableDescriptor*);
97
+
98
+ const char *AttachFD (int, bool, bool);
97
99
  int DetachFD (EventableDescriptor*);
100
+
98
101
  void ArmKqueueWriter (EventableDescriptor*);
99
102
  void ArmKqueueReader (EventableDescriptor*);
100
103
 
@@ -106,15 +109,37 @@ class EventMachine_t
106
109
  int SubprocessExitStatus;
107
110
 
108
111
  int GetConnectionCount();
112
+ float GetHeartbeatInterval();
113
+ int SetHeartbeatInterval(float);
114
+
115
+ const char *WatchFile (const char*);
116
+ void UnwatchFile (int);
117
+ void UnwatchFile (const char*);
118
+
119
+ #ifdef HAVE_KQUEUE
120
+ void _HandleKqueueFileEvent (struct kevent*);
121
+ void _RegisterKqueueFileEvent(int);
122
+ #endif
123
+
124
+ const char *WatchPid (int);
125
+ void UnwatchPid (int);
126
+ void UnwatchPid (const char *);
127
+
128
+ #ifdef HAVE_KQUEUE
129
+ void _HandleKqueuePidEvent (struct kevent*);
130
+ #endif
109
131
 
110
132
  // Temporary:
111
133
  void _UseEpoll();
112
134
  void _UseKqueue();
113
135
 
136
+ bool UsingKqueue() { return bKqueue; }
137
+ bool UsingEpoll() { return bEpoll; }
114
138
 
115
139
  private:
116
140
  bool _RunOnce();
117
141
  bool _RunTimers();
142
+ void _UpdateTime();
118
143
  void _AddNewDescriptors();
119
144
  void _ModifyDescriptors();
120
145
  void _InitializeLoopBreaker();
@@ -127,23 +152,27 @@ class EventMachine_t
127
152
 
128
153
  public:
129
154
  void _ReadLoopBreaker();
155
+ void _ReadInotifyEvents();
130
156
 
131
157
  private:
132
158
  enum {
133
- HeartbeatInterval = 2,
134
- MaxEpollDescriptors = 64*1024
159
+ MaxEpollDescriptors = 64*1024,
160
+ MaxEvents = 4096
135
161
  };
162
+ int HeartbeatInterval;
136
163
  void (*EventCallback)(const char*, int, const char*, int);
137
164
 
138
165
  class Timer_t: public Bindable_t {
139
166
  };
140
167
 
141
168
  multimap<Int64, Timer_t> Timers;
169
+ map<int, Bindable_t*> Files;
170
+ map<int, Bindable_t*> Pids;
142
171
  vector<EventableDescriptor*> Descriptors;
143
172
  vector<EventableDescriptor*> NewDescriptors;
144
173
  set<EventableDescriptor*> ModifiedDescriptors;
145
174
 
146
- time_t NextHeartbeatTime;
175
+ Int64 NextHeartbeatTime;
147
176
 
148
177
  int LoopBreakerReader;
149
178
  int LoopBreakerWriter;
@@ -156,9 +185,17 @@ class EventMachine_t
156
185
  private:
157
186
  bool bEpoll;
158
187
  int epfd; // Epoll file-descriptor
188
+ #ifdef HAVE_EPOLL
189
+ struct epoll_event epoll_events [MaxEvents];
190
+ #endif
159
191
 
160
192
  bool bKqueue;
161
193
  int kqfd; // Kqueue file-descriptor
194
+ #ifdef HAVE_KQUEUE
195
+ struct kevent Karray [MaxEvents];
196
+ #endif
197
+
198
+ InotifyDescriptor *inotify; // pollable descriptor for our inotify instance
162
199
  };
163
200
 
164
201
 
@@ -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);
@@ -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
  }
@@ -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;
@@ -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"
@@ -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