eventmachine-mkroman 1.3.0.dev.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) 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 +2243 -0
  37. data/ext/ed.h +463 -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 +291 -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 +1643 -0
  52. data/ext/ssl.cpp +701 -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 +802 -0
  70. data/lib/em/deferrable/pool.rb +2 -0
  71. data/lib/em/deferrable.rb +210 -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/header_and_content.rb +138 -0
  81. data/lib/em/protocols/httpclient.rb +303 -0
  82. data/lib/em/protocols/httpclient2.rb +602 -0
  83. data/lib/em/protocols/line_and_text.rb +125 -0
  84. data/lib/em/protocols/line_protocol.rb +33 -0
  85. data/lib/em/protocols/linetext2.rb +179 -0
  86. data/lib/em/protocols/memcache.rb +331 -0
  87. data/lib/em/protocols/object_protocol.rb +46 -0
  88. data/lib/em/protocols/postgres3.rb +246 -0
  89. data/lib/em/protocols/saslauth.rb +175 -0
  90. data/lib/em/protocols/smtpclient.rb +394 -0
  91. data/lib/em/protocols/smtpserver.rb +666 -0
  92. data/lib/em/protocols/socks4.rb +66 -0
  93. data/lib/em/protocols/stomp.rb +205 -0
  94. data/lib/em/protocols/tcptest.rb +54 -0
  95. data/lib/em/protocols.rb +37 -0
  96. data/lib/em/pure_ruby.rb +1300 -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 +319 -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 +165 -0
  114. data/tests/em_test_helper.rb +198 -0
  115. data/tests/encoded_client.key +54 -0
  116. data/tests/jruby/test_jeventmachine.rb +38 -0
  117. data/tests/test_attach.rb +199 -0
  118. data/tests/test_basic.rb +321 -0
  119. data/tests/test_channel.rb +75 -0
  120. data/tests/test_completion.rb +178 -0
  121. data/tests/test_connection_count.rb +83 -0
  122. data/tests/test_connection_write.rb +35 -0
  123. data/tests/test_defer.rb +35 -0
  124. data/tests/test_deferrable.rb +35 -0
  125. data/tests/test_epoll.rb +141 -0
  126. data/tests/test_error_handler.rb +38 -0
  127. data/tests/test_exc.rb +37 -0
  128. data/tests/test_file_watch.rb +86 -0
  129. data/tests/test_fork.rb +75 -0
  130. data/tests/test_futures.rb +170 -0
  131. data/tests/test_handler_check.rb +35 -0
  132. data/tests/test_hc.rb +155 -0
  133. data/tests/test_httpclient.rb +238 -0
  134. data/tests/test_httpclient2.rb +132 -0
  135. data/tests/test_idle_connection.rb +31 -0
  136. data/tests/test_inactivity_timeout.rb +102 -0
  137. data/tests/test_io_streamer.rb +48 -0
  138. data/tests/test_ipv4.rb +96 -0
  139. data/tests/test_ipv6.rb +107 -0
  140. data/tests/test_iterator.rb +122 -0
  141. data/tests/test_kb.rb +28 -0
  142. data/tests/test_keepalive.rb +113 -0
  143. data/tests/test_line_protocol.rb +33 -0
  144. data/tests/test_ltp.rb +155 -0
  145. data/tests/test_ltp2.rb +332 -0
  146. data/tests/test_many_fds.rb +21 -0
  147. data/tests/test_next_tick.rb +104 -0
  148. data/tests/test_object_protocol.rb +36 -0
  149. data/tests/test_pause.rb +109 -0
  150. data/tests/test_pending_connect_timeout.rb +52 -0
  151. data/tests/test_pool.rb +196 -0
  152. data/tests/test_process_watch.rb +50 -0
  153. data/tests/test_processes.rb +147 -0
  154. data/tests/test_proxy_connection.rb +180 -0
  155. data/tests/test_pure.rb +156 -0
  156. data/tests/test_queue.rb +64 -0
  157. data/tests/test_resolver.rb +129 -0
  158. data/tests/test_running.rb +14 -0
  159. data/tests/test_sasl.rb +46 -0
  160. data/tests/test_send_file.rb +217 -0
  161. data/tests/test_servers.rb +32 -0
  162. data/tests/test_shutdown_hooks.rb +23 -0
  163. data/tests/test_smtpclient.rb +75 -0
  164. data/tests/test_smtpserver.rb +90 -0
  165. data/tests/test_sock_opt.rb +53 -0
  166. data/tests/test_spawn.rb +290 -0
  167. data/tests/test_ssl_args.rb +70 -0
  168. data/tests/test_ssl_dhparam.rb +57 -0
  169. data/tests/test_ssl_ecdh_curve.rb +57 -0
  170. data/tests/test_ssl_extensions.rb +24 -0
  171. data/tests/test_ssl_inline_cert.rb +222 -0
  172. data/tests/test_ssl_methods.rb +31 -0
  173. data/tests/test_ssl_protocols.rb +190 -0
  174. data/tests/test_ssl_verify.rb +108 -0
  175. data/tests/test_stomp.rb +38 -0
  176. data/tests/test_system.rb +46 -0
  177. data/tests/test_threaded_resource.rb +68 -0
  178. data/tests/test_tick_loop.rb +58 -0
  179. data/tests/test_timers.rb +150 -0
  180. data/tests/test_ud.rb +8 -0
  181. data/tests/test_unbind_reason.rb +40 -0
  182. metadata +389 -0
