libc-eventmachine 0.12.5.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/Rakefile +195 -0
  2. data/docs/COPYING +60 -0
  3. data/docs/ChangeLog +211 -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 +582 -0
  20. data/ext/cplusplus.cpp +177 -0
  21. data/ext/ed.cpp +1522 -0
  22. data/ext/ed.h +380 -0
  23. data/ext/em.cpp +1947 -0
  24. data/ext/em.h +186 -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 +98 -0
  30. data/ext/eventmachine_cpp.h +96 -0
  31. data/ext/extconf.rb +129 -0
  32. data/ext/fastfilereader/extconf.rb +77 -0
  33. data/ext/fastfilereader/mapper.cpp +214 -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 +351 -0
  42. data/ext/project.h +119 -0
  43. data/ext/rubymain.cpp +858 -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 +1920 -0
  73. data/lib/eventmachine_version.rb +31 -0
  74. data/lib/evma/callback.rb +32 -0
  75. data/lib/evma/container.rb +75 -0
  76. data/lib/evma/factory.rb +77 -0
  77. data/lib/evma/protocol.rb +87 -0
  78. data/lib/evma/reactor.rb +48 -0
  79. data/lib/evma.rb +32 -0
  80. data/lib/jeventmachine.rb +140 -0
  81. data/lib/pr_eventmachine.rb +1017 -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 +803 -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/memcache.rb +293 -0
  89. data/lib/protocols/postgres.rb +261 -0
  90. data/lib/protocols/saslauth.rb +179 -0
  91. data/lib/protocols/smtpclient.rb +308 -0
  92. data/lib/protocols/smtpserver.rb +556 -0
  93. data/lib/protocols/stomp.rb +153 -0
  94. data/lib/protocols/tcptest.rb +57 -0
  95. data/tasks/cpp.rake +77 -0
  96. data/tasks/project.rake +78 -0
  97. data/tasks/tests.rake +193 -0
  98. data/tests/test_attach.rb +83 -0
  99. data/tests/test_basic.rb +231 -0
  100. data/tests/test_bind.rb +73 -0
  101. data/tests/test_connection_count.rb +35 -0
  102. data/tests/test_defer.rb +47 -0
  103. data/tests/test_epoll.rb +163 -0
  104. data/tests/test_error_handler.rb +32 -0
  105. data/tests/test_errors.rb +82 -0
  106. data/tests/test_eventables.rb +77 -0
  107. data/tests/test_exc.rb +58 -0
  108. data/tests/test_futures.rb +214 -0
  109. data/tests/test_handler_check.rb +37 -0
  110. data/tests/test_hc.rb +218 -0
  111. data/tests/test_httpclient.rb +215 -0
  112. data/tests/test_httpclient2.rb +155 -0
  113. data/tests/test_kb.rb +61 -0
  114. data/tests/test_ltp.rb +188 -0
  115. data/tests/test_ltp2.rb +320 -0
  116. data/tests/test_next_tick.rb +109 -0
  117. data/tests/test_processes.rb +56 -0
  118. data/tests/test_pure.rb +129 -0
  119. data/tests/test_running.rb +47 -0
  120. data/tests/test_sasl.rb +74 -0
  121. data/tests/test_send_file.rb +243 -0
  122. data/tests/test_servers.rb +80 -0
  123. data/tests/test_smtpclient.rb +83 -0
  124. data/tests/test_smtpserver.rb +93 -0
  125. data/tests/test_spawn.rb +329 -0
  126. data/tests/test_ssl_args.rb +68 -0
  127. data/tests/test_ssl_methods.rb +50 -0
  128. data/tests/test_timers.rb +148 -0
  129. data/tests/test_ud.rb +43 -0
  130. data/tests/testem.rb +31 -0
  131. metadata +230 -0
