eventmachine-le 1.1.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+