data/ext/ed.cpp ADDED
@@ -0,0 +1,2243 @@
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, PrivateKey, PrivateKeyPass, CertChainFilename, Cert, 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 *privkey, const char *privkeypass, const char *certchain_filename, const char *cert, 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 (privkey && *privkey)
1394
+ PrivateKey = privkey;
1395
+ if (privkeypass && *privkeypass)
1396
+ PrivateKeyPass = privkeypass;
1397
+ if (certchain_filename && *certchain_filename)
1398
+ CertChainFilename = certchain_filename;
1399
+ if (cert && *cert)
1400
+ Cert = cert;
1401
+ bSslVerifyPeer = verify_peer;
1402
+ bSslFailIfNoPeerCert = fail_if_no_peer_cert;
1403
+
1404
+ if (sni_hostname && *sni_hostname)
1405
+ SniHostName = sni_hostname;
1406
+ if (cipherlist && *cipherlist)
1407
+ CipherList = cipherlist;
1408
+ if (ecdh_curve && *ecdh_curve)
1409
+ EcdhCurve = ecdh_curve;
1410
+ if (dhparam && *dhparam)
1411
+ DhParam = dhparam;
1412
+ Protocols = protocols;
1413
+ }
1414
+ #else
1415
+ void ConnectionDescriptor::SetTlsParms (const char *privkey_filename UNUSED, const char *privkey UNUSED, const char *privkeypass UNUSED, const char *certchain_filename UNUSED, const char *cert 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)
1416
+ {
1417
+ throw std::runtime_error ("Encryption not available on this event-machine");
1418
+ }
1419
+ #endif
1420
+
1421
+
1422
+ /*********************************
1423
+ ConnectionDescriptor::GetPeerCert
1424
+ *********************************/
1425
+
1426
+ #ifdef WITH_SSL
1427
+ X509 *ConnectionDescriptor::GetPeerCert()
1428
+ {
1429
+ if (!SslBox)
1430
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1431
+ return SslBox->GetPeerCert();
1432
+ }
1433
+ #endif
1434
+
1435
+
1436
+ /*********************************
1437
+ ConnectionDescriptor::GetCipherBits
1438
+ *********************************/
1439
+
1440
+ #ifdef WITH_SSL
1441
+ int ConnectionDescriptor::GetCipherBits()
1442
+ {
1443
+ if (!SslBox)
1444
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1445
+ return SslBox->GetCipherBits();
1446
+ }
1447
+ #endif
1448
+
1449
+
1450
+ /*********************************
1451
+ ConnectionDescriptor::GetCipherName
1452
+ *********************************/
1453
+
1454
+ #ifdef WITH_SSL
1455
+ const char *ConnectionDescriptor::GetCipherName()
1456
+ {
1457
+ if (!SslBox)
1458
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1459
+ return SslBox->GetCipherName();
1460
+ }
1461
+ #endif
1462
+
1463
+
1464
+ /*********************************
1465
+ ConnectionDescriptor::GetCipherProtocol
1466
+ *********************************/
1467
+
1468
+ #ifdef WITH_SSL
1469
+ const char *ConnectionDescriptor::GetCipherProtocol()
1470
+ {
1471
+ if (!SslBox)
1472
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1473
+ return SslBox->GetCipherProtocol();
1474
+ }
1475
+ #endif
1476
+
1477
+
1478
+ /*********************************
1479
+ ConnectionDescriptor::GetSNIHostname
1480
+ *********************************/
1481
+
1482
+ #ifdef WITH_SSL
1483
+ const char *ConnectionDescriptor::GetSNIHostname()
1484
+ {
1485
+ if (!SslBox)
1486
+ throw std::runtime_error ("SSL/TLS not running on this connection");
1487
+ return SslBox->GetSNIHostname();
1488
+ }
1489
+ #endif
1490
+
1491
+
1492
+ /***********************************
1493
+ ConnectionDescriptor::VerifySslPeer
1494
+ ***********************************/
1495
+
1496
+ #ifdef WITH_SSL
1497
+ bool ConnectionDescriptor::VerifySslPeer(const char *cert)
1498
+ {
1499
+ bSslPeerAccepted = false;
1500
+
1501
+ if (EventCallback)
1502
+ (*EventCallback)(GetBinding(), EM_SSL_VERIFY, cert, strlen(cert));
1503
+
1504
+ return bSslPeerAccepted;
1505
+ }
1506
+ #endif
1507
+
1508
+
1509
+ /***********************************
1510
+ ConnectionDescriptor::AcceptSslPeer
1511
+ ***********************************/
1512
+
1513
+ #ifdef WITH_SSL
1514
+ void ConnectionDescriptor::AcceptSslPeer()
1515
+ {
1516
+ bSslPeerAccepted = true;
1517
+ }
1518
+ #endif
1519
+
1520
+
1521
+ /*****************************************
1522
+ ConnectionDescriptor::_DispatchCiphertext
1523
+ *****************************************/
1524
+
1525
+ #ifdef WITH_SSL
1526
+ void ConnectionDescriptor::_DispatchCiphertext()
1527
+ {
1528
+ assert (SslBox);
1529
+
1530
+
1531
+ char BigBuf [SSLBOX_OUTPUT_CHUNKSIZE];
1532
+ bool did_work;
1533
+
1534
+ do {
1535
+ did_work = false;
1536
+
1537
+ // try to drain ciphertext
1538
+ while (SslBox->CanGetCiphertext()) {
1539
+ int r = SslBox->GetCiphertext (BigBuf, sizeof(BigBuf));
1540
+ assert (r > 0);
1541
+ _SendRawOutboundData (BigBuf, r);
1542
+ did_work = true;
1543
+ }
1544
+
1545
+ // Pump the SslBox, in case it has queued outgoing plaintext
1546
+ // This will return >0 if data was written,
1547
+ // 0 if no data was written, and <0 if there was a fatal error.
1548
+ bool pump;
1549
+ do {
1550
+ pump = false;
1551
+ int w = SslBox->PutPlaintext (NULL, 0);
1552
+ if (w > 0) {
1553
+ did_work = true;
1554
+ pump = true;
1555
+ }
1556
+ else if (w < 0)
1557
+ ScheduleClose (false);
1558
+ } while (pump);
1559
+
1560
+ // try to put plaintext. INCOMPLETE, doesn't belong here?
1561
+ // In SendOutboundData, we're spooling plaintext directly
1562
+ // into SslBox. That may be wrong, we may need to buffer it
1563
+ // up here!
1564
+ /*
1565
+ const char *ptr;
1566
+ int ptr_length;
1567
+ while (OutboundPlaintext.GetPage (&ptr, &ptr_length)) {
1568
+ assert (ptr && (ptr_length > 0));
1569
+ int w = SslMachine.PutPlaintext (ptr, ptr_length);
1570
+ if (w > 0) {
1571
+ OutboundPlaintext.DiscardBytes (w);
1572
+ did_work = true;
1573
+ }
1574
+ else
1575
+ break;
1576
+ }
1577
+ */
1578
+
1579
+ } while (did_work);
1580
+
1581
+ }
1582
+ #endif
1583
+
1584
+
1585
+
1586
+ /*******************************
1587
+ ConnectionDescriptor::Heartbeat
1588
+ *******************************/
1589
+
1590
+ void ConnectionDescriptor::Heartbeat()
1591
+ {
1592
+ /* When TLS is enabled, it can skew the delivery of heartbeats and
1593
+ * the LastActivity time-keeping by hundreds of microseconds on fast
1594
+ * machines up to tens of thousands of microseconds on very slow
1595
+ * machines. To prevent failing to timeout in a timely fashion we use
1596
+ * the timer-quantum to compensate for the discrepancy so the
1597
+ * comparisons are more likely to match when they are nearly equal.
1598
+ */
1599
+ uint64_t skew = MyEventMachine->GetTimerQuantum();
1600
+
1601
+ /* Only allow a certain amount of time to go by while waiting
1602
+ * for a pending connect. If it expires, then kill the socket.
1603
+ * For a connected socket, close it if its inactivity timer
1604
+ * has expired.
1605
+ */
1606
+
1607
+ if (bConnectPending) {
1608
+ if ((MyEventMachine->GetCurrentLoopTime() - CreatedAt) >= PendingConnectTimeout) {
1609
+ UnbindReasonCode = ETIMEDOUT;
1610
+ ScheduleClose (false);
1611
+ //bCloseNow = true;
1612
+ }
1613
+ }
1614
+ else {
1615
+ if (InactivityTimeout && ((skew + MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout)) {
1616
+ UnbindReasonCode = ETIMEDOUT;
1617
+ ScheduleClose (false);
1618
+ //bCloseNow = true;
1619
+ }
1620
+ }
1621
+ }
1622
+
1623
+
1624
+ /****************************************
1625
+ LoopbreakDescriptor::LoopbreakDescriptor
1626
+ ****************************************/
1627
+
1628
+ LoopbreakDescriptor::LoopbreakDescriptor (SOCKET sd, EventMachine_t *parent_em):
1629
+ EventableDescriptor (sd, parent_em)
1630
+ {
1631
+ /* This is really bad and ugly. Change someday if possible.
1632
+ * We have to know about an event-machine (probably the one that owns us),
1633
+ * so we can pass newly-created connections to it.
1634
+ */
1635
+
1636
+ bCallbackUnbind = false;
1637
+
1638
+ #ifdef HAVE_EPOLL
1639
+ EpollEvent.events = EPOLLIN;
1640
+ #endif
1641
+ #ifdef HAVE_KQUEUE
1642
+ MyEventMachine->ArmKqueueReader (this);
1643
+ #endif
1644
+ }
1645
+
1646
+
1647
+
1648
+
1649
+ /*************************
1650
+ LoopbreakDescriptor::Read
1651
+ *************************/
1652
+
1653
+ void LoopbreakDescriptor::Read()
1654
+ {
1655
+ // TODO, refactor, this code is probably in the wrong place.
1656
+ assert (MyEventMachine);
1657
+ MyEventMachine->_ReadLoopBreaker();
1658
+ }
1659
+
1660
+
1661
+ /**************************
1662
+ LoopbreakDescriptor::Write
1663
+ **************************/
1664
+
1665
+ void LoopbreakDescriptor::Write()
1666
+ {
1667
+ // Why are we here?
1668
+ throw std::runtime_error ("bad code path in loopbreak");
1669
+ }
1670
+
1671
+ /**************************************
1672
+ AcceptorDescriptor::AcceptorDescriptor
1673
+ **************************************/
1674
+
1675
+ AcceptorDescriptor::AcceptorDescriptor (SOCKET sd, EventMachine_t *parent_em):
1676
+ EventableDescriptor (sd, parent_em)
1677
+ {
1678
+ #ifdef HAVE_EPOLL
1679
+ EpollEvent.events = EPOLLIN;
1680
+ #endif
1681
+ #ifdef HAVE_KQUEUE
1682
+ MyEventMachine->ArmKqueueReader (this);
1683
+ #endif
1684
+ }
1685
+
1686
+
1687
+ /***************************************
1688
+ AcceptorDescriptor::~AcceptorDescriptor
1689
+ ***************************************/
1690
+
1691
+ AcceptorDescriptor::~AcceptorDescriptor()
1692
+ {
1693
+ }
1694
+
1695
+ /****************************************
1696
+ STATIC: AcceptorDescriptor::StopAcceptor
1697
+ ****************************************/
1698
+
1699
+ void AcceptorDescriptor::StopAcceptor (const uintptr_t binding)
1700
+ {
1701
+ // TODO: This is something of a hack, or at least it's a static method of the wrong class.
1702
+ AcceptorDescriptor *ad = dynamic_cast <AcceptorDescriptor*> (Bindable_t::GetObject (binding));
1703
+ if (ad)
1704
+ ad->ScheduleClose (false);
1705
+ else
1706
+ throw std::runtime_error ("failed to close nonexistent acceptor");
1707
+ }
1708
+
1709
+
1710
+ /************************
1711
+ AcceptorDescriptor::Read
1712
+ ************************/
1713
+
1714
+ void AcceptorDescriptor::Read()
1715
+ {
1716
+ /* Accept up to a certain number of sockets on the listening connection.
1717
+ * Don't try to accept all that are present, because this would allow a DoS attack
1718
+ * in which no data were ever read or written. We should accept more than one,
1719
+ * if available, to keep the partially accepted sockets from backing up in the kernel.
1720
+ */
1721
+
1722
+ /* Make sure we use non-blocking i/o on the acceptor socket, since we're selecting it
1723
+ * for readability. According to Stevens UNP, it's possible for an acceptor to select readable
1724
+ * and then block when we call accept. For example, the other end resets the connection after
1725
+ * the socket selects readable and before we call accept. The kernel will remove the dead
1726
+ * socket from the accept queue. If the accept queue is now empty, accept will block.
1727
+ */
1728
+
1729
+
1730
+ struct sockaddr_in6 pin;
1731
+ socklen_t addrlen = sizeof (pin);
1732
+ int accept_count = EventMachine_t::GetSimultaneousAcceptCount();
1733
+
1734
+ for (int i=0; i < accept_count; i++) {
1735
+ #if defined(HAVE_CONST_SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
1736
+ SOCKET sd = accept4 (GetSocket(), (struct sockaddr*)&pin, &addrlen, SOCK_CLOEXEC);
1737
+ if (sd == INVALID_SOCKET) {
1738
+ // We may be running in a kernel where
1739
+ // SOCK_CLOEXEC is not supported - fall back:
1740
+ sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
1741
+ }
1742
+ #else
1743
+ SOCKET sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
1744
+ #endif
1745
+ if (sd == INVALID_SOCKET) {
1746
+ // This breaks the loop when we've accepted everything on the kernel queue,
1747
+ // up to 10 new connections. But what if the *first* accept fails?
1748
+ // Does that mean anything serious is happening, beyond the situation
1749
+ // described in the note above?
1750
+ break;
1751
+ }
1752
+
1753
+ // Set the newly-accepted socket non-blocking and to close on exec.
1754
+ // On Windows, this may fail because, weirdly, Windows inherits the non-blocking
1755
+ // attribute that we applied to the acceptor socket into the accepted one.
1756
+ if (!SetFdCloexec(sd) || !SetSocketNonblocking (sd)) {
1757
+ //int val = fcntl (sd, F_GETFL, 0);
1758
+ //if (fcntl (sd, F_SETFL, val | O_NONBLOCK) == -1) {
1759
+ shutdown (sd, 1);
1760
+ close (sd);
1761
+ continue;
1762
+ }
1763
+
1764
+ // Disable slow-start (Nagle algorithm). Eventually make this configurable.
1765
+ int one = 1;
1766
+ setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one));
1767
+
1768
+
1769
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, MyEventMachine);
1770
+ if (!cd)
1771
+ throw std::runtime_error ("no newly accepted connection");
1772
+ cd->SetServerMode();
1773
+ if (EventCallback) {
1774
+ (*EventCallback) (GetBinding(), EM_CONNECTION_ACCEPTED, NULL, cd->GetBinding());
1775
+ }
1776
+ #ifdef HAVE_EPOLL
1777
+ cd->GetEpollEvent()->events = 0;
1778
+ if (cd->SelectForRead())
1779
+ cd->GetEpollEvent()->events |= EPOLLIN;
1780
+ if (cd->SelectForWrite())
1781
+ cd->GetEpollEvent()->events |= EPOLLOUT;
1782
+ #endif
1783
+ assert (MyEventMachine);
1784
+ MyEventMachine->Add (cd);
1785
+ #ifdef HAVE_KQUEUE
1786
+ bKqueueArmWrite = cd->SelectForWrite();
1787
+ if (bKqueueArmWrite)
1788
+ MyEventMachine->Modify (cd);
1789
+ if (cd->SelectForRead())
1790
+ MyEventMachine->ArmKqueueReader (cd);
1791
+ #endif
1792
+ }
1793
+
1794
+ }
1795
+
1796
+
1797
+ /*************************
1798
+ AcceptorDescriptor::Write
1799
+ *************************/
1800
+
1801
+ void AcceptorDescriptor::Write()
1802
+ {
1803
+ // Why are we here?
1804
+ throw std::runtime_error ("bad code path in acceptor");
1805
+ }
1806
+
1807
+
1808
+ /*****************************
1809
+ AcceptorDescriptor::Heartbeat
1810
+ *****************************/
1811
+
1812
+ void AcceptorDescriptor::Heartbeat()
1813
+ {
1814
+ // No-op
1815
+ }
1816
+
1817
+
1818
+ /**************************************
1819
+ DatagramDescriptor::DatagramDescriptor
1820
+ **************************************/
1821
+
1822
+ DatagramDescriptor::DatagramDescriptor (SOCKET sd, EventMachine_t *parent_em):
1823
+ EventableDescriptor (sd, parent_em),
1824
+ OutboundDataSize (0)
1825
+ {
1826
+ memset (&ReturnAddress, 0, sizeof(ReturnAddress));
1827
+
1828
+ /* Provisionally added 19Oct07. All datagram sockets support broadcasting.
1829
+ * Until now, sending to a broadcast address would give EACCES (permission denied)
1830
+ * on systems like Linux and BSD that require the SO_BROADCAST socket-option in order
1831
+ * to accept a packet to a broadcast address. Solaris doesn't require it. I think
1832
+ * Windows DOES require it but I'm not sure.
1833
+ *
1834
+ * Ruby does NOT do what we're doing here. In Ruby, you have to explicitly set SO_BROADCAST
1835
+ * on a UDP socket in order to enable broadcasting. The reason for requiring the option
1836
+ * in the first place is so that applications don't send broadcast datagrams by mistake.
1837
+ * I imagine that could happen if a user of an application typed in an address that happened
1838
+ * to be a broadcast address on that particular subnet.
1839
+ *
1840
+ * This is provisional because someone may eventually come up with a good reason not to
1841
+ * do it for all UDP sockets. If that happens, then we'll need to add a usercode-level API
1842
+ * to set the socket option, just like Ruby does. AND WE'LL ALSO BREAK CODE THAT DOESN'T
1843
+ * EXPLICITLY SET THE OPTION.
1844
+ */
1845
+
1846
+ int oval = 1;
1847
+ setsockopt (GetSocket(), SOL_SOCKET, SO_BROADCAST, (char*)&oval, sizeof(oval));
1848
+
1849
+ #ifdef HAVE_EPOLL
1850
+ EpollEvent.events = EPOLLIN;
1851
+ #endif
1852
+ #ifdef HAVE_KQUEUE
1853
+ MyEventMachine->ArmKqueueReader (this);
1854
+ #endif
1855
+ }
1856
+
1857
+
1858
+ /***************************************
1859
+ DatagramDescriptor::~DatagramDescriptor
1860
+ ***************************************/
1861
+
1862
+ DatagramDescriptor::~DatagramDescriptor()
1863
+ {
1864
+ // Run down any stranded outbound data.
1865
+ for (size_t i=0; i < OutboundPages.size(); i++)
1866
+ OutboundPages[i].Free();
1867
+ }
1868
+
1869
+
1870
+ /*****************************
1871
+ DatagramDescriptor::Heartbeat
1872
+ *****************************/
1873
+
1874
+ void DatagramDescriptor::Heartbeat()
1875
+ {
1876
+ // Close it if its inactivity timer has expired.
1877
+
1878
+ if (InactivityTimeout && ((MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout))
1879
+ ScheduleClose (false);
1880
+ //bCloseNow = true;
1881
+ }
1882
+
1883
+
1884
+ /************************
1885
+ DatagramDescriptor::Read
1886
+ ************************/
1887
+
1888
+ void DatagramDescriptor::Read()
1889
+ {
1890
+ SOCKET sd = GetSocket();
1891
+ assert (sd != INVALID_SOCKET);
1892
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
1893
+
1894
+ // This is an extremely large read buffer.
1895
+ // In many cases you wouldn't expect to get any more than 4K.
1896
+ char readbuffer [16 * 1024];
1897
+
1898
+ for (int i=0; i < 10; i++) {
1899
+ // Don't read just one buffer and then move on. This is faster
1900
+ // if there is a lot of incoming.
1901
+ // But don't read indefinitely. Give other sockets a chance to run.
1902
+ // NOTICE, we're reading one less than the buffer size.
1903
+ // That's so we can put a guard byte at the end of what we send
1904
+ // to user code.
1905
+
1906
+ struct sockaddr_in6 sin;
1907
+ socklen_t slen = sizeof (sin);
1908
+ memset (&sin, 0, slen);
1909
+
1910
+ int r = recvfrom (sd, readbuffer, sizeof(readbuffer) - 1, 0, (struct sockaddr*)&sin, &slen);
1911
+ //cerr << "<R:" << r << ">";
1912
+
1913
+ // In UDP, a zero-length packet is perfectly legal.
1914
+ if (r >= 0) {
1915
+
1916
+ // Add a null-terminator at the the end of the buffer
1917
+ // that we will send to the callback.
1918
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
1919
+ // to be able to depend on this behavior, so they will have
1920
+ // the option to do some things faster. Additionally it's
1921
+ // a security guard against buffer overflows.
1922
+ readbuffer [r] = 0;
1923
+
1924
+
1925
+ // Set up a "temporary" return address so that callers can "reply" to us
1926
+ // from within the callback we are about to invoke. That means that ordinary
1927
+ // calls to "send_data_to_connection" (which is of course misnamed in this
1928
+ // case) will result in packets being sent back to the same place that sent
1929
+ // us this one.
1930
+ // There is a different call (evma_send_datagram) for cases where the caller
1931
+ // actually wants to send a packet somewhere else.
1932
+
1933
+ memset (&ReturnAddress, 0, sizeof(ReturnAddress));
1934
+ memcpy (&ReturnAddress, &sin, slen);
1935
+
1936
+ _GenericInboundDispatch(readbuffer, r);
1937
+
1938
+ }
1939
+ else {
1940
+ // Basically a would-block, meaning we've read everything there is to read.
1941
+ break;
1942
+ }
1943
+
1944
+ }
1945
+
1946
+
1947
+ }
1948
+
1949
+
1950
+ /*************************
1951
+ DatagramDescriptor::Write
1952
+ *************************/
1953
+
1954
+ void DatagramDescriptor::Write()
1955
+ {
1956
+ /* It's possible for a socket to select writable and then no longer
1957
+ * be writable by the time we get around to writing. The kernel might
1958
+ * have used up its available output buffers between the select call
1959
+ * and when we get here. So this condition is not an error.
1960
+ * This code is very reminiscent of ConnectionDescriptor::_WriteOutboundData,
1961
+ * but differs in the that the outbound data pages (received from the
1962
+ * user) are _message-structured._ That is, we send each of them out
1963
+ * one message at a time.
1964
+ * TODO, we are currently suppressing the EMSGSIZE error!!!
1965
+ */
1966
+
1967
+ SOCKET sd = GetSocket();
1968
+ assert (sd != INVALID_SOCKET);
1969
+ LastActivity = MyEventMachine->GetCurrentLoopTime();
1970
+
1971
+ assert (OutboundPages.size() > 0);
1972
+
1973
+ // Send out up to 10 packets, then cycle the machine.
1974
+ for (int i = 0; i < 10; i++) {
1975
+ if (OutboundPages.size() <= 0)
1976
+ break;
1977
+ OutboundPage *op = &(OutboundPages[0]);
1978
+
1979
+ // The nasty cast to (char*) is needed because Windows is brain-dead.
1980
+ int s = sendto (sd, (char*)op->Buffer, op->Length, 0, (struct sockaddr*)&(op->From),
1981
+ (op->From.sin6_family == AF_INET6 ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr_in)));
1982
+ #ifdef OS_WIN32
1983
+ int e = WSAGetLastError();
1984
+ #else
1985
+ int e = errno;
1986
+ #endif
1987
+
1988
+ OutboundDataSize -= op->Length;
1989
+ op->Free();
1990
+ OutboundPages.pop_front();
1991
+
1992
+ if (s == SOCKET_ERROR) {
1993
+ #ifdef OS_UNIX
1994
+ if ((e != EINPROGRESS) && (e != EWOULDBLOCK) && (e != EINTR)) {
1995
+ #endif
1996
+ #ifdef OS_WIN32
1997
+ if ((e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK)) {
1998
+ #endif
1999
+ UnbindReasonCode = e;
2000
+ Close();
2001
+ break;
2002
+ }
2003
+ }
2004
+ }
2005
+
2006
+ #ifdef HAVE_EPOLL
2007
+ EpollEvent.events = EPOLLIN;
2008
+ if (SelectForWrite())
2009
+ EpollEvent.events |= EPOLLOUT;
2010
+ assert (MyEventMachine);
2011
+ MyEventMachine->Modify (this);
2012
+ #endif
2013
+ #ifdef HAVE_KQUEUE
2014
+ bKqueueArmWrite = SelectForWrite();
2015
+ assert (MyEventMachine);
2016
+ MyEventMachine->Modify (this);
2017
+ #endif
2018
+ }
2019
+
2020
+
2021
+ /**********************************
2022
+ DatagramDescriptor::SelectForWrite
2023
+ **********************************/
2024
+
2025
+ bool DatagramDescriptor::SelectForWrite()
2026
+ {
2027
+ /* Changed 15Nov07, per bug report by Mark Zvillius.
2028
+ * The outbound data size will be zero if there are zero-length outbound packets,
2029
+ * so we now select writable in case the outbound page buffer is not empty.
2030
+ * Note that the superclass ShouldDelete method still checks for outbound data size,
2031
+ * which may be wrong.
2032
+ */
2033
+ //return (GetOutboundDataSize() > 0); (Original)
2034
+ return (OutboundPages.size() > 0);
2035
+ }
2036
+
2037
+
2038
+ /************************************
2039
+ DatagramDescriptor::SendOutboundData
2040
+ ************************************/
2041
+
2042
+ int DatagramDescriptor::SendOutboundData (const char *data, unsigned long length)
2043
+ {
2044
+ // This is almost an exact clone of ConnectionDescriptor::_SendRawOutboundData.
2045
+ // That means most of it could be factored to a common ancestor. Note that
2046
+ // empty datagrams are meaningful, which isn't the case for TCP streams.
2047
+
2048
+ if (IsCloseScheduled())
2049
+ return 0;
2050
+
2051
+ if (!data && (length > 0))
2052
+ throw std::runtime_error ("bad outbound data");
2053
+ char *buffer = (char *) malloc (length + 1);
2054
+ if (!buffer)
2055
+ throw std::runtime_error ("no allocation for outbound data");
2056
+ memcpy (buffer, data, length);
2057
+ buffer [length] = 0;
2058
+ OutboundPages.push_back (OutboundPage (buffer, length, ReturnAddress));
2059
+ OutboundDataSize += length;
2060
+
2061
+ #ifdef HAVE_EPOLL
2062
+ EpollEvent.events = (EPOLLIN | EPOLLOUT);
2063
+ assert (MyEventMachine);
2064
+ MyEventMachine->Modify (this);
2065
+ #endif
2066
+ #ifdef HAVE_KQUEUE
2067
+ bKqueueArmWrite = true;
2068
+ assert (MyEventMachine);
2069
+ MyEventMachine->Modify (this);
2070
+ #endif
2071
+
2072
+ return length;
2073
+ }
2074
+
2075
+
2076
+ /****************************************
2077
+ DatagramDescriptor::SendOutboundDatagram
2078
+ ****************************************/
2079
+
2080
+ int DatagramDescriptor::SendOutboundDatagram (const char *data, unsigned long length, const char *address, int port)
2081
+ {
2082
+ // This is an exact clone of ConnectionDescriptor::SendOutboundData.
2083
+ // That means it needs to move to a common ancestor.
2084
+ // TODO: Refactor this so there's no overlap with SendOutboundData.
2085
+
2086
+ if (IsCloseScheduled())
2087
+ //if (bCloseNow || bCloseAfterWriting)
2088
+ return 0;
2089
+
2090
+ if (!address || !*address || !port)
2091
+ return 0;
2092
+
2093
+ struct sockaddr_in6 addr_here;
2094
+ size_t addr_here_len = sizeof addr_here;
2095
+ if (0 != EventMachine_t::name2address (address, port, SOCK_DGRAM, (struct sockaddr *)&addr_here, &addr_here_len))
2096
+ return -1;
2097
+
2098
+ if (!data && (length > 0))
2099
+ throw std::runtime_error ("bad outbound data");
2100
+ char *buffer = (char *) malloc (length + 1);
2101
+ if (!buffer)
2102
+ throw std::runtime_error ("no allocation for outbound data");
2103
+ memcpy (buffer, data, length);
2104
+ buffer [length] = 0;
2105
+ OutboundPages.push_back (OutboundPage (buffer, length, addr_here));
2106
+ OutboundDataSize += length;
2107
+
2108
+ #ifdef HAVE_EPOLL
2109
+ EpollEvent.events = (EPOLLIN | EPOLLOUT);
2110
+ assert (MyEventMachine);
2111
+ MyEventMachine->Modify (this);
2112
+ #endif
2113
+ #ifdef HAVE_KQUEUE
2114
+ bKqueueArmWrite = true;
2115
+ assert (MyEventMachine);
2116
+ MyEventMachine->Modify (this);
2117
+ #endif
2118
+
2119
+ return length;
2120
+ }
2121
+
2122
+
2123
+ /**********************************************
2124
+ ConnectionDescriptor::GetCommInactivityTimeout
2125
+ **********************************************/
2126
+
2127
+ uint64_t ConnectionDescriptor::GetCommInactivityTimeout()
2128
+ {
2129
+ return InactivityTimeout / 1000;
2130
+ }
2131
+
2132
+
2133
+ /**********************************************
2134
+ ConnectionDescriptor::SetCommInactivityTimeout
2135
+ **********************************************/
2136
+
2137
+ int ConnectionDescriptor::SetCommInactivityTimeout (uint64_t value)
2138
+ {
2139
+ InactivityTimeout = value * 1000;
2140
+ MyEventMachine->QueueHeartbeat(this);
2141
+ return 1;
2142
+ }
2143
+
2144
+ /*******************************
2145
+ DatagramDescriptor::GetPeername
2146
+ *******************************/
2147
+
2148
+ bool DatagramDescriptor::GetPeername (struct sockaddr *s, socklen_t *len)
2149
+ {
2150
+ bool ok = false;
2151
+ if (s) {
2152
+ *len = sizeof(ReturnAddress);
2153
+ memset (s, 0, sizeof(ReturnAddress));
2154
+ memcpy (s, &ReturnAddress, sizeof(ReturnAddress));
2155
+ ok = true;
2156
+ }
2157
+ return ok;
2158
+ }
2159
+
2160
+
2161
+ /********************************************
2162
+ DatagramDescriptor::GetCommInactivityTimeout
2163
+ ********************************************/
2164
+
2165
+ uint64_t DatagramDescriptor::GetCommInactivityTimeout()
2166
+ {
2167
+ return InactivityTimeout / 1000;
2168
+ }
2169
+
2170
+ /********************************************
2171
+ DatagramDescriptor::SetCommInactivityTimeout
2172
+ ********************************************/
2173
+
2174
+ int DatagramDescriptor::SetCommInactivityTimeout (uint64_t value)
2175
+ {
2176
+ if (value > 0) {
2177
+ InactivityTimeout = value * 1000;
2178
+ MyEventMachine->QueueHeartbeat(this);
2179
+ return 1;
2180
+ }
2181
+ return 0;
2182
+ }
2183
+
2184
+
2185
+ /************************************
2186
+ InotifyDescriptor::InotifyDescriptor
2187
+ *************************************/
2188
+
2189
+ InotifyDescriptor::InotifyDescriptor (EventMachine_t *em):
2190
+ EventableDescriptor(0, em)
2191
+ {
2192
+ bCallbackUnbind = false;
2193
+
2194
+ #ifndef HAVE_INOTIFY
2195
+ throw std::runtime_error("no inotify support on this system");
2196
+ #else
2197
+
2198
+ int fd = inotify_init();
2199
+ if (fd == -1) {
2200
+ char buf[200];
2201
+ snprintf (buf, sizeof(buf)-1, "unable to create inotify descriptor: %s", strerror(errno));
2202
+ throw std::runtime_error (buf);
2203
+ }
2204
+
2205
+ MySocket = fd;
2206
+ SetSocketNonblocking(MySocket);
2207
+ #ifdef HAVE_EPOLL
2208
+ EpollEvent.events = EPOLLIN;
2209
+ #endif
2210
+
2211
+ #endif
2212
+ }
2213
+
2214
+
2215
+ /*************************************
2216
+ InotifyDescriptor::~InotifyDescriptor
2217
+ **************************************/
2218
+
2219
+ InotifyDescriptor::~InotifyDescriptor()
2220
+ {
2221
+ close(MySocket);
2222
+ MySocket = INVALID_SOCKET;
2223
+ }
2224
+
2225
+ /***********************
2226
+ InotifyDescriptor::Read
2227
+ ************************/
2228
+
2229
+ void InotifyDescriptor::Read()
2230
+ {
2231
+ assert (MyEventMachine);
2232
+ MyEventMachine->_ReadInotifyEvents();
2233
+ }
2234
+
2235
+
2236
+ /************************
2237
+ InotifyDescriptor::Write
2238
+ *************************/
2239
+
2240
+ void InotifyDescriptor::Write()
2241
+ {
2242
+ throw std::runtime_error("bad code path in inotify");
2243
+ }