eventmachine 0.12.8 → 0.12.10

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 +2 -1
  2. data/Rakefile +155 -45
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +13 -14
  5. data/ext/binder.h +5 -7
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +20 -20
  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 +4 -4
  15. data/ext/extconf.rb +28 -13
  16. data/ext/fastfilereader/extconf.rb +11 -5
  17. data/ext/project.h +12 -1
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +3 -3
  20. data/ext/ssl.h +2 -2
  21. data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +5 -0
  38. data/lib/em/protocols.rb +1 -0
  39. data/lib/em/protocols/httpclient2.rb +8 -0
  40. data/lib/em/protocols/line_and_text.rb +0 -1
  41. data/lib/em/protocols/linetext2.rb +1 -0
  42. data/lib/em/protocols/object_protocol.rb +8 -2
  43. data/lib/em/protocols/smtpclient.rb +42 -16
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +1 -1
  46. data/lib/em/timers.rb +2 -1
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +124 -9
  50. data/tasks/{cpp.rake → cpp.rake_example} +0 -0
  51. data/tests/test_attach.rb +29 -4
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +10 -20
  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 +0 -6
  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 +16 -5
  63. data/tests/test_timers.rb +22 -1
  64. metadata +14 -12
  65. data/tasks/project.rake +0 -79
  66. data/tasks/tests.rake +0 -193
@@ -30,6 +30,8 @@
30
30
  package com.rubyeventmachine;
31
31
 
32
32
  import java.nio.ByteBuffer;
33
+ import java.io.IOException;
34
+ import java.nio.channels.ClosedChannelException;
33
35
 
34
36
  public interface EventableChannel {
35
37
 
@@ -37,21 +39,31 @@ public interface EventableChannel {
37
39
 
38
40
  public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort);
39
41
 
40
- public void scheduleClose (boolean afterWriting);
42
+ public boolean scheduleClose (boolean afterWriting);
41
43
 
42
44
  public void startTls();
43
45
 
44
- public String getBinding();
46
+ public long getBinding();
45
47
 
46
- public void readInboundData (ByteBuffer dst);
48
+ public void readInboundData (ByteBuffer dst) throws IOException;
47
49
 
50
+ public void register() throws ClosedChannelException;
51
+
48
52
  /**
49
53
  * This is called by the reactor after it finishes running.
50
54
  * The idea is to free network resources.
51
55
  */
52
56
  public void close();
53
57
 
54
- public boolean writeOutboundData();
58
+ public boolean writeOutboundData() throws IOException;
55
59
 
56
60
  public void setCommInactivityTimeout (long seconds);
61
+
62
+ public Object[] getPeerName();
63
+
64
+ public boolean isWatchOnly();
65
+
66
+ public boolean isNotifyReadable();
67
+ public boolean isNotifyWritable();
68
+
57
69
  }
@@ -50,14 +50,14 @@ public class EventableDatagramChannel implements EventableChannel {
50
50
  }
51
51
 
52
52
  DatagramChannel channel;
53
- String binding;
53
+ long binding;
54
54
  Selector selector;
55
55
  boolean bCloseScheduled;
56
56
  LinkedList<Packet> outboundQ;
57
57
  SocketAddress returnAddress;
58
58
 
59
59
 
