eventmachine 0.12.8-x86-mswin32-60 → 0.12.10-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +14 -13
  2. data/Rakefile +374 -264
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +125 -126
  5. data/ext/binder.h +46 -48
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +202 -202
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +96 -96
  15. data/ext/extconf.rb +147 -132
  16. data/ext/fastfilereader/extconf.rb +82 -76
  17. data/ext/project.h +151 -140
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +460 -460
  20. data/ext/ssl.h +94 -94
  21. data/java/src/com/rubyeventmachine/EmReactor.java +570 -423
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +69 -57
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +189 -171
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -244
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +194 -200
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +74 -74
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +36 -36
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +46 -46
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +38 -38
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +54 -54
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +109 -108
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +148 -146
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -53
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +75 -74
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +90 -89
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +191 -186
  38. data/lib/em/protocols.rb +36 -35
  39. data/lib/em/protocols/httpclient2.rb +590 -582
  40. data/lib/em/protocols/line_and_text.rb +125 -126
  41. data/lib/em/protocols/linetext2.rb +161 -160
  42. data/lib/em/protocols/object_protocol.rb +45 -39
  43. data/lib/em/protocols/smtpclient.rb +357 -331
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +60 -60
  46. data/lib/em/timers.rb +56 -55
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +257 -142
  50. data/tasks/{cpp.rake → cpp.rake_example} +76 -76
  51. data/tests/test_attach.rb +125 -100
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +34 -44
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +182 -188
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +78 -67
  63. data/tests/test_timers.rb +162 -141
  64. metadata +13 -11
  65. data/tasks/project.rake +0 -79
  66. data/tasks/tests.rake +0 -193
