sonixlabs-eventmachine-java 1.0.0.rc.7-java → 1.0.3.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -12
  2. data/.travis.yml +12 -0
  3. data/CHANGELOG.md +33 -0
  4. data/Gemfile +0 -1
  5. data/README.md +2 -2
  6. data/README_JP.md +10 -2
  7. data/eventmachine.gemspec +10 -7
  8. data/ext/binder.cpp +1 -1
  9. data/ext/cmain.cpp +11 -0
  10. data/ext/ed.cpp +22 -7
  11. data/ext/ed.h +5 -5
  12. data/ext/em.cpp +64 -66
  13. data/ext/em.h +10 -5
  14. data/ext/eventmachine.h +1 -0
  15. data/ext/extconf.rb +4 -3
  16. data/ext/fastfilereader/extconf.rb +1 -1
  17. data/ext/rubymain.cpp +22 -1
  18. data/ext/ssl.cpp +1 -1
  19. data/java/.classpath +1 -3
  20. data/java/.gitignore +1 -0
  21. data/java/src/com/rubyeventmachine/DatagramPacket.java +13 -0
  22. data/java/src/com/rubyeventmachine/EmReactor.java +502 -561
  23. data/java/src/com/rubyeventmachine/EventCallback.java +7 -0
  24. data/java/src/com/rubyeventmachine/EventCode.java +26 -0
  25. data/java/src/com/rubyeventmachine/EventableChannel.java +102 -42
  26. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +146 -161
  27. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +371 -334
  28. data/java/src/com/rubyeventmachine/SslBox.java +310 -0
  29. data/lib/em/iterator.rb +5 -44
  30. data/lib/em/processes.rb +1 -1
  31. data/lib/em/protocols/httpclient.rb +2 -2
  32. data/lib/em/protocols/line_protocol.rb +2 -2
  33. data/lib/em/protocols/smtpclient.rb +1 -1
  34. data/lib/em/protocols/smtpserver.rb +10 -7
  35. data/lib/em/protocols/stomp.rb +5 -2
  36. data/lib/em/protocols.rb +1 -0
  37. data/lib/em/version.rb +1 -1
  38. data/lib/eventmachine.rb +35 -14
  39. data/lib/jeventmachine.rb +65 -18
  40. data/rakelib/package.rake +15 -18
  41. data/tests/server.crt +36 -0
  42. data/tests/server.key +51 -0
  43. data/tests/test_attach.rb +24 -0
  44. data/tests/test_connection_count.rb +21 -1
  45. data/tests/test_epoll.rb +15 -0
  46. data/tests/test_httpclient2.rb +5 -0
  47. data/tests/test_idle_connection.rb +6 -4
  48. data/tests/test_iterator.rb +97 -0
  49. data/tests/test_line_protocol.rb +33 -0
  50. data/tests/test_pause.rb +24 -0
  51. data/tests/test_set_sock_opt.rb +1 -1
  52. data/tests/test_ssl_echo_data.rb +60 -0
  53. data/tests/test_ssl_methods.rb +15 -7
  54. data/tests/test_ssl_verify.rb +4 -4
  55. data/tests/test_stomp.rb +37 -0
  56. data/tests/test_system.rb +42 -0
  57. metadata +45 -42
  58. data/lib/rubyeventmachine.jar +0 -0
@@ -1,33 +1,33 @@
1
1
  /**
2
2
  * $Id$
3
- *
3
+ *
4
4
  * Author:: Francis Cianfrocca (gmail: blackhedd)
5
5
  * Homepage:: http://rubyeventmachine.com
6
6
  * Date:: 15 Jul 2007
7
- *
7
+ *
8
8
  * See EventMachine and EventMachine::Connection for documentation and
9
9
  * usage examples.
10
- *
10
+ *
11
11
  *
12
12
  *----------------------------------------------------------------------------
13
13
  *
14
14
  * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
15
15
  * Gmail: blackhedd
16
- *
16
+ *
17
17
  * This program is free software; you can redistribute it and/or modify
18
18
  * it under the terms of either: 1) the GNU General Public License
19
19
  * as published by the Free Software Foundation; either version 2 of the
20
20
  * License, or (at your option) any later version; or 2) Ruby's License.
21
- *
21
+ *
22
22
  * See the file COPYING for complete licensing information.
23
23
  *
24
24
  *---------------------------------------------------------------------------
25
25
  *
26
- *
26
+ *
27
27
  */
28
28
 
29
29
  /**
30
- *
30
+ *
31
31
  */