60
- public EventableDatagramChannel (DatagramChannel dc, String _binding, Selector sel) throws ClosedChannelException {
60
+ public EventableDatagramChannel (DatagramChannel dc, long _binding, Selector sel) throws ClosedChannelException {
61
61
  channel = dc;
62
62
  binding = _binding;
63
63
  selector = sel;
@@ -89,18 +89,23 @@ public class EventableDatagramChannel implements EventableChannel {
89
89
  }
90
90
  }
91
91
 
92
- public void scheduleClose (boolean afterWriting) {
92
+ public boolean scheduleClose (boolean afterWriting) {
93
93
  System.out.println ("NOT SCHEDULING CLOSE ON DATAGRAM");
94
+ return false;
94
95
  }
95
96
 
96
97
  public void startTls() {
97
98
  throw new RuntimeException ("TLS is unimplemented on this Channel");
98
99
  }
99
100
 
100
- public String getBinding() {
101
+ public long getBinding() {
101
102
  return binding;
102
103
  }
103
-
104
+
105
+ public void register() throws ClosedChannelException {
106
+ // TODO
107
+ }
108
+
104
109
  /**
105
110
  * Terminate with extreme prejudice. Don't assume there will be another pass through
106
111
  * the reactor core.
@@ -168,4 +173,17 @@ public class EventableDatagramChannel implements EventableChannel {
168
173
  // TODO
169
174
  System.out.println ("DATAGRAM: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
170
175
  }
176
+
177
+ public Object[] getPeerName () {
178
+ if (returnAddress != null) {
179
+ InetSocketAddress inetAddr = (InetSocketAddress) returnAddress;
180
+ return new Object[]{ inetAddr.getPort(), inetAddr.getHostName() };
181
+ } else {
182
+ return null;
183
+ }
184
+ }
185
+
186
+ public boolean isWatchOnly() { return false; }
187
+ public boolean isNotifyReadable() { return false; }
188
+ public boolean isNotifyWritable() { return false; }
171
189
  }
@@ -40,71 +40,139 @@ import java.nio.channels.*;
40
40
  import java.nio.*;
41
41
  import java.util.*;
42
42
  import java.io.*;
43
+ import java.net.Socket;
43
44
  import javax.net.ssl.*;
44
45
  import javax.net.ssl.SSLEngineResult.*;
46
+ import java.lang.reflect.Field;
45
47
 
46
48
  import java.security.*;
47
49
 
48
50
  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
51
  Selector selector;
52
+ SelectionKey channelKey;
53
+ SocketChannel channel;
54
+
55
+ long binding;
54
56
  LinkedList<ByteBuffer> outboundQ;
57
+
55
58
  boolean bCloseScheduled;
56
59
  boolean bConnectPending;
60
+ boolean bWatchOnly;
61
+ boolean bAttached;
62
+ boolean bNotifyReadable;
63
+ boolean bNotifyWritable;
57
64
 
58
65
  SSLEngine sslEngine;
59
-
60
-
61
66
  SSLContext sslContext;
62
67
 
63
-
64
- public EventableSocketChannel (SocketChannel sc, String _binding, Selector sel) throws ClosedChannelException {
68
+ public EventableSocketChannel (SocketChannel sc, long _binding, Selector sel) {
65
69
  channel = sc;
66
70
  binding = _binding;
67
71
  selector = sel;
68
72
  bCloseScheduled = false;
69
73
  bConnectPending = false;
74
+ bWatchOnly = false;
75
+ bAttached = false;
76
+ bNotifyReadable = false;
77
+ bNotifyWritable = false;
70
78
  outboundQ = new LinkedList<ByteBuffer>();
71
-
72
- sc.register(selector, SelectionKey.OP_READ, this);
73
79
  }
74
80
 
75
- public String getBinding() {
81
+ public long getBinding() {
76
82
  return binding;
77
83
  }
78
-
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
+
79
96
  /**
80
97
  * Terminate with extreme prejudice. Don't assume there will be another pass through
81
98
  * the reactor core.
82
99
  */
83
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
+
84
136
  try {
85
137
  channel.close();
86
138
  } catch (IOException e) {
87
139
  }
88
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
+ }
89
158
 
90
159
  public void scheduleOutboundData (ByteBuffer bb) {
91
- try {
92
- if ((!bCloseScheduled) && (bb.remaining() > 0)) {
93
- if (sslEngine != null) {
160
+ if (!bCloseScheduled && bb.remaining() > 0) {
161
+ if (sslEngine != null) {
162
+ try {
94
163
  ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer.
95
164
  sslEngine.wrap(bb, b);
96
165
  b.flip();
97
166
  outboundQ.addLast(b);
167
+ } catch (SSLException e) {
168
+ throw new RuntimeException ("ssl error");
98
169
  }
99
- else {
100
- outboundQ.addLast(bb);
101
- }
102
- channel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ | (bConnectPending ? SelectionKey.OP_CONNECT : 0), this);
103
170
  }
104
- } catch (ClosedChannelException e) {
105
- throw new RuntimeException ("no outbound data");
106
- } catch (SSLException e) {
107
- throw new RuntimeException ("no outbound data");
171
+ else {
172
+ outboundQ.addLast(bb);
173
+ }
174
+
175
+ updateEvents();
108
176
  }
109
177
  }
110
178
 
@@ -115,17 +183,14 @@ public class EventableSocketChannel implements EventableChannel {
115
183
  /**
116
184
  * Called by the reactor when we have selected readable.
117
185
  */
118
- public void readInboundData (ByteBuffer bb) {
119
- try {
120
- channel.read(bb);
121
- } catch (IOException e) {
122
- throw new RuntimeException ("i/o error");
123
- }
186
+ public void readInboundData (ByteBuffer bb) throws IOException {
187
+ if (channel.read(bb) == -1)
188
+ throw new IOException ("eof");
124
189
  }
190
+
125
191
  /**
126
192
  * Called by the reactor when we have selected writable.
127
193
  * 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
194
  * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
130
195
  * possible to become unwritable between the poll and when we get here. The way
131
196
  * this code is written, we're depending on a nonblocking write NOT TO CONSUME
@@ -135,16 +200,11 @@ public class EventableSocketChannel implements EventableChannel {
135
200
  * Ought to be a big performance enhancer.
136
201
  * @return
137
202
  */
138
- public boolean writeOutboundData(){
203
+ public boolean writeOutboundData() throws IOException {
139
204
  while (!outboundQ.isEmpty()) {
140
205
  ByteBuffer b = outboundQ.getFirst();
141
- try {
142
- if (b.remaining() > 0)
143
- channel.write(b);
144
- }
145
- catch (IOException e) {
146
- return false;
147
- }
206
+ if (b.remaining() > 0)
207
+ channel.write(b);
148
208
 
149
209
  // Did we consume the whole outbound buffer? If yes,
150
210
  // pop it off and keep looping. If no, the outbound network
@@ -155,52 +215,47 @@ public class EventableSocketChannel implements EventableChannel {
155
215
  break;
156
216
  }
157
217
 
158
- if (outboundQ.isEmpty()) {
159
- try {
160
- channel.register(selector, SelectionKey.OP_READ, this);
161
- } catch (ClosedChannelException e) {
162
- }
218
+ if (outboundQ.isEmpty() && !bCloseScheduled) {
219
+ updateEvents();
163
220
  }
164
-
221
+
165
222
  // ALWAYS drain the outbound queue before triggering a connection close.
166
223
  // If anyone wants to close immediately, they're responsible for clearing
167
224
  // the outbound queue.
168
225
  return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
169
226
  }
170
227
 
171
- public void setConnectPending() throws ClosedChannelException {
172
- channel.register(selector, SelectionKey.OP_CONNECT, this);
228
+ public void setConnectPending() {
173
229
  bConnectPending = true;
230
+ updateEvents();
174
231
  }
175
232
 
176
233
  /**
177
234
  * Called by the reactor when we have selected connectable.
178
235
  * Return false to indicate an error that should cause the connection to close.
179
- * @throws ClosedChannelException
180
236
  */
181
- public boolean finishConnecting() throws ClosedChannelException {
182
- try {
183
- channel.finishConnect();
184
- }
185
- catch (IOException e) {
186
- return false;
187
- }
237
+ public boolean finishConnecting() throws IOException {
238
+ channel.finishConnect();
239
+
188
240
  bConnectPending = false;
189
- channel.register(selector, SelectionKey.OP_READ | (outboundQ.isEmpty() ? 0 : SelectionKey.OP_WRITE), this);
241
+ updateEvents();
190
242
  return true;
191
243
  }
192
244
 
193
- public void scheduleClose (boolean afterWriting) {
245
+ public boolean scheduleClose (boolean afterWriting) {
194
246
  // TODO: What the hell happens here if bConnectPending is set?
195
247
  if (!afterWriting)
196
248
  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.
249
+
250
+ if (outboundQ.isEmpty())
251
+ return true;
252
+ else {
253
+ updateEvents();
254
+ bCloseScheduled = true;
255
+ return false;
201
256
  }
202
- bCloseScheduled = true;
203
257
  }
258
+
204
259
  public void startTls() {
205
260
  if (sslEngine == null) {
206
261
  try {
@@ -241,4 +296,69 @@ public class EventableSocketChannel implements EventableChannel {
241
296
  // TODO
242
297
  System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
243
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
+ }
244
364
  }
@@ -29,7 +29,7 @@
29
29
  /**
30
30
  *
31
31
  */
32
- package com.rubyeventmachine;
32
+ package com.rubyeventmachine.application;
33
33
 
34
34
  import java.nio.ByteBuffer;
35
35
  import java.nio.channels.*;
@@ -38,6 +38,8 @@ import java.io.*;
38
38
  import java.net.*;
39
39
  import java.net.SocketAddress;
40
40
 
41
+ import com.rubyeventmachine.*;
42
+
41
43
  /**
42
44
  * @author francis
43
45
  *
@@ -48,25 +50,23 @@ public class Application {
48
50
  public class Reactor extends EmReactor {
49
51
 
50
52
  private Application application;
51
- private TreeMap<String, Timer> timers;
52
- private TreeMap<String, Connection> connections;
53
- private TreeMap<String, ConnectionFactory> acceptors;
53
+ private TreeMap<Long, Timer> timers;
54
+ private TreeMap<Long, Connection> connections;
55
+ private TreeMap<Long, ConnectionFactory> acceptors;
54
56
  /**
55
57
  *
56
58
  */
57
59
  public Reactor (Application app) {
58
60
  application = app;
59
- timers = new TreeMap<String, Timer>();
60
- connections = new TreeMap<String, Connection>();
61
- acceptors = new TreeMap<String, ConnectionFactory>();
61
+ timers = new TreeMap<Long, Timer>();
62
+ connections = new TreeMap<Long, Connection>();
63
+ acceptors = new TreeMap<Long, ConnectionFactory>();
62
64
  }
63
65
 
64
66
 
65
- public void eventCallback (String sig, int eventType, ByteBuffer data) {
67
+ public void eventCallback (long sig, int eventType, ByteBuffer data, long data2) {
66
68
  if (eventType == EM_TIMER_FIRED) {
67
- String timersig = new String (data.array());
68
- //System.out.println ("EVSIG "+sig + "..."+new String(data.array()));
69
- Timer r = timers.remove(timersig);
69
+ Timer r = timers.remove(data2);
70
70
  if (r != null)
71
71
  r._fire();
72
72
  else
@@ -93,7 +93,7 @@ public class Application {
93
93
  ConnectionFactory f = acceptors.get(sig);
94
94
  if (f != null) {
95
95
  Connection c = f.connection();
96
- c.signature = new String (data.array());
96
+ c.signature = data2;
97
97
  c.application = application;
98
98
  connections.put(c.signature, c);
99
99
  c.postInit();
@@ -124,19 +124,17 @@ public class Application {
124
124
  public void addTimer (double seconds, Timer t) {
125
125
  t.application = this;
126
126
  t.interval = seconds;
127
- String s = reactor.installOneshotTimer ((int)(seconds * 1000));
127
+ long s = reactor.installOneshotTimer ((int)(seconds * 1000));
128
128
  reactor.timers.put(s, t);
129
129
 
130
130
  }
131
131
 
132
132
  public void bindConnect (String bindAddr, int bindPort, String host, int port, Connection c) {
133
- try {
134
- String s = reactor.connectTcpServer(bindAddr, bindPort, host, port);
135
- c.application = this;
136
- c.signature = s;
137
- reactor.connections.put(s, c);
138
- c.postInit();
139
- } catch (ClosedChannelException e) {}
133
+ long s = reactor.connectTcpServer(bindAddr, bindPort, host, port);
134
+ c.application = this;
135
+ c.signature = s;
136
+ reactor.connections.put(s, c);
137
+ c.postInit();
140
138
  }
141
139
 
142
140
  public void connect (String host, int port, Connection c) {
@@ -144,7 +142,7 @@ public class Application {
144
142
  }
145
143
 
146
144
  public void startServer (SocketAddress sa, ConnectionFactory f) throws EmReactorException {
147
- String s = reactor.startTcpServer(sa);
145
+ long s = reactor.startTcpServer(sa);
148
146
  reactor.acceptors.put(s, f);
149
147
  }
150
148
 
@@ -152,9 +150,7 @@ public class Application {
152
150
  reactor.stop();
153
151
  }
154
152
  public void run() {
155
- try {
156
- reactor.run();
157
- } catch (IOException e) {}
153
+ reactor.run();
158
154
  }
159
155
  public void run (final Runnable r) {
160
156
  addTimer(0, new Timer() {
@@ -165,20 +161,18 @@ public class Application {
165
161
  run();
166
162
  }
167
163
 
168
- public void sendData (String sig, ByteBuffer bb) {
164
+ public void sendData (long sig, ByteBuffer bb) {
169
165
  try {
170
166
  reactor.sendData(sig, bb);
171
167
  } catch (IOException e) {}
172
168
  }
173
169
 
174
- public void sendDatagram (String sig, ByteBuffer bb, InetSocketAddress target) {
170
+ public void sendDatagram (long sig, ByteBuffer bb, InetSocketAddress target) {
175
171
  reactor.sendDatagram(sig, bb, target.getHostName(), target.getPort());
176
172
  }
177
173
 
178
- public void closeConnection (String sig, boolean afterWriting) {
179
- try {
180
- reactor.closeConnection(sig, afterWriting);
181
- } catch (ClosedChannelException e) {}
174
+ public void closeConnection (long sig, boolean afterWriting) {
175
+ reactor.closeConnection(sig, afterWriting);
182
176
  }
183
177
 
184
178
  public void openDatagramSocket (Connection c) {
@@ -186,7 +180,7 @@ public class Application {
186
180
  }
187
181
  public void openDatagramSocket (InetSocketAddress addr, Connection c) {
188
182
  try {
189
- String s = reactor.openUdpSocket(addr);
183
+ long s = reactor.openUdpSocket(addr);
190
184
  c.application = this;
191
185
  c.signature = s;
192
186
  reactor.connections.put(s, c);