eventmachine 0.12.6-x86-mswin32-60 → 0.12.8-x86-mswin32-60

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