You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/03/09 05:12:05 UTC
svn commit: r156607 - in
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io:
datagram/DatagramAcceptor.java filter/SSLByteBufferPool.java
filter/SSLFilter.java filter/SSLHandler.java socket/SocketAcceptor.java
Author: trustin
Date: Tue Mar 8 20:12:03 2005
New Revision: 156607
URL: http://svn.apache.org/viewcvs?view=rev&rev=156607
Log:
* Merged Jan's SSL fixes
* Fixed: SSLHandler.unwrap() cannot unwrap if the buffer contains multiple encrypted chunks.
* Separated unwrap() into unwrap() and unwrapHandshake()
Modified:
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/datagram/DatagramAcceptor.java
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLByteBufferPool.java
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLFilter.java
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLHandler.java
incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/socket/SocketAcceptor.java
Modified: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/datagram/DatagramAcceptor.java
URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/datagram/DatagramAcceptor.java?view=diff&r1=156606&r2=156607
==============================================================================
--- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/datagram/DatagramAcceptor.java (original)
+++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/datagram/DatagramAcceptor.java Tue Mar 8 20:12:03 2005
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
-import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
@@ -32,9 +31,9 @@
import java.util.Set;
import org.apache.mina.common.ByteBuffer;
-import org.apache.mina.io.IoAcceptor;
import org.apache.mina.io.DefaultExceptionMonitor;
import org.apache.mina.io.ExceptionMonitor;
+import org.apache.mina.io.IoAcceptor;
import org.apache.mina.io.IoHandler;
import org.apache.mina.io.IoHandlerFilter;
import org.apache.mina.util.IoHandlerFilterManager;
@@ -92,30 +91,14 @@
if( ( ( InetSocketAddress ) address ).getPort() == 0 )
throw new IllegalArgumentException( "Unsupported port number: 0" );
- DatagramChannel ch = DatagramChannel.open();
- boolean bound = false;
- try
+ RegistrationRequest request = new RegistrationRequest( address, handler );
+ synchronized( registerQueue )
{
- ch.configureBlocking( false );
- ch.socket().bind( address );
- bound = true;
- }
- finally
- {
- if( !bound )
- {
- ch.close();
- }
+ registerQueue.push( request );
}
synchronized( this )
{
- synchronized( registerQueue )
- {
- registerQueue.push( new RegistrationRequest( ch, handler ) );
- }
- channels.put( address, ch );
-
if( worker == null )
{
worker = new Worker();
@@ -124,6 +107,25 @@
}
selector.wakeup();
+
+ synchronized( request )
+ {
+ while( !request.done )
+ {
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+ }
+
+ if( request.exception != null )
+ {
+ throw request.exception;
+ }
}
public void unbind( SocketAddress address )
@@ -131,25 +133,27 @@
if( address == null )
throw new NullPointerException( "address" );
- DatagramChannel ch;
-
- synchronized( this )
+ CancellationRequest request = new CancellationRequest( address );
+ synchronized( cancelQueue )
{
- ch = ( DatagramChannel ) channels.get( address );
-
- if( ch == null )
- return;
+ cancelQueue.push( request );
+ }
- SelectionKey key = ch.keyFor( selector );
- channels.remove( address );
- synchronized( cancelQueue )
+ selector.wakeup();
+
+ synchronized( request )
+ {
+ while( !request.done )
{
- cancelQueue.push( key );
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ }
}
}
-
- selector.wakeup();
- ch.socket().close();
}
public void flushSession( DatagramSession session )
@@ -380,7 +384,7 @@
}
}
- private void registerNew() throws ClosedChannelException
+ private void registerNew()
{
if( registerQueue.isEmpty() )
return;
@@ -396,8 +400,39 @@
if( req == null )
break;
- req.channel
- .register( selector, SelectionKey.OP_READ, req.handler );
+ DatagramChannel ch = null;
+ try
+ {
+ ch = DatagramChannel.open();
+ ch.configureBlocking( false );
+ ch.socket().bind( req.address );
+ ch.register( selector, SelectionKey.OP_READ, req.handler );
+ channels.put( req.address, ch );
+ }
+ catch( IOException e )
+ {
+ req.exception = e;
+ }
+ finally
+ {
+ synchronized( req )
+ {
+ req.done = true;
+ req.notify();
+ }
+
+ if( ch != null && req.exception != null )
+ {
+ try
+ {
+ ch.close();
+ }
+ catch( IOException e )
+ {
+ exceptionMonitor.exceptionCaught( this, e );
+ }
+ }
+ }
}
}
@@ -408,18 +443,41 @@
for( ;; )
{
- SelectionKey key;
+ CancellationRequest request;
synchronized( cancelQueue )
{
- key = ( SelectionKey ) cancelQueue.pop();
+ request = ( CancellationRequest ) cancelQueue.pop();
}
-
- if( key == null )
+
+ if( request == null )
+ {
break;
- else
+ }
+
+ DatagramChannel ch = ( DatagramChannel ) channels.get( request.address );
+ if( ch == null )
+ continue;
+
+ SelectionKey key = ch.keyFor( selector );
+ key.cancel();
+ selector.wakeup(); // wake up again to trigger thread death
+
+ // close the channel
+ try
+ {
+ ch.close();
+ }
+ catch( IOException e )
+ {
+ exceptionMonitor.exceptionCaught( this, e );
+ }
+ finally
{
- key.cancel();
- selector.wakeup(); // wake up again to trigger thread death
+ synchronized( request )
+ {
+ request.done = true;
+ request.notify();
+ }
}
}
}
@@ -446,15 +504,30 @@
private static class RegistrationRequest
{
- private final DatagramChannel channel;
-
+ private final SocketAddress address;
+
private final IoHandler handler;
-
- private RegistrationRequest( DatagramChannel channel,
- IoHandler handler )
+
+ private IOException exception;
+
+ private boolean done;
+
+ private RegistrationRequest( SocketAddress address, IoHandler handler )
{
- this.channel = channel;
+ this.address = address;
this.handler = handler;
+ }
+ }
+
+ private static class CancellationRequest
+ {
+ private final SocketAddress address;
+
+ private boolean done;
+
+ private CancellationRequest( SocketAddress address )
+ {
+ this.address = address;
}
}
Modified: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLByteBufferPool.java
URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLByteBufferPool.java?view=diff&r1=156606&r2=156607
==============================================================================
--- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLByteBufferPool.java (original)
+++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLByteBufferPool.java Tue Mar 8 20:12:03 2005
@@ -58,7 +58,7 @@
*
* @param sslEngine SSLEngine
*/
- static void initiate( SSLEngine sslEngine )
+ static synchronized void initiate( SSLEngine sslEngine )
{
if( !initiated )
{
@@ -71,7 +71,11 @@
}
// init buffer sizes from SSLEngine
packetBufferSize = sslEngine.getSession().getPacketBufferSize();
- appBufferSize = sslEngine.getSession().getApplicationBufferSize();
+
+ // application buffer size has been doubled because SSLEngine
+ // returns BUFFER_OVERFLOW even if there is enough room for the buffer.
+ // So I doubled the size as a workaround.
+ appBufferSize = sslEngine.getSession().getApplicationBufferSize() * 2;
initiateBufferStacks();
initiated = true;
}
Modified: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLFilter.java
URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLFilter.java?view=diff&r1=156606&r2=156607
==============================================================================
--- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLFilter.java (original)
+++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLFilter.java Tue Mar 8 20:12:03 2005
@@ -156,6 +156,11 @@
SSLHandler sslHandler = getSSLSessionHandler( session );
if( sslHandler != null )
{
+ if( debug != null )
+ {
+ debug.print( "Data Read: " + sslHandler + " ("
+ + buf.getHexDump() + ')' );
+ }
synchronized( sslHandler )
{
try
@@ -165,6 +170,16 @@
// Handle data to be forwarded to application or written to net
handleSSLData( nextHandler, session, sslHandler );
+
+ if( sslHandler.isClosed() )
+ {
+ if( debug != null )
+ {
+ debug
+ .print( "SSL Session closed. Closing connection.." );
+ }
+ session.close();
+ }
}
catch( SSLException ssle )
{
@@ -196,6 +211,10 @@
{
SSLHandler sslHandler = getSSLSessionHandler( session );
+ if( debug != null )
+ {
+ debug.print( "Filtered Write: " + sslHandler );
+ }
if( sslHandler != null )
{
synchronized( sslHandler )
@@ -221,7 +240,12 @@
sslHandler.encrypt( buf.buf() );
ByteBuffer encryptedBuffer = copy( sslHandler
.getOutNetBuffer() );
- //debug("encrypted data: {0}", encryptedBuffer.getHexDump());
+
+ if( debug != null )
+ {
+ debug.print( "encrypted data: "
+ + encryptedBuffer.getHexDump() );
+ }
return encryptedBuffer;
}
catch( SSLException ssle )
@@ -236,6 +260,7 @@
}
// Utiliities
+
private void handleSSLData( IoHandler nextHandler, IoSession session,
SSLHandler sslHandler ) throws SSLException
{
@@ -258,9 +283,8 @@
ByteBuffer readBuffer = copy( sslHandler.getAppBuffer() );
if( debug != null )
{
- debug.print( "app data read: " + readBuffer );
+ debug.print( "app data read: " + readBuffer + " (" + readBuffer.getHexDump() + ')' );
}
- //debug("app data: {0}", readBuffer.getHexDump());
nextHandler.dataRead( session, readBuffer );
}
}
@@ -387,7 +411,7 @@
* This will print out the messages to Commons-Logging or stdout.
*/
static final Debug ON = new DebugOn();
-
+
/**
* This will suppress debug messages.
*/
Modified: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLHandler.java
URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLHandler.java?view=diff&r1=156606&r2=156607
==============================================================================
--- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLHandler.java (original)
+++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/filter/SSLHandler.java Tue Mar 8 20:12:03 2005
@@ -131,6 +131,14 @@
}
/**
+ * Check if SSL sesssion closed
+ */
+ public boolean isClosed()
+ {
+ return closed;
+ }
+
+ /**
* Check if there is any need to complete initial handshake.
*/
public boolean needToCompleteInitialHandshake()
@@ -212,7 +220,10 @@
*/
public void shutdown() throws SSLException
{
- doShutdown();
+ if( !shutdown )
+ {
+ doShutdown();
+ }
}
/**
@@ -244,12 +255,24 @@
throw new IllegalStateException();
}
- SSLEngineResult.Status status = unwrap();
- if( status != SSLEngineResult.Status.OK
- && status != SSLEngineResult.Status.CLOSED )
+ unwrap();
+ }
+
+ /**
+ * @param status
+ * @throws SSLException
+ */
+ private SSLEngineResult.Status checkStatus( SSLEngineResult.Status status ) throws SSLException
+ {
+ if( status != SSLEngineResult.Status.OK &&
+ status != SSLEngineResult.Status.CLOSED &&
+ status != SSLEngineResult.Status.BUFFER_UNDERFLOW )
{
- throw new SSLException( "Unexpected SSLEngineResult: " + status );
+ throw new SSLException( "SSLEngine error during decrypt: " +
+ status );
}
+
+ return status;
}
private void doEncrypt( ByteBuffer src ) throws SSLException
@@ -266,7 +289,7 @@
outNetBuffer.flip();
- if ( result.getStatus() == SSLEngineResult.Status.OK )
+ if( result.getStatus() == SSLEngineResult.Status.OK )
{
if( result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK )
{
@@ -275,7 +298,7 @@
}
else
{
- throw new SSLException( "SSLEngine error during data write: "
+ throw new SSLException( "SSLEngine error during encrypt: "
+ result.getStatus() );
}
}
@@ -292,7 +315,7 @@
}
while( true )
{
- if ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED )
+ if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED )
{
if( parent.debug != null )
{
@@ -301,7 +324,7 @@
initialHandshakeComplete = true;
return;
}
- else if ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_TASK )
+ else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_TASK )
{
if( parent.debug != null )
{
@@ -309,7 +332,7 @@
}
initialHandshakeStatus = doTasks();
}
- else if ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP )
+ else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP )
{
// we need more data read
if( parent.debug != null )
@@ -317,14 +340,15 @@
parent.debug
.print( " initialHandshakeStatus=NEED_UNWRAP" );
}
- SSLEngineResult.Status status = unwrap();
- if( status == SSLEngineResult.Status.BUFFER_UNDERFLOW || closed )
+ SSLEngineResult.Status status = unwrapHandshake();
+ if( status == SSLEngineResult.Status.BUFFER_UNDERFLOW
+ || closed )
{
// We need more data or the session is closed
return;
}
}
- else if ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP )
+ else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP )
{
if( parent.debug != null )
{
@@ -342,6 +366,11 @@
}
outNetBuffer.clear();
SSLEngineResult result = sslEngine.wrap( hsBB, outNetBuffer );
+ if( parent.debug != null )
+ {
+ parent.debug.print( "Wrap res:" + result );
+ }
+
outNetBuffer.flip();
initialHandshakeStatus = result.getHandshakeStatus();
// return to allow data on out buffer being sent
@@ -364,12 +393,12 @@
// Prepare the application buffer to receive decrypted data
appBuffer.clear();
+ // Prepare the net data for reading.
+ inNetBuffer.flip();
+
SSLEngineResult res;
do
{
- // Prepare the net data for reading.
- inNetBuffer.flip();
-
if( parent.debug != null )
{
parent.debug.print( " inNetBuffer: " + inNetBuffer );
@@ -380,48 +409,71 @@
{
parent.debug.print( "Unwrap res:" + res );
}
- // prepare to be written again
- inNetBuffer.compact();
+ }
+ while( res.getStatus() == SSLEngineResult.Status.OK );
- /*
- * Could check here for a renegotation, but we're only
- * doing a simple read/write, and won't have enough state
- * transitions to do a complete handshake, so ignore that
- * possibility.
- */
- SSLEngineResult.Status status = res.getStatus();
- if( status == SSLEngineResult.Status.BUFFER_UNDERFLOW ||
- status == SSLEngineResult.Status.OK )
- {
- if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK )
- {
- doTasks();
- }
- }
- else if( status == SSLEngineResult.Status.CLOSED )
+ // If we are CLOSED, set flag
+ if( res.getStatus() == SSLEngineResult.Status.CLOSED )
+ {
+ closed = true;
+ }
+
+ // prepare to be written again
+ inNetBuffer.compact();
+ // prepare app data to be read
+ appBuffer.flip();
+
+ /*
+ * The status may be:
+ * OK - Normal operation
+ * OVERFLOW - Should never happen since the application buffer is
+ * sized to hold the maximum packet size.
+ * UNDERFLOW - Need to read more data from the socket. It's normal.
+ * CLOSED - The other peer closed the socket. Also normal.
+ */
+ return checkStatus( res.getStatus() );
+ }
+
+ SSLEngineResult.Status unwrapHandshake() throws SSLException
+ {
+ if( parent.debug != null )
+ {
+ parent.debug.print( "unwrapHandshake()" );
+ }
+ // Prepare the application buffer to receive decrypted data
+ appBuffer.clear();
+
+ // Prepare the net data for reading.
+ inNetBuffer.flip();
+
+ SSLEngineResult res;
+ do
+ {
+ if( parent.debug != null )
{
- if( parent.debug != null )
- {
- parent.debug.print( "Closed while unwrapping" );
- }
- break;
+ parent.debug.print( " inNetBuffer: " + inNetBuffer );
+ parent.debug.print( " appBuffer: " + appBuffer );
}
- else
+ res = sslEngine.unwrap( inNetBuffer, appBuffer );
+ if( parent.debug != null )
{
- throw new SSLException( "SSLEngine error during data read: "
- + res.getStatus() );
+ parent.debug.print( "Unwrap res:" + res );
}
+
}
- while( ( inNetBuffer.position() != 0 )
- && res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW );
+ while( res.getStatus() == SSLEngineResult.Status.OK &&
+ res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP );
// If we are CLOSED, set flag
if( res.getStatus() == SSLEngineResult.Status.CLOSED )
{
closed = true;
}
+
+ // prepare to be written again
+ inNetBuffer.compact();
- // prepare app datat to be read
+ // prepare app data to be read
appBuffer.flip();
/*
@@ -433,7 +485,7 @@
* CLOSED - The other peer closed the socket. Also normal.
*/
initialHandshakeStatus = res.getHandshakeStatus();
- return res.getStatus();
+ return checkStatus( res.getStatus() );
}
/**
Modified: incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/socket/SocketAcceptor.java
URL: http://svn.apache.org/viewcvs/incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/socket/SocketAcceptor.java?view=diff&r1=156606&r2=156607
==============================================================================
--- incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/socket/SocketAcceptor.java (original)
+++ incubator/directory/network/mina/trunk/src/java/org/apache/mina/io/socket/SocketAcceptor.java Tue Mar 8 20:12:03 2005
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
-import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
@@ -31,9 +30,9 @@
import java.util.List;
import java.util.Map;
-import org.apache.mina.io.IoAcceptor;
import org.apache.mina.io.DefaultExceptionMonitor;
import org.apache.mina.io.ExceptionMonitor;
+import org.apache.mina.io.IoAcceptor;
import org.apache.mina.io.IoHandler;
import org.apache.mina.io.IoHandlerFilter;
import org.apache.mina.util.IoHandlerFilterManager;
@@ -102,30 +101,14 @@
if( ( ( InetSocketAddress ) address ).getPort() == 0 )
throw new IllegalArgumentException( "Unsupported port number: 0" );
- ServerSocketChannel ssc = ServerSocketChannel.open();
- boolean bound = false;
- try
+ RegistrationRequest request = new RegistrationRequest( address, backlog, handler );
+ synchronized( registerQueue )
{
- ssc.configureBlocking( false );
- ssc.socket().bind( address, backlog );
- bound = true;
- }
- finally
- {
- if( !bound )
- {
- ssc.close();
- }
+ registerQueue.push( request );
}
synchronized( this )
{
- synchronized( registerQueue )
- {
- registerQueue.push( new RegistrationRequest( ssc, handler ) );
- }
- channels.put( address, ssc );
-
if( worker == null )
{
worker = new Worker();
@@ -134,39 +117,52 @@
}
selector.wakeup();
+
+ synchronized( request )
+ {
+ while( !request.done )
+ {
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+ }
+
+ if( request.exception != null )
+ {
+ throw request.exception;
+ }
}
public void unbind( SocketAddress address )
{
if( address == null )
throw new NullPointerException( "address" );
-
- ServerSocketChannel ssc;
-
- synchronized( this )
+
+ CancellationRequest request = new CancellationRequest( address );
+ synchronized( cancelQueue )
{
- ssc = ( ServerSocketChannel ) channels.get( address );
-
- if( ssc == null )
- return;
-
- SelectionKey key = ssc.keyFor( selector );
- channels.remove( address );
- synchronized( cancelQueue )
- {
- cancelQueue.push( key );
- }
+ cancelQueue.push( request );
}
selector.wakeup();
- try
- {
- ssc.close();
- }
- catch( IOException e )
+ synchronized( request )
{
- exceptionMonitor.exceptionCaught( this, e );
+ while( !request.done )
+ {
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
}
}
@@ -243,7 +239,7 @@
}
}
- private void registerNew() throws ClosedChannelException
+ private void registerNew()
{
if( registerQueue.isEmpty() )
return;
@@ -259,8 +255,40 @@
if( req == null )
break;
- req.channel.register( selector, SelectionKey.OP_ACCEPT,
- req.handler );
+ ServerSocketChannel ssc = null;
+ try
+ {
+ ssc = ServerSocketChannel.open();
+ ssc.configureBlocking( false );
+ ssc.socket().bind( req.address, req.backlog );
+ ssc.register( selector, SelectionKey.OP_ACCEPT,
+ req.handler );
+ channels.put( req.address, ssc );
+ }
+ catch( IOException e )
+ {
+ req.exception = e;
+ }
+ finally
+ {
+ synchronized( req )
+ {
+ req.done = true;
+ req.notify();
+ }
+
+ if( ssc != null && req.exception != null )
+ {
+ try
+ {
+ ssc.close();
+ }
+ catch( IOException e )
+ {
+ exceptionMonitor.exceptionCaught( this, e );
+ }
+ }
+ }
}
}
@@ -271,18 +299,41 @@
for( ;; )
{
- SelectionKey key;
+ CancellationRequest request;
synchronized( cancelQueue )
{
- key = ( SelectionKey ) cancelQueue.pop();
+ request = ( CancellationRequest ) cancelQueue.pop();
}
-
- if( key == null )
+
+ if( request == null )
+ {
break;
- else
+ }
+
+ ServerSocketChannel ssc = ( ServerSocketChannel ) channels.get( request.address );
+ if( ssc == null )
+ continue;
+
+ SelectionKey key = ssc.keyFor( selector );
+ key.cancel();
+ selector.wakeup(); // wake up again to trigger thread death
+
+ // close the channel
+ try
{
- key.cancel();
- selector.wakeup(); // wake up again to trigger thread death
+ ssc.close();
+ }
+ catch( IOException e )
+ {
+ exceptionMonitor.exceptionCaught( this, e );
+ }
+ finally
+ {
+ synchronized( request )
+ {
+ request.done = true;
+ request.notify();
+ }
}
}
}
@@ -309,15 +360,34 @@
private static class RegistrationRequest
{
- private final ServerSocketChannel channel;
+ private final SocketAddress address;
+
+ private final int backlog;
private final IoHandler handler;
-
- private RegistrationRequest( ServerSocketChannel channel,
- IoHandler handler )
+
+ private IOException exception;
+
+ private boolean done;
+
+ private RegistrationRequest( SocketAddress address, int backlog,
+ IoHandler handler )
{
- this.channel = channel;
+ this.address = address;
+ this.backlog = backlog;
this.handler = handler;
+ }
+ }
+
+ private static class CancellationRequest
+ {
+ private final SocketAddress address;
+
+ private boolean done;
+
+ private CancellationRequest( SocketAddress address )
+ {
+ this.address = address;
}
}