eventmachine-with-ipv6 1.0.0.beta.4.ipv6.0

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