sonixlabs-eventmachine-java 1.0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +7 -0
  5. data/CHANGELOG.md +33 -0
  6. data/GNU +281 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +60 -0
  9. data/README.md +109 -0
  10. data/README_JP.md +18 -0
  11. data/Rakefile +20 -0
  12. data/docs/DocumentationGuidesIndex.md +27 -0
  13. data/docs/GettingStarted.md +521 -0
  14. data/docs/old/ChangeLog +211 -0
  15. data/docs/old/DEFERRABLES +246 -0
  16. data/docs/old/EPOLL +141 -0
  17. data/docs/old/INSTALL +13 -0
  18. data/docs/old/KEYBOARD +42 -0
  19. data/docs/old/LEGAL +25 -0
  20. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  21. data/docs/old/PURE_RUBY +75 -0
  22. data/docs/old/RELEASE_NOTES +94 -0
  23. data/docs/old/SMTP +4 -0
  24. data/docs/old/SPAWNED_PROCESSES +148 -0
  25. data/docs/old/TODO +8 -0
  26. data/eventmachine.gemspec +38 -0
  27. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  28. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  29. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  30. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  31. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  32. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  33. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  34. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  35. data/examples/old/ex_channel.rb +43 -0
  36. data/examples/old/ex_queue.rb +2 -0
  37. data/examples/old/ex_tick_loop_array.rb +15 -0
  38. data/examples/old/ex_tick_loop_counter.rb +32 -0
  39. data/examples/old/helper.rb +2 -0
  40. data/ext/binder.cpp +124 -0
  41. data/ext/binder.h +46 -0
  42. data/ext/cmain.cpp +887 -0
  43. data/ext/ed.cpp +1988 -0
  44. data/ext/ed.h +422 -0
  45. data/ext/em.cpp +2351 -0
  46. data/ext/em.h +244 -0
  47. data/ext/eventmachine.h +128 -0
  48. data/ext/extconf.rb +177 -0
  49. data/ext/fastfilereader/extconf.rb +103 -0
  50. data/ext/fastfilereader/mapper.cpp +214 -0
  51. data/ext/fastfilereader/mapper.h +59 -0
  52. data/ext/fastfilereader/rubymain.cpp +127 -0
  53. data/ext/kb.cpp +79 -0
  54. data/ext/page.cpp +107 -0
  55. data/ext/page.h +51 -0
  56. data/ext/pipe.cpp +347 -0
  57. data/ext/project.h +156 -0
  58. data/ext/rubymain.cpp +1318 -0
  59. data/ext/ssl.cpp +468 -0
  60. data/ext/ssl.h +94 -0
  61. data/java/.classpath +6 -0
  62. data/java/.gitignore +1 -0
  63. data/java/.project +17 -0
  64. data/java/src/com/rubyeventmachine/DatagramPacket.java +13 -0
  65. data/java/src/com/rubyeventmachine/EmReactor.java +529 -0
  66. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  67. data/java/src/com/rubyeventmachine/EventCallback.java +7 -0
  68. data/java/src/com/rubyeventmachine/EventCode.java +26 -0
  69. data/java/src/com/rubyeventmachine/EventableChannel.java +130 -0
  70. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +180 -0
  71. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +405 -0
  72. data/java/src/com/rubyeventmachine/SslBox.java +310 -0
  73. data/lib/em/buftok.rb +110 -0
  74. data/lib/em/callback.rb +58 -0
  75. data/lib/em/channel.rb +64 -0
  76. data/lib/em/completion.rb +304 -0
  77. data/lib/em/connection.rb +712 -0
  78. data/lib/em/deferrable.rb +210 -0
  79. data/lib/em/deferrable/pool.rb +2 -0
  80. data/lib/em/file_watch.rb +73 -0
  81. data/lib/em/future.rb +61 -0
  82. data/lib/em/iterator.rb +231 -0
  83. data/lib/em/messages.rb +66 -0
  84. data/lib/em/pool.rb +151 -0
  85. data/lib/em/process_watch.rb +45 -0
  86. data/lib/em/processes.rb +123 -0
  87. data/lib/em/protocols.rb +37 -0
  88. data/lib/em/protocols/header_and_content.rb +138 -0
  89. data/lib/em/protocols/httpclient.rb +279 -0
  90. data/lib/em/protocols/httpclient2.rb +600 -0
  91. data/lib/em/protocols/line_and_text.rb +125 -0
  92. data/lib/em/protocols/line_protocol.rb +29 -0
  93. data/lib/em/protocols/linetext2.rb +161 -0
  94. data/lib/em/protocols/memcache.rb +331 -0
  95. data/lib/em/protocols/object_protocol.rb +46 -0
  96. data/lib/em/protocols/postgres3.rb +246 -0
  97. data/lib/em/protocols/saslauth.rb +175 -0
  98. data/lib/em/protocols/smtpclient.rb +365 -0
  99. data/lib/em/protocols/smtpserver.rb +643 -0
  100. data/lib/em/protocols/socks4.rb +66 -0
  101. data/lib/em/protocols/stomp.rb +205 -0
  102. data/lib/em/protocols/tcptest.rb +54 -0
  103. data/lib/em/pure_ruby.rb +1017 -0
  104. data/lib/em/queue.rb +71 -0
  105. data/lib/em/resolver.rb +192 -0
  106. data/lib/em/spawnable.rb +84 -0
  107. data/lib/em/streamer.rb +118 -0
  108. data/lib/em/threaded_resource.rb +90 -0
  109. data/lib/em/tick_loop.rb +85 -0
  110. data/lib/em/timers.rb +61 -0
  111. data/lib/em/version.rb +3 -0
  112. data/lib/eventmachine.rb +1553 -0
  113. data/lib/jeventmachine.rb +331 -0
  114. data/lib/sonixlabs-eventmachine-java.rb +1 -0
  115. data/rakelib/cpp.rake_example +77 -0
  116. data/rakelib/package.rake +96 -0
  117. data/rakelib/test.rake +8 -0
  118. data/tests/client.crt +31 -0
  119. data/tests/client.key +51 -0
  120. data/tests/em_test_helper.rb +64 -0
  121. data/tests/server.crt +36 -0
  122. data/tests/server.key +51 -0
  123. data/tests/test_attach.rb +150 -0
  124. data/tests/test_basic.rb +294 -0
  125. data/tests/test_channel.rb +62 -0
  126. data/tests/test_completion.rb +177 -0
  127. data/tests/test_connection_count.rb +53 -0
  128. data/tests/test_defer.rb +18 -0
  129. data/tests/test_deferrable.rb +35 -0
  130. data/tests/test_epoll.rb +145 -0
  131. data/tests/test_error_handler.rb +38 -0
  132. data/tests/test_exc.rb +28 -0
  133. data/tests/test_file_watch.rb +65 -0
  134. data/tests/test_futures.rb +170 -0
  135. data/tests/test_get_sock_opt.rb +37 -0
  136. data/tests/test_handler_check.rb +35 -0
  137. data/tests/test_hc.rb +155 -0
  138. data/tests/test_httpclient.rb +190 -0
  139. data/tests/test_httpclient2.rb +133 -0
  140. data/tests/test_idle_connection.rb +25 -0
  141. data/tests/test_inactivity_timeout.rb +54 -0
  142. data/tests/test_iterator.rb +97 -0
  143. data/tests/test_kb.rb +34 -0
  144. data/tests/test_line_protocol.rb +33 -0
  145. data/tests/test_ltp.rb +138 -0
  146. data/tests/test_ltp2.rb +288 -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 +102 -0
  150. data/tests/test_pending_connect_timeout.rb +52 -0
  151. data/tests/test_pool.rb +194 -0
  152. data/tests/test_process_watch.rb +48 -0
  153. data/tests/test_processes.rb +128 -0
  154. data/tests/test_proxy_connection.rb +180 -0
  155. data/tests/test_pure.rb +88 -0
  156. data/tests/test_queue.rb +50 -0
  157. data/tests/test_resolver.rb +55 -0
  158. data/tests/test_running.rb +14 -0
  159. data/tests/test_sasl.rb +47 -0
  160. data/tests/test_send_file.rb +217 -0
  161. data/tests/test_servers.rb +33 -0
  162. data/tests/test_set_sock_opt.rb +37 -0
  163. data/tests/test_shutdown_hooks.rb +23 -0
  164. data/tests/test_smtpclient.rb +55 -0
  165. data/tests/test_smtpserver.rb +57 -0
  166. data/tests/test_spawn.rb +293 -0
  167. data/tests/test_ssl_args.rb +78 -0
  168. data/tests/test_ssl_echo_data.rb +60 -0
  169. data/tests/test_ssl_methods.rb +56 -0
  170. data/tests/test_ssl_verify.rb +82 -0
  171. data/tests/test_stomp.rb +37 -0
  172. data/tests/test_system.rb +42 -0
  173. data/tests/test_threaded_resource.rb +53 -0
  174. data/tests/test_tick_loop.rb +59 -0
  175. data/tests/test_timers.rb +123 -0
  176. data/tests/test_ud.rb +8 -0
  177. data/tests/test_unbind_reason.rb +48 -0
  178. metadata +298 -0