32
32
  package com.rubyeventmachine;
33
33
 
@@ -36,333 +36,370 @@ package com.rubyeventmachine;
36
36
  *
37
37
  */
38
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.*;
39
+ import java.io.FileDescriptor;
40
+ import java.io.IOException;
46
41
  import java.lang.reflect.Field;
42
+ import java.net.Socket;
43
+ import java.nio.ByteBuffer;
44
+ import java.nio.channels.ClosedChannelException;
45
+ import java.nio.channels.SelectionKey;
46
+ import java.nio.channels.Selector;
47
+ import java.nio.channels.SocketChannel;
48
+ import java.security.KeyStore;
49
+ import java.security.cert.CertificateException;
50
+ import java.security.cert.X509Certificate;
51
+
52
+ import javax.net.ssl.X509TrustManager;
53
+
54
+ public class EventableSocketChannel extends EventableChannel<ByteBuffer> {
55
+ SelectionKey channelKey;
56
+ SocketChannel channel;
57
+
58
+ boolean bCloseScheduled;
59
+ boolean bConnectPending;
60
+ boolean bWatchOnly;
61
+ boolean bAttached;
62
+ boolean bNotifyReadable;
63
+ boolean bNotifyWritable;
64
+
65
+ SslBox sslBox;
66
+ private KeyStore keyStore;
67
+ private boolean verifyPeer;
68
+ private boolean bIsServer;
69
+ private boolean shouldAcceptSslPeer = false;
70
+
71
+ public EventableSocketChannel (SocketChannel sc, long _binding, Selector sel, EventCallback callback) {
72
+ super(_binding, sel, callback);
73
+ channel = sc;
74
+ bCloseScheduled = false;
75
+ bConnectPending = false;
76
+ bWatchOnly = false;
77
+ bAttached = false;
78
+ bNotifyReadable = false;
79
+ bNotifyWritable = false;
80
+ bIsServer = false;
81
+ }
82
+
83
+ public SocketChannel getChannel() {
84
+ return channel;
85
+ }
86
+
87
+ public void register() throws ClosedChannelException {
88
+ if (channelKey == null) {
89
+ int events = currentEvents();
90
+ channelKey = channel.register(selector, events, this);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Terminate with extreme prejudice. Don't assume there will be another pass through
96
+ * the reactor core.
97
+ */
98
+ public void close() {
99
+ if (channelKey != null) {
100
+ channelKey.cancel();
101
+ channelKey = null;
102
+ }
103
+
104
+ if (bAttached) {
105
+ // attached channels are copies, so reset the file descriptor to prevent java from close()ing it
106
+ Field f;
107
+ FileDescriptor fd;
108
+
109
+ try {
110
+ /* do _NOT_ clobber fdVal here, it will break epoll/kqueue on jdk6!
111
+ * channelKey.cancel() above does not occur until the next call to select
112
+ * and if fdVal is gone, we will continue to get events for this fd.
113
+ *
114
+ * instead, remove fdVal in cleanup(), which is processed via DetachedConnections,
115
+ * after UnboundConnections but before NewConnections.
116
+ */
117
+
118
+ f = channel.getClass().getDeclaredField("fd");
119
+ f.setAccessible(true);
120
+ fd = (FileDescriptor) f.get(channel);
121
+
122
+ f = fd.getClass().getDeclaredField("fd");
123
+ f.setAccessible(true);
124
+ f.set(fd, -1);
125
+ } catch (java.lang.NoSuchFieldException e) {
126
+ e.printStackTrace();
127
+ } catch (java.lang.IllegalAccessException e) {
128
+ e.printStackTrace();
129
+ }
130
+
131
+ return;
132
+ }
133
+
134
+ try {
135
+ channel.close();
136
+ } catch (IOException e) {
137
+ }
138
+ }
139
+
140
+ public void cleanup() {
141
+ if (bAttached) {
142
+ Field f;
143
+ try {
144
+ f = channel.getClass().getDeclaredField("fdVal");
145
+ f.setAccessible(true);
146
+ f.set(channel, -1);
147
+ } catch (java.lang.NoSuchFieldException e) {
148
+ e.printStackTrace();
149
+ } catch (java.lang.IllegalAccessException e) {
150
+ e.printStackTrace();
151
+ }
152
+ }
153
+
154
+ channel = null;
155
+ }
156
+
157
+ public void scheduleOutboundData (ByteBuffer bb) {
158
+ if (!bCloseScheduled && bb.remaining() > 0) {
159
+ outboundQ.addLast( bb );
160
+ updateEvents();
161
+ }
162
+ }
163
+
164
+ public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
165
+ throw new RuntimeException ("datagram sends not supported on this channel");
166
+ }
167
+
168
+ /**
169
+ * Called by the reactor when we have selected readable.
170
+ */
171
+ public void readInboundData (ByteBuffer bb) throws IOException {
172
+ int bytesRead = (sslBox != null) ? sslBox.read(bb) : channel.read(bb);
173
+ if (bytesRead == -1)
174
+ throw new IOException ("eof");
175
+ }
176
+
177
+ /**
178
+ * Called by the reactor when we have selected writable.
179
+ * Return false to indicate an error that should cause the connection to close.
180
+ * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
181
+ * possible to become unwritable between the poll and when we get here. The way
182
+ * this code is written, we're depending on a nonblocking write NOT TO CONSUME
183
+ * the whole outbound buffer in this case, rather than firing an exception.
184
+ * We should somehow verify that this is indeed Java's defined behavior.
185
+ * Also TODO, see if we can use gather I/O rather than one write at a time.
186
+ * Ought to be a big performance enhancer.
187
+ * @return
188
+ */
189
+ protected boolean writeOutboundData() throws IOException {
190
+ while (!outboundQ.isEmpty()) {
191
+ ByteBuffer b = outboundQ.getFirst();
192
+ if (b.remaining() > 0) {
193
+ if (sslBox != null)
194
+ sslBox.write(b);
195
+ else
196
+ channel.write(b);
197
+ }
198
+
199
+ // Did we consume the whole outbound buffer? If yes,
200
+ // pop it off and keep looping. If no, the outbound network
201
+ // buffers are full, so break out of here.
202
+ if (b.remaining() == 0)
203
+ outboundQ.removeFirst();
204
+ else
205
+ break;
206
+ }
207
+
208
+ if (outboundQ.isEmpty() && !bCloseScheduled) {
209
+ updateEvents();
210
+ }
211
+
212
+ // ALWAYS drain the outbound queue before triggering a connection close.
213
+ // If anyone wants to close immediately, they're responsible for clearing
214
+ // the outbound queue.
215
+ return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
216
+ }
217
+
218
+ public void setConnectPending() {
219
+ bConnectPending = true;
220
+ updateEvents();
221
+ }
222
+
223
+ /**
224
+ * Called by the reactor when we have selected connectable.
225
+ * Return false to indicate an error that should cause the connection to close.
226
+ */
227
+ public boolean finishConnecting() {
228
+ try {
229
+ channel.finishConnect();
230
+ bConnectPending = false;
231
+ updateEvents();
232
+ callback.trigger(binding, EventCode.EM_CONNECTION_COMPLETED, null, 0);
233
+ return true;
234
+ } catch (IOException e) {
235
+ return false;
236
+ }
237
+ }
238
+
239
+ public boolean scheduleClose (boolean afterWriting) {
240
+ // TODO: What the hell happens here if bConnectPending is set?
241
+ if (!afterWriting)
242
+ outboundQ.clear();
243
+
244
+ if (outboundQ.isEmpty())
245
+ return true;
246
+ else {
247
+ updateEvents();
248
+ bCloseScheduled = true;
249
+ return false;
250
+ }
251
+ }
252
+
253
+ public void setTlsParms(KeyStore keyStore, boolean verifyPeer) {
254
+ this.keyStore = keyStore;
255
+ this.verifyPeer = verifyPeer;
256
+ }
257
+
258
+ public void startTls() {
259
+ if (sslBox == null) {
260
+ Object[] peerName = getPeerName();
261
+ int port = (Integer) peerName[0];
262
+ String host = (String) peerName[1];
263
+ X509TrustManager tm = new CallbackBasedTrustManager();
264
+ sslBox = new SslBox(bIsServer, channel, keyStore, tm, verifyPeer, host, port);
265
+ updateEvents();
266
+ }
267
+ }
268
+
269
+ public Object[] getPeerName () {
270
+ Socket sock = channel.socket();
271
+ return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
272
+ }
273
+
274
+ public Object[] getSockName () {
275
+ Socket sock = channel.socket();
276
+ return new Object[]{ sock.getLocalPort(),
277
+ sock.getLocalAddress().getHostAddress() };
278
+ }
279
+
280
+ public void setWatchOnly() {
281
+ bWatchOnly = true;
282
+ updateEvents();
283
+ }
284
+ public boolean isWatchOnly() { return bWatchOnly; }
285
+
286
+ public void setAttached() {
287
+ bAttached = true;
288
+ }
289
+ public boolean isAttached() { return bAttached; }
290
+
291
+ public void setNotifyReadable (boolean mode) {
292
+ bNotifyReadable = mode;
293
+ updateEvents();
294
+ }
295
+ public boolean isNotifyReadable() { return bNotifyReadable; }
296
+
297
+ public void setNotifyWritable (boolean mode) {
298
+ bNotifyWritable = mode;
299
+ updateEvents();
300
+ }
301
+ public boolean isNotifyWritable() { return bNotifyWritable; }
302
+
303
+ private void updateEvents() {
304
+ if (channelKey == null)
305
+ return;
306
+
307
+ int events = currentEvents();
308
+
309
+ if (channelKey.interestOps() != events) {
310
+ channelKey.interestOps(events);
311
+ }
312
+ }
313
+
314
+ private int currentEvents() {
315
+ int events = 0;
316
+
317
+ if (bWatchOnly)
318
+ {
319
+ if (bNotifyReadable)
320
+ events |= SelectionKey.OP_READ;
321
+
322
+ if (bNotifyWritable)
323
+ events |= SelectionKey.OP_WRITE;
324
+ }
325
+ else
326
+ {
327
+ if (bConnectPending)
328
+ events |= SelectionKey.OP_CONNECT;
329
+ else {
330
+ events |= SelectionKey.OP_READ;
331
+
332
+ if (!outboundQ.isEmpty() || (sslBox != null && sslBox.handshakeNeeded()))
333
+ events |= SelectionKey.OP_WRITE;
334
+ }
335
+ }
336
+
337
+ return events;
338
+ }
339
+
340
+ public void setServerMode() {
341
+ bIsServer = true;
342
+ }
343
+
344
+ @Override
345
+ protected boolean handshakeNeeded() {
346
+ return sslBox != null && sslBox.handshakeNeeded();
347
+ }
348
+
349
+ @Override
350
+ protected boolean performHandshake() {
351
+ if (sslBox == null) return true;
352
+
353
+ if (sslBox.handshake(channelKey)) {
354
+ if (!sslBox.handshakeNeeded()) {
355
+ callback.trigger(binding, EventCode.EM_SSL_HANDSHAKE_COMPLETED, null, 0);
356
+ updateEvents();
357
+ }
358
+ return true;
359
+ }
360
+ return false;
361
+ }
362
+
363
+ public void acceptSslPeer() {
364
+ this.shouldAcceptSslPeer = true;
365
+ }
366
+
367
+ public class CallbackBasedTrustManager implements X509TrustManager {
368
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
369
+ if (verifyPeer) fireEvent(chain[0]);
370
+ }
371
+
372
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
373
+ if (verifyPeer) fireEvent(chain[0]);
374
+ }
375
+
376
+ public X509Certificate[] getAcceptedIssuers() {
377
+ return new X509Certificate[0];
378
+ }
379
+
380
+ private void fireEvent(X509Certificate cert) throws CertificateException {
381
+
382
+ ByteBuffer data = ByteBuffer.wrap(cert.getEncoded());
383
+
384
+ callback.trigger(binding, EventCode.EM_SSL_VERIFY, data, 0);
385
+
386
+ // If we should accept, the trigger will ultimately call our acceptSslPeer method.
387
+ if (! shouldAcceptSslPeer) {
388
+ throw new CertificateException("JRuby trigger was not fired");
389
+ }
390
+ }
391
+ }
392
+
393
+ public byte[] getPeerCert() {
394
+ if (sslBox != null) {
395
+ try {
396
+ javax.security.cert.X509Certificate peerCert = sslBox.getPeerCert();
397
+ return peerCert.getEncoded();
398
+ } catch (Exception e) {
399
+ }
400
+ }
401
+ return null;
402
+ }
403
+
47
404
 
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
-
58
- boolean bCloseScheduled;
59
- boolean bConnectPending;
60
- boolean bWatchOnly;
61
- boolean bAttached;
62
- boolean bNotifyReadable;
63
- boolean bNotifyWritable;
64
-
65
- SSLEngine sslEngine;
66
- SSLContext sslContext;
67
-
68
- public EventableSocketChannel (SocketChannel sc, long _binding, Selector sel) {
69
- channel = sc;
70
- binding = _binding;
71
- selector = sel;
72
- bCloseScheduled = false;
73
- bConnectPending = false;
74
- bWatchOnly = false;
75
- bAttached = false;
76
- bNotifyReadable = false;
77
- bNotifyWritable = false;
78
- outboundQ = new LinkedList<ByteBuffer>();
79
- }
80
-
81
- public long getBinding() {
82
- return binding;
83
- }
84
-
85
- public SocketChannel getChannel() {
86
- return channel;
87
- }
88
-
89
- public void register() throws ClosedChannelException {
90
- if (channelKey == null) {
91
- int events = currentEvents();
92
- channelKey = channel.register(selector, events, this);
93
- }
94
- }
95
-
96
- /**
97
- * Terminate with extreme prejudice. Don't assume there will be another pass through
98
- * the reactor core.
99
- */
100
- public void close() {
101
- if (channelKey != null) {
102
- channelKey.cancel();
103
- channelKey = null;
104
- }
105
-
106
- if (bAttached) {
107
- // attached channels are copies, so reset the file descriptor to prevent java from close()ing it
108
- Field f;
109
- FileDescriptor fd;
110
-
111
- try {
112
- /* do _NOT_ clobber fdVal here, it will break epoll/kqueue on jdk6!
113
- * channelKey.cancel() above does not occur until the next call to select
114
- * and if fdVal is gone, we will continue to get events for this fd.
115
- *
116
- * instead, remove fdVal in cleanup(), which is processed via DetachedConnections,
117
- * after UnboundConnections but before NewConnections.
118
- */
119
-
120
- f = channel.getClass().getDeclaredField("fd");
121
- f.setAccessible(true);
122
- fd = (FileDescriptor) f.get(channel);
123
-
124
- f = fd.getClass().getDeclaredField("fd");
125
- f.setAccessible(true);
126
- f.set(fd, -1);
127
- } catch (java.lang.NoSuchFieldException e) {
128
- e.printStackTrace();
129
- } catch (java.lang.IllegalAccessException e) {
130
- e.printStackTrace();
131
- }
132
-
133
- return;
134
- }
135
-
136
- try {
137
- channel.close();
138
- } catch (IOException e) {
139
- }
140
- }
141
-
142
- public void cleanup() {
143
- if (bAttached) {
144
- Field f;
145
- try {
146
- f = channel.getClass().getDeclaredField("fdVal");
147
- f.setAccessible(true);
148
- f.set(channel, -1);
149
- } catch (java.lang.NoSuchFieldException e) {
150
- e.printStackTrace();
151
- } catch (java.lang.IllegalAccessException e) {
152
- e.printStackTrace();
153
- }
154
- }
155
-
156
- channel = null;
157
- }
158
-
159
- public void scheduleOutboundData (ByteBuffer bb) {
160
- if (!bCloseScheduled && bb.remaining() > 0) {
161
- if (sslEngine != null) {
162
- try {
163
- ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer.
164
- sslEngine.wrap(bb, b);
165
- b.flip();
166
- outboundQ.addLast(b);
167
- } catch (SSLException e) {
168
- throw new RuntimeException ("ssl error");
169
- }
170
- }
171
- else {
172
- outboundQ.addLast(bb);
173
- }
174
-
175
- updateEvents();
176
- }
177
- }
178
-
179
- public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
180
- throw new RuntimeException ("datagram sends not supported on this channel");
181
- }
182
-
183
- /**
184
- * Called by the reactor when we have selected readable.
185
- */
186
- public void readInboundData (ByteBuffer bb) throws IOException {
187
- if (channel.read(bb) == -1)
188
- throw new IOException ("eof");
189
- }
190
-
191
- /**
192
- * Called by the reactor when we have selected writable.
193
- * Return false to indicate an error that should cause the connection to close.
194
- * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
195
- * possible to become unwritable between the poll and when we get here. The way
196
- * this code is written, we're depending on a nonblocking write NOT TO CONSUME
197
- * the whole outbound buffer in this case, rather than firing an exception.
198
- * We should somehow verify that this is indeed Java's defined behavior.
199
- * Also TODO, see if we can use gather I/O rather than one write at a time.
200
- * Ought to be a big performance enhancer.
201
- * @return
202
- */
203
- synchronized public boolean writeOutboundData() throws IOException {
204
- try {
205
- while (!outboundQ.isEmpty()) {
206
- ByteBuffer b = outboundQ.getFirst();
207
- while (b.remaining() > 0) {
208
- channel.write(b);
209
- }
210
- outboundQ.removeFirst();
211
- }
212
- } catch (IOException e) {
213
- System.out.println("IOException in [eventmachine] EventableSocketChannel#writeOutboundData");
214
- }
215
-
216
- if (outboundQ.isEmpty() && !bCloseScheduled) {
217
- updateEvents();
218
- }
219
-
220
- // ALWAYS drain the outbound queue before triggering a connection close.
221
- // If anyone wants to close immediately, they're responsible for clearing
222
- // the outbound queue.
223
- return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
224
- }
225
-
226
- public void setConnectPending() {
227
- bConnectPending = true;
228
- updateEvents();
229
- }
230
-
231
- /**
232
- * Called by the reactor when we have selected connectable.
233
- * Return false to indicate an error that should cause the connection to close.
234
- */
235
- public boolean finishConnecting() throws IOException {
236
- channel.finishConnect();
237
-
238
- bConnectPending = false;
239
- updateEvents();
240
- return true;
241
- }
242
-
243
- public boolean scheduleClose (boolean afterWriting) {
244
- // TODO: What the hell happens here if bConnectPending is set?
245
- if (!afterWriting)
246
- outboundQ.clear();
247
-
248
- if (outboundQ.isEmpty())
249
- return true;
250
- else {
251
- updateEvents();
252
- bCloseScheduled = true;
253
- return false;
254
- }
255
- }
256
-
257
- public void startTls() {
258
- if (sslEngine == null) {
259
- try {
260
- sslContext = SSLContext.getInstance("TLS");
261
- sslContext.init(null, null, null); // TODO, fill in the parameters.
262
- sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use.
263
- sslEngine.setUseClientMode(false);
264
- } catch (NoSuchAlgorithmException e) {
265
- throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
266
- } catch (KeyManagementException e) {
267
- throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
268
- }
269
- }
270
- System.out.println ("Starting TLS");
271
- }
272
-
273
- public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException {
274
- if (sslEngine != null) {
275
- if (true) throw new RuntimeException ("TLS currently unimplemented");
276
- System.setProperty("javax.net.debug", "all");
277
- ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer.
278
- SSLEngineResult res = sslEngine.unwrap(bb, w);
279
- if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
280
- Runnable r;
281
- while ((r = sslEngine.getDelegatedTask()) != null) {
282
- r.run();
283
- }
284
- }
285
- System.out.println (bb);
286
- w.flip();
287
- return w;
288
- }
289
- else
290
- return bb;
291
- }
292
-
293
- public void setCommInactivityTimeout (long seconds) {
294
- // TODO
295
- System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
296
- }
297
-
298
- public Object[] getPeerName () {
299
- Socket sock = channel.socket();
300
- return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
301
- }
302
-
303
- public Object[] getSockName () {
304
- Socket sock = channel.socket();
305
- return new Object[]{ sock.getLocalPort(),
306
- sock.getLocalAddress().getHostAddress() };
307
- }
308
-
309
- public void setWatchOnly() {
310
- bWatchOnly = true;
311
- updateEvents();
312
- }
313
- public boolean isWatchOnly() { return bWatchOnly; }
314
-
315
- public void setAttached() {
316
- bAttached = true;
317
- }
318
- public boolean isAttached() { return bAttached; }
319
-
320
- public void setNotifyReadable (boolean mode) {
321
- bNotifyReadable = mode;
322
- updateEvents();
323
- }
324
- public boolean isNotifyReadable() { return bNotifyReadable; }
325
-
326
- public void setNotifyWritable (boolean mode) {
327
- bNotifyWritable = mode;
328
- updateEvents();
329
- }
330
- public boolean isNotifyWritable() { return bNotifyWritable; }
331
-
332
- private void updateEvents() {
333
- if (channelKey == null)
334
- return;
335
-
336
- int events = currentEvents();
337
-
338
- if (channelKey.interestOps() != events) {
339
- channelKey.interestOps(events);
340
- }
341
- }
342
-
343
- private int currentEvents() {
344
- int events = 0;
345
-
346
- if (bWatchOnly)
347
- {
348
- if (bNotifyReadable)
349
- events |= SelectionKey.OP_READ;
350
-
351
- if (bNotifyWritable)
352
- events |= SelectionKey.OP_WRITE;
353
- }
354
- else
355
- {
356
- if (bConnectPending)
357
- events |= SelectionKey.OP_CONNECT;
358
- else {
359
- events |= SelectionKey.OP_READ;
360
-
361
- if (!outboundQ.isEmpty())
362
- events |= SelectionKey.OP_WRITE;
363
- }
364
- }
365
-
366
- return events;
367
- }
368
405
  }