sensu-em 2.4.0-x86-mingw32

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