wj_eventmachine 1.3.0.dev.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +179 -0
  3. data/GNU +281 -0
  4. data/LICENSE +60 -0
  5. data/README.md +110 -0
  6. data/docs/DocumentationGuidesIndex.md +27 -0
  7. data/docs/GettingStarted.md +520 -0
  8. data/docs/old/ChangeLog +211 -0
  9. data/docs/old/DEFERRABLES +246 -0
  10. data/docs/old/EPOLL +141 -0
  11. data/docs/old/INSTALL +13 -0
  12. data/docs/old/KEYBOARD +42 -0
  13. data/docs/old/LEGAL +25 -0
  14. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  15. data/docs/old/PURE_RUBY +75 -0
  16. data/docs/old/RELEASE_NOTES +94 -0
  17. data/docs/old/SMTP +4 -0
  18. data/docs/old/SPAWNED_PROCESSES +148 -0
  19. data/docs/old/TODO +8 -0
  20. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  21. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  22. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  23. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  24. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  25. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  26. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  27. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  28. data/examples/old/ex_channel.rb +43 -0
  29. data/examples/old/ex_queue.rb +2 -0
  30. data/examples/old/ex_tick_loop_array.rb +15 -0
  31. data/examples/old/ex_tick_loop_counter.rb +32 -0
  32. data/examples/old/helper.rb +2 -0
  33. data/ext/binder.cpp +124 -0
  34. data/ext/binder.h +52 -0
  35. data/ext/cmain.cpp +1046 -0
  36. data/ext/ed.cpp +2238 -0
  37. data/ext/ed.h +460 -0
  38. data/ext/em.cpp +2378 -0
  39. data/ext/em.h +266 -0
  40. data/ext/eventmachine.h +152 -0
  41. data/ext/extconf.rb +285 -0
  42. data/ext/fastfilereader/extconf.rb +120 -0
  43. data/ext/fastfilereader/mapper.cpp +214 -0
  44. data/ext/fastfilereader/mapper.h +59 -0
  45. data/ext/fastfilereader/rubymain.cpp +126 -0
  46. data/ext/kb.cpp +79 -0
  47. data/ext/page.cpp +107 -0
  48. data/ext/page.h +51 -0
  49. data/ext/pipe.cpp +354 -0
  50. data/ext/project.h +174 -0
  51. data/ext/rubymain.cpp +1610 -0
  52. data/ext/ssl.cpp +627 -0
  53. data/ext/ssl.h +103 -0
  54. data/ext/wait_for_single_fd.h +36 -0
  55. data/java/.classpath +8 -0
  56. data/java/.project +17 -0
  57. data/java/src/com/rubyeventmachine/EmReactor.java +625 -0
  58. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  59. data/java/src/com/rubyeventmachine/EmReactorInterface.java +70 -0
  60. data/java/src/com/rubyeventmachine/EventableChannel.java +72 -0
  61. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +201 -0
  62. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +415 -0
  63. data/java/src/com/rubyeventmachine/NullEmReactor.java +157 -0
  64. data/java/src/com/rubyeventmachine/NullEventableChannel.java +81 -0
  65. data/lib/em/buftok.rb +59 -0
  66. data/lib/em/callback.rb +58 -0
  67. data/lib/em/channel.rb +69 -0
  68. data/lib/em/completion.rb +307 -0
  69. data/lib/em/connection.rb +776 -0
  70. data/lib/em/deferrable.rb +210 -0
  71. data/lib/em/deferrable/pool.rb +2 -0
  72. data/lib/em/file_watch.rb +73 -0
  73. data/lib/em/future.rb +61 -0
  74. data/lib/em/io_streamer.rb +68 -0
  75. data/lib/em/iterator.rb +252 -0
  76. data/lib/em/messages.rb +66 -0
  77. data/lib/em/pool.rb +151 -0
  78. data/lib/em/process_watch.rb +45 -0
  79. data/lib/em/processes.rb +123 -0
  80. data/lib/em/protocols.rb +37 -0
  81. data/lib/em/protocols/header_and_content.rb +138 -0
  82. data/lib/em/protocols/httpclient.rb +303 -0
  83. data/lib/em/protocols/httpclient2.rb +602 -0
  84. data/lib/em/protocols/line_and_text.rb +125 -0
  85. data/lib/em/protocols/line_protocol.rb +33 -0
  86. data/lib/em/protocols/linetext2.rb +179 -0
  87. data/lib/em/protocols/memcache.rb +331 -0
  88. data/lib/em/protocols/object_protocol.rb +46 -0
  89. data/lib/em/protocols/postgres3.rb +246 -0
  90. data/lib/em/protocols/saslauth.rb +175 -0
  91. data/lib/em/protocols/smtpclient.rb +394 -0
  92. data/lib/em/protocols/smtpserver.rb +666 -0
  93. data/lib/em/protocols/socks4.rb +66 -0
  94. data/lib/em/protocols/stomp.rb +205 -0
  95. data/lib/em/protocols/tcptest.rb +54 -0
  96. data/lib/em/pure_ruby.rb +1299 -0
  97. data/lib/em/queue.rb +80 -0
  98. data/lib/em/resolver.rb +232 -0
  99. data/lib/em/spawnable.rb +84 -0
  100. data/lib/em/streamer.rb +118 -0
  101. data/lib/em/threaded_resource.rb +90 -0
  102. data/lib/em/tick_loop.rb +85 -0
  103. data/lib/em/timers.rb +61 -0
  104. data/lib/em/version.rb +3 -0
  105. data/lib/eventmachine.rb +1602 -0
  106. data/lib/jeventmachine.rb +318 -0
  107. data/rakelib/package.rake +120 -0
  108. data/rakelib/test.rake +6 -0
  109. data/rakelib/test_pure.rake +11 -0
  110. data/tests/client.crt +31 -0
  111. data/tests/client.key +51 -0
  112. data/tests/dhparam.pem +13 -0
  113. data/tests/em_ssl_handlers.rb +153 -0
  114. data/tests/em_test_helper.rb +198 -0
  115. data/tests/jruby/test_jeventmachine.rb +38 -0
  116. data/tests/test_attach.rb +199 -0
  117. data/tests/test_basic.rb +321 -0
  118. data/tests/test_channel.rb +75 -0
  119. data/tests/test_completion.rb +178 -0
  120. data/tests/test_connection_count.rb +83 -0
  121. data/tests/test_connection_write.rb +35 -0
  122. data/tests/test_defer.rb +35 -0
  123. data/tests/test_deferrable.rb +35 -0
  124. data/tests/test_epoll.rb +141 -0
  125. data/tests/test_error_handler.rb +38 -0
  126. data/tests/test_exc.rb +37 -0
  127. data/tests/test_file_watch.rb +86 -0
  128. data/tests/test_fork.rb +75 -0
  129. data/tests/test_futures.rb +170 -0
  130. data/tests/test_handler_check.rb +35 -0
  131. data/tests/test_hc.rb +155 -0
  132. data/tests/test_httpclient.rb +238 -0
  133. data/tests/test_httpclient2.rb +132 -0
  134. data/tests/test_idle_connection.rb +31 -0
  135. data/tests/test_inactivity_timeout.rb +102 -0
  136. data/tests/test_io_streamer.rb +47 -0
  137. data/tests/test_ipv4.rb +96 -0
  138. data/tests/test_ipv6.rb +107 -0
  139. data/tests/test_iterator.rb +122 -0
  140. data/tests/test_kb.rb +28 -0
  141. data/tests/test_keepalive.rb +113 -0
  142. data/tests/test_line_protocol.rb +33 -0
  143. data/tests/test_ltp.rb +155 -0
  144. data/tests/test_ltp2.rb +332 -0
  145. data/tests/test_many_fds.rb +21 -0
  146. data/tests/test_next_tick.rb +104 -0
  147. data/tests/test_object_protocol.rb +36 -0
  148. data/tests/test_pause.rb +109 -0
  149. data/tests/test_pending_connect_timeout.rb +52 -0
  150. data/tests/test_pool.rb +196 -0
  151. data/tests/test_process_watch.rb +50 -0
  152. data/tests/test_processes.rb +128 -0
  153. data/tests/test_proxy_connection.rb +180 -0
  154. data/tests/test_pure.rb +156 -0
  155. data/tests/test_queue.rb +64 -0
  156. data/tests/test_resolver.rb +129 -0
  157. data/tests/test_running.rb +14 -0
  158. data/tests/test_sasl.rb +46 -0
  159. data/tests/test_send_file.rb +217 -0
  160. data/tests/test_servers.rb +32 -0
  161. data/tests/test_shutdown_hooks.rb +23 -0
  162. data/tests/test_smtpclient.rb +75 -0
  163. data/tests/test_smtpserver.rb +90 -0
  164. data/tests/test_sock_opt.rb +53 -0
  165. data/tests/test_spawn.rb +290 -0
  166. data/tests/test_ssl_args.rb +41 -0
  167. data/tests/test_ssl_dhparam.rb +57 -0
  168. data/tests/test_ssl_ecdh_curve.rb +57 -0
  169. data/tests/test_ssl_extensions.rb +24 -0
  170. data/tests/test_ssl_methods.rb +31 -0
  171. data/tests/test_ssl_protocols.rb +190 -0
  172. data/tests/test_ssl_verify.rb +52 -0
  173. data/tests/test_stomp.rb +38 -0
  174. data/tests/test_system.rb +46 -0
  175. data/tests/test_threaded_resource.rb +68 -0
  176. data/tests/test_tick_loop.rb +58 -0
  177. data/tests/test_timers.rb +150 -0
  178. data/tests/test_ud.rb +8 -0
  179. data/tests/test_unbind_reason.rb +40 -0
  180. metadata +384 -0
