smparkes-eventmachine 0.12.10

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