data/ext/pipe.cpp ADDED
@@ -0,0 +1,351 @@
1
+ /*****************************************************************************
2
+
3
+ $Id$
4
+
5
+ File: pipe.cpp
6
+ Date: 30May07
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
+ #include "project.h"
21
+
22
+
23
+ #ifdef OS_UNIX
24
+ // THIS ENTIRE FILE IS ONLY COMPILED ON UNIX-LIKE SYSTEMS.
25
+
26
+ /******************************
27
+ PipeDescriptor::PipeDescriptor
28
+ ******************************/
29
+
30
+ PipeDescriptor::PipeDescriptor (int fd, pid_t subpid, EventMachine_t *parent_em):
31
+ EventableDescriptor (fd, parent_em),
32
+ bReadAttemptedAfterClose (false),
33
+ LastIo (gCurrentLoopTime),
34
+ InactivityTimeout (0),
35
+ OutboundDataSize (0),
36
+ SubprocessPid (subpid)
37
+ {
38
+ #ifdef HAVE_EPOLL
39
+ EpollEvent.events = EPOLLIN;
40
+ #endif
41
+ #ifdef HAVE_KQUEUE
42
+ MyEventMachine->ArmKqueueReader (this);
43
+ #endif
44
+ }
45
+
46
+
47
+ /*******************************
48
+ PipeDescriptor::~PipeDescriptor
49
+ *******************************/
50
+
51
+ PipeDescriptor::~PipeDescriptor()
52
+ {
53
+ // Run down any stranded outbound data.
54
+ for (size_t i=0; i < OutboundPages.size(); i++)
55
+ OutboundPages[i].Free();
56
+
57
+ /* As a virtual destructor, we come here before the base-class
58
+ * destructor that closes our file-descriptor.
59
+ * We have to make sure the subprocess goes down (if it's not
60
+ * already down) and we have to reap the zombie.
61
+ *
62
+ * This implementation is PROVISIONAL and will surely be improved.
63
+ * The intention here is that we never block, hence the highly
64
+ * undesirable sleeps. But if we can't reap the subprocess even
65
+ * after sending it SIGKILL, then something is wrong and we
66
+ * throw a fatal exception, which is also not something we should
67
+ * be doing.
68
+ *
69
+ * Eventually the right thing to do will be to have the reactor
70
+ * core respond to SIGCHLD by chaining a handler on top of the
71
+ * one Ruby may have installed, and dealing with a list of dead
72
+ * children that are pending cleanup.
73
+ *
74
+ * Since we want to have a signal processor integrated into the
75
+ * client-visible API, let's wait until that is done before cleaning
76
+ * this up.
77
+ *
78
+ * Added a very ugly hack to support passing the subprocess's exit
79
+ * status to the user. It only makes logical sense for user code to access
80
+ * the subprocess exit status in the unbind callback. But unbind is called
81
+ * back during the EventableDescriptor destructor. So by that time there's
82
+ * no way to call back this object through an object binding, because it's
83
+ * already been cleaned up. We might have added a parameter to the unbind
84
+ * callback, but that would probably break a huge amount of existing code.
85
+ * So the hack-solution is to define an instance variable in the EventMachine
86
+ * object and stick the exit status in there, where it can easily be accessed
87
+ * with an accessor visible to user code.
88
+ * User code should ONLY access the exit status from within the unbind callback.
89
+ * Otherwise there's no guarantee it'll be valid.
90
+ * This hack won't make it impossible to run multiple EventMachines in a single
91
+ * process, but it will make it impossible to reliably nest unbind calls
92
+ * within other unbind calls. (Not sure if that's even possible.)
93
+ */
94
+
95
+ assert (MyEventMachine);
96
+
97
+ /* Another hack to make the SubprocessPid available to get_subprocess_status */
98
+ MyEventMachine->SubprocessPid = SubprocessPid;
99
+
100
+ /* 01Mar09: Updated to use a small nanosleep in a loop. When nanosleep is interrupted by SIGCHLD,
101
+ * it resumes the system call after processing the signal (resulting in unnecessary latency).
102
+ * Calling nanosleep in a loop avoids this problem.
103
+ */
104
+ struct timespec req = {0, 50000000}; // 0.05s
105
+ int n;
106
+
107
+ // wait 0.25s for the process to die
108
+ for (n=0; n<5; n++) {
109
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
110
+ nanosleep (&req, NULL);
111
+ }
112
+
113
+ // send SIGTERM and wait another 0.5s
114
+ kill (SubprocessPid, SIGTERM);
115
+ for (n=0; n<10; n++) {
116
+ nanosleep (&req, NULL);
117
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
118
+ }
119
+
120
+ // send SIGKILL and wait another 1s
121
+ kill (SubprocessPid, SIGKILL);
122
+ for (n=0; n<20; n++) {
123
+ nanosleep (&req, NULL);
124
+ if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
125
+ }
126
+
127
+ // still not dead, give up!
128
+ throw std::runtime_error ("unable to reap subprocess");
129
+ }
130
+
131
+
132
+
133
+ /********************
134
+ PipeDescriptor::Read
135
+ ********************/
136
+
137
+ void PipeDescriptor::Read()
138
+ {
139
+ int sd = GetSocket();
140
+ if (sd == INVALID_SOCKET) {
141
+ assert (!bReadAttemptedAfterClose);
142
+ bReadAttemptedAfterClose = true;
143
+ return;
144
+ }
145
+
146
+ LastIo = gCurrentLoopTime;
147
+
148
+ int total_bytes_read = 0;
149
+ char readbuffer [16 * 1024];
150
+
151
+ for (int i=0; i < 10; i++) {
152
+ // Don't read just one buffer and then move on. This is faster
153
+ // if there is a lot of incoming.
154
+ // But don't read indefinitely. Give other sockets a chance to run.
155
+ // NOTICE, we're reading one less than the buffer size.
156
+ // That's so we can put a guard byte at the end of what we send
157
+ // to user code.
158
+ // Use read instead of recv, which on Linux gives a "socket operation
159
+ // on nonsocket" error.
160
+
161
+
162
+ int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
163
+ //cerr << "<R:" << r << ">";
164
+
165
+ if (r > 0) {
166
+ total_bytes_read += r;
167
+ LastRead = gCurrentLoopTime;
168
+
169
+ // Add a null-terminator at the the end of the buffer
170
+ // that we will send to the callback.
171
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
172
+ // to be able to depend on this behavior, so they will have
173
+ // the option to do some things faster. Additionally it's
174
+ // a security guard against buffer overflows.
175
+ readbuffer [r] = 0;
176
+ if (EventCallback)
177
+ (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, readbuffer, r);
178
+ }
179
+ else if (r == 0) {
180
+ break;
181
+ }
182
+ else {
183
+ // Basically a would-block, meaning we've read everything there is to read.
184
+ break;
185
+ }
186
+
187
+ }
188
+
189
+
190
+ if (total_bytes_read == 0) {
191
+ // If we read no data on a socket that selected readable,
192
+ // it generally means the other end closed the connection gracefully.
193
+ ScheduleClose (false);
194
+ //bCloseNow = true;
195
+ }
196
+
197
+ }
198
+
199
+ /*********************
200
+ PipeDescriptor::Write
201
+ *********************/
202
+
203
+ void PipeDescriptor::Write()
204
+ {
205
+ int sd = GetSocket();
206
+ assert (sd != INVALID_SOCKET);
207
+
208
+ LastIo = gCurrentLoopTime;
209
+ char output_buffer [16 * 1024];
210
+ size_t nbytes = 0;
211
+
212
+ while ((OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
213
+ OutboundPage *op = &(OutboundPages[0]);
214
+ if ((nbytes + op->Length - op->Offset) < sizeof (output_buffer)) {
215
+ memcpy (output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset);
216
+ nbytes += (op->Length - op->Offset);
217
+ op->Free();
218
+ OutboundPages.pop_front();
219
+ }
220
+ else {
221
+ int len = sizeof(output_buffer) - nbytes;
222
+ memcpy (output_buffer + nbytes, op->Buffer + op->Offset, len);
223
+ op->Offset += len;
224
+ nbytes += len;
225
+ }
226
+ }
227
+
228
+ // We should never have gotten here if there were no data to write,
229
+ // so assert that as a sanity check.
230
+ // Don't bother to make sure nbytes is less than output_buffer because
231
+ // if it were we probably would have crashed already.
232
+ assert (nbytes > 0);
233
+
234
+ assert (GetSocket() != INVALID_SOCKET);
235
+ int bytes_written = write (GetSocket(), output_buffer, nbytes);
236
+
237
+ if (bytes_written > 0) {
238
+ OutboundDataSize -= bytes_written;
239
+ if ((size_t)bytes_written < nbytes) {
240
+ int len = nbytes - bytes_written;
241
+ char *buffer = (char*) malloc (len + 1);
242
+ if (!buffer)
243
+ throw std::runtime_error ("bad alloc throwing back data");
244
+ memcpy (buffer, output_buffer + bytes_written, len);
245
+ buffer [len] = 0;
246
+ OutboundPages.push_front (OutboundPage (buffer, len));
247
+ }
248
+ #ifdef HAVE_EPOLL
249
+ EpollEvent.events = (EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0));
250
+ assert (MyEventMachine);
251
+ MyEventMachine->Modify (this);
252
+ #endif
253
+ }
254
+ else {
255
+ #ifdef OS_UNIX
256
+ if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK) && (errno != EINTR))
257
+ #endif
258
+ #ifdef OS_WIN32
259
+ if ((errno != WSAEINPROGRESS) && (errno != WSAEWOULDBLOCK))
260
+ #endif
261
+ Close();
262
+ }
263
+ }
264
+
265
+
266
+ /*************************
267
+ PipeDescriptor::Heartbeat
268
+ *************************/
269
+
270
+ void PipeDescriptor::Heartbeat()
271
+ {
272
+ // If an inactivity timeout is defined, then check for it.
273
+ if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout))
274
+ ScheduleClose (false);
275
+ //bCloseNow = true;
276
+ }
277
+
278
+
279
+ /*****************************
280
+ PipeDescriptor::SelectForRead
281
+ *****************************/
282
+
283
+ bool PipeDescriptor::SelectForRead()
284
+ {
285
+ /* Pipe descriptors, being local by definition, don't have
286
+ * a pending state, so this is simpler than for the
287
+ * ConnectionDescriptor object.
288
+ */
289
+ return true;
290
+ }
291
+
292
+ /******************************
293
+ PipeDescriptor::SelectForWrite
294
+ ******************************/
295
+
296
+ bool PipeDescriptor::SelectForWrite()
297
+ {
298
+ /* Pipe descriptors, being local by definition, don't have
299
+ * a pending state, so this is simpler than for the
300
+ * ConnectionDescriptor object.
301
+ */
302
+ return (GetOutboundDataSize() > 0);
303
+ }
304
+
305
+
306
+
307
+
308
+ /********************************
309
+ PipeDescriptor::SendOutboundData
310
+ ********************************/
311
+
312
+ int PipeDescriptor::SendOutboundData (const char *data, int length)
313
+ {
314
+ //if (bCloseNow || bCloseAfterWriting)
315
+ if (IsCloseScheduled())
316
+ return 0;
317
+
318
+ if (!data && (length > 0))
319
+ throw std::runtime_error ("bad outbound data");
320
+ char *buffer = (char *) malloc (length + 1);
321
+ if (!buffer)
322
+ throw std::runtime_error ("no allocation for outbound data");
323
+ memcpy (buffer, data, length);
324
+ buffer [length] = 0;
325
+ OutboundPages.push_back (OutboundPage (buffer, length));
326
+ OutboundDataSize += length;
327
+ #ifdef HAVE_EPOLL
328
+ EpollEvent.events = (EPOLLIN | EPOLLOUT);
329
+ assert (MyEventMachine);
330
+ MyEventMachine->Modify (this);
331
+ #endif
332
+ return length;
333
+ }
334
+
335
+ /********************************
336
+ PipeDescriptor::GetSubprocessPid
337
+ ********************************/
338
+
339
+ bool PipeDescriptor::GetSubprocessPid (pid_t *pid)
340
+ {
341
+ bool ok = false;
342
+ if (pid && (SubprocessPid > 0)) {
343
+ *pid = SubprocessPid;
344
+ ok = true;
345
+ }
346
+ return ok;
347
+ }
348
+
349
+
350
+ #endif // OS_UNIX
351
+
data/ext/project.h ADDED
@@ -0,0 +1,119 @@
1
+ /*****************************************************************************
2
+
3
+ $Id$
4
+
5
+ File: project.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
+
21
+ #ifndef __Project__H_
22
+ #define __Project__H_
23
+
24
+
25
+ #ifdef OS_WIN32
26
+ #pragma warning(disable:4786)
27
+ #endif
28
+
29
+ #include <iostream>
30
+ #include <map>
31
+ #include <set>
32
+ #include <vector>
33
+ #include <deque>
34
+ #include <string>
35
+ #include <sstream>
36
+ #include <stdexcept>
37
+
38
+
39
+ #ifdef OS_UNIX
40
+ #include <signal.h>
41
+ #include <netdb.h>
42
+ #include <time.h>
43
+ #include <sys/time.h>
44
+ #include <sys/types.h>
45
+ #include <sys/stat.h>
46
+ #include <sys/socket.h>
47
+ #include <sys/un.h>
48
+ #include <sys/resource.h>
49
+ #include <sys/wait.h>
50
+ #include <assert.h>
51
+ #include <unistd.h>
52
+ #include <fcntl.h>
53
+ #include <errno.h>
54
+ #include <netinet/in.h>
55
+ #include <netinet/tcp.h>
56
+ #include <arpa/inet.h>
57
+ #include <pwd.h>
58
+ typedef int SOCKET;
59
+ #define closesocket close
60
+ #define INVALID_SOCKET -1
61
+ #define SOCKET_ERROR -1
62
+ #ifdef OS_SOLARIS8
63
+ #include <strings.h>
64
+ #include <sys/un.h>
65
+ #ifndef AF_LOCAL
66
+ #define AF_LOCAL AF_UNIX
67
+ #endif
68
+ // INADDR_NONE is undefined on Solaris < 8. Thanks to Brett Eisenberg and Tim Pease.
69
+ #ifndef INADDR_NONE
70
+ #define INADDR_NONE ((unsigned long)-1)
71
+ #endif
72
+ #endif
73
+ #endif
74
+
75
+
76
+ #ifdef OS_WIN32
77
+ #define WIN32_LEAN_AND_MEAN
78
+ #include <windows.h>
79
+ #include <winsock2.h>
80
+ #include <ws2tcpip.h>
81
+ #include <rpc.h>
82
+ #include <fcntl.h>
83
+ #include <assert.h>
84
+ typedef int socklen_t;
85
+ typedef int pid_t;
86
+ #endif
87
+
88
+
89
+ using namespace std;
90
+
91
+ #ifdef WITH_SSL
92
+ #include <openssl/ssl.h>
93
+ #include <openssl/err.h>
94
+ #endif
95
+
96
+ #ifdef HAVE_EPOLL
97
+ #include <sys/epoll.h>
98
+ #endif
99
+
100
+ #ifdef HAVE_KQUEUE
101
+ #include <sys/event.h>
102
+ #include <sys/queue.h>
103
+ #endif
104
+
105
+ #include "binder.h"
106
+ #include "em.h"
107
+ #include "epoll.h"
108
+ #include "sigs.h"
109
+ #include "ed.h"
110
+ #include "files.h"
111
+ #include "page.h"
112
+ #include "ssl.h"
113
+ #include "eventmachine.h"
114
+ #include "eventmachine_cpp.h"
115
+
116
+
117
+
118
+
119
+ #endif // __Project__H_