eventmachine 1.2.0.dev.2-x64-mingw32

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