|
7 | 7 | import com.koushikdutta.async.callback.ConnectCallback; |
8 | 8 | import com.koushikdutta.async.callback.ListenCallback; |
9 | 9 | import com.koushikdutta.async.future.Cancellable; |
| 10 | +import com.koushikdutta.async.future.Future; |
| 11 | +import com.koushikdutta.async.future.FutureCallback; |
10 | 12 | import com.koushikdutta.async.future.SimpleCancellable; |
11 | 13 | import com.koushikdutta.async.future.SimpleFuture; |
| 14 | +import com.koushikdutta.async.future.TransformFuture; |
12 | 15 |
|
13 | 16 | import java.io.IOException; |
14 | 17 | import java.net.InetAddress; |
|
20 | 23 | import java.util.LinkedList; |
21 | 24 | import java.util.Set; |
22 | 25 | import java.util.WeakHashMap; |
| 26 | +import java.util.concurrent.ExecutorService; |
| 27 | +import java.util.concurrent.Executors; |
23 | 28 | import java.util.concurrent.Semaphore; |
24 | 29 | import java.util.concurrent.TimeUnit; |
25 | 30 |
|
@@ -365,111 +370,119 @@ public void stop() { |
365 | 370 | } |
366 | 371 | }); |
367 | 372 | } |
368 | | - |
369 | | - private void connectSocketInternal(final SocketChannel socket, final SocketAddress remote, ConnectFuture cancel) { |
370 | | - if (cancel.isCancelled()) |
371 | | - return; |
372 | | - SelectionKey ckey = null; |
373 | | - try { |
374 | | - socket.configureBlocking(false); |
375 | | - ckey = socket.register(mSelector, SelectionKey.OP_CONNECT); |
376 | | - ckey.attach(cancel); |
377 | | - socket.connect(remote); |
378 | | - } |
379 | | - catch (Exception e) { |
380 | | - if (ckey != null) |
381 | | - ckey.cancel(); |
382 | | - if (cancel.setComplete(e)) |
383 | | - cancel.callback.onConnectCompleted(e, null); |
384 | | - } |
385 | | - } |
386 | | - |
| 373 | + |
387 | 374 | private class ConnectFuture extends SimpleFuture<AsyncNetworkSocket> { |
388 | 375 | @Override |
389 | | - public boolean cancel() { |
390 | | - if (!super.cancel()) |
391 | | - return false; |
392 | | - |
| 376 | + protected void cancelCleanup() { |
| 377 | + super.cancelCleanup(); |
393 | 378 | post(new Runnable() { |
394 | 379 | @Override |
395 | 380 | public void run() { |
396 | 381 | try { |
397 | | - socket.close(); |
| 382 | + if (socket != null) |
| 383 | + socket.close(); |
398 | 384 | } |
399 | 385 | catch (IOException e) { |
400 | 386 | } |
401 | 387 | } |
402 | 388 | }); |
403 | | - return true; |
404 | 389 | } |
405 | 390 |
|
406 | 391 | SocketChannel socket; |
407 | 392 | ConnectCallback callback; |
408 | 393 | } |
409 | 394 |
|
410 | | - private ConnectFuture prepareConnectSocketCancelable(final SocketChannel socket, ConnectCallback handler) { |
411 | | - ConnectFuture cancelable = new ConnectFuture(); |
412 | | - cancelable.socket = socket; |
413 | | - cancelable.callback = handler; |
414 | | - return cancelable; |
415 | | - } |
416 | | - |
417 | | - public Cancellable connectSocket(final InetSocketAddress remote, final ConnectCallback handler) { |
418 | | - try { |
419 | | - final SocketChannel socket = SocketChannel.open(); |
420 | | - final ConnectFuture cancel = prepareConnectSocketCancelable(socket, handler); |
421 | | - post(new Runnable() { |
422 | | - @Override |
423 | | - public void run() { |
424 | | - connectSocketInternal(socket, new InetSocketAddress(remote.getHostName(), remote.getPort()), cancel); |
425 | | - } |
426 | | - }); |
427 | | - return cancel; |
428 | | - } |
429 | | - catch (final Exception e) { |
430 | | - post(new Runnable() { |
431 | | - @Override |
432 | | - public void run() { |
433 | | - handler.onConnectCompleted(e, null); |
434 | | - } |
435 | | - }); |
436 | | - return SimpleCancellable.COMPLETED; |
437 | | - } |
438 | | - } |
439 | | - |
440 | | - public Cancellable connectSocket(final String host, final int port, final ConnectCallback handler) { |
441 | | - try { |
442 | | - final SocketChannel socket = SocketChannel.open(); |
443 | | - final ConnectFuture cancel = prepareConnectSocketCancelable(socket, handler); |
| 395 | + private ConnectFuture connectResolvedInetSocketAddress(final InetSocketAddress address, final ConnectCallback callback) { |
| 396 | + final ConnectFuture cancel = new ConnectFuture(); |
| 397 | + assert !address.isUnresolved(); |
444 | 398 |
|
445 | | - post(new Runnable() { |
446 | | - @Override |
447 | | - public void run() { |
448 | | - SocketAddress remote; |
| 399 | + post(new Runnable() { |
| 400 | + @Override |
| 401 | + public void run() { |
| 402 | + if (cancel.isCancelled()) |
| 403 | + return; |
| 404 | + |
| 405 | + cancel.callback = callback; |
| 406 | + SelectionKey ckey = null; |
| 407 | + SocketChannel socket = null; |
| 408 | + try { |
| 409 | + socket = cancel.socket = SocketChannel.open(); |
| 410 | + socket.configureBlocking(false); |
| 411 | + ckey = socket.register(mSelector, SelectionKey.OP_CONNECT); |
| 412 | + ckey.attach(cancel); |
| 413 | + socket.connect(address); |
| 414 | + } |
| 415 | + catch (Exception e) { |
| 416 | + if (ckey != null) |
| 417 | + ckey.cancel(); |
449 | 418 | try { |
450 | | - remote = new InetSocketAddress(host, port); |
| 419 | + if (socket != null) |
| 420 | + socket.close(); |
451 | 421 | } |
452 | | - catch (Exception e) { |
453 | | - if (cancel.setComplete(e)) |
454 | | - handler.onConnectCompleted(e, null); |
455 | | - return; |
| 422 | + catch (Exception ignored) { |
456 | 423 | } |
457 | | - |
458 | | - connectSocketInternal(socket, remote, cancel); |
| 424 | + cancel.setComplete(e); |
459 | 425 | } |
460 | | - }); |
461 | | - |
462 | | - return cancel; |
| 426 | + } |
| 427 | + }); |
| 428 | + |
| 429 | + return cancel; |
| 430 | + } |
| 431 | + |
| 432 | + public Cancellable connectSocket(final InetSocketAddress remote, final ConnectCallback callback) { |
| 433 | + if (!remote.isUnresolved()) |
| 434 | + return connectResolvedInetSocketAddress(remote, callback); |
| 435 | + |
| 436 | + return new TransformFuture<AsyncSocket, InetAddress>() { |
| 437 | + @Override |
| 438 | + protected void transform(InetAddress result) throws Exception { |
| 439 | + setParent(connectResolvedInetSocketAddress(new InetSocketAddress(remote.getHostName(), remote.getPort()), callback)); |
| 440 | + } |
463 | 441 | } |
464 | | - catch (final Exception e) { |
465 | | - post(new Runnable() { |
466 | | - @Override |
467 | | - public void run() { |
468 | | - handler.onConnectCompleted(e, null); |
| 442 | + .from(getByName(remote.getHostName())); |
| 443 | + } |
| 444 | + |
| 445 | + public Cancellable connectSocket(final String host, final int port, final ConnectCallback callback) { |
| 446 | + return connectSocket(InetSocketAddress.createUnresolved(host, port), callback); |
| 447 | + } |
| 448 | + |
| 449 | + ExecutorService synchronousWorkers = Executors.newFixedThreadPool(4); |
| 450 | + public Future<InetAddress[]> getAllByName(final String host) { |
| 451 | + final SimpleFuture<InetAddress[]> ret = new SimpleFuture<InetAddress[]>(); |
| 452 | + synchronousWorkers.execute(new Runnable() { |
| 453 | + @Override |
| 454 | + public void run() { |
| 455 | + try { |
| 456 | + final InetAddress[] result = InetAddress.getAllByName(host); |
| 457 | + if (result == null || result.length == 0) |
| 458 | + throw new Exception("no addresses for host"); |
| 459 | + post(new Runnable() { |
| 460 | + @Override |
| 461 | + public void run() { |
| 462 | + ret.setComplete(null, result); |
| 463 | + } |
| 464 | + }); |
| 465 | + } catch (final Exception e) { |
| 466 | + post(new Runnable() { |
| 467 | + @Override |
| 468 | + public void run() { |
| 469 | + ret.setComplete(e, null); |
| 470 | + } |
| 471 | + }); |
469 | 472 | } |
470 | | - }); |
471 | | - return SimpleCancellable.COMPLETED; |
| 473 | + } |
| 474 | + }); |
| 475 | + return ret; |
| 476 | + } |
| 477 | + |
| 478 | + public Future<InetAddress> getByName(String host) { |
| 479 | + return new TransformFuture<InetAddress, InetAddress[]>() { |
| 480 | + @Override |
| 481 | + protected void transform(InetAddress[] result) throws Exception { |
| 482 | + setComplete(result[0]); |
| 483 | + } |
472 | 484 | } |
| 485 | + .from(getAllByName(host)); |
473 | 486 | } |
474 | 487 |
|
475 | 488 | public AsyncDatagramSocket connectDatagram(final String host, final int port) throws IOException { |
@@ -800,7 +813,7 @@ else if (key.isConnectable()) { |
800 | 813 | catch (Exception ex) { |
801 | 814 | key.cancel(); |
802 | 815 | sc.close(); |
803 | | - if (cancel.setComplete()) |
| 816 | + if (cancel.setComplete(ex)) |
804 | 817 | cancel.callback.onConnectCompleted(ex, null); |
805 | 818 | } |
806 | 819 | } |
|
0 commit comments