@@ -0,0 +1,94 @@
1
+ /*****************************************************************************
2
+
3
+ $Id$
4
+
5
+ File: ssl.h
6
+ Date: 30Apr06
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 __SslBox__H_
22
+ #define __SslBox__H_
23
+
24
+
25
+
26
+
27
+ #ifdef WITH_SSL
28
+
29
+ /******************
30
+ class SslContext_t
31
+ ******************/
32
+
33
+ class SslContext_t
34
+ {
35
+ public:
36
+ SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile);
37
+ virtual ~SslContext_t();
38
+
39
+ private:
40
+ static bool bLibraryInitialized;
41
+
42
+ private:
43
+ bool bIsServer;
44
+ SSL_CTX *pCtx;
45
+
46
+ EVP_PKEY *PrivateKey;
47
+ X509 *Certificate;
48
+
49
+ friend class SslBox_t;
50
+ };
51
+
52
+
53
+ /**************
54
+ class SslBox_t
55
+ **************/
56
+
57
+ class SslBox_t
58
+ {
59
+ public:
60
+ SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const unsigned long binding);
61
+ virtual ~SslBox_t();
62
+
63
+ int PutPlaintext (const char*, int);
64
+ int GetPlaintext (char*, int);
65
+
66
+ bool PutCiphertext (const char*, int);
67
+ bool CanGetCiphertext();
68
+ int GetCiphertext (char*, int);
69
+ bool IsHandshakeCompleted() {return bHandshakeCompleted;}
70
+
71
+ X509 *GetPeerCert();
72
+
73
+ void Shutdown();
74
+
75
+ protected:
76
+ SslContext_t *Context;
77
+
78
+ bool bIsServer;
79
+ bool bHandshakeCompleted;
80
+ bool bVerifyPeer;
81
+ SSL *pSSL;
82
+ BIO *pbioRead;
83
+ BIO *pbioWrite;
84
+
85
+ PageList OutboundQ;
86
+ };
87
+
88
+ extern "C" int ssl_verify_wrapper(int, X509_STORE_CTX*);
89
+
90
+ #endif // WITH_SSL
91
+
92
+
93
+ #endif // __SslBox__H_
94
+
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <classpath>
3
+ <classpathentry kind="src" path="src"/>
4
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
5
+ <classpathentry kind="output" path="bin"/>
6
+ </classpath>
@@ -0,0 +1 @@
1
+ /bin
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>em_reactor</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>org.eclipse.jdt.core.javanature</nature>
16
+ </natures>
17
+ </projectDescription>
@@ -0,0 +1,13 @@
1
+ package com.rubyeventmachine;
2
+
3
+ import java.net.SocketAddress;
4
+ import java.nio.ByteBuffer;
5
+
6
+ class DatagramPacket {
7
+ public ByteBuffer bb;
8
+ public SocketAddress recipient;
9
+ public DatagramPacket (ByteBuffer _bb, SocketAddress _recipient) {
10
+ bb = _bb;
11
+ recipient = _recipient;
12
+ }
13
+ }
@@ -0,0 +1,529 @@
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
+ package com.rubyeventmachine;
30
+
31
+ import java.io.IOException;
32
+ import java.net.InetSocketAddress;
33
+ import java.net.SocketAddress;
34
+ import java.nio.ByteBuffer;
35
+ import java.nio.channels.ClosedChannelException;
36
+ import java.nio.channels.DatagramChannel;
37
+ import java.nio.channels.SelectionKey;
38
+ import java.nio.channels.Selector;
39
+ import java.nio.channels.ServerSocketChannel;
40
+ import java.nio.channels.SocketChannel;
41
+ import java.security.KeyManagementException;
42
+ import java.security.KeyStore;
43
+ import java.security.NoSuchAlgorithmException;
44
+ import java.util.ArrayList;
45
+ import java.util.Date;
46
+ import java.util.HashMap;
47
+ import java.util.Iterator;
48
+ import java.util.TreeMap;
49
+ import java.util.concurrent.atomic.AtomicBoolean;
50
+
51
+ public class EmReactor {
52
+ private Selector mySelector;
53
+ private TreeMap<Long, ArrayList<Long>> Timers;
54
+ private HashMap<Long, EventableChannel<?>> Connections;
55
+ private HashMap<Long, ServerSocketChannel> Acceptors;
56
+ private ArrayList<Long> NewConnections;
57
+ private ArrayList<Long> UnboundConnections;
58
+ private ArrayList<EventableSocketChannel> DetachedConnections;
59
+
60
+ private boolean bRunReactor;
61
+ private long BindingIndex;
62
+ private AtomicBoolean loopBreaker;
63
+ private int timerQuantum;
64
+ private EventCallback callback;
65
+
66
+ public EmReactor(EventCallback callback) {
67
+ this.callback = callback;
68
+ Timers = new TreeMap<Long, ArrayList<Long>>();
69
+ Connections = new HashMap<Long, EventableChannel<?>>();
70
+ Acceptors = new HashMap<Long, ServerSocketChannel>();
71
+ NewConnections = new ArrayList<Long>();
72
+ UnboundConnections = new ArrayList<Long>();
73
+ DetachedConnections = new ArrayList<EventableSocketChannel>();
74
+
75
+ BindingIndex = 0;
76
+ loopBreaker = new AtomicBoolean();
77
+ loopBreaker.set(false);
78
+ timerQuantum = 98;
79
+ }
80
+
81
+ public void run() {
82
+ try {
83
+ mySelector = Selector.open();
84
+ bRunReactor = true;
85
+ } catch (IOException e) {
86
+ throw new RuntimeException ("Could not open selector", e);
87
+ }
88
+
89
+ while (bRunReactor) {
90
+ runLoopbreaks();
91
+ if (!bRunReactor) break;
92
+
93
+ runTimers();
94
+ if (!bRunReactor) break;
95
+
96
+ removeUnboundConnections();
97
+ checkIO();
98
+ addNewConnections();
99
+ processIO();
100
+ }
101
+
102
+ close();
103
+ }
104
+
105
+ void addNewConnections() {
106
+ for (EventableSocketChannel ec : DetachedConnections) {
107
+ ec.cleanup();
108
+ }
109
+ DetachedConnections.clear();
110
+
111
+ for (long b : NewConnections) {
112
+ EventableChannel<?> ec = Connections.get(b);
113
+ if (ec != null) {
114
+ try {
115
+ ec.register();
116
+ } catch (ClosedChannelException e) {
117
+ UnboundConnections.add (ec.getBinding());
118
+ }
119
+ }
120
+ }
121
+ NewConnections.clear();
122
+ }
123
+
124
+ void removeUnboundConnections() {
125
+ for (long b : UnboundConnections) {
126
+ EventableChannel<?> ec = Connections.remove(b);
127
+ if (ec != null) {
128
+ callback.trigger(b, EventCode.EM_CONNECTION_UNBOUND, null, (long) 0);
129
+ ec.close();
130
+
131
+ EventableSocketChannel sc = (EventableSocketChannel) ec;
132
+ if (sc != null && sc.isAttached())
133
+ DetachedConnections.add (sc);
134
+ }
135
+ }
136
+ UnboundConnections.clear();
137
+ }
138
+
139
+ void checkIO() {
140
+ long timeout;
141
+
142
+ if (NewConnections.size() > 0) {
143
+ timeout = -1;
144
+ } else if (!Timers.isEmpty()) {
145
+ long now = new Date().getTime();
146
+ long k = Timers.firstKey();
147
+ long diff = k-now;
148
+
149
+ if (diff <= 0)
150
+ timeout = -1; // don't wait, just poll once
151
+ else
152
+ timeout = diff;
153
+ } else {
154
+ timeout = 0; // wait indefinitely
155
+ }
156
+
157
+ try {
158
+ if (timeout == -1)
159
+ mySelector.selectNow();
160
+ else
161
+ mySelector.select(timeout);
162
+ } catch (IOException e) {
163
+ e.printStackTrace();
164
+ }
165
+ }
166
+
167
+ void processIO() {
168
+ Iterator<SelectionKey> it = mySelector.selectedKeys().iterator();
169
+ while (it.hasNext()) {
170
+ SelectionKey k = it.next();
171
+ it.remove();
172
+ if (k.isConnectable()) {
173
+ isConnectable(k);
174
+ }
175
+ else if (k.isAcceptable()) {
176
+ isAcceptable(k);
177
+ }
178
+ else {
179
+ if (k.isWritable())
180
+ isWritable(k);
181
+
182
+ if (k.isReadable())
183
+ isReadable(k);
184
+ }
185
+ }
186
+ }
187
+
188
+ void isAcceptable (SelectionKey k) {
189
+ ServerSocketChannel ss = (ServerSocketChannel) k.channel();
190
+ SocketChannel sn;
191
+ long b;
192
+
193
+ for (int n = 0; n < 10; n++) {
194
+ try {
195
+ sn = ss.accept();
196
+ if (sn == null)
197
+ break;
198
+ } catch (IOException e) {
199
+ e.printStackTrace();
200
+ k.cancel();
201
+
202
+ ServerSocketChannel server = Acceptors.remove(k.attachment());
203
+ if (server != null)
204
+ try{ server.close(); } catch (IOException ex) {};
205
+ break;
206
+ }
207
+
208
+ try {
209
+ sn.configureBlocking(false);
210
+ } catch (IOException e) {
211
+ e.printStackTrace();
212
+ continue;
213
+ }
214
+
215
+ b = createBinding();
216
+ EventableSocketChannel ec = new EventableSocketChannel (sn, b, mySelector, callback);
217
+ ec.setServerMode();
218
+ Connections.put (b, ec);
219
+ NewConnections.add (b);
220
+
221
+ callback.trigger(((Long)k.attachment()).longValue(), EventCode.EM_CONNECTION_ACCEPTED, null, b);
222
+ }
223
+ }
224
+
225
+ void isReadable (SelectionKey k) {
226
+ EventableChannel<?> ec = (EventableChannel<?>) k.attachment();
227
+ if (!ec.read()) {
228
+ UnboundConnections.add (ec.getBinding());
229
+ }
230
+ }
231
+
232
+ void isWritable (SelectionKey k) {
233
+ EventableChannel<?> ec = (EventableChannel<?>) k.attachment();
234
+ if (!ec.write()) {
235
+ UnboundConnections.add (ec.getBinding());
236
+ }
237
+ }
238
+
239
+ void isConnectable (SelectionKey k) {
240
+ EventableSocketChannel ec = (EventableSocketChannel) k.attachment();
241
+ if (!ec.finishConnecting()) {
242
+ UnboundConnections.add (ec.getBinding());
243
+ }
244
+ }
245
+
246
+ void close() {
247
+ try {
248
+ if (mySelector != null)
249
+ mySelector.close();
250
+ } catch (IOException e) {}
251
+ mySelector = null;
252
+
253
+ // run down open connections and sockets.
254
+ for (ServerSocketChannel c : Acceptors.values()) {
255
+ try {
256
+ c.close();
257
+ } catch (IOException e) {}
258
+ }
259
+
260
+ // 29Sep09: We create an ArrayList of the existing connections, then iterate over
261
+ // that to call unbind on them. This is because an unbind can trigger a reconnect,
262
+ // which will add to the Connections HashMap, causing a ConcurrentModificationException.
263
+ // XXX: The correct behavior here would be to latch the various reactor methods to return
264
+ // immediately if the reactor is shutting down.
265
+ ArrayList<EventableChannel<?>> conns = new ArrayList<EventableChannel<?>>();
266
+ for (EventableChannel<?> ec : Connections.values()) {
267
+ if (ec != null) {
268
+ conns.add (ec);
269
+ }
270
+ }
271
+ Connections.clear();
272
+
273
+ for (EventableChannel<?> ec : conns) {
274
+ callback.trigger(ec.getBinding(), EventCode.EM_CONNECTION_UNBOUND, null, (long) 0);
275
+ ec.close();
276
+
277
+ EventableSocketChannel sc = (EventableSocketChannel) ec;
278
+ if (sc != null && sc.isAttached())
279
+ DetachedConnections.add (sc);
280
+ }
281
+
282
+ for (EventableSocketChannel ec : DetachedConnections) {
283
+ ec.cleanup();
284
+ }
285
+ DetachedConnections.clear();
286
+ }
287
+
288
+ void runLoopbreaks() {
289
+ if (loopBreaker.getAndSet(false)) {
290
+ callback.trigger((long) 0, EventCode.EM_LOOPBREAK_SIGNAL, null, (long) 0);
291
+ }
292
+ }
293
+
294
+ public void stop() {
295
+ bRunReactor = false;
296
+ signalLoopbreak();
297
+ }
298
+
299
+ void runTimers() {
300
+ long now = new Date().getTime();
301
+ while (!Timers.isEmpty()) {
302
+ long k = Timers.firstKey();
303
+ if (k > now)
304
+ break;
305
+
306
+ ArrayList<Long> callbacks = Timers.get(k);
307
+ Timers.remove(k);
308
+
309
+ // Fire all timers at this timestamp
310
+ for (long timerCallback : callbacks) {
311
+ callback.trigger((long) 0, EventCode.EM_TIMER_FIRED, null, timerCallback);
312
+ }
313
+ }
314
+ }
315
+
316
+ public long installOneshotTimer (int milliseconds) {
317
+ long s = createBinding();
318
+ long deadline = new Date().getTime() + milliseconds;
319
+
320
+ if (Timers.containsKey(deadline)) {
321
+ Timers.get(deadline).add(s);
322
+ } else {
323
+ ArrayList<Long> callbacks = new ArrayList<Long>();
324
+ callbacks.add(s);
325
+ Timers.put(deadline, callbacks);
326
+ }
327
+
328
+ return s;
329
+ }
330
+
331
+ public long startTcpServer (SocketAddress sa) throws EmReactorException {
332
+ try {
333
+ ServerSocketChannel server = ServerSocketChannel.open();
334
+ server.configureBlocking(false);
335
+ server.socket().bind (sa);
336
+ long s = createBinding();
337
+ Acceptors.put(s, server);
338
+ server.register(mySelector, SelectionKey.OP_ACCEPT, s);
339
+ return s;
340
+ } catch (IOException e) {
341
+ throw new EmReactorException ("unable to open socket acceptor: " + e.toString());
342
+ }
343
+ }
344
+
345
+ public long startTcpServer (String address, int port) throws EmReactorException {
346
+ return startTcpServer (new InetSocketAddress (address, port));
347
+ }
348
+
349
+ public void stopTcpServer (long signature) throws IOException {
350
+ ServerSocketChannel server = Acceptors.remove(signature);
351
+ if (server != null)
352
+ server.close();
353
+ else
354
+ throw new RuntimeException ("failed to close unknown acceptor");
355
+ }
356
+
357
+ public long openUdpSocket (InetSocketAddress address) throws IOException {
358
+ // TODO, don't throw an exception out of here.
359
+ DatagramChannel dg = DatagramChannel.open();
360
+ dg.configureBlocking(false);
361
+ dg.socket().bind(address);
362
+ long b = createBinding();
363
+ EventableChannel<?> ec = new EventableDatagramChannel (dg, b, mySelector, callback);
364
+ dg.register(mySelector, SelectionKey.OP_READ, ec);
365
+ Connections.put(b, ec);
366
+ return b;
367
+ }
368
+
369
+ public long openUdpSocket (String address, int port) throws IOException {
370
+ return openUdpSocket (new InetSocketAddress (address, port));
371
+ }
372
+
373
+ public void sendData (long sig, ByteBuffer bb) throws IOException {
374
+ Connections.get(sig).scheduleOutboundData( bb );
375
+ }
376
+
377
+ public void sendData (long sig, byte[] data) throws IOException {
378
+ sendData (sig, ByteBuffer.wrap(data));
379
+ }
380
+
381
+ public void setCommInactivityTimeout (long sig, long mills) {
382
+ Connections.get(sig).setCommInactivityTimeout (mills);
383
+ }
384
+
385
+ public void sendDatagram (long sig, byte[] data, int length, String recipAddress, int recipPort) {
386
+ sendDatagram (sig, ByteBuffer.wrap(data), recipAddress, recipPort);
387
+ }
388
+
389
+ public void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort) {
390
+ (Connections.get(sig)).scheduleOutboundDatagram( bb, recipAddress, recipPort);
391
+ }
392
+
393
+ public long connectTcpServer (String address, int port) {
394
+ return connectTcpServer(null, 0, address, port);
395
+ }
396
+
397
+ public long connectTcpServer (String bindAddr, int bindPort, String address, int port) {
398
+ long b = createBinding();
399
+
400
+ try {
401
+ SocketChannel sc = SocketChannel.open();
402
+ sc.configureBlocking(false);
403
+ if (bindAddr != null)
404
+ sc.socket().bind(new InetSocketAddress (bindAddr, bindPort));
405
+
406
+ EventableSocketChannel ec = new EventableSocketChannel (sc, b, mySelector, callback);
407
+
408
+ if (sc.connect (new InetSocketAddress (address, port))) {
409
+ // Connection returned immediately. Can happen with localhost connections.
410
+ // WARNING, this code is untested due to lack of available test conditions.
411
+ // Ought to be be able to come here from a localhost connection, but that
412
+ // doesn't happen on Linux. (Maybe on FreeBSD?)
413
+ // The reason for not handling this until we can test it is that we
414
+ // really need to return from this function WITHOUT triggering any EM events.
415
+ // That's because until the user code has seen the signature we generated here,
416
+ // it won't be able to properly dispatch them. The C++ EM deals with this
417
+ // by setting pending mode as a flag in ALL eventable descriptors and making
418
+ // the descriptor select for writable. Then, it can send UNBOUND and
419
+ // CONNECTION_COMPLETED on the next pass through the loop, because writable will
420
+ // fire.
421
+ throw new RuntimeException ("immediate-connect unimplemented");
422
+ }
423
+ else {
424
+ ec.setConnectPending();
425
+ Connections.put (b, ec);
426
+ NewConnections.add (b);
427
+ }
428
+ } catch (IOException e) {
429
+ // Can theoretically come here if a connect failure can be determined immediately.
430
+ // I don't know how to make that happen for testing purposes.
431
+ throw new RuntimeException ("immediate-connect unimplemented: " + e.toString());
432
+ }
433
+ return b;
434
+ }
435
+
436
+ public void closeConnection (long sig, boolean afterWriting) {
437
+ EventableChannel<?> ec = Connections.get(sig);
438
+ if (ec != null)
439
+ if (ec.scheduleClose (afterWriting))
440
+ UnboundConnections.add (sig);
441
+ }
442
+
443
+ long createBinding() {
444
+ return ++BindingIndex;
445
+ }
446
+
447
+ public void signalLoopbreak() {
448
+ loopBreaker.set(true);
449
+ if (mySelector != null)
450
+ mySelector.wakeup();
451
+ }
452
+
453
+ public void setTlsParms(long sig, KeyStore keyStore, boolean verifyPeer) {
454
+ ((EventableSocketChannel) Connections.get(sig)).setTlsParms(keyStore, verifyPeer);
455
+ }
456
+
457
+ public void startTls (long sig) throws NoSuchAlgorithmException, KeyManagementException {
458
+ Connections.get(sig).startTls();
459
+ }
460
+
461
+ public void acceptSslPeer (long sig) {
462
+ EventableSocketChannel sc = (EventableSocketChannel) Connections.get(sig);
463
+ sc.acceptSslPeer();
464
+ }
465
+
466
+ public byte[] getPeerCert (long sig) {
467
+ EventableSocketChannel sc = (EventableSocketChannel) Connections.get(sig);
468
+ return sc.getPeerCert();
469
+ }
470
+
471
+ public void setTimerQuantum (int mills) {
472
+ if (mills < 5 || mills > 2500)
473
+ throw new RuntimeException ("attempt to set invalid timer-quantum value: "+mills);
474
+ timerQuantum = mills;
475
+ }
476
+
477
+ public Object[] getPeerName (long sig) {
478
+ return Connections.get(sig).getPeerName();
479
+ }
480
+
481
+ public Object[] getSockName (long sig) {
482
+ return Connections.get(sig).getSockName();
483
+ }
484
+
485
+ public long attachChannel (SocketChannel sc, boolean watch_mode) {
486
+ long b = createBinding();
487
+
488
+ EventableSocketChannel ec = new EventableSocketChannel (sc, b, mySelector, callback);
489
+
490
+ ec.setAttached();
491
+ if (watch_mode)
492
+ ec.setWatchOnly();
493
+
494
+ Connections.put (b, ec);
495
+ NewConnections.add (b);
496
+
497
+ return b;
498
+ }
499
+
500
+ public SocketChannel detachChannel (long sig) {
501
+ EventableSocketChannel ec = (EventableSocketChannel) Connections.get (sig);
502
+ if (ec != null) {
503
+ UnboundConnections.add (sig);
504
+ return ec.getChannel();
505
+ } else {
506
+ return null;
507
+ }
508
+ }
509
+
510
+ public void setNotifyReadable (long sig, boolean mode) {
511
+ ((EventableSocketChannel) Connections.get(sig)).setNotifyReadable(mode);
512
+ }
513
+
514
+ public void setNotifyWritable (long sig, boolean mode) {
515
+ ((EventableSocketChannel) Connections.get(sig)).setNotifyWritable(mode);
516
+ }
517
+
518
+ public boolean isNotifyReadable (long sig) {
519
+ return Connections.get(sig).isNotifyReadable();
520
+ }
521
+
522
+ public boolean isNotifyWritable (long sig) {
523
+ return Connections.get(sig).isNotifyWritable();
524
+ }
525
+
526
+ public int getConnectionCount() {
527
+ return Connections.size() + Acceptors.size();
528
+ }
529
+ }