@@ -0,0 +1,2238 @@
1
+ /*****************************************************************************
2
+
3
+ $Id$
4
+
5
+ File: ed.cpp
6
+ Date: 06Apr06
7
+
8
+ Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
9
+ Gmail: blackhedd
10
+
11
+ This program is free software; you can redistribute it and/or modify
12
+ it under the terms of either: 1) the GNU General Public License
13
+ as published by the Free Software Foundation; either version 2 of the
14
+ License, or (at your option) any later version; or 2) Ruby's License.
15
+
16
+ See the file COPYING for complete licensing information.
17
+
18
+ *****************************************************************************/
19
+
20
+ #include "project.h"
21
+
22
+
23
+
24
+ /********************
25
+ SetSocketNonblocking
26
+ ********************/
27
+
28
+ bool SetSocketNonblocking (SOCKET sd)
29
+ {
30
+ #ifdef OS_UNIX
31
+ int val = fcntl (sd, F_GETFL, 0);
32
+ return (fcntl (sd, F_SETFL, val | O_NONBLOCK) != SOCKET_ERROR) ? true : false;
33
+ #endif
34
+
35
+ #ifdef OS_WIN32
36
+ #ifdef BUILD_FOR_RUBY
37
+ // 14Jun09 Ruby provides its own wrappers for ioctlsocket. On 1.8 this is a simple wrapper,
38
+ // however, 1.9 keeps its own state about the socket.
39
+ // NOTE: F_GETFL is not supported
40
+ return (fcntl (sd, F_SETFL, O_NONBLOCK) == 0) ? true : false;
41
+ #else
42
+ unsigned long one = 1;
43
+ return (ioctlsocket (sd, FIONBIO, &one) == 0) ? true : false;
44
+ #endif
45
+ #endif
46
+ }
47
+
48
+ /************
49
+ SetFdCloexec
50
+ ************/
51
+
52
+ #ifdef OS_UNIX
53
+ bool SetFdCloexec (int fd)
54
+ {
55
+ int flags = fcntl(fd, F_GETFD, 0);
56
+ assert (flags >= 0);
57
+ flags |= FD_CLOEXEC;
58
+ return (fcntl(fd, F_SETFD, FD_CLOEXEC) == 0) ? true : false;
59
+ }
60
+ #else
61
+ bool SetFdCloexec (int fd UNUSED)
62
+ {
63
+ return true;
64
+ }
65
+ #endif
66
+
67
+ /****************************************
68
+ EventableDescriptor::EventableDescriptor
69
+ ****************************************/
70
+
71
+ EventableDescriptor::EventableDescriptor (SOCKET sd, EventMachine_t *em):
72
+ bCloseNow (false),
73
+ bCloseAfterWriting (false),
74
+ MySocket (sd),
75
+ bAttached (false),
76
+ bWatchOnly (false),
77
+ EventCallback (NULL),
78
+ bCallbackUnbind (true),
79
+ UnbindReasonCode (0),
80
+ ProxyTarget(NULL),
81
+ ProxiedFrom(NULL),
82
+ ProxiedBytes(0),
83
+ MaxOutboundBufSize(0),
84
+ MyEventMachine (em),
85
+ PendingConnectTimeout(20000000),
86
+ InactivityTimeout (0),
87
+ NextHeartbeat (0),
88
+ bPaused (false)
89
+ {
90
+ /* There are three ways to close a socket, all of which should
91
+ * automatically signal to the event machine that this object
92
+ * should be removed from the polling scheduler.
93
+ * First is a hard close, intended for bad errors or possible
94
+ * security violations. It immediately closes the connection
95
+ * and puts this object into an error state.
96
+ * Second is to set bCloseNow, which will cause the event machine
97
+ * to delete this object (and thus close the connection in our
98
+ * destructor) the next chance it gets. bCloseNow also inhibits
99
+ * the writing of new data on the socket (but not necessarily
100
+ * the reading of new data).
101
+ * The third way is to set bCloseAfterWriting, which inhibits
102
+ * the writing of new data and converts to bCloseNow as soon
103
+ * as everything in the outbound queue has been written.
104
+ * bCloseAfterWriting is really for use only by protocol handlers
105
+ * (for example, HTTP writes an HTML page and then closes the
106
+ * connection). All of the error states we generate internally
107
+ * cause an immediate close to be scheduled, which may have the
108
+ * effect of discarding outbound data.
109
+ */
110
+
111
+ if (sd == INVALID_SOCKET)
112
+ throw std::runtime_error ("bad eventable descriptor");
113
+ if (MyEventMachine == NULL)
114
+ throw std::runtime_error ("bad em in eventable descriptor");
115
+ CreatedAt = MyEventMachine->GetCurrentLoopTime();
116
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
117
+
118
+ #ifdef HAVE_EPOLL
119
+ EpollEvent.events = 0;
120
+ EpollEvent.data.ptr = this;
121
+ #endif
122
+ }
123
+
124
+
125
+ /*****************************************
126
+ EventableDescriptor::~EventableDescriptor
127
+ *****************************************/
128
+
129
+ EventableDescriptor::~EventableDescriptor() NO_EXCEPT_FALSE
130
+ {
131
+ if (NextHeartbeat)
132
+ MyEventMachine->ClearHeartbeat(NextHeartbeat, this);
133
+ if (EventCallback && bCallbackUnbind)
134
+ (*EventCallback)(GetBinding(), EM_CONNECTION_UNBOUND, NULL, UnbindReasonCode);
135
+ if (ProxiedFrom) {
136
+ (*EventCallback)(ProxiedFrom->GetBinding(), EM_PROXY_TARGET_UNBOUND, NULL, 0);
137
+ ProxiedFrom->StopProxy();
138
+ }
139
+ MyEventMachine->NumCloseScheduled--;
140
+ StopProxy();
141
+ Close();
142
+ }
143
+
144
+
145
+ /*************************************
146
+ EventableDescriptor::SetEventCallback
147
+ *************************************/
148
+
149
+ void EventableDescriptor::SetEventCallback (EMCallback cb)
150
+ {
151
+ EventCallback = cb;
152
+ }
153
+
154
+
155
+ /**************************
156
+ EventableDescriptor::Close
157
+ **************************/
158
+
159
+ void EventableDescriptor::Close()
160
+ {
161
+ /* EventMachine relies on the fact that when close(fd)
162
+ * is called that the fd is removed from any
163
+ * epoll event queues.
164
+ *
165
+ * However, this is not *always* the behavior of close(fd)
166
+ *
167
+ * See man 4 epoll Q6/A6 and then consider what happens
168
+ * when using pipes with eventmachine.
169
+ * (As is often done when communicating with a subprocess)
170
+ *
171
+ * The pipes end up looking like:
172
+ *
173
+ * ls -l /proc/<pid>/fd
174
+ * ...
175
+ * lr-x------ 1 root root 64 2011-08-19 21:31 3 -> pipe:[940970]
176
+ * l-wx------ 1 root root 64 2011-08-19 21:31 4 -> pipe:[940970]
177
+ *
178
+ * This meets the critera from man 4 epoll Q6/A4 for not
179
+ * removing fds from epoll event queues until all fds
180
+ * that reference the underlying file have been removed.
181
+ *
182
+ * If the EventableDescriptor associated with fd 3 is deleted,
183
+ * its dtor will call EventableDescriptor::Close(),
184
+ * which will call ::close(int fd).
185
+ *
186
+ * However, unless the EventableDescriptor associated with fd 4 is
187
+ * also deleted before the next call to epoll_wait, events may fire
188
+ * for fd 3 that were registered with an already deleted
189
+ * EventableDescriptor.
190
+ *
191
+ * Therefore, it is necessary to notify EventMachine that
192
+ * the fd associated with this EventableDescriptor is
193
+ * closing.
194
+ *
195
+ * EventMachine also never closes fds for STDIN, STDOUT and
196
+ * STDERR (0, 1 & 2)
197
+ */
198
+
199
+ // Close the socket right now. Intended for emergencies.
200
+ if (MySocket != INVALID_SOCKET) {
201
+ MyEventMachine->Deregister (this);
202
+
203
+ // Do not close STDIN, STDOUT, STDERR
204
+ if (MySocket > 2 && !bAttached) {
205
+ shutdown (MySocket, 1);
206
+ close (MySocket);
207
+ }
208
+
209
+ MySocket = INVALID_SOCKET;
210
+ }
211
+ }
212
+
213
+
214
+ /*********************************
215
+ EventableDescriptor::ShouldDelete
216
+ *********************************/
217
+
218
+ bool EventableDescriptor::ShouldDelete()
219
+ {
220
+ /* For use by a socket manager, which needs to know if this object
221
+ * should be removed from scheduling events and deleted.
222
+ * Has an immediate close been scheduled, or are we already closed?
223
+ * If either of these are the case, return true. In theory, the manager will
224
+ * then delete us, which in turn will make sure the socket is closed.
225
+ * Note, if bCloseAfterWriting is true, we check a virtual method to see
226
+ * if there is outbound data to write, and only request a close if there is none.
227
+ */
228
+
229
+ return ((MySocket == INVALID_SOCKET) || bCloseNow || (bCloseAfterWriting && (GetOutboundDataSize() <= 0)));
230
+ }
231
+
232
+
233
+ /**********************************
234
+ EventableDescriptor::ScheduleClose
235
+ **********************************/
236
+
237
+ void EventableDescriptor::ScheduleClose (bool after_writing)
238
+ {
239
+ if (IsCloseScheduled()) {
240
+ if (!after_writing) {
241
+ // If closing has become more urgent, then upgrade the scheduled
242
+ // after_writing close to one NOW.
243
+ bCloseNow = true;
244
+ }
245
+ return;
246
+ }
247
+ MyEventMachine->NumCloseScheduled++;
248
+ // KEEP THIS SYNCHRONIZED WITH ::IsCloseScheduled.
249
+ if (after_writing)
250
+ bCloseAfterWriting = true;
251
+ else
252
+ bCloseNow = true;
253
+ }
254
+
255
+
256
+ /*************************************
257
+ EventableDescriptor::IsCloseScheduled
258
+ *************************************/
259
+
260
+ bool EventableDescriptor::IsCloseScheduled()
261
+ {
262
+ // KEEP THIS SYNCHRONIZED WITH ::ScheduleClose.
263
+ return (bCloseNow || bCloseAfterWriting);
264
+ }
265
+
266
+
267
+ /***********************************
268
+ EventableDescriptor::EnableKeepalive
269
+ ***********************************/
270
+ int EventableDescriptor::EnableKeepalive(int idle, int intvl, int cnt)
271
+ {
272
+ int ret;
273
+
274
+ #ifdef OS_WIN32
275
+ DWORD len;
276
+ struct tcp_keepalive args;
277
+
278
+ args.onoff = 1;
279
+
280
+ if (idle > 0)
281
+ args.keepalivetime = idle * 1000;
282
+ if (intvl > 0)
283
+ args.keepaliveinterval = intvl * 1000;
284
+
285
+ ret = WSAIoctl(MySocket, SIO_KEEPALIVE_VALS, &args, sizeof(args), NULL, 0, &len, NULL, NULL);
286
+ if (ret < 0) {
287
+ int err = WSAGetLastError();
288
+ char buf[200];
289
+ buf[0] = '\0';
290
+
291
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
292
+ NULL, err, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof(buf), NULL);
293
+
294
+ if (! buf[0])
295
+ snprintf (buf, sizeof(buf)-1, "unable to enable keepalive: %d", err);
296
+
297
+ throw std::runtime_error (buf);
298
+ }
299
+
300
+ #else
301
+ int val = 1;
302
+
303
+ // All the Unixen
304
+ ret = setsockopt(MySocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
305
+ if (ret < 0) {
306
+ char buf[200];
307
+ snprintf (buf, sizeof(buf)-1, "unable to enable keepalive: %s", strerror(errno));
308
+ throw std::runtime_error (buf);
309
+ }
310
+
311
+ #ifdef TCP_KEEPALIVE
312
+ // BSDs and Mac OS X: idle time used when SO_KEEPALIVE is enabled
313
+ // 0 means use the system default value, so we let it through
314
+ if (idle >= 0) {
315
+ ret = setsockopt(MySocket, IPPROTO_TCP, TCP_KEEPALIVE, &idle, sizeof(idle));
316
+ if (ret < 0) {
317
+ char buf[200];
318
+ snprintf (buf, sizeof(buf)-1, "unable set keepalive idle: %s", strerror(errno));
319
+ throw std::runtime_error (buf);
320
+ }
321
+ }
322
+ #endif
323
+ #ifdef TCP_KEEPIDLE
324
+ // Linux: interval between last data pkt and first keepalive pkt
325
+ if (idle > 0) {
326
+ ret = setsockopt(MySocket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
327
+ if (ret < 0) {
328
+ char buf[200];
329
+ snprintf (buf, sizeof(buf)-1, "unable set keepalive idle: %s", strerror(errno));
330
+ throw std::runtime_error (buf);
331
+ }
332
+ }
333
+ #endif
334
+ #ifdef TCP_KEEPINTVL
335
+ // Linux (and recent BSDs, Mac OS X, Solaris): interval between keepalives
336
+ if (intvl > 0) {
337
+ ret = setsockopt(MySocket, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
338
+ if (ret < 0) {
339
+ char buf[200];
340
+ snprintf (buf, sizeof(buf)-1, "unable set keepalive interval: %s", strerror(errno));
341
+ throw std::runtime_error (buf);
342
+ }
343
+ }
344
+ #endif
345
+ #ifdef TCP_KEEPCNT
346
+ // Linux (and recent BSDs, Mac OS X, Solaris): number of dropped probes before disconnect
347
+ if (cnt > 0) {
348
+ ret = setsockopt(MySocket, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
349
+ if (ret < 0) {
350
+ char buf[200];
351
+ snprintf (buf, sizeof(buf)-1, "unable set keepalive count: %s", strerror(errno));
352
+ throw std::runtime_error (buf);
353
+ }
354
+ }
355
+ #endif
356
+ #endif
357
+
358
+ return ret;
359
+ }
360
+
361
+ /***********************************
362
+ EventableDescriptor::DisableKeepalive
363
+ ***********************************/
364
+ int EventableDescriptor::DisableKeepalive()
365
+ {
366
+ int ret;
367
+
368
+ #ifdef OS_WIN32
369
+ DWORD len;
370
+ struct tcp_keepalive args;
371
+ args.onoff = 0;
372
+ ret = WSAIoctl(MySocket, SIO_KEEPALIVE_VALS, &args, sizeof(args), NULL, 0, &len, NULL, NULL);
373
+ if (ret < 0) {
374
+ int err = WSAGetLastError();
375
+ char buf[200];
376
+ buf[0] = '\0';
377
+
378
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
379
+ NULL, err, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof(buf), NULL);
380
+
381
+ if (! buf[0])
382
+ snprintf (buf, sizeof(buf)-1, "unable to enable keepalive: %d", err);
383
+
384
+ throw std::runtime_error (buf);
385
+ }
386
+ #else
387
+ int val = 0;
388
+ ret = setsockopt(MySocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
389
+ if (ret < 0) {
390
+ char buf[200];
391
+ snprintf (buf, sizeof(buf)-1, "unable to disable keepalive: %s", strerror(errno));
392
+ throw std::runtime_error (buf);
393
+ }
394
+ #endif
395
+
396
+ return ret;
397
+ }
398
+
399
+
400
+ /*******************************
401
+ EventableDescriptor::StartProxy
402
+ *******************************/
403
+
404
+ void EventableDescriptor::StartProxy(const uintptr_t to, const unsigned long bufsize, const unsigned long length)
405
+ {
406
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (to));
407
+ if (ed) {
408
+ StopProxy();
409
+ ProxyTarget = ed;
410
+ BytesToProxy = length;
411
+ ProxiedBytes = 0;
412
+ ed->SetProxiedFrom(this, bufsize);
413
+ return;
414
+ }
415
+ throw std::runtime_error ("Tried to proxy to an invalid descriptor");
416
+ }
417
+
418
+
419
+ /******************************
420
+ EventableDescriptor::StopProxy
421
+ ******************************/
422
+
423
+ void EventableDescriptor::StopProxy()
424
+ {
425
+ if (ProxyTarget) {
426
+ ProxyTarget->SetProxiedFrom(NULL, 0);
427
+ ProxyTarget = NULL;
428
+ }
429
+ }
430
+
431
+
432
+ /***********************************
433
+ EventableDescriptor::SetProxiedFrom
434
+ ***********************************/
435
+
436
+ void EventableDescriptor::SetProxiedFrom(EventableDescriptor *from, const unsigned long bufsize)
437
+ {
438
+ if (from != NULL && ProxiedFrom != NULL)
439
+ throw std::runtime_error ("Tried to proxy to a busy target");
440
+
441
+ ProxiedFrom = from;
442
+ MaxOutboundBufSize = bufsize;
443
+ }
444
+
445
+
446
+ /********************************************
447
+ EventableDescriptor::_GenericInboundDispatch
448
+ ********************************************/
449
+
450
+ void EventableDescriptor::_GenericInboundDispatch(const char *buf, unsigned long size)
451
+ {
452
+ assert(EventCallback);
453
+
454
+ if (ProxyTarget) {
455
+ if (BytesToProxy > 0) {
456
+ unsigned long proxied = std::min(BytesToProxy, size);
457
+ ProxyTarget->SendOutboundData(buf, proxied);
458
+ ProxiedBytes += (unsigned long) proxied;
459
+ BytesToProxy -= proxied;
460
+ if (BytesToProxy == 0) {
461
+ StopProxy();
462
+ (*EventCallback)(GetBinding(), EM_PROXY_COMPLETED, NULL, 0);
463
+ if (proxied < size) {
464
+ (*EventCallback)(GetBinding(), EM_CONNECTION_READ, buf + proxied, size - proxied);
465
+ }
466
+ }
467
+ } else {
468
+ ProxyTarget->SendOutboundData(buf, size);
469
+ ProxiedBytes += size;
470
+ }
471
+ } else {
472
+ (*EventCallback)(GetBinding(), EM_CONNECTION_READ, buf, size);
473
+ }
474
+ }
475
+
476
+
477
+ /*********************************
478
+ EventableDescriptor::_GenericGetPeername
479
+ *********************************/
480
+
481
+ bool EventableDescriptor::_GenericGetPeername (struct sockaddr *s, socklen_t *len)
482
+ {
483
+ if (!s)
484
+ return false;
485
+
486
+ int gp = getpeername (GetSocket(), s, len);
487
+ if (gp == -1) {
488
+ char buf[200];
489
+ snprintf (buf, sizeof(buf)-1, "unable to get peer name: %s", strerror(errno));
490
+ throw std::runtime_error (buf);
491
+ }
492
+
493
+ return true;
494
+ }
495
+
496
+ /*********************************
497
+ EventableDescriptor::_GenericGetSockname
498
+ *********************************/
499
+
500
+ bool EventableDescriptor::_GenericGetSockname (struct sockaddr *s, socklen_t *len)
501
+ {
502
+ if (!s)
503
+ return false;
504
+
505
+ int gp = getsockname (GetSocket(), s, len);
506
+ if (gp == -1) {
507
+ char buf[200];
508
+ snprintf (buf, sizeof(buf)-1, "unable to get sock name: %s", strerror(errno));
509
+ throw std::runtime_error (buf);
510
+ }
511
+
512
+ return true;
513
+ }
514
+
515
+
516
+ /*********************************************
517
+ EventableDescriptor::GetPendingConnectTimeout
518
+ *********************************************/
519
+
520
+ uint64_t EventableDescriptor::GetPendingConnectTimeout()
521
+ {
522
+ return PendingConnectTimeout / 1000;
523
+ }
524
+
525
+
526
+ /*********************************************
527
+ EventableDescriptor::SetPendingConnectTimeout
528
+ *********************************************/
529
+
530
+ int EventableDescriptor::SetPendingConnectTimeout (uint64_t value)
531
+ {
532
+ if (value > 0) {
533
+ PendingConnectTimeout = value * 1000;
534
+ MyEventMachine->QueueHeartbeat(this);
535
+ return 1;
536
+ }
537
+ return 0;
538
+ }
539
+
540
+
541
+ /*************************************
542
+ EventableDescriptor::GetNextHeartbeat
543
+ *************************************/
544
+
545
+ uint64_t EventableDescriptor::GetNextHeartbeat()
546
+ {
547
+ if (NextHeartbeat)
548
+ MyEventMachine->ClearHeartbeat(NextHeartbeat, this);
549
+
550
+ NextHeartbeat = 0;
551
+
552
+ if (!ShouldDelete()) {
553
+ uint64_t time_til_next = InactivityTimeout;
554
+ if (IsConnectPending()) {
555
+ if (time_til_next == 0 || PendingConnectTimeout < time_til_next)
556
+ time_til_next = PendingConnectTimeout;
557
+ }
558
+ if (time_til_next == 0)
559
+ return 0;
560
+ NextHeartbeat = time_til_next + MyEventMachine->GetRealTime();
561
+ }
562
+
563
+ return NextHeartbeat;
564
+ }
565
+
566
+
567
+ /******************************************
568
+ ConnectionDescriptor::ConnectionDescriptor
569
+ ******************************************/
570
+
571
+ ConnectionDescriptor::ConnectionDescriptor (SOCKET sd, EventMachine_t *em):
572
+ EventableDescriptor (sd, em),
573
+ bConnectPending (false),
574
+ bNotifyReadable (false),
575
+ bNotifyWritable (false),
576
+ bReadAttemptedAfterClose (false),
577
+ bWriteAttemptedAfterClose (false),
578
+ OutboundDataSize (0),
579
+ #ifdef WITH_SSL
580
+ SslBox (NULL),
581
+ bHandshakeSignaled (false),
582
+ bSslVerifyPeer (false),
583
+ bSslPeerAccepted(false),
584
+ #endif
585
+ #ifdef HAVE_KQUEUE
586
+ bGotExtraKqueueEvent(false),
587
+ #endif
588
+ bIsServer (false)
589
+ {
590
+ // 22Jan09: Moved ArmKqueueWriter into SetConnectPending() to fix assertion failure in _WriteOutboundData()
591
+ // 5May09: Moved EPOLLOUT into SetConnectPending() so it doesn't happen for attached read pipes
592
+ }
593
+
594
+
595
+ /*******************************************
596
+ ConnectionDescriptor::~ConnectionDescriptor
597
+ *******************************************/
598
+
599
+ ConnectionDescriptor::~ConnectionDescriptor()
600
+ {
601
+ // Run down any stranded outbound data.
602
+ for (size_t i=0; i < OutboundPages.size(); i++)
603
+ OutboundPages[i].Free();
604
+
605
+ #ifdef WITH_SSL
606
+ if (SslBox)
607
+ delete SslBox;
608
+ #endif
609
+ }
610
+
611
+
612
+ /***********************************
613
+ ConnectionDescriptor::_UpdateEvents
614
+ ************************************/
615
+
616
+ void ConnectionDescriptor::_UpdateEvents()
617
+ {
618
+ _UpdateEvents(true, true);
619
+ }
620
+
621
+ void ConnectionDescriptor::_UpdateEvents(bool read, bool write)
622
+ {
623
+ if (MySocket == INVALID_SOCKET)
624
+ return;
625
+
626
+ if (!read && !write)
627
+ return;
628
+
629
+ #ifdef HAVE_EPOLL
630
+ unsigned int old = EpollEvent.events;
631
+
632
+ if (read) {
633
+ if (SelectForRead())
634
+ EpollEvent.events |= EPOLLIN;
635
+ else
636
+ EpollEvent.events &= ~EPOLLIN;
637
+ }
638
+
639
+ if (write) {
640
+ if (SelectForWrite())
641
+ EpollEvent.events |= EPOLLOUT;
642
+ else
643
+ EpollEvent.events &= ~EPOLLOUT;
644
+ }
645
+
646
+ if (old != EpollEvent.events)
647
+ MyEventMachine->Modify (this);
648
+ #endif
649
+
650
+ #ifdef HAVE_KQUEUE
651
+ if (read && SelectForRead())
652
+ MyEventMachine->ArmKqueueReader (this);
653
+ bKqueueArmWrite = SelectForWrite();
654
+ if (write && bKqueueArmWrite)
655
+ MyEventMachine->Modify (this);
656
+ #endif
657
+ }
658
+
659
+ /***************************************
660
+ ConnectionDescriptor::SetConnectPending
661
+ ****************************************/
662
+
663
+ void ConnectionDescriptor::SetConnectPending(bool f)
664
+ {
665
+ bConnectPending = f;
666
+ MyEventMachine->QueueHeartbeat(this);
667
+ _UpdateEvents();
668
+ }
669
+
670
+
671
+ /**********************************
672
+ ConnectionDescriptor::SetAttached
673
+ ***********************************/
674
+
675
+ void ConnectionDescriptor::SetAttached(bool state)
676
+ {
677
+ bAttached = state;
678
+ }
679
+
680
+
681
+ /**********************************
682
+ ConnectionDescriptor::SetWatchOnly
683
+ ***********************************/
684
+
685
+ void ConnectionDescriptor::SetWatchOnly(bool watching)
686
+ {
687
+ bWatchOnly = watching;
688
+ _UpdateEvents();
689
+ }
690
+
691
+
692
+ /*********************************
693
+ ConnectionDescriptor::HandleError
694
+ *********************************/
695
+
696
+ void ConnectionDescriptor::HandleError()
697
+ {
698
+ if (bWatchOnly) {
699
+ // An EPOLLHUP | EPOLLIN condition will call Read() before HandleError(), in which case the
700
+ // socket is already detached and invalid, so we don't need to do anything.
701
+ if (MySocket == INVALID_SOCKET) return;
702
+
703
+ // HandleError() is called on WatchOnly descriptors by the epoll reactor
704
+ // when it gets a EPOLLERR | EPOLLHUP. Usually this would show up as a readable and
705
+ // writable event on other reactors, so we have to fire those events ourselves.
706
+ if (bNotifyReadable) Read();
707
+ if (bNotifyWritable) Write();
708
+ } else {
709
+ ScheduleClose (false);
710
+ }
711
+ }
712
+
713
+
714
+ /***********************************
715
+ ConnectionDescriptor::ScheduleClose
716
+ ***********************************/
717
+
718
+ void ConnectionDescriptor::ScheduleClose (bool after_writing)
719
+ {
720
+ if (bWatchOnly)
721
+ throw std::runtime_error ("cannot close 'watch only' connections");
722
+
723
+ EventableDescriptor::ScheduleClose(after_writing);
724
+ }
725
+
726
+
727
+ /***************************************
728
+ ConnectionDescriptor::SetNotifyReadable
729
+ ****************************************/
730
+
731
+ void ConnectionDescriptor::SetNotifyReadable(bool readable)
732
+ {
733
+ if (!bWatchOnly)
734
+ throw std::runtime_error ("notify_readable must be on 'watch only' connections");
735
+
736
+ bNotifyReadable = readable;
737
+ _UpdateEvents(true, false);
738
+ }
739
+
740
+
741
+ /***************************************
742
+ ConnectionDescriptor::SetNotifyWritable
743
+ ****************************************/
744
+
745
+ void ConnectionDescriptor::SetNotifyWritable(bool writable)
746
+ {
747
+ if (!bWatchOnly)
748
+ throw std::runtime_error ("notify_writable must be on 'watch only' connections");
749
+
750
+ bNotifyWritable = writable;
751
+ _UpdateEvents(false, true);
752
+ }
753
+
754
+
755
+ /**************************************
756
+ ConnectionDescriptor::SendOutboundData
757
+ **************************************/
758
+
759
+ int ConnectionDescriptor::SendOutboundData (const char *data, unsigned long length)
760
+ {
761
+ if (bWatchOnly)
762
+ throw std::runtime_error ("cannot send data on a 'watch only' connection");
763
+
764
+ if (ProxiedFrom && MaxOutboundBufSize && (unsigned int)(GetOutboundDataSize() + length) > MaxOutboundBufSize)
765
+ ProxiedFrom->Pause();
766
+
767
+ #ifdef WITH_SSL
768
+ if (SslBox) {
769
+ if (length > 0) {
770
+ unsigned long writed = 0;
771
+ char *p = (char*)data;
772
+
773
+ while (writed < length) {
774
+ int to_write = SSLBOX_INPUT_CHUNKSIZE;
775
+ int remaining = length - writed;
776
+
777
+ if (remaining < SSLBOX_INPUT_CHUNKSIZE)
778
+ to_write = remaining;
779
+
780
+ int w = SslBox->PutPlaintext (p, to_write);
781
+ if (w < 0) {
782
+ ScheduleClose (false);
783
+ }else
784
+ _DispatchCiphertext();
785
+
786
+ p += to_write;
787
+ writed += to_write;
788
+ }
789
+ }
790
+ // TODO: What's the correct return value?
791
+ return 1; // That's a wild guess, almost certainly wrong.
792
+ }
793
+ else
794
+ #endif
795
+ return _SendRawOutboundData (data, length);
796
+ }
797
+
798
+
799
+
800
+ /******************************************
801
+ ConnectionDescriptor::_SendRawOutboundData
802
+ ******************************************/
803
+
804
+ int ConnectionDescriptor::_SendRawOutboundData (const char *data, unsigned long length)
805
+ {
806
+ /* This internal method is called to schedule bytes that
807
+ * will be sent out to the remote peer.
808
+ * It's not directly accessed by the caller, who hits ::SendOutboundData,
809
+ * which may or may not filter or encrypt the caller's data before
810
+ * sending it here.
811
+ */
812
+
813
+ // Highly naive and incomplete implementation.
814
+ // There's no throttle for runaways (which should abort only this connection
815
+ // and not the whole process), and no coalescing of small pages.
816
+ // (Well, not so bad, small pages are coalesced in ::Write)
817
+
818
+ if (IsCloseScheduled())
819
+ return 0;
820
+ // 25Mar10: Ignore 0 length packets as they are not meaningful in TCP (as opposed to UDP)
821
+ // and can cause the assert(nbytes>0) to fail when OutboundPages has a bunch of 0 length pages.
822
+ if (length == 0)
823
+ return 0;
824
+
825
+ if (!data && (length > 0))
826
+ throw std::runtime_error ("bad outbound data");
827
+ char *buffer = (char *) malloc (length + 1);
828
+ if (!buffer)
829
+ throw std::runtime_error ("no allocation for outbound data");
830
+
831
+ memcpy (buffer, data, length);
832
+ buffer [length] = 0;
833
+ OutboundPages.push_back (OutboundPage (buffer, length));
834
+ OutboundDataSize += length;
835
+
836
+ _UpdateEvents(false, true);
837
+
838
+ return length;
839
+ }
840
+
841
+
842
+
843
+ /***********************************
844
+ ConnectionDescriptor::SelectForRead
845
+ ***********************************/
846
+
847
+ bool ConnectionDescriptor::SelectForRead()
848
+ {
849
+ /* A connection descriptor is always scheduled for read,
850
+ * UNLESS it's in a pending-connect state.
851
+ * On Linux, unlike Unix, a nonblocking socket on which
852
+ * connect has been called, does NOT necessarily select
853
+ * both readable and writable in case of error.
854
+ * The socket will select writable when the disposition
855
+ * of the connect is known. On the other hand, a socket
856
+ * which successfully connects and selects writable may
857
+ * indeed have some data available on it, so it will
858
+ * select readable in that case, violating expectations!
859
+ * So we will not poll for readability until the socket
860
+ * is known to be in a connected state.
861
+ */
862
+
863
+ if (bPaused)
864
+ return false;
865
+ else if (bConnectPending)
866
+ return false;
867
+ else if (bWatchOnly)
868
+ return bNotifyReadable ? true : false;
869
+ else
870
+ return true;
871
+ }
872
+
873
+
874
+ /************************************
875
+ ConnectionDescriptor::SelectForWrite
876
+ ************************************/
877
+
878
+ bool ConnectionDescriptor::SelectForWrite()
879
+ {
880
+ /* Cf the notes under SelectForRead.
881
+ * In a pending-connect state, we ALWAYS select for writable.
882
+ * In a normal state, we only select for writable when we
883
+ * have outgoing data to send.
884
+ */
885
+
886
+ if (bPaused)
887
+ return false;
888
+ else if (bConnectPending)
889
+ return true;
890
+ else if (bWatchOnly)
891
+ return bNotifyWritable ? true : false;
892
+ else
893
+ return (GetOutboundDataSize() > 0);
894
+ }
895
+
896
+ /***************************
897
+ ConnectionDescriptor::Pause
898
+ ***************************/
899
+
900
+ bool ConnectionDescriptor::Pause()
901
+ {
902
+ if (bWatchOnly)
903
+ throw std::runtime_error ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
904
+
905
+ bool old = bPaused;
906
+ bPaused = true;
907
+ _UpdateEvents();
908
+ return old == false;
909
+ }
910
+
911
+ /****************************
912
+ ConnectionDescriptor::Resume
913
+ ****************************/
914
+
915
+ bool ConnectionDescriptor::Resume()
916
+ {
917
+ if (bWatchOnly)
918
+ throw std::runtime_error ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
919
+
920
+ bool old = bPaused;
921
+ bPaused = false;
922
+ _UpdateEvents();
923
+ return old == true;
924
+ }
925
+
926
+ /**************************
927
+ ConnectionDescriptor::Read
928
+ **************************/
929
+
930
+ void ConnectionDescriptor::Read()
931
+ {
932
+ /* Read and dispatch data on a socket that has selected readable.
933
+ * It's theoretically possible to get and dispatch incoming data on
934
+ * a socket that has already been scheduled for closing or close-after-writing.
935
+ * In those cases, we'll leave it up the to protocol handler to "do the
936
+ * right thing" (which probably means to ignore the incoming data).
937
+ *
938
+ * 22Aug06: Chris Ochs reports that on FreeBSD, it's possible to come
939
+ * here with the socket already closed, after the process receives
940
+ * a ctrl-C signal (not sure if that's TERM or INT on BSD). The application
941
+ * was one in which network connections were doing a lot of interleaved reads
942
+ * and writes.
943
+ * Since we always write before reading (in order to keep the outbound queues
944
+ * as light as possible), I think what happened is that an interrupt caused
945
+ * the socket to be closed in ConnectionDescriptor::Write. We'll then
946
+ * come here in the same pass through the main event loop, and won't get
947
+ * cleaned up until immediately after.
948
+ * We originally asserted that the socket was valid when we got here.
949
+ * To deal properly with the possibility that we are closed when we get here,
950
+ * I removed the assert. HOWEVER, the potential for an infinite loop scares me,
951
+ * so even though this is really clunky, I added a flag to assert that we never
952
+ * come here more than once after being closed. (FCianfrocca)
953
+ */
954
+
955
+ SOCKET sd = GetSocket();
956
+ //assert (sd != INVALID_SOCKET); (original, removed 22Aug06)
957
+ if (sd == INVALID_SOCKET) {
958
+ assert (!bReadAttemptedAfterClose);
959
+ bReadAttemptedAfterClose = true;
960
+ return;
961
+ }
962
+
963
+ if (bWatchOnly) {
964
+ if (bNotifyReadable && EventCallback)
965
+ (*EventCallback)(GetBinding(), EM_CONNECTION_NOTIFY_READABLE, NULL, 0);
966
+ return;
967
+ }
968
+
969
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
970
+
971
+ int total_bytes_read = 0;
972
+ char readbuffer [16 * 1024 + 1];
973
+
974
+ for (int i=0; i < 10; i++) {
975
+ // Don't read just one buffer and then move on. This is faster
976
+ // if there is a lot of incoming.
977
+ // But don't read indefinitely. Give other sockets a chance to run.
978
+ // NOTICE, we're reading one less than the buffer size.
979
+ // That's so we can put a guard byte at the end of what we send
980
+ // to user code.
981
+
982
+
983
+ int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
984
+ #ifdef OS_WIN32
985
+ int e = WSAGetLastError();
986
+ #else
987
+ int e = errno;
988
+ #endif
989
+ //cerr << "<R:" << r << ">";
990
+
991
+ if (r > 0) {
992
+ total_bytes_read += r;
993
+
994
+ // Add a null-terminator at the the end of the buffer
995
+ // that we will send to the callback.
996
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
997
+ // to be able to depend on this behavior, so they will have
998
+ // the option to do some things faster. Additionally it's
999
+ // a security guard against buffer overflows.
1000
+ readbuffer [r] = 0;
1001
+ _DispatchInboundData (readbuffer, r);
1002
+ if (bPaused)
1003
+ break;
1004
+ }
1005
+ else if (r == 0) {
1006
+ break;
1007
+ }
1008
+ else {
1009
+ #ifdef OS_UNIX
1010
+ if ((e != EINPROGRESS) && (e != EWOULDBLOCK) && (e != EAGAIN) && (e != EINTR)) {
1011
+ #endif
1012
+ #ifdef OS_WIN32
1013
+ if ((e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK)) {
1014
+ #endif
1015
+ // 26Mar11: Previously, all read errors were assumed to be EWOULDBLOCK and ignored.
1016
+ // Now, instead, we call Close() on errors like ECONNRESET and ENOTCONN.
1017
+ UnbindReasonCode = e;
1018
+ Close();
1019
+ break;
1020
+ } else {
1021
+ // Basically a would-block, meaning we've read everything there is to read.
1022
+ break;
1023
+ }
1024
+ }
1025
+
1026
+ }
1027
+
1028
+
1029
+ if (total_bytes_read == 0) {
1030
+ // If we read no data on a socket that selected readable,
1031
+ // it generally means the other end closed the connection gracefully.
1032
+ ScheduleClose (false);
1033
+ //bCloseNow = true;
1034
+ }
1035
+
1036
+ }
1037
+
1038
+
1039
+
1040
+ /******************************************
1041
+ ConnectionDescriptor::_DispatchInboundData
1042
+ ******************************************/
1043
+
1044
+ #ifdef WITH_SSL
1045
+ void ConnectionDescriptor::_DispatchInboundData (const char *buffer, unsigned long size)
1046
+ {
1047
+ if (SslBox) {
1048
+ SslBox->PutCiphertext (buffer, size);
1049
+
1050
+ int s;
1051
+ char B [2048];
1052
+ while ((s = SslBox->GetPlaintext (B, sizeof(B) - 1)) > 0) {
1053
+ _CheckHandshakeStatus();
1054
+ B [s] = 0;
1055
+ _GenericInboundDispatch(B, s);
1056
+ }
1057
+
1058
+ // If our SSL handshake had a problem, shut down the connection.
1059
+ if (s == -2) {
1060
+ #ifndef EPROTO // OpenBSD does not have EPROTO
1061
+ #define EPROTO EINTR
1062
+ #endif
1063
+ #ifdef OS_UNIX
1064
+ UnbindReasonCode = EPROTO;
1065
+ #endif
1066
+ #ifdef OS_WIN32
1067
+ UnbindReasonCode = WSAECONNABORTED;
1068
+ #endif
1069
+ ScheduleClose(false);
1070
+ return;
1071
+ }
1072
+
1073
+ _CheckHandshakeStatus();
1074
+ _DispatchCiphertext();
1075
+ }
1076
+ else {
1077
+ _GenericInboundDispatch(buffer, size);
1078
+ }
1079
+ }
1080
+ #else
1081
+ void ConnectionDescriptor::_DispatchInboundData (const char *buffer, unsigned long size)
1082
+ {
1083
+ _GenericInboundDispatch(buffer, size);
1084
+ }
1085
+ #endif
1086
+
1087
+
1088
+
1089
+ /*******************************************
1090
+ ConnectionDescriptor::_CheckHandshakeStatus
1091
+ *******************************************/
1092
+
1093
+ void ConnectionDescriptor::_CheckHandshakeStatus()
1094
+ {
1095
+ #ifdef WITH_SSL
1096
+ if (SslBox && (!bHandshakeSignaled) && SslBox->IsHandshakeCompleted()) {
1097
+ bHandshakeSignaled = true;
1098
+ if (EventCallback)
1099
+ (*EventCallback)(GetBinding(), EM_SSL_HANDSHAKE_COMPLETED, NULL, 0);
1100
+ }
1101
+ #endif
1102
+ }
1103
+
1104
+
1105
+
1106
+ /***************************
1107
+ ConnectionDescriptor::Write
1108
+ ***************************/
1109
+
1110
+ void ConnectionDescriptor::Write()
1111
+ {
1112
+ /* A socket which is in a pending-connect state will select
1113
+ * writable when the disposition of the connect is known.
1114
+ * At that point, check to be sure there are no errors,
1115
+ * and if none, then promote the socket out of the pending
1116
+ * state.
1117
+ * TODO: I haven't figured out how Windows signals errors on
1118
+ * unconnected sockets. Maybe it does the untraditional but
1119
+ * logical thing and makes the socket selectable for error.
1120
+ * If so, it's unsupported here for the time being, and connect
1121
+ * errors will have to be caught by the timeout mechanism.
1122
+ */
1123
+
1124
+ if (bConnectPending) {
1125
+ int error;
1126
+ socklen_t len;
1127
+ len = sizeof(error);
1128
+ #ifdef OS_UNIX
1129
+ int o = getsockopt (GetSocket(), SOL_SOCKET, SO_ERROR, &error, &len);
1130
+ #endif
1131
+ #ifdef OS_WIN32
1132
+ int o = getsockopt (GetSocket(), SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1133
+ #endif
1134
+ if ((o == 0) && (error == 0)) {
1135
+ if (EventCallback)
1136
+ (*EventCallback)(GetBinding(), EM_CONNECTION_COMPLETED, "", 0);
1137
+
1138
+ // 5May09: Moved epoll/kqueue read/write arming into SetConnectPending, so it can be called
1139
+ // from EventMachine_t::AttachFD as well.
1140
+ SetConnectPending (false);
1141
+ }
1142
+ else {
1143
+ if (o == 0)
1144
+ UnbindReasonCode = error;
1145
+ ScheduleClose (false);
1146
+ //bCloseNow = true;
1147
+ }
1148
+ }
1149
+ else {
1150
+
1151
+ if (bNotifyWritable) {
1152
+ if (EventCallback)
1153
+ (*EventCallback)(GetBinding(), EM_CONNECTION_NOTIFY_WRITABLE, NULL, 0);
1154
+
1155
+ _UpdateEvents(false, true);
1156
+ return;
1157
+ }
1158
+
1159
+ assert(!bWatchOnly);
1160
+
1161
+ /* 5May09: Kqueue bugs on OSX cause one extra writable event to fire even though we're using
1162
+ EV_ONESHOT. We ignore this extra event once, but only the first time. If it happens again,
1163
+ we should fall through to the assert(nbytes>0) failure to catch any EM bugs which might cause
1164
+ ::Write to be called in a busy-loop.
1165
+ */
1166
+ #ifdef HAVE_KQUEUE
1167
+ if (MyEventMachine->GetPoller() == Poller_Kqueue) {
1168
+ if (OutboundDataSize == 0 && !bGotExtraKqueueEvent) {
1169
+ bGotExtraKqueueEvent = true;
1170
+ return;
1171
+ } else if (OutboundDataSize > 0) {
1172
+ bGotExtraKqueueEvent = false;
1173
+ }
1174
+ }
1175
+ #endif
1176
+
1177
+ _WriteOutboundData();
1178
+ }
1179
+ }
1180
+
1181
+
1182
+ /****************************************
1183
+ ConnectionDescriptor::_WriteOutboundData
1184
+ ****************************************/
1185
+
1186
+ void ConnectionDescriptor::_WriteOutboundData()
1187
+ {
1188
+ /* This is a helper function called by ::Write.
1189
+ * It's possible for a socket to select writable and then no longer
1190
+ * be writable by the time we get around to writing. The kernel might
1191
+ * have used up its available output buffers between the select call
1192
+ * and when we get here. So this condition is not an error.
1193
+ *
1194
+ * 20Jul07, added the same kind of protection against an invalid socket
1195
+ * that is at the top of ::Read. Not entirely how this could happen in
1196
+ * real life (connection-reset from the remote peer, perhaps?), but I'm
1197
+ * doing it to address some reports of crashing under heavy loads.
1198
+ */
1199
+
1200
+ SOCKET sd = GetSocket();
1201
+ //assert (sd != INVALID_SOCKET);
1202
+ if (sd == INVALID_SOCKET) {
1203
+ assert (!bWriteAttemptedAfterClose);
1204
+ bWriteAttemptedAfterClose = true;
1205
+ return;
1206
+ }
1207
+
1208
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
1209
+ size_t nbytes = 0;
1210
+
1211
+ #ifdef HAVE_WRITEV
1212
+ int iovcnt = OutboundPages.size();
1213
+ // Max of 16 outbound pages at a time
1214
+ if (iovcnt > 16) iovcnt = 16;
1215
+
1216
+ iovec iov[16];
1217
+
1218
+ for(int i = 0; i < iovcnt; i++){
1219
+ OutboundPage *op = &(OutboundPages[i]);
1220
+ #ifdef CC_SUNWspro
1221
+ // TODO: The void * cast works fine on Solaris 11, but
1222
+ // I don't know at what point that changed from older Solaris.
1223
+ iov[i].iov_base = (char *)(op->Buffer + op->Offset);
1224
+ #else
1225
+ iov[i].iov_base = (void *)(op->Buffer + op->Offset);
1226
+ #endif
1227
+ iov[i].iov_len = op->Length - op->Offset;
1228
+
1229
+ nbytes += iov[i].iov_len;
1230
+ }
1231
+ #else
1232
+ char output_buffer [16 * 1024];
1233
+
1234
+ while ((OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
1235
+ OutboundPage *op = &(OutboundPages[0]);
1236
+ if ((nbytes + op->Length - op->Offset) < sizeof (output_buffer)) {
1237
+ memcpy (output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset);
1238
+ nbytes += (op->Length - op->Offset);
1239
+ op->Free();
1240
+ OutboundPages.pop_front();
1241
+ }
1242
+ else {
1243
+ int len = sizeof(output_buffer) - nbytes;
1244
+ memcpy (output_buffer + nbytes, op->Buffer + op->Offset, len);
1245
+ op->Offset += len;
1246
+ nbytes += len;
1247
+ }
1248
+ }
1249
+ #endif
1250
+
1251
+ // We should never have gotten here if there were no data to write,
1252
+ // so assert that as a sanity check.
1253
+ // Don't bother to make sure nbytes is less than output_buffer because
1254
+ // if it were we probably would have crashed already.
1255
+ assert (nbytes > 0);
1256
+
1257
+ assert (GetSocket() != INVALID_SOCKET);
1258
+ #ifdef HAVE_WRITEV
1259
+ int bytes_written = writev (GetSocket(), iov, iovcnt);
1260
+ #else
1261
+ int bytes_written = write (GetSocket(), output_buffer, nbytes);
1262
+ #endif
1263
+
1264
+ bool err = false;
1265
+ #ifdef OS_WIN32
1266
+ int e = WSAGetLastError();
1267
+ #else
1268
+ int e = errno;
1269
+ #endif
1270
+ if (bytes_written < 0) {
1271
+ err = true;
1272
+ bytes_written = 0;
1273
+ }
1274
+
1275
+ assert (bytes_written >= 0);
1276
+ OutboundDataSize -= bytes_written;
1277
+
1278
+ if (ProxiedFrom && MaxOutboundBufSize && (unsigned int)GetOutboundDataSize() < MaxOutboundBufSize && ProxiedFrom->IsPaused())
1279
+ ProxiedFrom->Resume();
1280
+
1281
+ #ifdef HAVE_WRITEV
1282
+ if (!err) {
1283
+ unsigned int sent = bytes_written;
1284
+ std::deque<OutboundPage>::iterator op = OutboundPages.begin();
1285
+
1286
+ for (int i = 0; i < iovcnt; i++) {
1287
+ if (iov[i].iov_len <= sent) {
1288
+ // Sent this page in full, free it.
1289
+ op->Free();
1290
+ OutboundPages.pop_front();
1291
+
1292
+ sent -= iov[i].iov_len;
1293
+ } else {
1294
+ // Sent part (or none) of this page, increment offset to send the remainder
1295
+ op->Offset += sent;
1296
+ break;
1297
+ }
1298
+
1299
+ // Shouldn't be possible run out of pages before the loop ends
1300
+ assert(op != OutboundPages.end());
1301
+ *op++;
1302
+ }
1303
+ }
1304
+ #else
1305
+ if ((size_t)bytes_written < nbytes) {
1306
+ int len = nbytes - bytes_written;
1307
+ char *buffer = (char*) malloc (len + 1);
1308
+ if (!buffer)
1309
+ throw std::runtime_error ("bad alloc throwing back data");
1310
+ memcpy (buffer, output_buffer + bytes_written, len);
1311
+ buffer [len] = 0;
1312
+ OutboundPages.push_front (OutboundPage (buffer, len));
1313
+ }
1314
+ #endif
1315
+
1316
+ _UpdateEvents(false, true);
1317
+
1318
+ if (err) {
1319
+ #ifdef OS_UNIX
1320
+ if ((e != EINPROGRESS) && (e != EWOULDBLOCK) && (e != EINTR)) {
1321
+ #endif
1322
+ #ifdef OS_WIN32
1323
+ if ((e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK)) {
1324
+ #endif
1325
+ UnbindReasonCode = e;
1326
+ Close();
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+
1332
+ /***************************************
1333
+ ConnectionDescriptor::ReportErrorStatus
1334
+ ***************************************/
1335
+
1336
+ int ConnectionDescriptor::ReportErrorStatus()
1337
+ {
1338
+ if (MySocket == INVALID_SOCKET) {
1339
+ return -1;
1340
+ }
1341
+
1342
+ int error;
1343
+ socklen_t len;
1344
+ len = sizeof(error);
1345
+ #ifdef OS_UNIX
1346
+ int o = getsockopt (GetSocket(), SOL_SOCKET, SO_ERROR, &error, &len);
1347
+ #endif
1348
+ #ifdef OS_WIN32
1349
+ int o = getsockopt (GetSocket(), SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1350
+ #endif
1351
+ if ((o == 0) && (error == 0))
1352
+ return 0;
1353
+ else if (o == 0)
1354
+ return error;
1355
+ else
1356
+ return -1;
1357
+ }
1358
+
1359
+
1360
+ /******************************
1361
+ ConnectionDescriptor::StartTls
1362
+ ******************************/
1363
+
1364
+ #ifdef WITH_SSL
1365
+ void ConnectionDescriptor::StartTls()
1366
+ {
1367
+ if (SslBox)
1368
+ throw std::runtime_error ("SSL/TLS already running on connection");
1369
+
1370
+ SslBox = new SslBox_t (bIsServer, PrivateKeyFilename, CertChainFilename, bSslVerifyPeer, bSslFailIfNoPeerCert, SniHostName, CipherList, EcdhCurve, DhParam, Protocols, GetBinding());
1371
+ _DispatchCiphertext();
1372
+
1373
+ }
1374
+ #else
1375
+ void ConnectionDescriptor::StartTls()
1376
+ {
1377
+ throw std::runtime_error ("Encryption not available on this event-machine");
1378
+ }
1379
+ #endif
1380
+
1381
+
1382
+ /*********************************
1383
+ ConnectionDescriptor::SetTlsParms
1384
+ *********************************/
1385
+
1386
+ #ifdef WITH_SSL
1387
+ void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer, bool fail_if_no_peer_cert, const char *sni_hostname, const char *cipherlist, const char *ecdh_curve, const char *dhparam, int protocols)
1388
+ {
1389
+ if (SslBox)
1390
+ throw std::runtime_error ("call SetTlsParms before calling StartTls");
1391
+ if (privkey_filename && *privkey_filename)
1392
+ PrivateKeyFilename = privkey_filename;
1393
+ if (certchain_filename && *certchain_filename)
1394
+ CertChainFilename = certchain_filename;
1395
+ bSslVerifyPeer = verify_peer;
1396
+ bSslFailIfNoPeerCert = fail_if_no_peer_cert;
1397
+
1398
+ if (sni_hostname && *sni_hostname)
1399
+ SniHostName = sni_hostname;
1400
+ if (cipherlist && *cipherlist)
1401
+ CipherList = cipherlist;
1402
+ if (ecdh_curve && *ecdh_curve)
1403
+ EcdhCurve = ecdh_curve;
1404
+ if (dhparam && *dhparam)
1405
+ DhParam = dhparam;
1406
+
1407
+ Protocols = protocols;
1408
+ }
1409
+ #else
1410
+ void ConnectionDescriptor::SetTlsParms (const char *privkey_filename UNUSED, const char *certchain_filename UNUSED, bool verify_peer UNUSED, bool fail_if_no_peer_cert UNUSED, const char *sni_hostname UNUSED, const char *cipherlist UNUSED, const char *ecdh_curve UNUSED, const char *dhparam UNUSED, int protocols UNUSED)
1411
+ {
1412
+ throw std::runtime_error ("Encryption not available on this event-machine");
1413
+ }
1414
+ #endif
1415
+
1416
+
1417
+ /*********************************
1418
+ ConnectionDescriptor::GetPeerCert
1419
+ *********************************/
1420
+
1421
+ #ifdef WITH_SSL
1422
+ X509 *ConnectionDescriptor::GetPeerCert()
1423
+ {
1424
+ if (!SslBox)
1425
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1426
+ return SslBox->GetPeerCert();
1427
+ }
1428
+ #endif
1429
+
1430
+
1431
+ /*********************************
1432
+ ConnectionDescriptor::GetCipherBits
1433
+ *********************************/
1434
+
1435
+ #ifdef WITH_SSL
1436
+ int ConnectionDescriptor::GetCipherBits()
1437
+ {
1438
+ if (!SslBox)
1439
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1440
+ return SslBox->GetCipherBits();
1441
+ }
1442
+ #endif
1443
+
1444
+
1445
+ /*********************************
1446
+ ConnectionDescriptor::GetCipherName
1447
+ *********************************/
1448
+
1449
+ #ifdef WITH_SSL
1450
+ const char *ConnectionDescriptor::GetCipherName()
1451
+ {
1452
+ if (!SslBox)
1453
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1454
+ return SslBox->GetCipherName();
1455
+ }
1456
+ #endif
1457
+
1458
+
1459
+ /*********************************
1460
+ ConnectionDescriptor::GetCipherProtocol
1461
+ *********************************/
1462
+
1463
+ #ifdef WITH_SSL
1464
+ const char *ConnectionDescriptor::GetCipherProtocol()
1465
+ {
1466
+ if (!SslBox)
1467
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1468
+ return SslBox->GetCipherProtocol();
1469
+ }
1470
+ #endif
1471
+
1472
+
1473
+ /*********************************
1474
+ ConnectionDescriptor::GetSNIHostname
1475
+ *********************************/
1476
+
1477
+ #ifdef WITH_SSL
1478
+ const char *ConnectionDescriptor::GetSNIHostname()
1479
+ {
1480
+ if (!SslBox)
1481
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1482
+ return SslBox->GetSNIHostname();
1483
+ }
1484
+ #endif
1485
+
1486
+
1487
+ /***********************************
1488
+ ConnectionDescriptor::VerifySslPeer
1489
+ ***********************************/
1490
+
1491
+ #ifdef WITH_SSL
1492
+ bool ConnectionDescriptor::VerifySslPeer(const char *cert)
1493
+ {
1494
+ bSslPeerAccepted = false;
1495
+
1496
+ if (EventCallback)
1497
+ (*EventCallback)(GetBinding(), EM_SSL_VERIFY, cert, strlen(cert));
1498
+
1499
+ return bSslPeerAccepted;
1500
+ }
1501
+ #endif
1502
+
1503
+
1504
+ /***********************************
1505
+ ConnectionDescriptor::AcceptSslPeer
1506
+ ***********************************/
1507
+
1508
+ #ifdef WITH_SSL
1509
+ void ConnectionDescriptor::AcceptSslPeer()
1510
+ {
1511
+ bSslPeerAccepted = true;
1512
+ }
1513
+ #endif
1514
+
1515
+
1516
+ /*****************************************
1517
+ ConnectionDescriptor::_DispatchCiphertext
1518
+ *****************************************/
1519
+
1520
+ #ifdef WITH_SSL
1521
+ void ConnectionDescriptor::_DispatchCiphertext()
1522
+ {
1523
+ assert (SslBox);
1524
+
1525
+
1526
+ char BigBuf [SSLBOX_OUTPUT_CHUNKSIZE];
1527
+ bool did_work;
1528
+
1529
+ do {
1530
+ did_work = false;
1531
+
1532
+ // try to drain ciphertext
1533
+ while (SslBox->CanGetCiphertext()) {
1534
+ int r = SslBox->GetCiphertext (BigBuf, sizeof(BigBuf));
1535
+ assert (r > 0);
1536
+ _SendRawOutboundData (BigBuf, r);
1537
+ did_work = true;
1538
+ }
1539
+
1540
+ // Pump the SslBox, in case it has queued outgoing plaintext
1541
+ // This will return >0 if data was written,
1542
+ // 0 if no data was written, and <0 if there was a fatal error.
1543
+ bool pump;
1544
+ do {
1545
+ pump = false;
1546
+ int w = SslBox->PutPlaintext (NULL, 0);
1547
+ if (w > 0) {
1548
+ did_work = true;
1549
+ pump = true;
1550
+ }
1551
+ else if (w < 0)
1552
+ ScheduleClose (false);
1553
+ } while (pump);
1554
+
1555
+ // try to put plaintext. INCOMPLETE, doesn't belong here?
1556
+ // In SendOutboundData, we're spooling plaintext directly
1557
+ // into SslBox. That may be wrong, we may need to buffer it
1558
+ // up here!
1559
+ /*
1560
+ const char *ptr;
1561
+ int ptr_length;
1562
+ while (OutboundPlaintext.GetPage (&ptr, &ptr_length)) {
1563
+ assert (ptr && (ptr_length > 0));
1564
+ int w = SslMachine.PutPlaintext (ptr, ptr_length);
1565
+ if (w > 0) {
1566
+ OutboundPlaintext.DiscardBytes (w);
1567
+ did_work = true;
1568
+ }
1569
+ else
1570
+ break;
1571
+ }
1572
+ */
1573
+
1574
+ } while (did_work);
1575
+
1576
+ }
1577
+ #endif
1578
+
1579
+
1580
+
1581
+ /*******************************
1582
+ ConnectionDescriptor::Heartbeat
1583
+ *******************************/
1584
+
1585
+ void ConnectionDescriptor::Heartbeat()
1586
+ {
1587
+ /* When TLS is enabled, it can skew the delivery of heartbeats and
1588
+ * the LastActivity time-keeping by hundreds of microseconds on fast
1589
+ * machines up to tens of thousands of microseconds on very slow
1590
+ * machines. To prevent failing to timeout in a timely fashion we use
1591
+ * the timer-quantum to compensate for the discrepancy so the
1592
+ * comparisons are more likely to match when they are nearly equal.
1593
+ */
1594
+ uint64_t skew = MyEventMachine->GetTimerQuantum();
1595
+
1596
+ /* Only allow a certain amount of time to go by while waiting
1597
+ * for a pending connect. If it expires, then kill the socket.
1598
+ * For a connected socket, close it if its inactivity timer
1599
+ * has expired.
1600
+ */
1601
+
1602
+ if (bConnectPending) {
1603
+ if ((MyEventMachine->GetCurrentLoopTime() - CreatedAt) >= PendingConnectTimeout) {
1604
+ UnbindReasonCode = ETIMEDOUT;
1605
+ ScheduleClose (false);
1606
+ //bCloseNow = true;
1607
+ }
1608
+ }
1609
+ else {
1610
+ if (InactivityTimeout && ((skew + MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout)) {
1611
+ UnbindReasonCode = ETIMEDOUT;
1612
+ ScheduleClose (false);
1613
+ //bCloseNow = true;
1614
+ }
1615
+ }
1616
+ }
1617
+
1618
+
1619
+ /****************************************
1620
+ LoopbreakDescriptor::LoopbreakDescriptor
1621
+ ****************************************/
1622
+
1623
+ LoopbreakDescriptor::LoopbreakDescriptor (SOCKET sd, EventMachine_t *parent_em):
1624
+ EventableDescriptor (sd, parent_em)
1625
+ {
1626
+ /* This is really bad and ugly. Change someday if possible.
1627
+ * We have to know about an event-machine (probably the one that owns us),
1628
+ * so we can pass newly-created connections to it.
1629
+ */
1630
+
1631
+ bCallbackUnbind = false;
1632
+
1633
+ #ifdef HAVE_EPOLL
1634
+ EpollEvent.events = EPOLLIN;
1635
+ #endif
1636
+ #ifdef HAVE_KQUEUE
1637
+ MyEventMachine->ArmKqueueReader (this);
1638
+ #endif
1639
+ }
1640
+
1641
+
1642
+
1643
+
1644
+ /*************************
1645
+ LoopbreakDescriptor::Read
1646
+ *************************/
1647
+
1648
+ void LoopbreakDescriptor::Read()
1649
+ {
1650
+ // TODO, refactor, this code is probably in the wrong place.
1651
+ assert (MyEventMachine);
1652
+ MyEventMachine->_ReadLoopBreaker();
1653
+ }
1654
+
1655
+
1656
+ /**************************
1657
+ LoopbreakDescriptor::Write
1658
+ **************************/
1659
+
1660
+ void LoopbreakDescriptor::Write()
1661
+ {
1662
+ // Why are we here?
1663
+ throw std::runtime_error ("bad code path in loopbreak");
1664
+ }
1665
+
1666
+ /**************************************
1667
+ AcceptorDescriptor::AcceptorDescriptor
1668
+ **************************************/
1669
+
1670
+ AcceptorDescriptor::AcceptorDescriptor (SOCKET sd, EventMachine_t *parent_em):
1671
+ EventableDescriptor (sd, parent_em)
1672
+ {
1673
+ #ifdef HAVE_EPOLL
1674
+ EpollEvent.events = EPOLLIN;
1675
+ #endif
1676
+ #ifdef HAVE_KQUEUE
1677
+ MyEventMachine->ArmKqueueReader (this);
1678
+ #endif
1679
+ }
1680
+
1681
+
1682
+ /***************************************
1683
+ AcceptorDescriptor::~AcceptorDescriptor
1684
+ ***************************************/
1685
+
1686
+ AcceptorDescriptor::~AcceptorDescriptor()
1687
+ {
1688
+ }
1689
+
1690
+ /****************************************
1691
+ STATIC: AcceptorDescriptor::StopAcceptor
1692
+ ****************************************/
1693
+
1694
+ void AcceptorDescriptor::StopAcceptor (const uintptr_t binding)
1695
+ {
1696
+ // TODO: This is something of a hack, or at least it's a static method of the wrong class.
1697
+ AcceptorDescriptor *ad = dynamic_cast <AcceptorDescriptor*> (Bindable_t::GetObject (binding));
1698
+ if (ad)
1699
+ ad->ScheduleClose (false);
1700
+ else
1701
+ throw std::runtime_error ("failed to close nonexistent acceptor");
1702
+ }
1703
+
1704
+
1705
+ /************************
1706
+ AcceptorDescriptor::Read
1707
+ ************************/
1708
+
1709
+ void AcceptorDescriptor::Read()
1710
+ {
1711
+ /* Accept up to a certain number of sockets on the listening connection.
1712
+ * Don't try to accept all that are present, because this would allow a DoS attack
1713
+ * in which no data were ever read or written. We should accept more than one,
1714
+ * if available, to keep the partially accepted sockets from backing up in the kernel.
1715
+ */
1716
+
1717
+ /* Make sure we use non-blocking i/o on the acceptor socket, since we're selecting it
1718
+ * for readability. According to Stevens UNP, it's possible for an acceptor to select readable
1719
+ * and then block when we call accept. For example, the other end resets the connection after
1720
+ * the socket selects readable and before we call accept. The kernel will remove the dead
1721
+ * socket from the accept queue. If the accept queue is now empty, accept will block.
1722
+ */
1723
+
1724
+
1725
+ struct sockaddr_in6 pin;
1726
+ socklen_t addrlen = sizeof (pin);
1727
+ int accept_count = EventMachine_t::GetSimultaneousAcceptCount();
1728
+
1729
+ for (int i=0; i < accept_count; i++) {
1730
+ #if defined(HAVE_CONST_SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
1731
+ SOCKET sd = accept4 (GetSocket(), (struct sockaddr*)&pin, &addrlen, SOCK_CLOEXEC);
1732
+ if (sd == INVALID_SOCKET) {
1733
+ // We may be running in a kernel where
1734
+ // SOCK_CLOEXEC is not supported - fall back:
1735
+ sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
1736
+ }
1737
+ #else
1738
+ SOCKET sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
1739
+ #endif
1740
+ if (sd == INVALID_SOCKET) {
1741
+ // This breaks the loop when we've accepted everything on the kernel queue,
1742
+ // up to 10 new connections. But what if the *first* accept fails?
1743
+ // Does that mean anything serious is happening, beyond the situation
1744
+ // described in the note above?
1745
+ break;
1746
+ }
1747
+
1748
+ // Set the newly-accepted socket non-blocking and to close on exec.
1749
+ // On Windows, this may fail because, weirdly, Windows inherits the non-blocking
1750
+ // attribute that we applied to the acceptor socket into the accepted one.
1751
+ if (!SetFdCloexec(sd) || !SetSocketNonblocking (sd)) {
1752
+ //int val = fcntl (sd, F_GETFL, 0);
1753
+ //if (fcntl (sd, F_SETFL, val | O_NONBLOCK) == -1) {
1754
+ shutdown (sd, 1);
1755
+ close (sd);
1756
+ continue;
1757
+ }
1758
+
1759
+ // Disable slow-start (Nagle algorithm). Eventually make this configurable.
1760
+ int one = 1;
1761
+ setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one));
1762
+
1763
+
1764
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, MyEventMachine);
1765
+ if (!cd)
1766
+ throw std::runtime_error ("no newly accepted connection");
1767
+ cd->SetServerMode();
1768
+ if (EventCallback) {
1769
+ (*EventCallback) (GetBinding(), EM_CONNECTION_ACCEPTED, NULL, cd->GetBinding());
1770
+ }
1771
+ #ifdef HAVE_EPOLL
1772
+ cd->GetEpollEvent()->events = 0;
1773
+ if (cd->SelectForRead())
1774
+ cd->GetEpollEvent()->events |= EPOLLIN;
1775
+ if (cd->SelectForWrite())
1776
+ cd->GetEpollEvent()->events |= EPOLLOUT;
1777
+ #endif
1778
+ assert (MyEventMachine);
1779
+ MyEventMachine->Add (cd);
1780
+ #ifdef HAVE_KQUEUE
1781
+ bKqueueArmWrite = cd->SelectForWrite();
1782
+ if (bKqueueArmWrite)
1783
+ MyEventMachine->Modify (cd);
1784
+ if (cd->SelectForRead())
1785
+ MyEventMachine->ArmKqueueReader (cd);
1786
+ #endif
1787
+ }
1788
+
1789
+ }
1790
+
1791
+
1792
+ /*************************
1793
+ AcceptorDescriptor::Write
1794
+ *************************/
1795
+
1796
+ void AcceptorDescriptor::Write()
1797
+ {
1798
+ // Why are we here?
1799
+ throw std::runtime_error ("bad code path in acceptor");
1800
+ }
1801
+
1802
+
1803
+ /*****************************
1804
+ AcceptorDescriptor::Heartbeat
1805
+ *****************************/
1806
+
1807
+ void AcceptorDescriptor::Heartbeat()
1808
+ {
1809
+ // No-op
1810
+ }
1811
+
1812
+
1813
+ /**************************************
1814
+ DatagramDescriptor::DatagramDescriptor
1815
+ **************************************/
1816
+
1817
+ DatagramDescriptor::DatagramDescriptor (SOCKET sd, EventMachine_t *parent_em):
1818
+ EventableDescriptor (sd, parent_em),
1819
+ OutboundDataSize (0)
1820
+ {
1821
+ memset (&ReturnAddress, 0, sizeof(ReturnAddress));
1822
+
1823
+ /* Provisionally added 19Oct07. All datagram sockets support broadcasting.
1824
+ * Until now, sending to a broadcast address would give EACCES (permission denied)
1825
+ * on systems like Linux and BSD that require the SO_BROADCAST socket-option in order
1826
+ * to accept a packet to a broadcast address. Solaris doesn't require it. I think
1827
+ * Windows DOES require it but I'm not sure.
1828
+ *
1829
+ * Ruby does NOT do what we're doing here. In Ruby, you have to explicitly set SO_BROADCAST
1830
+ * on a UDP socket in order to enable broadcasting. The reason for requiring the option
1831
+ * in the first place is so that applications don't send broadcast datagrams by mistake.
1832
+ * I imagine that could happen if a user of an application typed in an address that happened
1833
+ * to be a broadcast address on that particular subnet.
1834
+ *
1835
+ * This is provisional because someone may eventually come up with a good reason not to
1836
+ * do it for all UDP sockets. If that happens, then we'll need to add a usercode-level API
1837
+ * to set the socket option, just like Ruby does. AND WE'LL ALSO BREAK CODE THAT DOESN'T
1838
+ * EXPLICITLY SET THE OPTION.
1839
+ */
1840
+
1841
+ int oval = 1;
1842
+ setsockopt (GetSocket(), SOL_SOCKET, SO_BROADCAST, (char*)&oval, sizeof(oval));
1843
+
1844
+ #ifdef HAVE_EPOLL
1845
+ EpollEvent.events = EPOLLIN;
1846
+ #endif
1847
+ #ifdef HAVE_KQUEUE
1848
+ MyEventMachine->ArmKqueueReader (this);
1849
+ #endif
1850
+ }
1851
+
1852
+
1853
+ /***************************************
1854
+ DatagramDescriptor::~DatagramDescriptor
1855
+ ***************************************/
1856
+
1857
+ DatagramDescriptor::~DatagramDescriptor()
1858
+ {
1859
+ // Run down any stranded outbound data.
1860
+ for (size_t i=0; i < OutboundPages.size(); i++)
1861
+ OutboundPages[i].Free();
1862
+ }
1863
+
1864
+
1865
+ /*****************************
1866
+ DatagramDescriptor::Heartbeat
1867
+ *****************************/
1868
+
1869
+ void DatagramDescriptor::Heartbeat()
1870
+ {
1871
+ // Close it if its inactivity timer has expired.
1872
+
1873
+ if (InactivityTimeout && ((MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout))
1874
+ ScheduleClose (false);
1875
+ //bCloseNow = true;
1876
+ }
1877
+
1878
+
1879
+ /************************
1880
+ DatagramDescriptor::Read
1881
+ ************************/
1882
+
1883
+ void DatagramDescriptor::Read()
1884
+ {
1885
+ SOCKET sd = GetSocket();
1886
+ assert (sd != INVALID_SOCKET);
1887
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
1888
+
1889
+ // This is an extremely large read buffer.
1890
+ // In many cases you wouldn't expect to get any more than 4K.
1891
+ char readbuffer [16 * 1024];
1892
+
1893
+ for (int i=0; i < 10; i++) {
1894
+ // Don't read just one buffer and then move on. This is faster
1895
+ // if there is a lot of incoming.
1896
+ // But don't read indefinitely. Give other sockets a chance to run.
1897
+ // NOTICE, we're reading one less than the buffer size.
1898
+ // That's so we can put a guard byte at the end of what we send
1899
+ // to user code.
1900
+
1901
+ struct sockaddr_in6 sin;
1902
+ socklen_t slen = sizeof (sin);
1903
+ memset (&sin, 0, slen);
1904
+
1905
+ int r = recvfrom (sd, readbuffer, sizeof(readbuffer) - 1, 0, (struct sockaddr*)&sin, &slen);
1906
+ //cerr << "<R:" << r << ">";
1907
+
1908
+ // In UDP, a zero-length packet is perfectly legal.
1909
+ if (r >= 0) {
1910
+
1911
+ // Add a null-terminator at the the end of the buffer
1912
+ // that we will send to the callback.
1913
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
1914
+ // to be able to depend on this behavior, so they will have
1915
+ // the option to do some things faster. Additionally it's
1916
+ // a security guard against buffer overflows.
1917
+ readbuffer [r] = 0;
1918
+
1919
+
1920
+ // Set up a "temporary" return address so that callers can "reply" to us
1921
+ // from within the callback we are about to invoke. That means that ordinary
1922
+ // calls to "send_data_to_connection" (which is of course misnamed in this
1923
+ // case) will result in packets being sent back to the same place that sent
1924
+ // us this one.
1925
+ // There is a different call (evma_send_datagram) for cases where the caller
1926
+ // actually wants to send a packet somewhere else.
1927
+
1928
+ memset (&ReturnAddress, 0, sizeof(ReturnAddress));
1929
+ memcpy (&ReturnAddress, &sin, slen);
1930
+
1931
+ _GenericInboundDispatch(readbuffer, r);
1932
+
1933
+ }
1934
+ else {
1935
+ // Basically a would-block, meaning we've read everything there is to read.
1936
+ break;
1937
+ }
1938
+
1939
+ }
1940
+
1941
+
1942
+ }
1943
+
1944
+
1945
+ /*************************
1946
+ DatagramDescriptor::Write
1947
+ *************************/
1948
+
1949
+ void DatagramDescriptor::Write()
1950
+ {
1951
+ /* It's possible for a socket to select writable and then no longer
1952
+ * be writable by the time we get around to writing. The kernel might
1953
+ * have used up its available output buffers between the select call
1954
+ * and when we get here. So this condition is not an error.
1955
+ * This code is very reminiscent of ConnectionDescriptor::_WriteOutboundData,
1956
+ * but differs in the that the outbound data pages (received from the
1957
+ * user) are _message-structured._ That is, we send each of them out
1958
+ * one message at a time.
1959
+ * TODO, we are currently suppressing the EMSGSIZE error!!!
1960
+ */
1961
+
1962
+ SOCKET sd = GetSocket();
1963
+ assert (sd != INVALID_SOCKET);
1964
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
1965
+
1966
+ assert (OutboundPages.size() > 0);
1967
+
1968
+ // Send out up to 10 packets, then cycle the machine.
1969
+ for (int i = 0; i < 10; i++) {
1970
+ if (OutboundPages.size() <= 0)
1971
+ break;
1972
+ OutboundPage *op = &(OutboundPages[0]);
1973
+
1974
+ // The nasty cast to (char*) is needed because Windows is brain-dead.
1975
+ int s = sendto (sd, (char*)op->Buffer, op->Length, 0, (struct sockaddr*)&(op->From),
1976
+ (op->From.sin6_family == AF_INET6 ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr_in)));
1977
+ #ifdef OS_WIN32
1978
+ int e = WSAGetLastError();
1979
+ #else
1980
+ int e = errno;
1981
+ #endif
1982
+
1983
+ OutboundDataSize -= op->Length;
1984
+ op->Free();
1985
+ OutboundPages.pop_front();
1986
+
1987
+ if (s == SOCKET_ERROR) {
1988
+ #ifdef OS_UNIX
1989
+ if ((e != EINPROGRESS) && (e != EWOULDBLOCK) && (e != EINTR)) {
1990
+ #endif
1991
+ #ifdef OS_WIN32
1992
+ if ((e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK)) {
1993
+ #endif
1994
+ UnbindReasonCode = e;
1995
+ Close();
1996
+ break;
1997
+ }
1998
+ }
1999
+ }
2000
+
2001
+ #ifdef HAVE_EPOLL
2002
+ EpollEvent.events = EPOLLIN;
2003
+ if (SelectForWrite())
2004
+ EpollEvent.events |= EPOLLOUT;
2005
+ assert (MyEventMachine);
2006
+ MyEventMachine->Modify (this);
2007
+ #endif
2008
+ #ifdef HAVE_KQUEUE
2009
+ bKqueueArmWrite = SelectForWrite();
2010
+ assert (MyEventMachine);
2011
+ MyEventMachine->Modify (this);
2012
+ #endif
2013
+ }
2014
+
2015
+
2016
+ /**********************************
2017
+ DatagramDescriptor::SelectForWrite
2018
+ **********************************/
2019
+
2020
+ bool DatagramDescriptor::SelectForWrite()
2021
+ {
2022
+ /* Changed 15Nov07, per bug report by Mark Zvillius.
2023
+ * The outbound data size will be zero if there are zero-length outbound packets,
2024
+ * so we now select writable in case the outbound page buffer is not empty.
2025
+ * Note that the superclass ShouldDelete method still checks for outbound data size,
2026
+ * which may be wrong.
2027
+ */
2028
+ //return (GetOutboundDataSize() > 0); (Original)
2029
+ return (OutboundPages.size() > 0);
2030
+ }
2031
+
2032
+
2033
+ /************************************
2034
+ DatagramDescriptor::SendOutboundData
2035
+ ************************************/
2036
+
2037
+ int DatagramDescriptor::SendOutboundData (const char *data, unsigned long length)
2038
+ {
2039
+ // This is almost an exact clone of ConnectionDescriptor::_SendRawOutboundData.
2040
+ // That means most of it could be factored to a common ancestor. Note that
2041
+ // empty datagrams are meaningful, which isn't the case for TCP streams.
2042
+
2043
+ if (IsCloseScheduled())
2044
+ return 0;
2045
+
2046
+ if (!data && (length > 0))
2047
+ throw std::runtime_error ("bad outbound data");
2048
+ char *buffer = (char *) malloc (length + 1);
2049
+ if (!buffer)
2050
+ throw std::runtime_error ("no allocation for outbound data");
2051
+ memcpy (buffer, data, length);
2052
+ buffer [length] = 0;
2053
+ OutboundPages.push_back (OutboundPage (buffer, length, ReturnAddress));
2054
+ OutboundDataSize += length;
2055
+
2056
+ #ifdef HAVE_EPOLL
2057
+ EpollEvent.events = (EPOLLIN | EPOLLOUT);
2058
+ assert (MyEventMachine);
2059
+ MyEventMachine->Modify (this);
2060
+ #endif
2061
+ #ifdef HAVE_KQUEUE
2062
+ bKqueueArmWrite = true;
2063
+ assert (MyEventMachine);
2064
+ MyEventMachine->Modify (this);
2065
+ #endif
2066
+
2067
+ return length;
2068
+ }
2069
+
2070
+
2071
+ /****************************************
2072
+ DatagramDescriptor::SendOutboundDatagram
2073
+ ****************************************/
2074
+
2075
+ int DatagramDescriptor::SendOutboundDatagram (const char *data, unsigned long length, const char *address, int port)
2076
+ {
2077
+ // This is an exact clone of ConnectionDescriptor::SendOutboundData.
2078
+ // That means it needs to move to a common ancestor.
2079
+ // TODO: Refactor this so there's no overlap with SendOutboundData.
2080
+
2081
+ if (IsCloseScheduled())
2082
+ //if (bCloseNow || bCloseAfterWriting)
2083
+ return 0;
2084
+
2085
+ if (!address || !*address || !port)
2086
+ return 0;
2087
+
2088
+ struct sockaddr_in6 addr_here;
2089
+ size_t addr_here_len = sizeof addr_here;
2090
+ if (0 != EventMachine_t::name2address (address, port, SOCK_DGRAM, (struct sockaddr *)&addr_here, &addr_here_len))
2091
+ return -1;
2092
+
2093
+ if (!data && (length > 0))
2094
+ throw std::runtime_error ("bad outbound data");
2095
+ char *buffer = (char *) malloc (length + 1);
2096
+ if (!buffer)
2097
+ throw std::runtime_error ("no allocation for outbound data");
2098
+ memcpy (buffer, data, length);
2099
+ buffer [length] = 0;
2100
+ OutboundPages.push_back (OutboundPage (buffer, length, addr_here));
2101
+ OutboundDataSize += length;
2102
+
2103
+ #ifdef HAVE_EPOLL
2104
+ EpollEvent.events = (EPOLLIN | EPOLLOUT);
2105
+ assert (MyEventMachine);
2106
+ MyEventMachine->Modify (this);
2107
+ #endif
2108
+ #ifdef HAVE_KQUEUE
2109
+ bKqueueArmWrite = true;
2110
+ assert (MyEventMachine);
2111
+ MyEventMachine->Modify (this);
2112
+ #endif
2113
+
2114
+ return length;
2115
+ }
2116
+
2117
+
2118
+ /**********************************************
2119
+ ConnectionDescriptor::GetCommInactivityTimeout
2120
+ **********************************************/
2121
+
2122
+ uint64_t ConnectionDescriptor::GetCommInactivityTimeout()
2123
+ {
2124
+ return InactivityTimeout / 1000;
2125
+ }
2126
+
2127
+
2128
+ /**********************************************
2129
+ ConnectionDescriptor::SetCommInactivityTimeout
2130
+ **********************************************/
2131
+
2132
+ int ConnectionDescriptor::SetCommInactivityTimeout (uint64_t value)
2133
+ {
2134
+ InactivityTimeout = value * 1000;
2135
+ MyEventMachine->QueueHeartbeat(this);
2136
+ return 1;
2137
+ }
2138
+
2139
+ /*******************************
2140
+ DatagramDescriptor::GetPeername
2141
+ *******************************/
2142
+
2143
+ bool DatagramDescriptor::GetPeername (struct sockaddr *s, socklen_t *len)
2144
+ {
2145
+ bool ok = false;
2146
+ if (s) {
2147
+ *len = sizeof(ReturnAddress);
2148
+ memset (s, 0, sizeof(ReturnAddress));
2149
+ memcpy (s, &ReturnAddress, sizeof(ReturnAddress));
2150
+ ok = true;
2151
+ }
2152
+ return ok;
2153
+ }
2154
+
2155
+
2156
+ /********************************************
2157
+ DatagramDescriptor::GetCommInactivityTimeout
2158
+ ********************************************/
2159
+
2160
+ uint64_t DatagramDescriptor::GetCommInactivityTimeout()
2161
+ {
2162
+ return InactivityTimeout / 1000;
2163
+ }
2164
+
2165
+ /********************************************
2166
+ DatagramDescriptor::SetCommInactivityTimeout
2167
+ ********************************************/
2168
+
2169
+ int DatagramDescriptor::SetCommInactivityTimeout (uint64_t value)
2170
+ {
2171
+ if (value > 0) {
2172
+ InactivityTimeout = value * 1000;
2173
+ MyEventMachine->QueueHeartbeat(this);
2174
+ return 1;
2175
+ }
2176
+ return 0;
2177
+ }
2178
+
2179
+
2180
+ /************************************
2181
+ InotifyDescriptor::InotifyDescriptor
2182
+ *************************************/
2183
+
2184
+ InotifyDescriptor::InotifyDescriptor (EventMachine_t *em):
2185
+ EventableDescriptor(0, em)
2186
+ {
2187
+ bCallbackUnbind = false;
2188
+
2189
+ #ifndef HAVE_INOTIFY
2190
+ throw std::runtime_error("no inotify support on this system");
2191
+ #else
2192
+
2193
+ int fd = inotify_init();
2194
+ if (fd == -1) {
2195
+ char buf[200];
2196
+ snprintf (buf, sizeof(buf)-1, "unable to create inotify descriptor: %s", strerror(errno));
2197
+ throw std::runtime_error (buf);
2198
+ }
2199
+
2200
+ MySocket = fd;
2201
+ SetSocketNonblocking(MySocket);
2202
+ #ifdef HAVE_EPOLL
2203
+ EpollEvent.events = EPOLLIN;
2204
+ #endif
2205
+
2206
+ #endif
2207
+ }
2208
+
2209
+
2210
+ /*************************************
2211
+ InotifyDescriptor::~InotifyDescriptor
2212
+ **************************************/
2213
+
2214
+ InotifyDescriptor::~InotifyDescriptor()
2215
+ {
2216
+ close(MySocket);
2217
+ MySocket = INVALID_SOCKET;
2218
+ }
2219
+
2220
+ /***********************
2221
+ InotifyDescriptor::Read
2222
+ ************************/
2223
+
2224
+ void InotifyDescriptor::Read()
2225
+ {
2226
+ assert (MyEventMachine);
2227
+ MyEventMachine->_ReadInotifyEvents();
2228
+ }
2229
+
2230
+
2231
+ /************************
2232
+ InotifyDescriptor::Write
2233
+ *************************/
2234
+
2235
+ void InotifyDescriptor::Write()
2236
+ {
2237
+ throw std::runtime_error("bad code path in inotify");
2238
+ }