eventmachine-le 1.1.0.beta.1

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