eventmachine-mkroman 1.3.0.dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +179 -0
  3. data/GNU +281 -0
  4. data/LICENSE +60 -0
  5. data/README.md +110 -0
  6. data/docs/DocumentationGuidesIndex.md +27 -0
  7. data/docs/GettingStarted.md +520 -0
  8. data/docs/old/ChangeLog +211 -0
  9. data/docs/old/DEFERRABLES +246 -0
  10. data/docs/old/EPOLL +141 -0
  11. data/docs/old/INSTALL +13 -0
  12. data/docs/old/KEYBOARD +42 -0
  13. data/docs/old/LEGAL +25 -0
  14. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  15. data/docs/old/PURE_RUBY +75 -0
  16. data/docs/old/RELEASE_NOTES +94 -0
  17. data/docs/old/SMTP +4 -0
  18. data/docs/old/SPAWNED_PROCESSES +148 -0
  19. data/docs/old/TODO +8 -0
  20. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  21. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  22. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  23. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  24. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  25. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  26. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  27. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  28. data/examples/old/ex_channel.rb +43 -0
  29. data/examples/old/ex_queue.rb +2 -0
  30. data/examples/old/ex_tick_loop_array.rb +15 -0
  31. data/examples/old/ex_tick_loop_counter.rb +32 -0
  32. data/examples/old/helper.rb +2 -0
  33. data/ext/binder.cpp +124 -0
  34. data/ext/binder.h +52 -0
  35. data/ext/cmain.cpp +1046 -0
  36. data/ext/ed.cpp +2243 -0
  37. data/ext/ed.h +463 -0
  38. data/ext/em.cpp +2378 -0
  39. data/ext/em.h +266 -0
  40. data/ext/eventmachine.h +152 -0
  41. data/ext/extconf.rb +291 -0
  42. data/ext/fastfilereader/extconf.rb +120 -0
  43. data/ext/fastfilereader/mapper.cpp +214 -0
  44. data/ext/fastfilereader/mapper.h +59 -0
  45. data/ext/fastfilereader/rubymain.cpp +126 -0
  46. data/ext/kb.cpp +79 -0
  47. data/ext/page.cpp +107 -0
  48. data/ext/page.h +51 -0
  49. data/ext/pipe.cpp +354 -0
  50. data/ext/project.h +174 -0
  51. data/ext/rubymain.cpp +1643 -0
  52. data/ext/ssl.cpp +701 -0
  53. data/ext/ssl.h +103 -0
  54. data/ext/wait_for_single_fd.h +36 -0
  55. data/java/.classpath +8 -0
  56. data/java/.project +17 -0
  57. data/java/src/com/rubyeventmachine/EmReactor.java +625 -0
  58. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  59. data/java/src/com/rubyeventmachine/EmReactorInterface.java +70 -0
  60. data/java/src/com/rubyeventmachine/EventableChannel.java +72 -0
  61. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +201 -0
  62. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +415 -0
  63. data/java/src/com/rubyeventmachine/NullEmReactor.java +157 -0
  64. data/java/src/com/rubyeventmachine/NullEventableChannel.java +81 -0
  65. data/lib/em/buftok.rb +59 -0
  66. data/lib/em/callback.rb +58 -0
  67. data/lib/em/channel.rb +69 -0
  68. data/lib/em/completion.rb +307 -0
  69. data/lib/em/connection.rb +802 -0
  70. data/lib/em/deferrable/pool.rb +2 -0
  71. data/lib/em/deferrable.rb +210 -0
  72. data/lib/em/file_watch.rb +73 -0
  73. data/lib/em/future.rb +61 -0
  74. data/lib/em/io_streamer.rb +68 -0
  75. data/lib/em/iterator.rb +252 -0
  76. data/lib/em/messages.rb +66 -0
  77. data/lib/em/pool.rb +151 -0
  78. data/lib/em/process_watch.rb +45 -0
  79. data/lib/em/processes.rb +123 -0
  80. data/lib/em/protocols/header_and_content.rb +138 -0
  81. data/lib/em/protocols/httpclient.rb +303 -0
  82. data/lib/em/protocols/httpclient2.rb +602 -0
  83. data/lib/em/protocols/line_and_text.rb +125 -0
  84. data/lib/em/protocols/line_protocol.rb +33 -0
  85. data/lib/em/protocols/linetext2.rb +179 -0
  86. data/lib/em/protocols/memcache.rb +331 -0
  87. data/lib/em/protocols/object_protocol.rb +46 -0
  88. data/lib/em/protocols/postgres3.rb +246 -0
  89. data/lib/em/protocols/saslauth.rb +175 -0
  90. data/lib/em/protocols/smtpclient.rb +394 -0
  91. data/lib/em/protocols/smtpserver.rb +666 -0
  92. data/lib/em/protocols/socks4.rb +66 -0
  93. data/lib/em/protocols/stomp.rb +205 -0
  94. data/lib/em/protocols/tcptest.rb +54 -0
  95. data/lib/em/protocols.rb +37 -0
  96. data/lib/em/pure_ruby.rb +1300 -0
  97. data/lib/em/queue.rb +80 -0
  98. data/lib/em/resolver.rb +232 -0
  99. data/lib/em/spawnable.rb +84 -0
  100. data/lib/em/streamer.rb +118 -0
  101. data/lib/em/threaded_resource.rb +90 -0
  102. data/lib/em/tick_loop.rb +85 -0
  103. data/lib/em/timers.rb +61 -0
  104. data/lib/em/version.rb +3 -0
  105. data/lib/eventmachine.rb +1602 -0
  106. data/lib/jeventmachine.rb +319 -0
  107. data/rakelib/package.rake +120 -0
  108. data/rakelib/test.rake +6 -0
  109. data/rakelib/test_pure.rake +11 -0
  110. data/tests/client.crt +31 -0
  111. data/tests/client.key +51 -0
  112. data/tests/dhparam.pem +13 -0
  113. data/tests/em_ssl_handlers.rb +165 -0
  114. data/tests/em_test_helper.rb +198 -0
  115. data/tests/encoded_client.key +54 -0
  116. data/tests/jruby/test_jeventmachine.rb +38 -0
  117. data/tests/test_attach.rb +199 -0
  118. data/tests/test_basic.rb +321 -0
  119. data/tests/test_channel.rb +75 -0
  120. data/tests/test_completion.rb +178 -0
  121. data/tests/test_connection_count.rb +83 -0
  122. data/tests/test_connection_write.rb +35 -0
  123. data/tests/test_defer.rb +35 -0
  124. data/tests/test_deferrable.rb +35 -0
  125. data/tests/test_epoll.rb +141 -0
  126. data/tests/test_error_handler.rb +38 -0
  127. data/tests/test_exc.rb +37 -0
  128. data/tests/test_file_watch.rb +86 -0
  129. data/tests/test_fork.rb +75 -0
  130. data/tests/test_futures.rb +170 -0
  131. data/tests/test_handler_check.rb +35 -0
  132. data/tests/test_hc.rb +155 -0
  133. data/tests/test_httpclient.rb +238 -0
  134. data/tests/test_httpclient2.rb +132 -0
  135. data/tests/test_idle_connection.rb +31 -0
  136. data/tests/test_inactivity_timeout.rb +102 -0
  137. data/tests/test_io_streamer.rb +48 -0
  138. data/tests/test_ipv4.rb +96 -0
  139. data/tests/test_ipv6.rb +107 -0
  140. data/tests/test_iterator.rb +122 -0
  141. data/tests/test_kb.rb +28 -0
  142. data/tests/test_keepalive.rb +113 -0
  143. data/tests/test_line_protocol.rb +33 -0
  144. data/tests/test_ltp.rb +155 -0
  145. data/tests/test_ltp2.rb +332 -0
  146. data/tests/test_many_fds.rb +21 -0
  147. data/tests/test_next_tick.rb +104 -0
  148. data/tests/test_object_protocol.rb +36 -0
  149. data/tests/test_pause.rb +109 -0
  150. data/tests/test_pending_connect_timeout.rb +52 -0
  151. data/tests/test_pool.rb +196 -0
  152. data/tests/test_process_watch.rb +50 -0
  153. data/tests/test_processes.rb +147 -0
  154. data/tests/test_proxy_connection.rb +180 -0
  155. data/tests/test_pure.rb +156 -0
  156. data/tests/test_queue.rb +64 -0
  157. data/tests/test_resolver.rb +129 -0
  158. data/tests/test_running.rb +14 -0
  159. data/tests/test_sasl.rb +46 -0
  160. data/tests/test_send_file.rb +217 -0
  161. data/tests/test_servers.rb +32 -0
  162. data/tests/test_shutdown_hooks.rb +23 -0
  163. data/tests/test_smtpclient.rb +75 -0
  164. data/tests/test_smtpserver.rb +90 -0
  165. data/tests/test_sock_opt.rb +53 -0
  166. data/tests/test_spawn.rb +290 -0
  167. data/tests/test_ssl_args.rb +70 -0
  168. data/tests/test_ssl_dhparam.rb +57 -0
  169. data/tests/test_ssl_ecdh_curve.rb +57 -0
  170. data/tests/test_ssl_extensions.rb +24 -0
  171. data/tests/test_ssl_inline_cert.rb +222 -0
  172. data/tests/test_ssl_methods.rb +31 -0
  173. data/tests/test_ssl_protocols.rb +190 -0
  174. data/tests/test_ssl_verify.rb +108 -0
  175. data/tests/test_stomp.rb +38 -0
  176. data/tests/test_system.rb +46 -0
  177. data/tests/test_threaded_resource.rb +68 -0
  178. data/tests/test_tick_loop.rb +58 -0
  179. data/tests/test_timers.rb +150 -0
  180. data/tests/test_ud.rb +8 -0
  181. data/tests/test_unbind_reason.rb +40 -0
  182. metadata +389 -0
