wj_eventmachine 1.3.0.dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+ }