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,2282 +0,0 @@
1
- /*****************************************************************************
2
-
3
- $Id$
4
-
5
- File: em.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
- // THIS ENTIRE FILE WILL EVENTUALLY BE FOR UNIX BUILDS ONLY.
21
- //#ifdef OS_UNIX
22
-
23
-
24
- #include "project.h"
25
-
26
- // Keep a global variable floating around
27
- // with the current loop time as set by the Event Machine.
28
- // This avoids the need for frequent expensive calls to time(NULL);
29
- Int64 gCurrentLoopTime;
30
-
31
- #ifdef OS_WIN32
32
- unsigned gTickCountTickover;
33
- unsigned gLastTickCount;
34
- #endif
35
-
36
-
37
- /* The numer of max outstanding timers was once a const enum defined in em.h.
38
- * Now we define it here so that users can change its value if necessary.
39
- */
40
- static unsigned int MaxOutstandingTimers = 10000;
41
-
42
-
43
- /* Internal helper to convert strings to internet addresses. IPv6-aware.
44
- * Not reentrant or threadsafe, optimized for speed.
45
- */
46
- static struct sockaddr *name2address (const char *server, int port, int *family, int *bind_size);
47
-
48
- /***************************************
49
- STATIC EventMachine_t::GetMaxTimerCount
50
- ***************************************/
51
-
52
- int EventMachine_t::GetMaxTimerCount()
53
- {
54
- return MaxOutstandingTimers;
55
- }
56
-
57
-
58
- /***************************************
59
- STATIC EventMachine_t::SetMaxTimerCount
60
- ***************************************/
61
-
62
- void EventMachine_t::SetMaxTimerCount (int count)
63
- {
64
- /* Allow a user to increase the maximum number of outstanding timers.
65
- * If this gets "too high" (a metric that is of course platform dependent),
66
- * bad things will happen like performance problems and possible overuse
67
- * of memory.
68
- * The actual timer mechanism is very efficient so it's hard to know what
69
- * the practical max, but 100,000 shouldn't be too problematical.
70
- */
71
- if (count < 100)
72
- count = 100;
73
- MaxOutstandingTimers = count;
74
- }
75
-
76
-
77
-
78
- /******************************
79
- EventMachine_t::EventMachine_t
80
- ******************************/
81
-
82
- EventMachine_t::EventMachine_t (void (*event_callback)(const unsigned long, int, const char*, const unsigned long)):
83
- HeartbeatInterval(2000000),
84
- EventCallback (event_callback),
85
- NextHeartbeatTime (0),
86
- LoopBreakerReader (-1),
87
- LoopBreakerWriter (-1),
88
- bEpoll (false),
89
- epfd (-1),
90
- bKqueue (false),
91
- kqfd (-1),
92
- inotify (NULL)
93
- {
94
- // Default time-slice is just smaller than one hundred mills.
95
- Quantum.tv_sec = 0;
96
- Quantum.tv_usec = 90000;
97
-
98
- gTerminateSignalReceived = false;
99
- // Make sure the current loop time is sane, in case we do any initializations of
100
- // objects before we start running.
101
- _UpdateTime();
102
-
103
- /* We initialize the network library here (only on Windows of course)
104
- * and initialize "loop breakers." Our destructor also does some network-level
105
- * cleanup. There's thus an implicit assumption that any given instance of EventMachine_t
106
- * will only call ::Run once. Is that a good assumption? Should we move some of these
107
- * inits and de-inits into ::Run?
108
- */
109
- #ifdef OS_WIN32
110
- WSADATA w;
111
- WSAStartup (MAKEWORD (1, 1), &w);
112
- #endif
113
-
114
- _InitializeLoopBreaker();
115
- }
116
-
117
-
118
- /*******************************
119
- EventMachine_t::~EventMachine_t
120
- *******************************/
121
-
122
- EventMachine_t::~EventMachine_t()
123
- {
124
- // Run down descriptors
125
- size_t i;
126
- for (i = 0; i < NewDescriptors.size(); i++)
127
- delete NewDescriptors[i];
128
- for (i = 0; i < Descriptors.size(); i++)
129
- delete Descriptors[i];
130
-
131
- close (LoopBreakerReader);
132
- close (LoopBreakerWriter);
133
-
134
- // Remove any file watch descriptors
135
- while(!Files.empty()) {
136
- map<int, Bindable_t*>::iterator f = Files.begin();
137
- UnwatchFile (f->first);
138
- }
139
-
140
- if (epfd != -1)
141
- close (epfd);
142
- if (kqfd != -1)
143
- close (kqfd);
144
- }
145
-
146
-
147
- /*************************
148
- EventMachine_t::_UseEpoll
149
- *************************/
150
-
151
- void EventMachine_t::_UseEpoll()
152
- {
153
- /* Temporary.
154
- * Use an internal flag to switch in epoll-based functionality until we determine
155
- * how it should be integrated properly and the extent of the required changes.
156
- * A permanent solution needs to allow the integration of additional technologies,
157
- * like kqueue and Solaris's events.
158
- */
159
-
160
- #ifdef HAVE_EPOLL
161
- bEpoll = true;
162
- #endif
163
- }
164
-
165
- /**************************
166
- EventMachine_t::_UseKqueue
167
- **************************/
168
-
169
- void EventMachine_t::_UseKqueue()
170
- {
171
- /* Temporary.
172
- * See comments under _UseEpoll.
173
- */
174
-
175
- #ifdef HAVE_KQUEUE
176
- bKqueue = true;
177
- #endif
178
- }
179
-
180
-
181
- /****************************
182
- EventMachine_t::ScheduleHalt
183
- ****************************/
184
-
185
- void EventMachine_t::ScheduleHalt()
186
- {
187
- /* This is how we stop the machine.
188
- * This can be called by clients. Signal handlers will probably
189
- * set the global flag.
190
- * For now this means there can only be one EventMachine ever running at a time.
191
- *
192
- * IMPORTANT: keep this light, fast, and async-safe. Don't do anything frisky in here,
193
- * because it may be called from signal handlers invoked from code that we don't
194
- * control. At this writing (20Sep06), EM does NOT install any signal handlers of
195
- * its own.
196
- *
197
- * We need a FAQ. And one of the questions is: how do I stop EM when Ctrl-C happens?
198
- * The answer is to call evma_stop_machine, which calls here, from a SIGINT handler.
199
- */
200
- gTerminateSignalReceived = true;
201
- }
202
-
203
-
204
-
205
- /*******************************
206
- EventMachine_t::SetTimerQuantum
207
- *******************************/
208
-
209
- void EventMachine_t::SetTimerQuantum (int interval)
210
- {
211
- /* We get a timer-quantum expressed in milliseconds.
212
- * Don't set a quantum smaller than 5 or larger than 2500.
213
- */
214
-
215
- if ((interval < 5) || (interval > 2500))
216
- throw std::runtime_error ("invalid timer-quantum");
217
-
218
- Quantum.tv_sec = interval / 1000;
219
- Quantum.tv_usec = (interval % 1000) * 1000;
220
- }
221
-
222
-
223
- /*************************************
224
- (STATIC) EventMachine_t::SetuidString
225
- *************************************/
226
-
227
- void EventMachine_t::SetuidString (const char *username)
228
- {
229
- /* This method takes a caller-supplied username and tries to setuid
230
- * to that user. There is no meaningful implementation (and no error)
231
- * on Windows. On Unix, a failure to setuid the caller-supplied string
232
- * causes a fatal abort, because presumably the program is calling here
233
- * in order to fulfill a security requirement. If we fail silently,
234
- * the user may continue to run with too much privilege.
235
- *
236
- * TODO, we need to decide on and document a way of generating C++ level errors
237
- * that can be wrapped in documented Ruby exceptions, so users can catch
238
- * and handle them. And distinguish it from errors that we WON'T let the Ruby
239
- * user catch (like security-violations and resource-overallocation).
240
- * A setuid failure here would be in the latter category.
241
- */
242
-
243
- #ifdef OS_UNIX
244
- if (!username || !*username)
245
- throw std::runtime_error ("setuid_string failed: no username specified");
246
-
247
- struct passwd *p = getpwnam (username);
248
- if (!p)
249
- throw std::runtime_error ("setuid_string failed: unknown username");
250
-
251
- if (setuid (p->pw_uid) != 0)
252
- throw std::runtime_error ("setuid_string failed: no setuid");
253
-
254
- // Success.
255
- #endif
256
- }
257
-
258
-
259
- /****************************************
260
- (STATIC) EventMachine_t::SetRlimitNofile
261
- ****************************************/
262
-
263
- int EventMachine_t::SetRlimitNofile (int nofiles)
264
- {
265
- #ifdef OS_UNIX
266
- struct rlimit rlim;
267
- getrlimit (RLIMIT_NOFILE, &rlim);
268
- if (nofiles >= 0) {
269
- rlim.rlim_cur = nofiles;
270
- if ((unsigned int)nofiles > rlim.rlim_max)
271
- rlim.rlim_max = nofiles;
272
- setrlimit (RLIMIT_NOFILE, &rlim);
273
- // ignore the error return, for now at least.
274
- // TODO, emit an error message someday when we have proper debug levels.
275
- }
276
- getrlimit (RLIMIT_NOFILE, &rlim);
277
- return rlim.rlim_cur;
278
- #endif
279
-
280
- #ifdef OS_WIN32
281
- // No meaningful implementation on Windows.
282
- return 0;
283
- #endif
284
- }
285
-
286
-
287
- /*********************************
288
- EventMachine_t::SignalLoopBreaker
289
- *********************************/
290
-
291
- void EventMachine_t::SignalLoopBreaker()
292
- {
293
- #ifdef OS_UNIX
294
- write (LoopBreakerWriter, "", 1);
295
- #endif
296
- #ifdef OS_WIN32
297
- sendto (LoopBreakerReader, "", 0, 0, (struct sockaddr*)&(LoopBreakerTarget), sizeof(LoopBreakerTarget));
298
- #endif
299
- }
300
-
301
-
302
- /**************************************
303
- EventMachine_t::_InitializeLoopBreaker
304
- **************************************/
305
-
306
- void EventMachine_t::_InitializeLoopBreaker()
307
- {
308
- /* A "loop-breaker" is a socket-descriptor that we can write to in order
309
- * to break the main select loop. Primarily useful for things running on
310
- * threads other than the main EM thread, so they can trigger processing
311
- * of events that arise exogenously to the EM.
312
- * Keep the loop-breaker pipe out of the main descriptor set, otherwise
313
- * its events will get passed on to user code.
314
- */
315
-
316
- #ifdef OS_UNIX
317
- int fd[2];
318
- if (pipe (fd))
319
- throw std::runtime_error ("no loop breaker");
320
-
321
- LoopBreakerWriter = fd[1];
322
- LoopBreakerReader = fd[0];
323
- #endif
324
-
325
- #ifdef OS_WIN32
326
- int sd = socket (AF_INET, SOCK_DGRAM, 0);
327
- if (sd == INVALID_SOCKET)
328
- throw std::runtime_error ("no loop breaker socket");
329
- SetSocketNonblocking (sd);
330
-
331
- memset (&LoopBreakerTarget, 0, sizeof(LoopBreakerTarget));
332
- LoopBreakerTarget.sin_family = AF_INET;
333
- LoopBreakerTarget.sin_addr.s_addr = inet_addr ("127.0.0.1");
334
-
335
- srand ((int)time(NULL));
336
- int i;
337
- for (i=0; i < 100; i++) {
338
- int r = (rand() % 10000) + 20000;
339
- LoopBreakerTarget.sin_port = htons (r);
340
- if (bind (sd, (struct sockaddr*)&LoopBreakerTarget, sizeof(LoopBreakerTarget)) == 0)
341
- break;
342
- }
343
-
344
- if (i == 100)
345
- throw std::runtime_error ("no loop breaker");
346
- LoopBreakerReader = sd;
347
- #endif
348
- }
349
-
350
- /***************************
351
- EventMachine_t::_UpdateTime
352
- ***************************/
353
-
354
- void EventMachine_t::_UpdateTime()
355
- {
356
- #if defined(OS_UNIX)
357
- struct timeval tv;
358
- gettimeofday (&tv, NULL);
359
- gCurrentLoopTime = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec));
360
-
361
- #elif defined(OS_WIN32)
362
- unsigned tick = GetTickCount();
363
- if (tick < gLastTickCount)
364
- gTickCountTickover += 1;
365
- gLastTickCount = tick;
366
- gCurrentLoopTime = ((Int64)gTickCountTickover << 32) + (Int64)tick;
367
-
368
- #else
369
- gCurrentLoopTime = (Int64)time(NULL) * 1000000LL;
370
- #endif
371
- }
372
-
373
- /*******************
374
- EventMachine_t::Run
375
- *******************/
376
-
377
- void EventMachine_t::Run()
378
- {
379
- #ifdef OS_WIN32
380
- HookControlC (true);
381
- #endif
382
-
383
- #ifdef HAVE_EPOLL
384
- if (bEpoll) {
385
- epfd = epoll_create (MaxEpollDescriptors);
386
- if (epfd == -1) {
387
- char buf[200];
388
- snprintf (buf, sizeof(buf)-1, "unable to create epoll descriptor: %s", strerror(errno));
389
- throw std::runtime_error (buf);
390
- }
391
- int cloexec = fcntl (epfd, F_GETFD, 0);
392
- assert (cloexec >= 0);
393
- cloexec |= FD_CLOEXEC;
394
- fcntl (epfd, F_SETFD, cloexec);
395
-
396
- assert (LoopBreakerReader >= 0);
397
- LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
398
- assert (ld);
399
- Add (ld);
400
- }
401
- #endif
402
-
403
- #ifdef HAVE_KQUEUE
404
- if (bKqueue) {
405
- kqfd = kqueue();
406
- if (kqfd == -1) {
407
- char buf[200];
408
- snprintf (buf, sizeof(buf)-1, "unable to create kqueue descriptor: %s", strerror(errno));
409
- throw std::runtime_error (buf);
410
- }
411
- // cloexec not needed. By definition, kqueues are not carried across forks.
412
-
413
- assert (LoopBreakerReader >= 0);
414
- LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
415
- assert (ld);
416
- Add (ld);
417
- }
418
- #endif
419
-
420
- while (true) {
421
- _UpdateTime();
422
- if (!_RunTimers())
423
- break;
424
-
425
- /* _Add must precede _Modify because the same descriptor might
426
- * be on both lists during the same pass through the machine,
427
- * and to modify a descriptor before adding it would fail.
428
- */
429
- _AddNewDescriptors();
430
- _ModifyDescriptors();
431
-
432
- if (!_RunOnce())
433
- break;
434
- if (gTerminateSignalReceived)
435
- break;
436
- }
437
-
438
- #ifdef OS_WIN32
439
- HookControlC (false);
440
- #endif
441
- }
442
-
443
-
444
- /************************
445
- EventMachine_t::_RunOnce
446
- ************************/
447
-
448
- bool EventMachine_t::_RunOnce()
449
- {
450
- if (bEpoll)
451
- return _RunEpollOnce();
452
- else if (bKqueue)
453
- return _RunKqueueOnce();
454
- else
455
- return _RunSelectOnce();
456
- }
457
-
458
-
459
-
460
- /*****************************
461
- EventMachine_t::_RunEpollOnce
462
- *****************************/
463
-
464
- bool EventMachine_t::_RunEpollOnce()
465
- {
466
- #ifdef HAVE_EPOLL
467
- assert (epfd != -1);
468
- int s;
469
-
470
- #ifdef BUILD_FOR_RUBY
471
- TRAP_BEG;
472
- #endif
473
- s = epoll_wait (epfd, epoll_events, MaxEvents, 50);
474
- #ifdef BUILD_FOR_RUBY
475
- TRAP_END;
476
- #endif
477
-
478
- if (s > 0) {
479
- for (int i=0; i < s; i++) {
480
- EventableDescriptor *ed = (EventableDescriptor*) epoll_events[i].data.ptr;
481
-
482
- if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
483
- continue;
484
-
485
- assert(ed->GetSocket() != INVALID_SOCKET);
486
-
487
- if (epoll_events[i].events & EPOLLIN)
488
- ed->Read();
489
- if (epoll_events[i].events & EPOLLOUT)
490
- ed->Write();
491
- if (epoll_events[i].events & (EPOLLERR | EPOLLHUP))
492
- ed->HandleError();
493
- }
494
- }
495
- else if (s < 0) {
496
- // epoll_wait can fail on error in a handful of ways.
497
- // If this happens, then wait for a little while to avoid busy-looping.
498
- // If the error was EINTR, we probably caught SIGCHLD or something,
499
- // so keep the wait short.
500
- timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000};
501
- EmSelect (0, NULL, NULL, NULL, &tv);
502
- }
503
-
504
- { // cleanup dying sockets
505
- // vector::pop_back works in constant time.
506
- // TODO, rip this out and only delete the descriptors we know have died,
507
- // rather than traversing the whole list.
508
- // Modified 05Jan08 per suggestions by Chris Heath. It's possible that
509
- // an EventableDescriptor will have a descriptor value of -1. That will
510
- // happen if EventableDescriptor::Close was called on it. In that case,
511
- // don't call epoll_ctl to remove the socket's filters from the epoll set.
512
- // According to the epoll docs, this happens automatically when the
513
- // descriptor is closed anyway. This is different from the case where
514
- // the socket has already been closed but the descriptor in the ED object
515
- // hasn't yet been set to INVALID_SOCKET.
516
- int i, j;
517
- int nSockets = Descriptors.size();
518
- for (i=0, j=0; i < nSockets; i++) {
519
- EventableDescriptor *ed = Descriptors[i];
520
- assert (ed);
521
- if (ed->ShouldDelete()) {
522
- if (ed->GetSocket() != INVALID_SOCKET) {
523
- assert (bEpoll); // wouldn't be in this method otherwise.
524
- assert (epfd != -1);
525
- int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
526
- // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
527
- if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
528
- char buf [200];
529
- snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
530
- throw std::runtime_error (buf);
531
- }
532
- }
533
-
534
- ModifiedDescriptors.erase (ed);
535
- delete ed;
536
- }
537
- else
538
- Descriptors [j++] = ed;
539
- }
540
- while ((size_t)j < Descriptors.size())
541
- Descriptors.pop_back();
542
-
543
- }
544
-
545
- // TODO, heartbeats.
546
- // Added 14Sep07, its absence was noted by Brian Candler. But the comment was here, indicated
547
- // that this got thought about and not done when EPOLL was originally written. Was there a reason
548
- // not to do it, or was it an oversight? Certainly, running a heartbeat on 50,000 connections every
549
- // two seconds can get to be a real bear, especially if all we're doing is timing out dead ones.
550
- // Maybe there's a better way to do this. (Or maybe it's not that expensive after all.)
551
- //
552
- { // dispatch heartbeats
553
- if (gCurrentLoopTime >= NextHeartbeatTime) {
554
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
555
-
556
- for (int i=0; i < Descriptors.size(); i++) {
557
- EventableDescriptor *ed = Descriptors[i];
558
- assert (ed);
559
- ed->Heartbeat();
560
- }
561
- }
562
- }
563
-
564
- #ifdef BUILD_FOR_RUBY
565
- if (!rb_thread_alone()) {
566
- rb_thread_schedule();
567
- }
568
- #endif
569
-
570
- return true;
571
- #else
572
- throw std::runtime_error ("epoll is not implemented on this platform");
573
- #endif
574
- }
575
-
576
-
577
- /******************************
578
- EventMachine_t::_RunKqueueOnce
579
- ******************************/
580
-
581
- bool EventMachine_t::_RunKqueueOnce()
582
- {
583
- #ifdef HAVE_KQUEUE
584
- assert (kqfd != -1);
585
- struct timespec ts = {0, 10000000}; // Too frequent. Use blocking_region
586
-
587
- int k;
588
- #ifdef BUILD_FOR_RUBY
589
- TRAP_BEG;
590
- #endif
591
- k = kevent (kqfd, NULL, 0, Karray, MaxEvents, &ts);
592
- #ifdef BUILD_FOR_RUBY
593
- TRAP_END;
594
- #endif
595
-
596
- struct kevent *ke = Karray;
597
- while (k > 0) {
598
- switch (ke->filter)
599
- {
600
- case EVFILT_VNODE:
601
- _HandleKqueueFileEvent (ke);
602
- break;
603
-
604
- case EVFILT_PROC:
605
- _HandleKqueuePidEvent (ke);
606
- break;
607
-
608
- case EVFILT_READ:
609
- case EVFILT_WRITE:
610
- EventableDescriptor *ed = (EventableDescriptor*) (ke->udata);
611
- assert (ed);
612
-
613
- if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
614
- break;
615
-
616
- if (ke->filter == EVFILT_READ)
617
- ed->Read();
618
- else if (ke->filter == EVFILT_WRITE)
619
- ed->Write();
620
- else
621
- cerr << "Discarding unknown kqueue event " << ke->filter << endl;
622
-
623
- break;
624
- }
625
-
626
- --k;
627
- ++ke;
628
- }
629
-
630
- { // cleanup dying sockets
631
- // vector::pop_back works in constant time.
632
- // TODO, rip this out and only delete the descriptors we know have died,
633
- // rather than traversing the whole list.
634
- // In kqueue, closing a descriptor automatically removes its event filters.
635
-
636
- int i, j;
637
- int nSockets = Descriptors.size();
638
- for (i=0, j=0; i < nSockets; i++) {
639
- EventableDescriptor *ed = Descriptors[i];
640
- assert (ed);
641
- if (ed->ShouldDelete()) {
642
- ModifiedDescriptors.erase (ed);
643
- delete ed;
644
- }
645
- else
646
- Descriptors [j++] = ed;
647
- }
648
- while ((size_t)j < Descriptors.size())
649
- Descriptors.pop_back();
650
-
651
- }
652
-
653
- { // dispatch heartbeats
654
- if (gCurrentLoopTime >= NextHeartbeatTime) {
655
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
656
-
657
- for (unsigned int i=0; i < Descriptors.size(); i++) {
658
- EventableDescriptor *ed = Descriptors[i];
659
- assert (ed);
660
- ed->Heartbeat();
661
- }
662
- }
663
- }
664
-
665
-
666
- // TODO, replace this with rb_thread_blocking_region for 1.9 builds.
667
- #ifdef BUILD_FOR_RUBY
668
- if (!rb_thread_alone()) {
669
- rb_thread_schedule();
670
- }
671
- #endif
672
-
673
- return true;
674
- #else
675
- throw std::runtime_error ("kqueue is not implemented on this platform");
676
- #endif
677
- }
678
-
679
-
680
- /*********************************
681
- EventMachine_t::_ModifyEpollEvent
682
- *********************************/
683
-
684
- void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed)
685
- {
686
- #ifdef HAVE_EPOLL
687
- if (bEpoll) {
688
- assert (epfd != -1);
689
- assert (ed);
690
- assert (ed->GetSocket() != INVALID_SOCKET);
691
- int e = epoll_ctl (epfd, EPOLL_CTL_MOD, ed->GetSocket(), ed->GetEpollEvent());
692
- if (e) {
693
- char buf [200];
694
- snprintf (buf, sizeof(buf)-1, "unable to modify epoll event: %s", strerror(errno));
695
- throw std::runtime_error (buf);
696
- }
697
- }
698
- #endif
699
- }
700
-
701
-
702
-
703
- /**************************
704
- SelectData_t::SelectData_t
705
- **************************/
706
-
707
- SelectData_t::SelectData_t()
708
- {
709
- maxsocket = 0;
710
- FD_ZERO (&fdreads);
711
- FD_ZERO (&fdwrites);
712
- FD_ZERO (&fderrors);
713
- }
714
-
715
-
716
- #ifdef BUILD_FOR_RUBY
717
- /*****************
718
- _SelectDataSelect
719
- *****************/
720
-
721
- #ifdef HAVE_TBR
722
- static VALUE _SelectDataSelect (void *v)
723
- {
724
- SelectData_t *sd = (SelectData_t*)v;
725
- sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
726
- return Qnil;
727
- }
728
- #endif
729
-
730
- /*********************
731
- SelectData_t::_Select
732
- *********************/
733
-
734
- int SelectData_t::_Select()
735
- {
736
- #ifdef HAVE_TBR
737
- rb_thread_blocking_region (_SelectDataSelect, (void*)this, RUBY_UBF_IO, 0);
738
- return nSockets;
739
- #endif
740
-
741
- #ifndef HAVE_TBR
742
- return EmSelect (maxsocket+1, &fdreads, &fdwrites, &fderrors, &tv);
743
- #endif
744
- }
745
- #endif
746
-
747
-
748
-
749
- /******************************
750
- EventMachine_t::_RunSelectOnce
751
- ******************************/
752
-
753
- bool EventMachine_t::_RunSelectOnce()
754
- {
755
- // Crank the event machine once.
756
- // If there are no descriptors to process, then sleep
757
- // for a few hundred mills to avoid busy-looping.
758
- // Return T/F to indicate whether we should continue.
759
- // This is based on a select loop. Alternately provide epoll
760
- // if we know we're running on a 2.6 kernel.
761
- // epoll will be effective if we provide it as an alternative,
762
- // however it has the same problem interoperating with Ruby
763
- // threads that select does.
764
-
765
- //cerr << "X";
766
-
767
- /* This protection is now obsolete, because we will ALWAYS
768
- * have at least one descriptor (the loop-breaker) to read.
769
- */
770
- /*
771
- if (Descriptors.size() == 0) {
772
- #ifdef OS_UNIX
773
- timeval tv = {0, 200 * 1000};
774
- EmSelect (0, NULL, NULL, NULL, &tv);
775
- return true;
776
- #endif
777
- #ifdef OS_WIN32
778
- Sleep (200);
779
- return true;
780
- #endif
781
- }
782
- */
783
-
784
- SelectData_t SelectData;
785
- /*
786
- fd_set fdreads, fdwrites;
787
- FD_ZERO (&fdreads);
788
- FD_ZERO (&fdwrites);
789
-
790
- int maxsocket = 0;
791
- */
792
-
793
- // Always read the loop-breaker reader.
794
- // Changed 23Aug06, provisionally implemented for Windows with a UDP socket
795
- // running on localhost with a randomly-chosen port. (*Puke*)
796
- // Windows has a version of the Unix pipe() library function, but it doesn't
797
- // give you back descriptors that are selectable.
798
- FD_SET (LoopBreakerReader, &(SelectData.fdreads));
799
- if (SelectData.maxsocket < LoopBreakerReader)
800
- SelectData.maxsocket = LoopBreakerReader;
801
-
802
- // prepare the sockets for reading and writing
803
- size_t i;
804
- for (i = 0; i < Descriptors.size(); i++) {
805
- EventableDescriptor *ed = Descriptors[i];
806
- assert (ed);
807
- int sd = ed->GetSocket();
808
- if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
809
- continue;
810
- assert (sd != INVALID_SOCKET);
811
-
812
- if (ed->SelectForRead())
813
- FD_SET (sd, &(SelectData.fdreads));
814
- if (ed->SelectForWrite())
815
- FD_SET (sd, &(SelectData.fdwrites));
816
-
817
- #ifdef OS_WIN32
818
- /* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
819
- Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
820
- */
821
- FD_SET (sd, &(SelectData.fderrors));
822
- #endif
823
-
824
- if (SelectData.maxsocket < sd)
825
- SelectData.maxsocket = sd;
826
- }
827
-
828
-
829
- { // read and write the sockets
830
- //timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.
831
- //timeval tv = Quantum;
832
- SelectData.tv = Quantum;
833
- int s = SelectData._Select();
834
- //rb_thread_blocking_region(xxx,(void*)&SelectData,RUBY_UBF_IO,0);
835
- //int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv));
836
- //int s = SelectData.nSockets;
837
- if (s > 0) {
838
- /* Changed 01Jun07. We used to handle the Loop-breaker right here.
839
- * Now we do it AFTER all the regular descriptors. There's an
840
- * incredibly important and subtle reason for this. Code on
841
- * loop breakers is sometimes used to cause the reactor core to
842
- * cycle (for example, to allow outbound network buffers to drain).
843
- * If a loop-breaker handler reschedules itself (say, after determining
844
- * that the write buffers are still too full), then it will execute
845
- * IMMEDIATELY if _ReadLoopBreaker is done here instead of after
846
- * the other descriptors are processed. That defeats the whole purpose.
847
- */
848
- for (i=0; i < Descriptors.size(); i++) {
849
- EventableDescriptor *ed = Descriptors[i];
850
- assert (ed);
851
- int sd = ed->GetSocket();
852
- if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
853
- continue;
854
- assert (sd != INVALID_SOCKET);
855
-
856
- if (FD_ISSET (sd, &(SelectData.fdwrites)))
857
- ed->Write();
858
- if (FD_ISSET (sd, &(SelectData.fdreads)))
859
- ed->Read();
860
- if (FD_ISSET (sd, &(SelectData.fderrors)))
861
- ed->HandleError();
862
- }
863
-
864
- if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads)))
865
- _ReadLoopBreaker();
866
- }
867
- else if (s < 0) {
868
- // select can fail on error in a handful of ways.
869
- // If this happens, then wait for a little while to avoid busy-looping.
870
- // If the error was EINTR, we probably caught SIGCHLD or something,
871
- // so keep the wait short.
872
- timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000};
873
- EmSelect (0, NULL, NULL, NULL, &tv);
874
- }
875
- }
876
-
877
-
878
- { // dispatch heartbeats
879
- if (gCurrentLoopTime >= NextHeartbeatTime) {
880
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
881
-
882
- for (i=0; i < Descriptors.size(); i++) {
883
- EventableDescriptor *ed = Descriptors[i];
884
- assert (ed);
885
- ed->Heartbeat();
886
- }
887
- }
888
- }
889
-
890
- { // cleanup dying sockets
891
- // vector::pop_back works in constant time.
892
- int i, j;
893
- int nSockets = Descriptors.size();
894
- for (i=0, j=0; i < nSockets; i++) {
895
- EventableDescriptor *ed = Descriptors[i];
896
- assert (ed);
897
- if (ed->ShouldDelete())
898
- delete ed;
899
- else
900
- Descriptors [j++] = ed;
901
- }
902
- while ((size_t)j < Descriptors.size())
903
- Descriptors.pop_back();
904
-
905
- }
906
-
907
- return true;
908
- }
909
-
910
-
911
- /********************************
912
- EventMachine_t::_ReadLoopBreaker
913
- ********************************/
914
-
915
- void EventMachine_t::_ReadLoopBreaker()
916
- {
917
- /* The loop breaker has selected readable.
918
- * Read it ONCE (it may block if we try to read it twice)
919
- * and send a loop-break event back to user code.
920
- */
921
- char buffer [1024];
922
- read (LoopBreakerReader, buffer, sizeof(buffer));
923
- if (EventCallback)
924
- (*EventCallback)(NULL, EM_LOOPBREAK_SIGNAL, "", 0);
925
- }
926
-
927
-
928
- /**************************
929
- EventMachine_t::_RunTimers
930
- **************************/
931
-
932
- bool EventMachine_t::_RunTimers()
933
- {
934
- // These are caller-defined timer handlers.
935
- // Return T/F to indicate whether we should continue the main loop.
936
- // We rely on the fact that multimaps sort by their keys to avoid
937
- // inspecting the whole list every time we come here.
938
- // Just keep inspecting and processing the list head until we hit
939
- // one that hasn't expired yet.
940
-
941
- while (true) {
942
- multimap<Int64,Timer_t>::iterator i = Timers.begin();
943
- if (i == Timers.end())
944
- break;
945
- if (i->first > gCurrentLoopTime)
946
- break;
947
- if (EventCallback)
948
- (*EventCallback) (NULL, EM_TIMER_FIRED, NULL, i->second.GetBinding());
949
- Timers.erase (i);
950
- }
951
- return true;
952
- }
953
-
954
-
955
-
956
- /***********************************
957
- EventMachine_t::InstallOneshotTimer
958
- ***********************************/
959
-
960
- const unsigned long EventMachine_t::InstallOneshotTimer (int milliseconds)
961
- {
962
- if (Timers.size() > MaxOutstandingTimers)
963
- return false;
964
- // Don't use the global loop-time variable here, because we might
965
- // get called before the main event machine is running.
966
-
967
- #ifdef OS_UNIX
968
- struct timeval tv;
969
- gettimeofday (&tv, NULL);
970
- Int64 fire_at = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec));
971
- fire_at += ((Int64)milliseconds) * 1000LL;
972
- #endif
973
-
974
- #ifdef OS_WIN32
975
- unsigned tick = GetTickCount();
976
- if (tick < gLastTickCount)
977
- gTickCountTickover += 1;
978
- gLastTickCount = tick;
979
-
980
- Int64 fire_at = ((Int64)gTickCountTickover << 32) + (Int64)tick;
981
- fire_at += (Int64)milliseconds;
982
- #endif
983
-
984
- Timer_t t;
985
- #ifndef HAVE_MAKE_PAIR
986
- multimap<Int64,Timer_t>::iterator i = Timers.insert (multimap<Int64,Timer_t>::value_type (fire_at, t));
987
- #else
988
- multimap<Int64,Timer_t>::iterator i = Timers.insert (make_pair (fire_at, t));
989
- #endif
990
- return i->second.GetBinding();
991
- }
992
-
993
-
994
- /*******************************
995
- EventMachine_t::ConnectToServer
996
- *******************************/
997
-
998
- const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int bind_port, const char *server, int port)
999
- {
1000
- /* We want to spend no more than a few seconds waiting for a connection
1001
- * to a remote host. So we use a nonblocking connect.
1002
- * Linux disobeys the usual rules for nonblocking connects.
1003
- * Per Stevens (UNP p.410), you expect a nonblocking connect to select
1004
- * both readable and writable on error, and not to return EINPROGRESS
1005
- * if the connect can be fulfilled immediately. Linux violates both
1006
- * of these expectations.
1007
- * Any kind of nonblocking connect on Linux returns EINPROGRESS.
1008
- * The socket will then return writable when the disposition of the
1009
- * connect is known, but it will not also be readable in case of
1010
- * error! Weirdly, it will be readable in case there is data to read!!!
1011
- * (Which can happen with protocols like SSH and SMTP.)
1012
- * I suppose if you were so inclined you could consider this logical,
1013
- * but it's not the way Unix has historically done it.
1014
- * So we ignore the readable flag and read getsockopt to see if there
1015
- * was an error connecting. A select timeout works as expected.
1016
- * In regard to getsockopt: Linux does the Berkeley-style thing,
1017
- * not the Solaris-style, and returns zero with the error code in
1018
- * the error parameter.
1019
- * Return the binding-text of the newly-created pending connection,
1020
- * or NULL if there was a problem.
1021
- */
1022
-
1023
- if (!server || !*server || !port)
1024
- throw std::runtime_error ("invalid server or port");
1025
-
1026
- int family, bind_size;
1027
- struct sockaddr bind_as, *bind_as_ptr = name2address (server, port, &family, &bind_size);
1028
- if (!bind_as_ptr)
1029
- throw std::runtime_error ("unable to resolve server address");
1030
- bind_as = *bind_as_ptr; // copy because name2address points to a static
1031
-
1032
- int sd = socket (family, SOCK_STREAM, 0);
1033
- if (sd == INVALID_SOCKET)
1034
- throw std::runtime_error ("unable to create new socket");
1035
-
1036
- /*
1037
- sockaddr_in pin;
1038
- unsigned long HostAddr;
1039
-
1040
- HostAddr = inet_addr (server);
1041
- if (HostAddr == INADDR_NONE) {
1042
- hostent *hp = gethostbyname ((char*)server); // Windows requires (char*)
1043
- if (!hp) {
1044
- // TODO: This gives the caller a fatal error. Not good.
1045
- // They can respond by catching RuntimeError (blecch).
1046
- // Possibly we need to fire an unbind event and provide
1047
- // a status code so user code can detect the cause of the
1048
- // failure.
1049
- return NULL;
1050
- }
1051
- HostAddr = ((in_addr*)(hp->h_addr))->s_addr;
1052
- }
1053
-
1054
- memset (&pin, 0, sizeof(pin));
1055
- pin.sin_family = AF_INET;
1056
- pin.sin_addr.s_addr = HostAddr;
1057
- pin.sin_port = htons (port);
1058
-
1059
- int sd = socket (AF_INET, SOCK_STREAM, 0);
1060
- if (sd == INVALID_SOCKET)
1061
- return NULL;
1062
- */
1063
-
1064
- // From here on, ALL error returns must close the socket.
1065
- // Set the new socket nonblocking.
1066
- if (!SetSocketNonblocking (sd)) {
1067
- closesocket (sd);
1068
- throw std::runtime_error ("unable to set socket as non-blocking");
1069
- }
1070
- // Disable slow-start (Nagle algorithm).
1071
- int one = 1;
1072
- setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one));
1073
- // Set reuseaddr to improve performance on restarts
1074
- setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one));
1075
-
1076
- if (bind_addr) {
1077
- int bind_to_size, bind_to_family;
1078
- struct sockaddr *bind_to = name2address (bind_addr, bind_port, &bind_to_family, &bind_to_size);
1079
- if (!bind_to) {
1080
- closesocket (sd);
1081
- throw std::runtime_error ("invalid bind address");
1082
- }
1083
- if (bind (sd, bind_to, bind_to_size) < 0) {
1084
- closesocket (sd);
1085
- throw std::runtime_error ("couldn't bind to address");
1086
- }
1087
- }
1088
-
1089
- unsigned long out = NULL;
1090
-
1091
- #ifdef OS_UNIX
1092
- //if (connect (sd, (sockaddr*)&pin, sizeof pin) == 0) {
1093
- if (connect (sd, &bind_as, bind_size) == 0) {
1094
- // This is a connect success, which Linux appears
1095
- // never to give when the socket is nonblocking,
1096
- // even if the connection is intramachine or to
1097
- // localhost.
1098
-
1099
- /* Changed this branch 08Aug06. Evidently some kernels
1100
- * (FreeBSD for example) will actually return success from
1101
- * a nonblocking connect. This is a pretty simple case,
1102
- * just set up the new connection and clear the pending flag.
1103
- * Thanks to Chris Ochs for helping track this down.
1104
- * This branch never gets taken on Linux or (oddly) OSX.
1105
- * The original behavior was to throw an unimplemented,
1106
- * which the user saw as a fatal exception. Very unfriendly.
1107
- *
1108
- * Tweaked 10Aug06. Even though the connect disposition is
1109
- * known, we still set the connect-pending flag. That way
1110
- * some needed initialization will happen in the ConnectionDescriptor.
1111
- * (To wit, the ConnectionCompleted event gets sent to the client.)
1112
- */
1113
- ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1114
- if (!cd)
1115
- throw std::runtime_error ("no connection allocated");
1116
- cd->SetConnectPending (true);
1117
- Add (cd);
1118
- out = cd->GetBinding();
1119
- }
1120
- else if (errno == EINPROGRESS) {
1121
- // Errno will generally always be EINPROGRESS, but on Linux
1122
- // we have to look at getsockopt to be sure what really happened.
1123
- int error;
1124
- socklen_t len;
1125
- len = sizeof(error);
1126
- int o = getsockopt (sd, SOL_SOCKET, SO_ERROR, &error, &len);
1127
- if ((o == 0) && (error == 0)) {
1128
- // Here, there's no disposition.
1129
- // Put the connection on the stack and wait for it to complete
1130
- // or time out.
1131
- ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1132
- if (!cd)
1133
- throw std::runtime_error ("no connection allocated");
1134
- cd->SetConnectPending (true);
1135
- Add (cd);
1136
- out = cd->GetBinding();
1137
- }
1138
- else {
1139
- /* This could be connection refused or some such thing.
1140
- * We will come here on Linux if a localhost connection fails.
1141
- * Changed 16Jul06: Originally this branch was a no-op, and
1142
- * we'd drop down to the end of the method, close the socket,
1143
- * and return NULL, which would cause the caller to GET A
1144
- * FATAL EXCEPTION. Now we keep the socket around but schedule an
1145
- * immediate close on it, so the caller will get a close-event
1146
- * scheduled on it. This was only an issue for localhost connections
1147
- * to non-listening ports. We may eventually need to revise this
1148
- * revised behavior, in case it causes problems like making it hard
1149
- * for people to know that a failure occurred.
1150
- */
1151
- ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1152
- if (!cd)
1153
- throw std::runtime_error ("no connection allocated");
1154
- cd->ScheduleClose (false);
1155
- Add (cd);
1156
- out = cd->GetBinding();
1157
- }
1158
- }
1159
- else {
1160
- // The error from connect was something other then EINPROGRESS.
1161
- }
1162
- #endif
1163
-
1164
- #ifdef OS_WIN32
1165
- //if (connect (sd, (sockaddr*)&pin, sizeof pin) == 0) {
1166
- if (connect (sd, &bind_as, bind_size) == 0) {
1167
- // This is a connect success, which Windows appears
1168
- // never to give when the socket is nonblocking,
1169
- // even if the connection is intramachine or to
1170
- // localhost.
1171
- throw std::runtime_error ("unimplemented");
1172
- }
1173
- else if (WSAGetLastError() == WSAEWOULDBLOCK) {
1174
- // Here, there's no disposition.
1175
- // Windows appears not to surface refused connections or
1176
- // such stuff at this point.
1177
- // Put the connection on the stack and wait for it to complete
1178
- // or time out.
1179
- ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1180
- if (!cd)
1181
- throw std::runtime_error ("no connection allocated");
1182
- cd->SetConnectPending (true);
1183
- Add (cd);
1184
- out = cd->GetBinding();
1185
- }
1186
- else {
1187
- // The error from connect was something other then WSAEWOULDBLOCK.
1188
- }
1189
-
1190
- #endif
1191
-
1192
- if (!out)
1193
- closesocket (sd);
1194
- return out;
1195
- }
1196
-
1197
- /***********************************
1198
- EventMachine_t::ConnectToUnixServer
1199
- ***********************************/
1200
-
1201
- const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
1202
- {
1203
- /* Connect to a Unix-domain server, which by definition is running
1204
- * on the same host.
1205
- * There is no meaningful implementation on Windows.
1206
- * There's no need to do a nonblocking connect, since the connection
1207
- * is always local and can always be fulfilled immediately.
1208
- */
1209
-
1210
- #ifdef OS_WIN32
1211
- throw std::runtime_error ("unix-domain connection unavailable on this platform");
1212
- return NULL;
1213
- #endif
1214
-
1215
- // The whole rest of this function is only compiled on Unix systems.
1216
- #ifdef OS_UNIX
1217
-
1218
- unsigned long out = NULL;
1219
-
1220
- if (!server || !*server)
1221
- return NULL;
1222
-
1223
- sockaddr_un pun;
1224
- memset (&pun, 0, sizeof(pun));
1225
- pun.sun_family = AF_LOCAL;
1226
-
1227
- // You ordinarily expect the server name field to be at least 1024 bytes long,
1228
- // but on Linux it can be MUCH shorter.
1229
- if (strlen(server) >= sizeof(pun.sun_path))
1230
- throw std::runtime_error ("unix-domain server name is too long");
1231
-
1232
-
1233
- strcpy (pun.sun_path, server);
1234
-
1235
- int fd = socket (AF_LOCAL, SOCK_STREAM, 0);
1236
- if (fd == INVALID_SOCKET)
1237
- return NULL;
1238
-
1239
- // From here on, ALL error returns must close the socket.
1240
- // NOTE: At this point, the socket is still a blocking socket.
1241
- if (connect (fd, (struct sockaddr*)&pun, sizeof(pun)) != 0) {
1242
- closesocket (fd);
1243
- return NULL;
1244
- }
1245
-
1246
- // Set the newly-connected socket nonblocking.
1247
- if (!SetSocketNonblocking (fd)) {
1248
- closesocket (fd);
1249
- return NULL;
1250
- }
1251
-
1252
- // Set up a connection descriptor and add it to the event-machine.
1253
- // Observe, even though we know the connection status is connect-success,
1254
- // we still set the "pending" flag, so some needed initializations take
1255
- // place.
1256
- ConnectionDescriptor *cd = new ConnectionDescriptor (fd, this);
1257
- if (!cd)
1258
- throw std::runtime_error ("no connection allocated");
1259
- cd->SetConnectPending (true);
1260
- Add (cd);
1261
- out = cd->GetBinding();
1262
-
1263
- if (!out)
1264
- closesocket (fd);
1265
-
1266
- return out;
1267
- #endif
1268
- }
1269
-
1270
- /************************
1271
- EventMachine_t::AttachFD
1272
- ************************/
1273
-
1274
- const unsigned long EventMachine_t::AttachFD (int fd, bool watch_mode)
1275
- {
1276
- #ifdef OS_UNIX
1277
- if (fcntl(fd, F_GETFL, 0) < 0)
1278
- throw std::runtime_error ("invalid file descriptor");
1279
- #endif
1280
-
1281
- #ifdef OS_WIN32
1282
- // TODO: add better check for invalid file descriptors (see ioctlsocket or getsockopt)
1283
- if (fd == INVALID_SOCKET)
1284
- throw std::runtime_error ("invalid file descriptor");
1285
- #endif
1286
-
1287
- {// Check for duplicate descriptors
1288
- size_t i;
1289
- for (i = 0; i < Descriptors.size(); i++) {
1290
- EventableDescriptor *ed = Descriptors[i];
1291
- assert (ed);
1292
- if (ed->GetSocket() == fd)
1293
- throw std::runtime_error ("adding existing descriptor");
1294
- }
1295
-
1296
- for (i = 0; i < NewDescriptors.size(); i++) {
1297
- EventableDescriptor *ed = NewDescriptors[i];
1298
- assert (ed);
1299
- if (ed->GetSocket() == fd)
1300
- throw std::runtime_error ("adding existing new descriptor");
1301
- }
1302
- }
1303
-
1304
- if (!watch_mode)
1305
- SetSocketNonblocking(fd);
1306
-
1307
- ConnectionDescriptor *cd = new ConnectionDescriptor (fd, this);
1308
- if (!cd)
1309
- throw std::runtime_error ("no connection allocated");
1310
-
1311
- cd->SetWatchOnly(watch_mode);
1312
- cd->SetConnectPending (false);
1313
-
1314
- Add (cd);
1315
-
1316
- const unsigned long out = cd->GetBinding();
1317
- return out;
1318
- }
1319
-
1320
- /************************
1321
- EventMachine_t::DetachFD
1322
- ************************/
1323
-
1324
- int EventMachine_t::DetachFD (EventableDescriptor *ed)
1325
- {
1326
- if (!ed)
1327
- throw std::runtime_error ("detaching bad descriptor");
1328
-
1329
- int fd = ed->GetSocket();
1330
-
1331
- #ifdef HAVE_EPOLL
1332
- if (bEpoll) {
1333
- if (ed->GetSocket() != INVALID_SOCKET) {
1334
- assert (epfd != -1);
1335
- int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
1336
- // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
1337
- if (e && (errno != ENOENT) && (errno != EBADF)) {
1338
- char buf [200];
1339
- snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
1340
- throw std::runtime_error (buf);
1341
- }
1342
- }
1343
- }
1344
- #endif
1345
-
1346
- #ifdef HAVE_KQUEUE
1347
- if (bKqueue) {
1348
- // remove any read/write events for this fd
1349
- struct kevent k;
1350
- EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, ed);
1351
- int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1352
- if (t < 0 && (errno != ENOENT) && (errno != EBADF)) {
1353
- char buf [200];
1354
- snprintf (buf, sizeof(buf)-1, "unable to delete kqueue event: %s", strerror(errno));
1355
- throw std::runtime_error (buf);
1356
- }
1357
- }
1358
- #endif
1359
-
1360
- // Prevent the descriptor from being modified, in case DetachFD was called from a timer or next_tick
1361
- ModifiedDescriptors.erase (ed);
1362
-
1363
- // Set MySocket = INVALID_SOCKET so ShouldDelete() is true (and the descriptor gets deleted and removed),
1364
- // and also to prevent anyone from calling close() on the detached fd
1365
- ed->SetSocketInvalid();
1366
-
1367
- return fd;
1368
- }
1369
-
1370
- /************
1371
- name2address
1372
- ************/
1373
-
1374
- struct sockaddr *name2address (const char *server, int port, int *family, int *bind_size)
1375
- {
1376
- // THIS IS NOT RE-ENTRANT OR THREADSAFE. Optimize for speed.
1377
- // Check the more-common cases first.
1378
- // Return NULL if no resolution.
1379
-
1380
- static struct sockaddr_in in4;
1381
- #ifndef __CYGWIN__
1382
- static struct sockaddr_in6 in6;
1383
- #endif
1384
- struct hostent *hp;
1385
-
1386
- if (!server || !*server)
1387
- server = "0.0.0.0";
1388
-
1389
- memset (&in4, 0, sizeof(in4));
1390
- if ( (in4.sin_addr.s_addr = inet_addr (server)) != INADDR_NONE) {
1391
- if (family)
1392
- *family = AF_INET;
1393
- if (bind_size)
1394
- *bind_size = sizeof(in4);
1395
- in4.sin_family = AF_INET;
1396
- in4.sin_port = htons (port);
1397
- return (struct sockaddr*)&in4;
1398
- }
1399
-
1400
- #if defined(OS_UNIX) && !defined(__CYGWIN__)
1401
- memset (&in6, 0, sizeof(in6));
1402
- if (inet_pton (AF_INET6, server, in6.sin6_addr.s6_addr) > 0) {
1403
- if (family)
1404
- *family = AF_INET6;
1405
- if (bind_size)
1406
- *bind_size = sizeof(in6);
1407
- in6.sin6_family = AF_INET6;
1408
- in6.sin6_port = htons (port);
1409
- return (struct sockaddr*)&in6;
1410
- }
1411
- #endif
1412
-
1413
- #ifdef OS_WIN32
1414
- // TODO, must complete this branch. Windows doesn't have inet_pton.
1415
- // A possible approach is to make a getaddrinfo call with the supplied
1416
- // server address, constraining the hints to ipv6 and seeing if we
1417
- // get any addresses.
1418
- // For the time being, Ipv6 addresses aren't supported on Windows.
1419
- #endif
1420
-
1421
- hp = gethostbyname ((char*)server); // Windows requires the cast.
1422
- if (hp) {
1423
- in4.sin_addr.s_addr = ((in_addr*)(hp->h_addr))->s_addr;
1424
- if (family)
1425
- *family = AF_INET;
1426
- if (bind_size)
1427
- *bind_size = sizeof(in4);
1428
- in4.sin_family = AF_INET;
1429
- in4.sin_port = htons (port);
1430
- return (struct sockaddr*)&in4;
1431
- }
1432
-
1433
- return NULL;
1434
- }
1435
-
1436
-
1437
- /*******************************
1438
- EventMachine_t::CreateTcpServer
1439
- *******************************/
1440
-
1441
- const unsigned long EventMachine_t::CreateTcpServer (const char *server, int port)
1442
- {
1443
- /* Create a TCP-acceptor (server) socket and add it to the event machine.
1444
- * Return the binding of the new acceptor to the caller.
1445
- * This binding will be referenced when the new acceptor sends events
1446
- * to indicate accepted connections.
1447
- */
1448
-
1449
-
1450
- int family, bind_size;
1451
- struct sockaddr *bind_here = name2address (server, port, &family, &bind_size);
1452
- if (!bind_here)
1453
- return NULL;
1454
-
1455
- unsigned long output_binding = NULL;
1456
-
1457
- //struct sockaddr_in sin;
1458
-
1459
- int sd_accept = socket (family, SOCK_STREAM, 0);
1460
- if (sd_accept == INVALID_SOCKET) {
1461
- goto fail;
1462
- }
1463
-
1464
- /*
1465
- memset (&sin, 0, sizeof(sin));
1466
- sin.sin_family = AF_INET;
1467
- sin.sin_addr.s_addr = INADDR_ANY;
1468
- sin.sin_port = htons (port);
1469
-
1470
- if (server && *server) {
1471
- sin.sin_addr.s_addr = inet_addr (server);
1472
- if (sin.sin_addr.s_addr == INADDR_NONE) {
1473
- hostent *hp = gethostbyname ((char*)server); // Windows requires the cast.
1474
- if (hp == NULL) {
1475
- //__warning ("hostname not resolved: ", server);
1476
- goto fail;
1477
- }
1478
- sin.sin_addr.s_addr = ((in_addr*)(hp->h_addr))->s_addr;
1479
- }
1480
- }
1481
- */
1482
-
1483
- { // set reuseaddr to improve performance on restarts.
1484
- int oval = 1;
1485
- if (setsockopt (sd_accept, SOL_SOCKET, SO_REUSEADDR, (char*)&oval, sizeof(oval)) < 0) {
1486
- //__warning ("setsockopt failed while creating listener","");
1487
- goto fail;
1488
- }
1489
- }
1490
-
1491
- { // set CLOEXEC. Only makes sense on Unix
1492
- #ifdef OS_UNIX
1493
- int cloexec = fcntl (sd_accept, F_GETFD, 0);
1494
- assert (cloexec >= 0);
1495
- cloexec |= FD_CLOEXEC;
1496
- fcntl (sd_accept, F_SETFD, cloexec);
1497
- #endif
1498
- }
1499
-
1500
-
1501
- //if (bind (sd_accept, (struct sockaddr*)&sin, sizeof(sin))) {
1502
- if (bind (sd_accept, bind_here, bind_size)) {
1503
- //__warning ("binding failed");
1504
- goto fail;
1505
- }
1506
-
1507
- if (listen (sd_accept, 100)) {
1508
- //__warning ("listen failed");
1509
- goto fail;
1510
- }
1511
-
1512
- {
1513
- // Set the acceptor non-blocking.
1514
- // THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.
1515
- if (!SetSocketNonblocking (sd_accept)) {
1516
- //int val = fcntl (sd_accept, F_GETFL, 0);
1517
- //if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK) == -1) {
1518
- goto fail;
1519
- }
1520
- }
1521
-
1522
- { // Looking good.
1523
- AcceptorDescriptor *ad = new AcceptorDescriptor (sd_accept, this);
1524
- if (!ad)
1525
- throw std::runtime_error ("unable to allocate acceptor");
1526
- Add (ad);
1527
- output_binding = ad->GetBinding();
1528
- }
1529
-
1530
- return output_binding;
1531
-
1532
- fail:
1533
- if (sd_accept != INVALID_SOCKET)
1534
- closesocket (sd_accept);
1535
- return NULL;
1536
- }
1537
-
1538
-
1539
- /**********************************
1540
- EventMachine_t::OpenDatagramSocket
1541
- **********************************/
1542
-
1543
- const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int port)
1544
- {
1545
- unsigned long output_binding = NULL;
1546
-
1547
- int sd = socket (AF_INET, SOCK_DGRAM, 0);
1548
- if (sd == INVALID_SOCKET)
1549
- goto fail;
1550
- // from here on, early returns must close the socket!
1551
-
1552
-
1553
- struct sockaddr_in sin;
1554
- memset (&sin, 0, sizeof(sin));
1555
- sin.sin_family = AF_INET;
1556
- sin.sin_port = htons (port);
1557
-
1558
-
1559
- if (address && *address) {
1560
- sin.sin_addr.s_addr = inet_addr (address);
1561
- if (sin.sin_addr.s_addr == INADDR_NONE) {
1562
- hostent *hp = gethostbyname ((char*)address); // Windows requires the cast.
1563
- if (hp == NULL)
1564
- goto fail;
1565
- sin.sin_addr.s_addr = ((in_addr*)(hp->h_addr))->s_addr;
1566
- }
1567
- }
1568
- else
1569
- sin.sin_addr.s_addr = htonl (INADDR_ANY);
1570
-
1571
-
1572
- // Set the new socket nonblocking.
1573
- {
1574
- if (!SetSocketNonblocking (sd))
1575
- //int val = fcntl (sd, F_GETFL, 0);
1576
- //if (fcntl (sd, F_SETFL, val | O_NONBLOCK) == -1)
1577
- goto fail;
1578
- }
1579
-
1580
- if (bind (sd, (struct sockaddr*)&sin, sizeof(sin)) != 0)
1581
- goto fail;
1582
-
1583
- { // Looking good.
1584
- DatagramDescriptor *ds = new DatagramDescriptor (sd, this);
1585
- if (!ds)
1586
- throw std::runtime_error ("unable to allocate datagram-socket");
1587
- Add (ds);
1588
- output_binding = ds->GetBinding();
1589
- }
1590
-
1591
- return output_binding;
1592
-
1593
- fail:
1594
- if (sd != INVALID_SOCKET)
1595
- closesocket (sd);
1596
- return NULL;
1597
- }
1598
-
1599
-
1600
-
1601
- /*******************
1602
- EventMachine_t::Add
1603
- *******************/
1604
-
1605
- void EventMachine_t::Add (EventableDescriptor *ed)
1606
- {
1607
- if (!ed)
1608
- throw std::runtime_error ("added bad descriptor");
1609
- ed->SetEventCallback (EventCallback);
1610
- NewDescriptors.push_back (ed);
1611
- }
1612
-
1613
-
1614
- /*******************************
1615
- EventMachine_t::ArmKqueueWriter
1616
- *******************************/
1617
-
1618
- void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
1619
- {
1620
- #ifdef HAVE_KQUEUE
1621
- if (bKqueue) {
1622
- if (!ed)
1623
- throw std::runtime_error ("added bad descriptor");
1624
- struct kevent k;
1625
- EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, ed);
1626
- int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1627
- if (t < 0) {
1628
- char buf [200];
1629
- snprintf (buf, sizeof(buf)-1, "arm kqueue writer failed on %d: %s", ed->GetSocket(), strerror(errno));
1630
- throw std::runtime_error (buf);
1631
- }
1632
- }
1633
- #endif
1634
- }
1635
-
1636
- /*******************************
1637
- EventMachine_t::ArmKqueueReader
1638
- *******************************/
1639
-
1640
- void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
1641
- {
1642
- #ifdef HAVE_KQUEUE
1643
- if (bKqueue) {
1644
- if (!ed)
1645
- throw std::runtime_error ("added bad descriptor");
1646
- struct kevent k;
1647
- EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1648
- int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1649
- if (t < 0) {
1650
- char buf [200];
1651
- snprintf (buf, sizeof(buf)-1, "arm kqueue reader failed on %d: %s", ed->GetSocket(), strerror(errno));
1652
- throw std::runtime_error (buf);
1653
- }
1654
- }
1655
- #endif
1656
- }
1657
-
1658
- /**********************************
1659
- EventMachine_t::_AddNewDescriptors
1660
- **********************************/
1661
-
1662
- void EventMachine_t::_AddNewDescriptors()
1663
- {
1664
- /* Avoid adding descriptors to the main descriptor list
1665
- * while we're actually traversing the list.
1666
- * Any descriptors that are added as a result of processing timers
1667
- * or acceptors should go on a temporary queue and then added
1668
- * while we're not traversing the main list.
1669
- * Also, it (rarely) happens that a newly-created descriptor
1670
- * is immediately scheduled to close. It might be a good
1671
- * idea not to bother scheduling these for I/O but if
1672
- * we do that, we might bypass some important processing.
1673
- */
1674
-
1675
- for (size_t i = 0; i < NewDescriptors.size(); i++) {
1676
- EventableDescriptor *ed = NewDescriptors[i];
1677
- if (ed == NULL)
1678
- throw std::runtime_error ("adding bad descriptor");
1679
-
1680
- #if HAVE_EPOLL
1681
- if (bEpoll) {
1682
- assert (epfd != -1);
1683
- int e = epoll_ctl (epfd, EPOLL_CTL_ADD, ed->GetSocket(), ed->GetEpollEvent());
1684
- if (e) {
1685
- char buf [200];
1686
- snprintf (buf, sizeof(buf)-1, "unable to add new descriptor: %s", strerror(errno));
1687
- throw std::runtime_error (buf);
1688
- }
1689
- }
1690
- #endif
1691
-
1692
- #if HAVE_KQUEUE
1693
- /*
1694
- if (bKqueue) {
1695
- // INCOMPLETE. Some descriptors don't want to be readable.
1696
- assert (kqfd != -1);
1697
- struct kevent k;
1698
- EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1699
- int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1700
- assert (t == 0);
1701
- }
1702
- */
1703
- #endif
1704
-
1705
- Descriptors.push_back (ed);
1706
- }
1707
- NewDescriptors.clear();
1708
- }
1709
-
1710
-
1711
- /**********************************
1712
- EventMachine_t::_ModifyDescriptors
1713
- **********************************/
1714
-
1715
- void EventMachine_t::_ModifyDescriptors()
1716
- {
1717
- /* For implementations which don't level check every descriptor on
1718
- * every pass through the machine, as select does.
1719
- * If we're not selecting, then descriptors need a way to signal to the
1720
- * machine that their readable or writable status has changed.
1721
- * That's what the ::Modify call is for. We do it this way to avoid
1722
- * modifying descriptors during the loop traversal, where it can easily
1723
- * happen that an object (like a UDP socket) gets data written on it by
1724
- * the application during #post_init. That would take place BEFORE the
1725
- * descriptor even gets added to the epoll descriptor, so the modify
1726
- * operation will crash messily.
1727
- * Another really messy possibility is for a descriptor to put itself
1728
- * on the Modified list, and then get deleted before we get here.
1729
- * Remember, deletes happen after the I/O traversal and before the
1730
- * next pass through here. So we have to make sure when we delete a
1731
- * descriptor to remove it from the Modified list.
1732
- */
1733
-
1734
- #ifdef HAVE_EPOLL
1735
- if (bEpoll) {
1736
- set<EventableDescriptor*>::iterator i = ModifiedDescriptors.begin();
1737
- while (i != ModifiedDescriptors.end()) {
1738
- assert (*i);
1739
- _ModifyEpollEvent (*i);
1740
- ++i;
1741
- }
1742
- }
1743
- #endif
1744
-
1745
- ModifiedDescriptors.clear();
1746
- }
1747
-
1748
-
1749
- /**********************
1750
- EventMachine_t::Modify
1751
- **********************/
1752
-
1753
- void EventMachine_t::Modify (EventableDescriptor *ed)
1754
- {
1755
- if (!ed)
1756
- throw std::runtime_error ("modified bad descriptor");
1757
- ModifiedDescriptors.insert (ed);
1758
- }
1759
-
1760
-
1761
- /***********************************
1762
- EventMachine_t::_OpenFileForWriting
1763
- ***********************************/
1764
-
1765
- const unsigned long EventMachine_t::_OpenFileForWriting (const char *filename)
1766
- {
1767
- /*
1768
- * Return the binding-text of the newly-opened file,
1769
- * or NULL if there was a problem.
1770
- */
1771
-
1772
- if (!filename || !*filename)
1773
- return NULL;
1774
-
1775
- int fd = open (filename, O_CREAT|O_TRUNC|O_WRONLY|O_NONBLOCK, 0644);
1776
-
1777
- FileStreamDescriptor *fsd = new FileStreamDescriptor (fd, this);
1778
- if (!fsd)
1779
- throw std::runtime_error ("no file-stream allocated");
1780
- Add (fsd);
1781
- return fsd->GetBinding();
1782
-
1783
- }
1784
-
1785
-
1786
- /**************************************
1787
- EventMachine_t::CreateUnixDomainServer
1788
- **************************************/
1789
-
1790
- const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename)
1791
- {
1792
- /* Create a UNIX-domain acceptor (server) socket and add it to the event machine.
1793
- * Return the binding of the new acceptor to the caller.
1794
- * This binding will be referenced when the new acceptor sends events
1795
- * to indicate accepted connections.
1796
- * THERE IS NO MEANINGFUL IMPLEMENTATION ON WINDOWS.
1797
- */
1798
-
1799
- #ifdef OS_WIN32
1800
- throw std::runtime_error ("unix-domain server unavailable on this platform");
1801
- #endif
1802
-
1803
- // The whole rest of this function is only compiled on Unix systems.
1804
- #ifdef OS_UNIX
1805
- unsigned long output_binding = NULL;
1806
-
1807
- struct sockaddr_un s_sun;
1808
-
1809
- int sd_accept = socket (AF_LOCAL, SOCK_STREAM, 0);
1810
- if (sd_accept == INVALID_SOCKET) {
1811
- goto fail;
1812
- }
1813
-
1814
- if (!filename || !*filename)
1815
- goto fail;
1816
- unlink (filename);
1817
-
1818
- bzero (&s_sun, sizeof(s_sun));
1819
- s_sun.sun_family = AF_LOCAL;
1820
- strncpy (s_sun.sun_path, filename, sizeof(s_sun.sun_path)-1);
1821
-
1822
- // don't bother with reuseaddr for a local socket.
1823
-
1824
- { // set CLOEXEC. Only makes sense on Unix
1825
- #ifdef OS_UNIX
1826
- int cloexec = fcntl (sd_accept, F_GETFD, 0);
1827
- assert (cloexec >= 0);
1828
- cloexec |= FD_CLOEXEC;
1829
- fcntl (sd_accept, F_SETFD, cloexec);
1830
- #endif
1831
- }
1832
-
1833
- if (bind (sd_accept, (struct sockaddr*)&s_sun, sizeof(s_sun))) {
1834
- //__warning ("binding failed");
1835
- goto fail;
1836
- }
1837
-
1838
- if (listen (sd_accept, 100)) {
1839
- //__warning ("listen failed");
1840
- goto fail;
1841
- }
1842
-
1843
- {
1844
- // Set the acceptor non-blocking.
1845
- // THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.
1846
- if (!SetSocketNonblocking (sd_accept)) {
1847
- //int val = fcntl (sd_accept, F_GETFL, 0);
1848
- //if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK) == -1) {
1849
- goto fail;
1850
- }
1851
- }
1852
-
1853
- { // Looking good.
1854
- AcceptorDescriptor *ad = new AcceptorDescriptor (sd_accept, this);
1855
- if (!ad)
1856
- throw std::runtime_error ("unable to allocate acceptor");
1857
- Add (ad);
1858
- output_binding = ad->GetBinding();
1859
- }
1860
-
1861
- return output_binding;
1862
-
1863
- fail:
1864
- if (sd_accept != INVALID_SOCKET)
1865
- closesocket (sd_accept);
1866
- return NULL;
1867
- #endif // OS_UNIX
1868
- }
1869
-
1870
-
1871
- /*********************
1872
- EventMachine_t::Popen
1873
- *********************/
1874
- #if OBSOLETE
1875
- const char *EventMachine_t::Popen (const char *cmd, const char *mode)
1876
- {
1877
- #ifdef OS_WIN32
1878
- throw std::runtime_error ("popen is currently unavailable on this platform");
1879
- #endif
1880
-
1881
- // The whole rest of this function is only compiled on Unix systems.
1882
- // Eventually we need this functionality (or a full-duplex equivalent) on Windows.
1883
- #ifdef OS_UNIX
1884
- const char *output_binding = NULL;
1885
-
1886
- FILE *fp = popen (cmd, mode);
1887
- if (!fp)
1888
- return NULL;
1889
-
1890
- // From here, all early returns must pclose the stream.
1891
-
1892
- // According to the pipe(2) manpage, descriptors returned from pipe have both
1893
- // CLOEXEC and NONBLOCK clear. Do NOT set CLOEXEC. DO set nonblocking.
1894
- if (!SetSocketNonblocking (fileno (fp))) {
1895
- pclose (fp);
1896
- return NULL;
1897
- }
1898
-
1899
- { // Looking good.
1900
- PipeDescriptor *pd = new PipeDescriptor (fp, this);
1901
- if (!pd)
1902
- throw std::runtime_error ("unable to allocate pipe");
1903
- Add (pd);
1904
- output_binding = pd->GetBinding();
1905
- }
1906
-
1907
- return output_binding;
1908
- #endif
1909
- }
1910
- #endif // OBSOLETE
1911
-
1912
- /**************************
1913
- EventMachine_t::Socketpair
1914
- **************************/
1915
-
1916
- const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
1917
- {
1918
- #ifdef OS_WIN32
1919
- throw std::runtime_error ("socketpair is currently unavailable on this platform");
1920
- #endif
1921
-
1922
- // The whole rest of this function is only compiled on Unix systems.
1923
- // Eventually we need this functionality (or a full-duplex equivalent) on Windows.
1924
- #ifdef OS_UNIX
1925
- // Make sure the incoming array of command strings is sane.
1926
- if (!cmd_strings)
1927
- return NULL;
1928
- int j;
1929
- for (j=0; j < 100 && cmd_strings[j]; j++)
1930
- ;
1931
- if ((j==0) || (j==100))
1932
- return NULL;
1933
-
1934
- unsigned long output_binding = NULL;
1935
-
1936
- int sv[2];
1937
- if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
1938
- return NULL;
1939
- // from here, all early returns must close the pair of sockets.
1940
-
1941
- // Set the parent side of the socketpair nonblocking.
1942
- // We don't care about the child side, and most child processes will expect their
1943
- // stdout to be blocking. Thanks to Duane Johnson and Bill Kelly for pointing this out.
1944
- // Obviously DON'T set CLOEXEC.
1945
- if (!SetSocketNonblocking (sv[0])) {
1946
- close (sv[0]);
1947
- close (sv[1]);
1948
- return NULL;
1949
- }
1950
-
1951
- pid_t f = fork();
1952
- if (f > 0) {
1953
- close (sv[1]);
1954
- PipeDescriptor *pd = new PipeDescriptor (sv[0], f, this);
1955
- if (!pd)
1956
- throw std::runtime_error ("unable to allocate pipe");
1957
- Add (pd);
1958
- output_binding = pd->GetBinding();
1959
- }
1960
- else if (f == 0) {
1961
- close (sv[0]);
1962
- dup2 (sv[1], STDIN_FILENO);
1963
- close (sv[1]);
1964
- dup2 (STDIN_FILENO, STDOUT_FILENO);
1965
- execvp (cmd_strings[0], cmd_strings+1);
1966
- exit (-1); // end the child process if the exec doesn't work.
1967
- }
1968
- else
1969
- throw std::runtime_error ("no fork");
1970
-
1971
- return output_binding;
1972
- #endif
1973
- }
1974
-
1975
-
1976
- /****************************
1977
- EventMachine_t::OpenKeyboard
1978
- ****************************/
1979
-
1980
- const unsigned long EventMachine_t::OpenKeyboard()
1981
- {
1982
- KeyboardDescriptor *kd = new KeyboardDescriptor (this);
1983
- if (!kd)
1984
- throw std::runtime_error ("no keyboard-object allocated");
1985
- Add (kd);
1986
- return kd->GetBinding();
1987
- }
1988
-
1989
-
1990
- /**********************************
1991
- EventMachine_t::GetConnectionCount
1992
- **********************************/
1993
-
1994
- int EventMachine_t::GetConnectionCount ()
1995
- {
1996
- return Descriptors.size() + NewDescriptors.size();
1997
- }
1998
-
1999
-
2000
- /************************
2001
- EventMachine_t::WatchPid
2002
- ************************/
2003
-
2004
- const unsigned long EventMachine_t::WatchPid (int pid)
2005
- {
2006
- #ifdef HAVE_KQUEUE
2007
- if (!bKqueue)
2008
- throw std::runtime_error("must enable kqueue");
2009
-
2010
- struct kevent event;
2011
- int kqres;
2012
-
2013
- EV_SET(&event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT | NOTE_FORK, 0, 0);
2014
-
2015
- // Attempt to register the event
2016
- kqres = kevent(kqfd, &event, 1, NULL, 0, NULL);
2017
- if (kqres == -1) {
2018
- char errbuf[200];
2019
- sprintf(errbuf, "failed to register file watch descriptor with kqueue: %s", strerror(errno));
2020
- throw std::runtime_error(errbuf);
2021
- }
2022
- #endif
2023
-
2024
- #ifdef HAVE_KQUEUE
2025
- Bindable_t* b = new Bindable_t();
2026
- Pids.insert(make_pair (pid, b));
2027
-
2028
- return b->GetBinding();
2029
- #endif
2030
-
2031
- throw std::runtime_error("no pid watching support on this system");
2032
- }
2033
-
2034
- /**************************
2035
- EventMachine_t::UnwatchPid
2036
- **************************/
2037
-
2038
- void EventMachine_t::UnwatchPid (int pid)
2039
- {
2040
- Bindable_t *b = Pids[pid];
2041
- assert(b);
2042
- Pids.erase(pid);
2043
-
2044
- #ifdef HAVE_KQUEUE
2045
- struct kevent k;
2046
-
2047
- EV_SET(&k, pid, EVFILT_PROC, EV_DELETE, 0, 0, 0);
2048
- /*int t =*/ kevent (kqfd, &k, 1, NULL, 0, NULL);
2049
- // t==-1 if the process already exited; ignore this for now
2050
- #endif
2051
-
2052
- if (EventCallback)
2053
- (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2054
-
2055
- delete b;
2056
- }
2057
-
2058
- void EventMachine_t::UnwatchPid (const unsigned long sig)
2059
- {
2060
- for(map<int, Bindable_t*>::iterator i=Pids.begin(); i != Pids.end(); i++)
2061
- {
2062
- if (i->second->GetBinding() == sig) {
2063
- UnwatchPid (i->first);
2064
- return;
2065
- }
2066
- }
2067
-
2068
- throw std::runtime_error("attempted to remove invalid pid signature");
2069
- }
2070
-
2071
-
2072
- /*************************
2073
- EventMachine_t::WatchFile
2074
- *************************/
2075
-
2076
- const unsigned long EventMachine_t::WatchFile (const char *fpath)
2077
- {
2078
- struct stat sb;
2079
- int sres;
2080
- int wd = -1;
2081
-
2082
- sres = stat(fpath, &sb);
2083
-
2084
- if (sres == -1) {
2085
- char errbuf[300];
2086
- sprintf(errbuf, "error registering file %s for watching: %s", fpath, strerror(errno));
2087
- throw std::runtime_error(errbuf);
2088
- }
2089
-
2090
- #ifdef HAVE_INOTIFY
2091
- if (!inotify) {
2092
- inotify = new InotifyDescriptor(this);
2093
- assert (inotify);
2094
- Add(inotify);
2095
- }
2096
-
2097
- wd = inotify_add_watch(inotify->GetSocket(), fpath, IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF);
2098
- if (wd == -1) {
2099
- char errbuf[300];
2100
- sprintf(errbuf, "failed to open file %s for registering with inotify: %s", fpath, strerror(errno));
2101
- throw std::runtime_error(errbuf);
2102
- }
2103
- #endif
2104
-
2105
- #ifdef HAVE_KQUEUE
2106
- if (!bKqueue)
2107
- throw std::runtime_error("must enable kqueue");
2108
-
2109
- // With kqueue we have to open the file first and use the resulting fd to register for events
2110
- wd = open(fpath, O_RDONLY);
2111
- if (wd == -1) {
2112
- char errbuf[300];
2113
- sprintf(errbuf, "failed to open file %s for registering with kqueue: %s", fpath, strerror(errno));
2114
- throw std::runtime_error(errbuf);
2115
- }
2116
- _RegisterKqueueFileEvent(wd);
2117
- #endif
2118
-
2119
- if (wd != -1) {
2120
- Bindable_t* b = new Bindable_t();
2121
- Files.insert(make_pair (wd, b));
2122
-
2123
- return b->GetBinding();
2124
- }
2125
-
2126
- throw std::runtime_error("no file watching support on this system"); // is this the right thing to do?
2127
- }
2128
-
2129
-
2130
- /***************************
2131
- EventMachine_t::UnwatchFile
2132
- ***************************/
2133
-
2134
- void EventMachine_t::UnwatchFile (int wd)
2135
- {
2136
- Bindable_t *b = Files[wd];
2137
- assert(b);
2138
- Files.erase(wd);
2139
-
2140
- #ifdef HAVE_INOTIFY
2141
- inotify_rm_watch(inotify->GetSocket(), wd);
2142
- #elif HAVE_KQUEUE
2143
- // With kqueue, closing the monitored fd automatically clears all registered events for it
2144
- close(wd);
2145
- #endif
2146
-
2147
- if (EventCallback)
2148
- (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2149
-
2150
- delete b;
2151
- }
2152
-
2153
- void EventMachine_t::UnwatchFile (const unsigned long sig)
2154
- {
2155
- for(map<int, Bindable_t*>::iterator i=Files.begin(); i != Files.end(); i++)
2156
- {
2157
- if (i->second->GetBinding() == sig) {
2158
- UnwatchFile (i->first);
2159
- return;
2160
- }
2161
- }
2162
- throw std::runtime_error("attempted to remove invalid watch signature");
2163
- }
2164
-
2165
-
2166
- /***********************************
2167
- EventMachine_t::_ReadInotify_Events
2168
- ************************************/
2169
-
2170
- void EventMachine_t::_ReadInotifyEvents()
2171
- {
2172
- #ifdef HAVE_INOTIFY
2173
- struct inotify_event event;
2174
-
2175
- assert(EventCallback);
2176
-
2177
- while (read(inotify->GetSocket(), &event, INOTIFY_EVENT_SIZE) > 0) {
2178
- assert(event.len == 0);
2179
- if (event.mask & IN_MODIFY)
2180
- (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2181
- if (event.mask & IN_MOVE_SELF)
2182
- (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2183
- if (event.mask & IN_DELETE_SELF) {
2184
- (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2185
- UnwatchFile ((int)event.wd);
2186
- }
2187
- }
2188
- #endif
2189
- }
2190
-
2191
-
2192
- /*************************************
2193
- EventMachine_t::_HandleKqueuePidEvent
2194
- *************************************/
2195
-
2196
- #ifdef HAVE_KQUEUE
2197
- void EventMachine_t::_HandleKqueuePidEvent(struct kevent *event)
2198
- {
2199
- assert(EventCallback);
2200
-
2201
- if (event->fflags & NOTE_FORK)
2202
- (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "fork", 4);
2203
- if (event->fflags & NOTE_EXIT) {
2204
- (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "exit", 4);
2205
- // stop watching the pid if it died
2206
- UnwatchPid ((int)event->ident);
2207
- }
2208
- }
2209
- #endif
2210
-
2211
-
2212
- /**************************************
2213
- EventMachine_t::_HandleKqueueFileEvent
2214
- ***************************************/
2215
-
2216
- #ifdef HAVE_KQUEUE
2217
- void EventMachine_t::_HandleKqueueFileEvent(struct kevent *event)
2218
- {
2219
- assert(EventCallback);
2220
-
2221
- if (event->fflags & NOTE_WRITE)
2222
- (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2223
- if (event->fflags & NOTE_RENAME)
2224
- (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2225
- if (event->fflags & NOTE_DELETE) {
2226
- (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2227
- UnwatchFile ((int)event->ident);
2228
- }
2229
- }
2230
- #endif
2231
-
2232
-
2233
- /****************************************
2234
- EventMachine_t::_RegisterKqueueFileEvent
2235
- *****************************************/
2236
-
2237
- #ifdef HAVE_KQUEUE
2238
- void EventMachine_t::_RegisterKqueueFileEvent(int fd)
2239
- {
2240
- struct kevent newevent;
2241
- int kqres;
2242
-
2243
- // Setup the event with our fd and proper flags
2244
- EV_SET(&newevent, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_DELETE | NOTE_RENAME | NOTE_WRITE, 0, 0);
2245
-
2246
- // Attempt to register the event
2247
- kqres = kevent(kqfd, &newevent, 1, NULL, 0, NULL);
2248
- if (kqres == -1) {
2249
- char errbuf[200];
2250
- sprintf(errbuf, "failed to register file watch descriptor with kqueue: %s", strerror(errno));
2251
- close(fd);
2252
- throw std::runtime_error(errbuf);
2253
- }
2254
- }
2255
- #endif
2256
-
2257
-
2258
- /************************************
2259
- EventMachine_t::GetHeartbeatInterval
2260
- *************************************/
2261
-
2262
- float EventMachine_t::GetHeartbeatInterval()
2263
- {
2264
- return ((float)HeartbeatInterval / 1000000);
2265
- }
2266
-
2267
-
2268
- /************************************
2269
- EventMachine_t::SetHeartbeatInterval
2270
- *************************************/
2271
-
2272
- int EventMachine_t::SetHeartbeatInterval(float interval)
2273
- {
2274
- int iv = (int)(interval * 1000000);
2275
- if (iv > 0) {
2276
- HeartbeatInterval = iv;
2277
- return 1;
2278
- }
2279
- return 0;
2280
- }
2281
- //#endif // OS_UNIX
2282
-