sidekick-client 0.2.1 → 0.2.2

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