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/10/26 16:04:31 UTC
svn commit: r328648 - in /directory/network/trunk/src:
java/org/apache/mina/common/ java/org/apache/mina/common/support/
java/org/apache/mina/filter/ java/org/apache/mina/filter/support/
test/org/apache/mina/examples/echoserver/
Author: trustin
Date: Wed Oct 26 07:04:21 2005
New Revision: 328648
URL: http://svn.apache.org/viewcvs?rev=328648&view=rev
Log:
Resolving an issue: DIRMINA-106 - Add TLS closure to SSLFilter
* Modified ConntectorTest to test TLS closure
* Added SSLFilter.closeOutbound() to let user send close_notify
* Removed unused flags in SSLHandler
* Added WriteFuture.new(Not)WrittenFuture() method
* Added IoFilterChain.getNextFilter() method
I tested TLS closure work correctly. It worked great.
Modified:
directory/network/trunk/src/java/org/apache/mina/common/IoFilterChain.java
directory/network/trunk/src/java/org/apache/mina/common/WriteFuture.java
directory/network/trunk/src/java/org/apache/mina/common/support/AbstractIoFilterChain.java
directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java
directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java
directory/network/trunk/src/test/org/apache/mina/examples/echoserver/ConnectorTest.java
Modified: directory/network/trunk/src/java/org/apache/mina/common/IoFilterChain.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/common/IoFilterChain.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/common/IoFilterChain.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/common/IoFilterChain.java Wed Oct 26 07:04:21 2005
@@ -46,9 +46,19 @@
* Returns the name of the specified {@link IoFilter} in this chain.
* @return <tt>null</tt> if there's no such filter in this chain.
*/
-
String getName( IoFilter filter );
+ /**
+ * Returns the {@link NextFilter} of the {@link IoFilter} with the specified
+ * <tt>name</tt> in this chain.
+ */
+ NextFilter getNextFilter( String name );
+
+ /**
+ * Returns the {@link NextFilter} of the specified <tt>filter</tt> in this chain.
+ */
+ NextFilter getNextFilter( IoFilter filter );
+
/**
* Returns the list of all filters this chain contains.
*/
Modified: directory/network/trunk/src/java/org/apache/mina/common/WriteFuture.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/common/WriteFuture.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/common/WriteFuture.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/common/WriteFuture.java Wed Oct 26 07:04:21 2005
@@ -27,6 +27,26 @@
public class WriteFuture extends IoFuture
{
/**
+ * Returns a new {@link WriteFuture} which is already marked as 'written'.
+ */
+ public static WriteFuture newWrittenFuture()
+ {
+ WriteFuture unwrittenFuture = new WriteFuture();
+ unwrittenFuture.setWritten( true );
+ return unwrittenFuture;
+ }
+
+ /**
+ * Returns a new {@link WriteFuture} which is already marked as 'not written'.
+ */
+ public static WriteFuture newNotWrittenFuture()
+ {
+ WriteFuture unwrittenFuture = new WriteFuture();
+ unwrittenFuture.setWritten( false );
+ return unwrittenFuture;
+ }
+
+ /**
* Returns <tt>true</tt> if the write operation is finished successfully.
*/
public boolean isWritten()
Modified: directory/network/trunk/src/java/org/apache/mina/common/support/AbstractIoFilterChain.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/common/support/AbstractIoFilterChain.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/common/support/AbstractIoFilterChain.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/common/support/AbstractIoFilterChain.java Wed Oct 26 07:04:21 2005
@@ -261,6 +261,27 @@
return e.name;
}
+ public NextFilter getNextFilter( String name )
+ {
+ Entry e = ( Entry ) name2entry.get( name );
+ if ( e == null )
+ {
+ return null;
+ }
+ return e.nextFilter;
+ }
+
+ public NextFilter getNextFilter( IoFilter filter )
+ {
+ Entry e = ( Entry ) filter2entry.get( filter );
+ if( e == null )
+ {
+ return null;
+ }
+
+ return e.nextFilter;
+ }
+
public synchronized void addFirst( String name,
IoFilter filter ) throws Exception
{
Modified: directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java Wed Oct 26 07:04:21 2005
@@ -94,6 +94,8 @@
private static final Logger log = LoggerFactory.getLogger( SSLFilter.class );
+ private IoFilterChain parent;
+
// SSL Context
private SSLContext sslContext;
@@ -125,6 +127,31 @@
{
return ( SSLSession ) session.getAttribute( SSL_SESSION );
}
+
+ /**
+ * Sends TLS <tt>close_notify</tt> message to initiate TLS closure.
+ *
+ * @param session the {@link IoSession} to initiate TLS closure
+ * @throws SSLException if failed to initiate TLS closure
+ * @throws IllegalArgumentException if this filter is not managing the specified session
+ */
+ public WriteFuture closeOutbound( IoSession session ) throws SSLException
+ {
+ SSLHandler handler = getSSLSessionHandler( session );
+ if( handler == null )
+ {
+ // Return a dummy future to prevent NFE.
+ return WriteFuture.newNotWrittenFuture();
+ }
+
+ if( handler.getParent() != this )
+ {
+ throw new IllegalArgumentException( "Not managed by this filter." );
+ }
+
+ NextFilter nextFilter = parent.getNextFilter( this );
+ return initiateClosure( nextFilter, session );
+ }
/**
* Returns <tt>true</tt> if the engine is set to use client mode
@@ -226,12 +253,18 @@
public void init( IoFilterChain parent, NextFilter nextFilter ) throws SSLException
{
+ this.parent = parent;
Object managerOrSession = parent.getParent();
if( managerOrSession instanceof IoSession )
{
createSSLSessionHandler( nextFilter, ( IoSession ) managerOrSession );
}
}
+
+ public void destroy( IoFilterChain parent, NextFilter nextFilter )
+ {
+
+ }
// IoFilter impl.
@@ -244,27 +277,20 @@
public void sessionClosed( NextFilter nextFilter, IoSession session ) throws SSLException
{
- SSLHandler sslHandler = getSSLSessionHandler( session );
if( log.isDebugEnabled() )
{
- log.debug( session + " Closed: " + sslHandler );
+ log.debug( session + " Closed: " + getSSLSessionHandler( session ) );
}
- if( sslHandler != null )
+
+ // release resources
+ try
{
- synchronized( sslHandler )
- {
- // release resources
- removeSSLSessionHandler( session );
- try
- {
- sslHandler.release();
- }
- finally
- {
- // notify closed session
- nextFilter.sessionClosed( session );
- }
- }
+ removeSSLSessionHandler( session );
+ }
+ finally
+ {
+ // notify closed session
+ nextFilter.sessionClosed( session );
}
}
@@ -289,14 +315,22 @@
// Handle data to be forwarded to application or written to net
handleSSLData( nextFilter, session, sslHandler );
- if( sslHandler.isClosed() )
+ if( sslHandler.isInboundDone() )
{
- if( log.isDebugEnabled() )
+ if( sslHandler.isOutboundDone() )
{
- log.debug(
- session + " SSL Session closed. Closing connection.." );
+ if( log.isDebugEnabled() )
+ {
+ log.debug(
+ session + " SSL Session closed." );
+ }
+
+ removeSSLSessionHandler( session );
+ }
+ else
+ {
+ initiateClosure( nextFilter, session );
}
- session.close();
}
}
catch( SSLException ssle )
@@ -413,7 +447,7 @@
{
try
{
- initiateClosure( nextFilter, session );
+ initiateClosure( nextFilter, session ).join();
}
finally
{
@@ -421,37 +455,26 @@
}
}
- private void initiateClosure( NextFilter nextFilter, IoSession session ) throws SSLException
+ private WriteFuture initiateClosure( NextFilter nextFilter, IoSession session ) throws SSLException
{
SSLHandler handler = getSSLSessionHandler( session );
if( handler == null )
{
- return;
+ return WriteFuture.newNotWrittenFuture();
}
- WriteFuture future;
- try
+ synchronized( handler )
{
- synchronized( handler )
+ if( handler.isOutboundDone() )
{
- // shut down
- handler.shutdown();
-
- // there might be data to write out here?
- future = handler.writeNetBuffer( nextFilter, session );
-
- // release buffers
- handler.release();
+ return WriteFuture.newNotWrittenFuture();
}
+
+ // shut down
+ handler.closeOutbound();
- if( future != null )
- {
- future.join();
- }
- }
- finally
- {
- removeSSLSessionHandler( session );
+ // there might be data to write out here?
+ return handler.writeNetBuffer( nextFilter, session );
}
}
@@ -532,9 +555,18 @@
return ( SSLHandler ) session.getAttribute( SSL_HANDLER );
}
- private SSLHandler removeSSLSessionHandler( IoSession session )
+ private void removeSSLSessionHandler( IoSession session )
{
- return ( SSLHandler ) session.removeAttribute( SSL_HANDLER );
+ SSLHandler sslHandler = getSSLSessionHandler( session );
+ if( sslHandler != null )
+ {
+ synchronized( sslHandler )
+ {
+ // release resources
+ session.removeAttribute( SSL_HANDLER );
+ sslHandler.release();
+ }
+ }
}
private static class EncryptedBuffer extends ByteBufferProxy
Modified: directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java Wed Oct 26 07:04:21 2005
@@ -52,11 +52,8 @@
private static final Logger log = LoggerFactory.getLogger( SSLFilter.class );
private final SSLFilter parent;
-
private final IoSession session;
-
private final Queue scheduledWrites = new Queue();
-
private final SSLEngine sslEngine;
/**
@@ -89,14 +86,6 @@
*/
private boolean initialHandshakeComplete;
- /**
- * We have received the shutdown request by our caller, and have
- * closed our outbound side.
- */
- private boolean shutdown = false;
-
- private boolean closed = false;
-
private boolean isWritingEncryptedData = false;
/**
@@ -145,6 +134,11 @@
outNetBuffer.position( 0 );
outNetBuffer.limit( 0 );
}
+
+ public SSLFilter getParent()
+ {
+ return parent;
+ }
/**
* Indicate that we are writing encrypted data.
@@ -171,12 +165,14 @@
return initialHandshakeComplete;
}
- /**
- * Check if SSL sesssion closed
- */
- public boolean isClosed()
+ public boolean isInboundDone()
+ {
+ return sslEngine.isInboundDone();
+ }
+
+ public boolean isOutboundDone()
{
- return closed;
+ return sslEngine.isOutboundDone();
}
/**
@@ -184,7 +180,7 @@
*/
public boolean needToCompleteInitialHandshake()
{
- return ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !closed );
+ return ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone() );
}
public synchronized void scheduleWrite( NextFilter nextFilter, WriteRequest writeRequest )
@@ -295,9 +291,9 @@
*
* @throws SSLException on errors
*/
- public void shutdown() throws SSLException
+ public void closeOutbound() throws SSLException
{
- if( !shutdown )
+ if( !sslEngine.isOutboundDone() )
{
doShutdown();
}
@@ -445,7 +441,7 @@
SSLEngineResult.Status status = unwrapHandshake();
if( ( initialHandshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED
&& status == SSLEngineResult.Status.BUFFER_UNDERFLOW )
- || closed )
+ || isInboundDone() )
{
// We need more data or the session is closed
return;
@@ -494,7 +490,7 @@
if( !getOutNetBuffer().hasRemaining() )
{
// no; bail out
- return null;
+ return WriteFuture.newNotWrittenFuture();
}
WriteFuture writeFuture = null;
@@ -558,7 +554,14 @@
}
}
- return writeFuture;
+ if( writeFuture != null )
+ {
+ return writeFuture;
+ }
+ else
+ {
+ return WriteFuture.newNotWrittenFuture();
+ }
}
@@ -590,12 +593,6 @@
}
while( res.getStatus() == SSLEngineResult.Status.OK );
- // 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
@@ -663,12 +660,6 @@
} while (res.getStatus() == SSLEngineResult.Status.OK);
}
- // If we are CLOSED, set flag
- if( res.getStatus() == SSLEngineResult.Status.CLOSED )
- {
- closed = true;
- }
-
// prepare to be written again
inNetBuffer.compact();
@@ -724,10 +715,9 @@
void doShutdown() throws SSLException
{
- if( !shutdown )
+ if( !sslEngine.isOutboundDone() )
{
sslEngine.closeOutbound();
- shutdown = true;
}
// By RFC 2616, we can "fire and forget" our close_notify
Modified: directory/network/trunk/src/test/org/apache/mina/examples/echoserver/ConnectorTest.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/test/org/apache/mina/examples/echoserver/ConnectorTest.java?rev=328648&r1=328647&r2=328648&view=diff
==============================================================================
--- directory/network/trunk/src/test/org/apache/mina/examples/echoserver/ConnectorTest.java (original)
+++ directory/network/trunk/src/test/org/apache/mina/examples/echoserver/ConnectorTest.java Wed Oct 26 07:04:21 2005
@@ -76,7 +76,7 @@
new SSLFilter( BogusSSLContextFactory.getInstance( true ) );
IoAcceptor acceptor = registry.getAcceptor( TransportType.SOCKET );
acceptor.getFilterChain().addLast( "SSL", acceptorSSLFilter );
-
+
// Create a connector
IoConnector connector = new SocketConnector();
@@ -170,6 +170,11 @@
}
writeFuture.join();
+
+ // Send closeNotify to test TLS closure.
+ SSLFilter sslf = ( SSLFilter ) connector.getFilterChain().get("SSL");
+ sslf.closeOutbound( session ).join();
+
session.close();
Assert.assertEquals( 160, readBuf.position() );