eventmachine 0.12.6-x86-mswin32-60

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