@@ -1,244 +1,364 @@
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 javax.net.ssl.*;
44
- import javax.net.ssl.SSLEngineResult.*;
45
-
46
- import java.security.*;
47
-
48
- public class EventableSocketChannel implements EventableChannel {
49
-
50
- // TODO, must refactor this to permit channels that aren't sockets.
51
- SocketChannel channel;
52
- String binding;
53
- Selector selector;
54
- LinkedList<ByteBuffer> outboundQ;
55
- boolean bCloseScheduled;
56
- boolean bConnectPending;
57
-
58
- SSLEngine sslEngine;
59
-
60
-
61
- SSLContext sslContext;
62
-
63
-
64
- public EventableSocketChannel (SocketChannel sc, String _binding, Selector sel) throws ClosedChannelException {
65
- channel = sc;
66
- binding = _binding;
67
- selector = sel;
68
- bCloseScheduled = false;
69
- bConnectPending = false;
70
- outboundQ = new LinkedList<ByteBuffer>();
71
-
72
- sc.register(selector, SelectionKey.OP_READ, this);
73
- }
74
-
75
- public String getBinding() {
76
- return binding;
77
- }
78
-
79
- /**
80
- * Terminate with extreme prejudice. Don't assume there will be another pass through
81
- * the reactor core.
82
- */
83
- public void close() {
84
- try {
85
- channel.close();
86
- } catch (IOException e) {
87
- }
88
- }
89
-
90
- public void scheduleOutboundData (ByteBuffer bb) {
91
- try {
92
- if ((!bCloseScheduled) && (bb.remaining() > 0)) {
93
- if (sslEngine != null) {
94
- ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer.
95
- sslEngine.wrap(bb, b);
96
- b.flip();
97
- outboundQ.addLast(b);
98
- }
99
- else {
100
- outboundQ.addLast(bb);
101
- }
102
- channel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ | (bConnectPending ? SelectionKey.OP_CONNECT : 0), this);
103
- }
104
- } catch (ClosedChannelException e) {
105
- throw new RuntimeException ("no outbound data");
106
- } catch (SSLException e) {
107
- throw new RuntimeException ("no outbound data");
108
- }
109
- }
110
-
111
- public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
112
- throw new RuntimeException ("datagram sends not supported on this channel");
113
- }
114
-
115
- /**
116
- * Called by the reactor when we have selected readable.
117
- */
118
- public void readInboundData (ByteBuffer bb) {
119
- try {
120
- channel.read(bb);
121
- } catch (IOException e) {
122
- throw new RuntimeException ("i/o error");
123
- }
124
- }
125
- /**
126
- * Called by the reactor when we have selected writable.
127
- * Return false to indicate an error that should cause the connection to close.
128
- * We can get here with an empty outbound buffer if bCloseScheduled is true.
129
- * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
130
- * possible to become unwritable between the poll and when we get here. The way
131
- * this code is written, we're depending on a nonblocking write NOT TO CONSUME
132
- * the whole outbound buffer in this case, rather than firing an exception.
133
- * We should somehow verify that this is indeed Java's defined behavior.
134
- * Also TODO, see if we can use gather I/O rather than one write at a time.
135
- * Ought to be a big performance enhancer.
136
- * @return
137
- */
138
- public boolean writeOutboundData(){
139
- while (!outboundQ.isEmpty()) {
140
- ByteBuffer b = outboundQ.getFirst();
141
- try {
142
- if (b.remaining() > 0)
143
- channel.write(b);
144
- }
145
- catch (IOException e) {
146
- return false;
147
- }
148
-
149
- // Did we consume the whole outbound buffer? If yes,
150
- // pop it off and keep looping. If no, the outbound network
151
- // buffers are full, so break out of here.
152
- if (b.remaining() == 0)
153
- outboundQ.removeFirst();
154
- else
155
- break;
156
- }
157
-
158
- if (outboundQ.isEmpty()) {
159
- try {
160
- channel.register(selector, SelectionKey.OP_READ, this);
161
- } catch (ClosedChannelException e) {
162
- }
163
- }
164
-
165
- // ALWAYS drain the outbound queue before triggering a connection close.
166
- // If anyone wants to close immediately, they're responsible for clearing
167
- // the outbound queue.
168
- return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
169
- }
170
-
171
- public void setConnectPending() throws ClosedChannelException {
172
- channel.register(selector, SelectionKey.OP_CONNECT, this);
173
- bConnectPending = true;
174
- }
175
-
176
- /**
177
- * Called by the reactor when we have selected connectable.
178
- * Return false to indicate an error that should cause the connection to close.
179
- * @throws ClosedChannelException
180
- */
181
- public boolean finishConnecting() throws ClosedChannelException {
182
- try {
183
- channel.finishConnect();
184
- }
185
- catch (IOException e) {
186
- return false;
187
- }
188
- bConnectPending = false;
189
- channel.register(selector, SelectionKey.OP_READ | (outboundQ.isEmpty() ? 0 : SelectionKey.OP_WRITE), this);
190
- return true;
191
- }
192
-
193
- public void scheduleClose (boolean afterWriting) {
194
- // TODO: What the hell happens here if bConnectPending is set?
195
- if (!afterWriting)
196
- outboundQ.clear();
197
- try {
198
- channel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, this);
199
- } catch (ClosedChannelException e) {
200
- throw new RuntimeException ("unable to schedule close"); // TODO, get rid of this.
201
- }
202
- bCloseScheduled = true;
203
- }
204
- public void startTls() {
205
- if (sslEngine == null) {
206
- try {
207
- sslContext = SSLContext.getInstance("TLS");
208
- sslContext.init(null, null, null); // TODO, fill in the parameters.
209
- sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use.
210
- sslEngine.setUseClientMode(false);
211
- } catch (NoSuchAlgorithmException e) {
212
- throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
213
- } catch (KeyManagementException e) {
214
- throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
215
- }
216
- }
217
- System.out.println ("Starting TLS");
218
- }
219
-
220
- public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException {
221
- if (sslEngine != null) {
222
- if (true) throw new RuntimeException ("TLS currently unimplemented");
223
- System.setProperty("javax.net.debug", "all");
224
- ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer.
225
- SSLEngineResult res = sslEngine.unwrap(bb, w);
226
- if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
227
- Runnable r;
228
- while ((r = sslEngine.getDelegatedTask()) != null) {
229
- r.run();
230
- }
231
- }
232
- System.out.println (bb);
233
- w.flip();
234
- return w;
235
- }
236
- else
237
- return bb;
238
- }
239
-
240
- public void setCommInactivityTimeout (long seconds) {
241
- // TODO
242
- System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
243
- }
244
- }
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
+
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
+ public boolean writeOutboundData() throws IOException {
204
+ while (!outboundQ.isEmpty()) {
205
+ ByteBuffer b = outboundQ.getFirst();
206
+ if (b.remaining() > 0)
207
+ channel.write(b);
208
+
209
+ // Did we consume the whole outbound buffer? If yes,
210
+ // pop it off and keep looping. If no, the outbound network
211
+ // buffers are full, so break out of here.
212
+ if (b.remaining() == 0)
213
+ outboundQ.removeFirst();
214
+ else
215
+ break;
216
+ }
217
+
218
+ if (outboundQ.isEmpty() && !bCloseScheduled) {
219
+ updateEvents();
220
+ }
221
+
222
+ // ALWAYS drain the outbound queue before triggering a connection close.
223
+ // If anyone wants to close immediately, they're responsible for clearing
224
+ // the outbound queue.
225
+ return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
226
+ }
227
+
228
+ public void setConnectPending() {
229
+ bConnectPending = true;
230
+ updateEvents();
231
+ }
232
+
233
+ /**
234
+ * Called by the reactor when we have selected connectable.
235
+ * Return false to indicate an error that should cause the connection to close.
236
+ */
237
+ public boolean finishConnecting() throws IOException {
238
+ channel.finishConnect();
239
+
240
+ bConnectPending = false;
241
+ updateEvents();
242
+ return true;
243
+ }
244
+
245
+ public boolean scheduleClose (boolean afterWriting) {
246
+ // TODO: What the hell happens here if bConnectPending is set?
247
+ if (!afterWriting)
248
+ outboundQ.clear();
249
+
250
+ if (outboundQ.isEmpty())
251
+ return true;
252
+ else {
253
+ updateEvents();
254
+ bCloseScheduled = true;
255
+ return false;
256
+ }
257
+ }
258
+
259
+ public void startTls() {
260
+ if (sslEngine == null) {
261
+ try {
262
+ sslContext = SSLContext.getInstance("TLS");
263
+ sslContext.init(null, null, null); // TODO, fill in the parameters.
264
+ sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use.
265
+ sslEngine.setUseClientMode(false);
266
+ } catch (NoSuchAlgorithmException e) {
267
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
268
+ } catch (KeyManagementException e) {
269
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
270
+ }
271
+ }
272
+ System.out.println ("Starting TLS");
273
+ }
274
+
275
+ public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException {
276
+ if (sslEngine != null) {
277
+ if (true) throw new RuntimeException ("TLS currently unimplemented");
278
+ System.setProperty("javax.net.debug", "all");
279
+ ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer.
280
+ SSLEngineResult res = sslEngine.unwrap(bb, w);
281
+ if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
282
+ Runnable r;
283
+ while ((r = sslEngine.getDelegatedTask()) != null) {
284
+ r.run();
285
+ }
286
+ }
287
+ System.out.println (bb);
288
+ w.flip();
289
+ return w;
290
+ }
291
+ else
292
+ return bb;
293
+ }
294
+
295
+ public void setCommInactivityTimeout (long seconds) {
296
+ // TODO
297
+ System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
298
+ }
299
+
300
+ public Object[] getPeerName () {
301
+ Socket sock = channel.socket();
302
+ return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
303
+ }
304
+
305
+ public void setWatchOnly() {
306
+ bWatchOnly = true;
307
+ updateEvents();
308
+ }
309
+ public boolean isWatchOnly() { return bWatchOnly; }
310
+
311
+ public void setAttached() {
312
+ bAttached = true;
313
+ }
314
+ public boolean isAttached() { return bAttached; }
315
+
316
+ public void setNotifyReadable (boolean mode) {
317
+ bNotifyReadable = mode;
318
+ updateEvents();
319
+ }
320
+ public boolean isNotifyReadable() { return bNotifyReadable; }
321
+
322
+ public void setNotifyWritable (boolean mode) {
323
+ bNotifyWritable = mode;
324
+ updateEvents();
325
+ }
326
+ public boolean isNotifyWritable() { return bNotifyWritable; }
327
+
328
+ private void updateEvents() {
329
+ if (channelKey == null)
330
+ return;
331
+
332
+ int events = currentEvents();
333
+
334
+ if (channelKey.interestOps() != events) {
335
+ channelKey.interestOps(events);
336
+ }
337
+ }
338
+
339
+ private int currentEvents() {
340
+ int events = 0;
341
+
342
+ if (bWatchOnly)
343
+ {
344
+ if (bNotifyReadable)
345
+ events |= SelectionKey.OP_READ;
346
+
347
+ if (bNotifyWritable)
348
+ events |= SelectionKey.OP_WRITE;
349
+ }
350
+ else
351
+ {
352
+ if (bConnectPending)
353
+ events |= SelectionKey.OP_CONNECT;
354
+ else {
355
+ events |= SelectionKey.OP_READ;
356
+
357
+ if (!outboundQ.isEmpty())
358
+ events |= SelectionKey.OP_WRITE;
359
+ }
360
+ }
361
+
362
+ return events;
363
+ }
364
+ }