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