@@ -0,0 +1,415 @@
1
+ /**
2
+ * $Id$
3
+ *
4
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
5
+ * Homepage:: http://rubyeventmachine.com
6
+ * Date:: 15 Jul 2007
7
+ *
8
+ * See EventMachine and EventMachine::Connection for documentation and
9
+ * usage examples.
10
+ *
11
+ *
12
+ *----------------------------------------------------------------------------
13
+ *
14
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
15
+ * Gmail: blackhedd
16
+ *
17
+ * This program is free software; you can redistribute it and/or modify
18
+ * it under the terms of either: 1) the GNU General Public License
19
+ * as published by the Free Software Foundation; either version 2 of the
20
+ * License, or (at your option) any later version; or 2) Ruby's License.
21
+ *
22
+ * See the file COPYING for complete licensing information.
23
+ *
24
+ *---------------------------------------------------------------------------
25
+ *
26
+ *
27
+ */
28
+
29
+ /**
30
+ *
31
+ */
32
+ package com.rubyeventmachine;
33
+
34
+ /**
35
+ * @author francis
36
+ *
37
+ */
38
+
39
+ import java.nio.channels.*;
40
+ import java.nio.*;
41
+ import java.util.*;
42
+ import java.io.*;
43
+ import java.net.Socket;
44
+ import javax.net.ssl.*;
45
+ import javax.net.ssl.SSLEngineResult.*;
46
+ import java.lang.reflect.Field;
47
+
48
+ import java.security.*;
49
+
50
+ public class EventableSocketChannel implements EventableChannel {
51
+ Selector selector;
52
+ SelectionKey channelKey;
53
+ SocketChannel channel;
54
+
55
+ long binding;
56
+ LinkedList<ByteBuffer> outboundQ;
57
+ long outboundS;
58
+
59
+ boolean bCloseScheduled;
60
+ boolean bConnectPending;
61
+ boolean bWatchOnly;
62
+ boolean bAttached;
63
+ boolean bNotifyReadable;
64
+ boolean bNotifyWritable;
65
+ boolean bPaused;
66
+
67
+ SSLEngine sslEngine;
68
+ SSLContext sslContext;
69
+
70
+ public EventableSocketChannel (SocketChannel sc, long _binding, Selector sel) {
71
+ channel = sc;
72
+ binding = _binding;
73
+ selector = sel;
74
+ bCloseScheduled = false;
75
+ bConnectPending = false;
76
+ bWatchOnly = false;
77
+ bAttached = false;
78
+ bNotifyReadable = false;
79
+ bNotifyWritable = false;
80
+ outboundQ = new LinkedList<ByteBuffer>();
81
+ outboundS = 0;
82
+ }
83
+
84
+ public long getBinding() {
85
+ return binding;
86
+ }
87
+
88
+ public SocketChannel getChannel() {
89
+ return channel;
90
+ }
91
+
92
+ public void register() throws ClosedChannelException {
93
+ if (channelKey == null) {
94
+ int events = currentEvents();
95
+ channelKey = channel.register(selector, events, this);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Terminate with extreme prejudice. Don't assume there will be another pass through
101
+ * the reactor core.
102
+ */
103
+ public void close() {
104
+ if (channelKey != null) {
105
+ channelKey.cancel();
106
+ channelKey = null;
107
+ }
108
+
109
+ if (bAttached) {
110
+ // attached channels are copies, so reset the file descriptor to prevent java from close()ing it
111
+ Field f;
112
+ FileDescriptor fd;
113
+
114
+ try {
115
+ /* do _NOT_ clobber fdVal here, it will break epoll/kqueue on jdk6!
116
+ * channelKey.cancel() above does not occur until the next call to select
117
+ * and if fdVal is gone, we will continue to get events for this fd.
118
+ *
119
+ * instead, remove fdVal in cleanup(), which is processed via DetachedConnections,
120
+ * after UnboundConnections but before NewConnections.
121
+ */
122
+
123
+ f = channel.getClass().getDeclaredField("fd");
124
+ f.setAccessible(true);
125
+ fd = (FileDescriptor) f.get(channel);
126
+
127
+ f = fd.getClass().getDeclaredField("fd");
128
+ f.setAccessible(true);
129
+ f.set(fd, -1);
130
+ } catch (java.lang.NoSuchFieldException e) {
131
+ e.printStackTrace();
132
+ } catch (java.lang.IllegalAccessException e) {
133
+ e.printStackTrace();
134
+ }
135
+
136
+ return;
137
+ }
138
+
139
+ try {
140
+ channel.close();
141
+ } catch (IOException e) {
142
+ }
143
+ }
144
+
145
+ public void cleanup() {
146
+ if (bAttached) {
147
+ Field f;
148
+ try {
149
+ f = channel.getClass().getDeclaredField("fdVal");
150
+ f.setAccessible(true);
151
+ f.set(channel, -1);
152
+ } catch (java.lang.NoSuchFieldException e) {
153
+ e.printStackTrace();
154
+ } catch (java.lang.IllegalAccessException e) {
155
+ e.printStackTrace();
156
+ }
157
+ }
158
+
159
+ channel = null;
160
+ }
161
+
162
+ public void scheduleOutboundData (ByteBuffer bb) {
163
+ if (!bCloseScheduled && bb.remaining() > 0) {
164
+ if (sslEngine != null) {
165
+ try {
166
+ ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer.
167
+ sslEngine.wrap(bb, b);
168
+ b.flip();
169
+ outboundQ.addLast(b);
170
+ outboundS += b.remaining();
171
+ } catch (SSLException e) {
172
+ throw new RuntimeException ("ssl error");
173
+ }
174
+ }
175
+ else {
176
+ outboundQ.addLast(bb);
177
+ outboundS += bb.remaining();
178
+ }
179
+
180
+ updateEvents();
181
+ }
182
+ }
183
+
184
+ public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
185
+ throw new RuntimeException ("datagram sends not supported on this channel");
186
+ }
187
+
188
+ /**
189
+ * Called by the reactor when we have selected readable.
190
+ */
191
+ public void readInboundData (ByteBuffer bb) throws IOException {
192
+ if (channel.read(bb) == -1)
193
+ throw new IOException ("eof");
194
+ }
195
+
196
+ public long getOutboundDataSize() { return outboundS; }
197
+
198
+ /**
199
+ * Called by the reactor when we have selected writable.
200
+ * Return false to indicate an error that should cause the connection to close.
201
+ * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
202
+ * possible to become unwritable between the poll and when we get here. The way
203
+ * this code is written, we're depending on a nonblocking write NOT TO CONSUME
204
+ * the whole outbound buffer in this case, rather than firing an exception.
205
+ * We should somehow verify that this is indeed Java's defined behavior.
206
+ * @return
207
+ */
208
+ public boolean writeOutboundData() throws IOException {
209
+ ByteBuffer[] bufs = new ByteBuffer[64];
210
+ int i;
211
+ long written, toWrite;
212
+ while (!outboundQ.isEmpty()) {
213
+ i = 0;
214
+ toWrite = 0;
215
+ written = 0;
216
+ while (i < 64 && !outboundQ.isEmpty()) {
217
+ bufs[i] = outboundQ.removeFirst();
218
+ toWrite += bufs[i].remaining();
219
+ i++;
220
+ }
221
+ if (toWrite > 0)
222
+ written = channel.write(bufs, 0, i);
223
+
224
+ outboundS -= written;
225
+ // Did we consume the whole outbound buffer? If yes,
226
+ // pop it off and keep looping. If no, the outbound network
227
+ // buffers are full, so break out of here.
228
+ if (written < toWrite) {
229
+ while (i > 0 && bufs[i-1].remaining() > 0) {
230
+ outboundQ.addFirst(bufs[i-1]);
231
+ i--;
232
+ }
233
+ break;
234
+ }
235
+ }
236
+
237
+ if (outboundQ.isEmpty() && !bCloseScheduled) {
238
+ updateEvents();
239
+ }
240
+
241
+ // ALWAYS drain the outbound queue before triggering a connection close.
242
+ // If anyone wants to close immediately, they're responsible for clearing
243
+ // the outbound queue.
244
+ return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
245
+ }
246
+
247
+ public void setConnectPending() {
248
+ bConnectPending = true;
249
+ updateEvents();
250
+ }
251
+
252
+ /**
253
+ * Called by the reactor when we have selected connectable.
254
+ * Return false to indicate an error that should cause the connection to close.
255
+ */
256
+ public boolean finishConnecting() throws IOException {
257
+ channel.finishConnect();
258
+
259
+ bConnectPending = false;
260
+ updateEvents();
261
+ return true;
262
+ }
263
+
264
+ public boolean scheduleClose (boolean afterWriting) {
265
+ // TODO: What the hell happens here if bConnectPending is set?
266
+ if (!afterWriting) {
267
+ outboundQ.clear();
268
+ outboundS = 0;
269
+ }
270
+
271
+ if (outboundQ.isEmpty())
272
+ return true;
273
+ else {
274
+ updateEvents();
275
+ bCloseScheduled = true;
276
+ return false;
277
+ }
278
+ }
279
+
280
+ public void startTls() {
281
+ if (sslEngine == null) {
282
+ try {
283
+ sslContext = SSLContext.getInstance("TLS");
284
+ sslContext.init(null, null, null); // TODO, fill in the parameters.
285
+ sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use.
286
+ sslEngine.setUseClientMode(false);
287
+ } catch (NoSuchAlgorithmException e) {
288
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
289
+ } catch (KeyManagementException e) {
290
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
291
+ }
292
+ }
293
+ System.out.println ("Starting TLS");
294
+ }
295
+
296
+ public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException {
297
+ if (sslEngine != null) {
298
+ if (true) throw new RuntimeException ("TLS currently unimplemented");
299
+ System.setProperty("javax.net.debug", "all");
300
+ ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer.
301
+ SSLEngineResult res = sslEngine.unwrap(bb, w);
302
+ if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
303
+ Runnable r;
304
+ while ((r = sslEngine.getDelegatedTask()) != null) {
305
+ r.run();
306
+ }
307
+ }
308
+ System.out.println (bb);
309
+ w.flip();
310
+ return w;
311
+ }
312
+ else
313
+ return bb;
314
+ }
315
+
316
+ public void setCommInactivityTimeout (long seconds) {
317
+ // TODO
318
+ System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
319
+ }
320
+
321
+ public Object[] getPeerName () {
322
+ Socket sock = channel.socket();
323
+ return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
324
+ }
325
+
326
+ public Object[] getSockName () {
327
+ Socket sock = channel.socket();
328
+ return new Object[]{ sock.getLocalPort(),
329
+ sock.getLocalAddress().getHostAddress() };
330
+ }
331
+
332
+ public void setWatchOnly() {
333
+ bWatchOnly = true;
334
+ updateEvents();
335
+ }
336
+ public boolean isWatchOnly() { return bWatchOnly; }
337
+
338
+ public void setAttached() {
339
+ bAttached = true;
340
+ }
341
+ public boolean isAttached() { return bAttached; }
342
+
343
+ public void setNotifyReadable (boolean mode) {
344
+ bNotifyReadable = mode;
345
+ updateEvents();
346
+ }
347
+ public boolean isNotifyReadable() { return bNotifyReadable; }
348
+
349
+ public void setNotifyWritable (boolean mode) {
350
+ bNotifyWritable = mode;
351
+ updateEvents();
352
+ }
353
+ public boolean isNotifyWritable() { return bNotifyWritable; }
354
+
355
+ public boolean pause() {
356
+ if (bWatchOnly) {
357
+ throw new RuntimeException ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
358
+ }
359
+ boolean old = bPaused;
360
+ bPaused = true;
361
+ updateEvents();
362
+ return !old;
363
+ }
364
+
365
+ public boolean resume() {
366
+ if (bWatchOnly) {
367
+ throw new RuntimeException ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
368
+ }
369
+ boolean old = bPaused;
370
+ bPaused = false;
371
+ updateEvents();
372
+ return old;
373
+ }
374
+
375
+ public boolean isPaused() {
376
+ return bPaused;
377
+ }
378
+
379
+ private void updateEvents() {
380
+ if (channelKey == null)
381
+ return;
382
+
383
+ int events = currentEvents();
384
+
385
+ if (channelKey.interestOps() != events) {
386
+ channelKey.interestOps(events);
387
+ }
388
+ }
389
+
390
+ private int currentEvents() {
391
+ int events = 0;
392
+
393
+ if (bWatchOnly)
394
+ {
395
+ if (bNotifyReadable)
396
+ events |= SelectionKey.OP_READ;
397
+
398
+ if (bNotifyWritable)
399
+ events |= SelectionKey.OP_WRITE;
400
+ }
401
+ else if (!bPaused)
402
+ {
403
+ if (bConnectPending)
404
+ events |= SelectionKey.OP_CONNECT;
405
+ else {
406
+ events |= SelectionKey.OP_READ;
407
+
408
+ if (!outboundQ.isEmpty())
409
+ events |= SelectionKey.OP_WRITE;
410
+ }
411
+ }
412
+
413
+ return events;
414
+ }
415
+ }
@@ -0,0 +1,157 @@
1
+ package com.rubyeventmachine;
2
+
3
+ import java.io.IOException;
4
+ import java.net.InetSocketAddress;
5
+ import java.net.SocketAddress;
6
+ import java.nio.ByteBuffer;
7
+ import java.nio.channels.SocketChannel;
8
+ import java.security.KeyManagementException;
9
+ import java.security.NoSuchAlgorithmException;
10
+
11
+ public class NullEmReactor implements EmReactorInterface
12
+ {
13
+ public void eventCallback(long sig, int eventType, ByteBuffer data, long data2)
14
+ {
15
+
16
+ }
17
+
18
+ public void eventCallback(long sig, int eventType, ByteBuffer data)
19
+ {
20
+
21
+ }
22
+
23
+ public void run()
24
+ {
25
+
26
+ }
27
+
28
+ public void stop()
29
+ {
30
+
31
+ }
32
+
33
+ public long installOneshotTimer(long milliseconds)
34
+ {
35
+ return 0;
36
+ }
37
+
38
+ public long startTcpServer(SocketAddress sa) throws EmReactorException
39
+ {
40
+ return 0;
41
+ }
42
+
43
+ public long startTcpServer(String address, int port) throws EmReactorException
44
+ {
45
+ return 0;
46
+ }
47
+
48
+ public void stopTcpServer(long signature) throws IOException
49
+ {
50
+
51
+ }
52
+
53
+ public long openUdpSocket(InetSocketAddress address) throws IOException
54
+ {
55
+ return 0;
56
+ }
57
+
58
+ public long openUdpSocket(String address, int port) throws IOException
59
+ {
60
+ return 0;
61
+ }
62
+
63
+ public void sendData(long sig, ByteBuffer bb) throws IOException
64
+ {
65
+
66
+ }
67
+
68
+ public void sendData(long sig, byte[] data) throws IOException
69
+ {
70
+
71
+ }
72
+
73
+ public void setCommInactivityTimeout(long sig, long mills)
74
+ {
75
+
76
+ }
77
+
78
+ public void sendDatagram(long sig, byte[] data, int length, String recipAddress, int recipPort)
79
+ {
80
+
81
+ }
82
+
83
+ public void sendDatagram(long sig, ByteBuffer bb, String recipAddress, int recipPort)
84
+ {
85
+
86
+ }
87
+
88
+ public long connectTcpServer(String address, int port)
89
+ {
90
+ return 0;
91
+ }
92
+
93
+ public long connectTcpServer(String bindAddr, int bindPort, String address, int port)
94
+ {
95
+ return 0;
96
+ }
97
+
98
+ public void closeConnection(long sig, boolean afterWriting)
99
+ {
100
+
101
+ }
102
+
103
+ public void signalLoopbreak()
104
+ {
105
+
106
+ }
107
+
108
+ public void startTls(long sig) throws NoSuchAlgorithmException, KeyManagementException
109
+ {
110
+
111
+ }
112
+
113
+ public void setTimerQuantum(int mills)
114
+ {
115
+
116
+ }
117
+
118
+ public Object[] getPeerName(long sig)
119
+ {
120
+ return new Object[0];
121
+ }
122
+
123
+ public long attachChannel(SocketChannel sc, boolean watch_mode)
124
+ {
125
+ return 0;
126
+ }
127
+
128
+ public SocketChannel detachChannel(long sig)
129
+ {
130
+ return null;
131
+ }
132
+
133
+ public void setNotifyReadable(long sig, boolean mode)
134
+ {
135
+
136
+ }
137
+
138
+ public void setNotifyWritable(long sig, boolean mode)
139
+ {
140
+
141
+ }
142
+
143
+ public boolean isNotifyReadable(long sig)
144
+ {
145
+ return false;
146
+ }
147
+
148
+ public boolean isNotifyWritable(long sig)
149
+ {
150
+ return false;
151
+ }
152
+
153
+ public int getConnectionCount()
154
+ {
155
+ return 0;
156
+ }
157
+ }
@@ -0,0 +1,81 @@
1
+ package com.rubyeventmachine;
2
+
3
+ import java.io.IOException;
4
+ import java.nio.ByteBuffer;
5
+ import java.nio.channels.ClosedChannelException;
6
+
7
+ public class NullEventableChannel implements EventableChannel
8
+ {
9
+ public void scheduleOutboundData(ByteBuffer bb)
10
+ {
11
+ }
12
+
13
+ public void scheduleOutboundDatagram(ByteBuffer bb, String recipAddress, int recipPort)
14
+ {
15
+ }
16
+
17
+ public boolean scheduleClose(boolean afterWriting)
18
+ {
19
+ return false;
20
+ }
21
+
22
+ public void startTls()
23
+ {
24
+ }
25
+
26
+ public long getBinding()
27
+ {
28
+ return 0;
29
+ }
30
+
31
+ public void readInboundData(ByteBuffer dst) throws IOException
32
+ {
33
+ }
34
+
35
+ public void register() throws ClosedChannelException
36
+ {
37
+ }
38
+
39
+ public void close()
40
+ {
41
+ }
42
+
43
+ public boolean writeOutboundData() throws IOException
44
+ {
45
+ return false;
46
+ }
47
+
48
+ public void setCommInactivityTimeout(long seconds)
49
+ {
50
+ }
51
+
52
+ public Object[] getPeerName()
53
+ {
54
+ return new Object[0];
55
+ }
56
+
57
+ public Object[] getSockName()
58
+ {
59
+ return new Object[0];
60
+ }
61
+
62
+ public boolean isWatchOnly()
63
+ {
64
+ return false;
65
+ }
66
+
67
+ public boolean isNotifyReadable()
68
+ {
69
+ return false;
70
+ }
71
+
72
+ public boolean isNotifyWritable()
73
+ {
74
+ return false;
75
+ }
76
+
77
+ public long getOutboundDataSize ()
78
+ {
79
+ return 0;
80
+ }
81
+ }
data/lib/em/buftok.rb ADDED
@@ -0,0 +1,59 @@
1
+ # BufferedTokenizer takes a delimiter upon instantiation, or acts line-based
2
+ # by default. It allows input to be spoon-fed from some outside source which
3
+ # receives arbitrary length datagrams which may-or-may-not contain the token
4
+ # by which entities are delimited. In this respect it's ideally paired with
5
+ # something like EventMachine (http://rubyeventmachine.com/).
6
+ class BufferedTokenizer
7
+ # New BufferedTokenizers will operate on lines delimited by a delimiter,
8
+ # which is by default the global input delimiter $/ ("\n").
9
+ #
10
+ # The input buffer is stored as an array. This is by far the most efficient
11
+ # approach given language constraints (in C a linked list would be a more
12
+ # appropriate data structure). Segments of input data are stored in a list
13
+ # which is only joined when a token is reached, substantially reducing the
14
+ # number of objects required for the operation.
15
+ def initialize(delimiter = $/)
16
+ @delimiter = delimiter
17
+ @input = []
18
+ @tail = ''
19
+ @trim = @delimiter.length - 1
20
+ end
21
+
22
+ # Extract takes an arbitrary string of input data and returns an array of
23
+ # tokenized entities, provided there were any available to extract. This
24
+ # makes for easy processing of datagrams using a pattern like:
25
+ #
26
+ # tokenizer.extract(data).map { |entity| Decode(entity) }.each do ...
27
+ #
28
+ # Using -1 makes split to return "" if the token is at the end of
29
+ # the string, meaning the last element is the start of the next chunk.
30
+ def extract(data)
31
+ if @trim > 0
32
+ tail_end = @tail.slice!(-@trim, @trim) # returns nil if string is too short
33
+ data = tail_end + data if tail_end
34
+ end
35
+
36
+ @input << @tail
37
+ entities = data.split(@delimiter, -1)
38
+ @tail = entities.shift
39
+
40
+ unless entities.empty?
41
+ @input << @tail
42
+ entities.unshift @input.join
43
+ @input.clear
44
+ @tail = entities.pop
45
+ end
46
+
47
+ entities
48
+ end
49
+
50
+ # Flush the contents of the input buffer, i.e. return the input buffer even though
51
+ # a token has not yet been encountered
52
+ def flush
53
+ @input << @tail
54
+ buffer = @input.join
55
+ @input.clear
56
+ @tail = "" # @tail.clear is slightly faster, but not supported on 1.8.7
57
+ buffer
58
+ end
59
+ end