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/28 08:00:26 UTC

svn commit: r329113 - in /directory/network/trunk/src/java/org/apache/mina/filter: SSLFilter.java support/SSLHandler.java

Author: trustin
Date: Thu Oct 27 23:00:16 2005
New Revision: 329113

URL: http://svn.apache.org/viewcvs?rev=329113&view=rev
Log:
Fixed some concurrency issues of SSLFilter in a multi-processor machine.

Modified:
    directory/network/trunk/src/java/org/apache/mina/filter/SSLFilter.java
    directory/network/trunk/src/java/org/apache/mina/filter/support/SSLHandler.java

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=329113&r1=329112&r2=329113&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 Thu Oct 27 23:00:16 2005
@@ -149,10 +149,7 @@
 
             if( handler.isOutboundDone() )
             {
-                synchronized( session )
-                {
-                    session.removeAttribute( SSL_HANDLER );
-                }
+                session.removeAttribute( SSL_HANDLER );
             }
             else
             {
@@ -178,10 +175,7 @@
             return true;
         }
         
-        synchronized( handler )
-        {
-            return !handler.isOutboundDone();
-        }
+        return !handler.isOutboundDone();
     }
 
     /**
@@ -393,7 +387,7 @@
                     sslHandler.messageReceived( nextFilter, buf.buf() );
 
                     // Handle data to be forwarded to application or written to net
-                    handleSSLData( nextFilter, session, sslHandler );
+                    handleSSLData( nextFilter, sslHandler );
 
                     if( sslHandler.isInboundDone() )
                     {
@@ -559,16 +553,14 @@
         
         synchronized( handler )
         {
-            if( handler.isOutboundDone() )
+            // shut down
+            if( !handler.closeOutbound() )
             {
                 return WriteFuture.newNotWrittenFuture();
             }
-
-            // shut down
-            handler.closeOutbound();
             
             // there might be data to write out here?
-            WriteFuture future = handler.writeNetBuffer( nextFilter, session );
+            WriteFuture future = handler.writeNetBuffer( nextFilter );
             
             if( handler.isInboundDone() )
             {
@@ -581,8 +573,7 @@
 
     // Utiliities
 
-    private void handleSSLData( NextFilter nextFilter, IoSession session,
-                                SSLHandler handler ) throws SSLException
+    private void handleSSLData( NextFilter nextFilter, SSLHandler handler ) throws SSLException
     {
         // Flush any buffered write requests occurred before handshaking.
         if( handler.isInitialHandshakeComplete() )
@@ -591,29 +582,32 @@
         }
 
         // Write encrypted data to be written (if any)
-        handler.writeNetBuffer( nextFilter, session );
+        handler.writeNetBuffer( nextFilter );
 
         // handle app. data read (if any)
-        handleAppDataRead( nextFilter, session, handler );
+        handleAppDataRead( nextFilter, handler );
     }
 
-    private void handleAppDataRead( NextFilter nextFilter, IoSession session,
-                                   SSLHandler sslHandler )
+    private void handleAppDataRead( NextFilter nextFilter, SSLHandler sslHandler )
     {
+        IoSession session = sslHandler.getSession();
+        if( !sslHandler.getAppBuffer().hasRemaining() )
+        {
+            return;
+        }
+
         if( log.isDebugEnabled() )
         {
             log.debug( session + " appBuffer: " + sslHandler.getAppBuffer() );
         }
-        if( sslHandler.getAppBuffer().hasRemaining() )
+
+        // forward read app data
+        ByteBuffer readBuffer = SSLHandler.copy( sslHandler.getAppBuffer() );
+        if( log.isDebugEnabled() )
         {
-            // forward read app data
-            ByteBuffer readBuffer = SSLHandler.copy( sslHandler.getAppBuffer() );
-            if( log.isDebugEnabled() )
-            {
-                log.debug( session + " app data read: " + readBuffer + " (" + readBuffer.getHexDump() + ')' );
-            }
-            nextFilter.messageReceived( session, readBuffer );
+            log.debug( session + " app data read: " + readBuffer + " (" + readBuffer.getHexDump() + ')' );
         }
+        nextFilter.messageReceived( session, readBuffer );
     }
 
     // Utilities to mainpulate SSLHandler based on IoSession
@@ -661,11 +655,8 @@
         SSLHandler sslHandler = getSSLSessionHandler( session );
         if( sslHandler != null )
         {
-            synchronized( sslHandler )
-            {
-                // release resources
-                sslHandler.release();
-            }
+            // release resources
+            sslHandler.release();
         }
     }
 

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=329113&r1=329112&r2=329113&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 Thu Oct 27 23:00:16 2005
@@ -86,7 +86,7 @@
      */
     private boolean initialHandshakeComplete;
 
-    private boolean isWritingEncryptedData = false;
+    private boolean writingEncryptedData = false;
     
     /**
      * Constuctor.
@@ -139,38 +139,34 @@
     {
         return parent;
     }
-
-    /**
-     * Indicate that we are writing encrypted data.
-     * Only used as a flag by IoSSLFiler
-     */
-    public void setWritingEncryptedData( boolean flag )
+    
+    public IoSession getSession()
     {
-        isWritingEncryptedData = flag;
+        return session;
     }
 
     /**
      * Check we are writing encrypted data.
      */
-    public boolean isWritingEncryptedData()
+    public synchronized boolean isWritingEncryptedData()
     {
-        return isWritingEncryptedData;
+        return writingEncryptedData;
     }
 
     /**
      * Check if initial handshake is completed.
      */
-    public boolean isInitialHandshakeComplete()
+    public synchronized boolean isInitialHandshakeComplete()
     {
         return initialHandshakeComplete;
     }
 
-    public boolean isInboundDone()
+    public synchronized boolean isInboundDone()
     {
         return sslEngine.isInboundDone();
     }
 
-    public boolean isOutboundDone()
+    public synchronized boolean isOutboundDone()
     {
         return sslEngine.isOutboundDone();
     }
@@ -178,7 +174,7 @@
     /**
      * Check if there is any need to complete initial handshake.
      */
-    public boolean needToCompleteInitialHandshake()
+    public synchronized boolean needToCompleteInitialHandshake()
     {
         return ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone() );
     }
@@ -210,7 +206,7 @@
      * @param buf buffer to decrypt
      * @throws SSLException on errors
      */
-    public void messageReceived( NextFilter nextFilter, ByteBuffer buf ) throws SSLException
+    public synchronized void messageReceived( NextFilter nextFilter, ByteBuffer buf ) throws SSLException
     {
         if ( buf.limit() > inNetBuffer.remaining() ) {
             // We have to expand inNetBuffer
@@ -237,7 +233,7 @@
         }
         else
         {
-            doDecrypt();
+            decrypt();
         }
 
         if( isInboundDone() )
@@ -253,7 +249,7 @@
      *
      * @throws SSLException on errors
      */
-    public void continueHandshake( NextFilter nextFilter ) throws SSLException
+    public synchronized void continueHandshake( NextFilter nextFilter ) throws SSLException
     {
         if( log.isDebugEnabled() )
         {
@@ -285,31 +281,87 @@
     /**
      * Encrypt provided buffer. Encytpted data reurned by getOutNetBuffer().
      *
-     * @param buf data to encrypt
+     * @param src data to encrypt
      * @throws SSLException on errors
      */
-    public void encrypt( ByteBuffer buf ) throws SSLException
+    public synchronized void encrypt( ByteBuffer src ) throws SSLException
     {
-        doEncrypt( buf );
+        if( !initialHandshakeComplete )
+        {
+            throw new IllegalStateException();
+        }
+
+        // The data buffer is (must be) empty, we can reuse the entire
+        // buffer.
+        outNetBuffer.clear();
+
+        SSLEngineResult result;
+
+        // Loop until there is no more data in src
+        while ( src.hasRemaining() ) {
+
+            if ( src.remaining() > ( ( outNetBuffer.capacity() - outNetBuffer.position() ) / 2 ) ) {
+                // We have to expand outNetBuffer
+                // Note: there is no way to know the exact size required, but enrypted data
+                // shouln't need to be larger than twice the source data size?
+                outNetBuffer = SSLByteBufferPool.expandBuffer( outNetBuffer, src.capacity() * 2 );
+                if ( log.isDebugEnabled() ) {
+                    log.debug( session + " expanded outNetBuffer:" + outNetBuffer );
+                }
+            }
+
+            result = sslEngine.wrap( src, outNetBuffer );
+            if ( log.isDebugEnabled() ) {
+                log.debug( session + " Wrap res:" + result );
+            }
+
+            if ( result.getStatus() == SSLEngineResult.Status.OK ) {
+                if ( result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK ) {
+                    doTasks();
+                }
+            } else {
+                throw new SSLException( "SSLEngine error during encrypt: "
+                        + result.getStatus() +
+                        " src: " + src + "outNetBuffer: " + outNetBuffer);
+            }
+        }
+
+        outNetBuffer.flip();
     }
 
     /**
-     * Start SSL shutdown process
+     * Start SSL shutdown process.
+     * 
+     * @return <tt>true</tt> if shutdown process is started.
+     *         <tt>false</tt> if shutdown process is already finished.
      *
      * @throws SSLException on errors
      */
-    public void closeOutbound() throws SSLException
+    public synchronized boolean closeOutbound() throws SSLException
     {
-        if( !sslEngine.isOutboundDone() )
+        if( sslEngine.isOutboundDone() )
         {
-            doShutdown();
+            return false;
         }
+        
+        sslEngine.closeOutbound();
+
+        // By RFC 2616, we can "fire and forget" our close_notify
+        // message, so that's what we'll do here.
+        outNetBuffer.clear();
+        SSLEngineResult result = sslEngine.wrap( hsBB, outNetBuffer );
+        if( result.getStatus() != SSLEngineResult.Status.CLOSED )
+        {
+            throw new SSLException( "Improper close state: " + result );
+        }
+        outNetBuffer.flip();
+        return true;
     }
 
     /**
      * Release allocated ByteBuffers.
      */
-    public void release()
+    public synchronized void release()
     {
         SSLByteBufferPool.release( appBuffer );
         SSLByteBufferPool.release( inNetBuffer );
@@ -321,7 +373,7 @@
      *
      * @throws SSLException
      */
-    private void doDecrypt() throws SSLException
+    private void decrypt() throws SSLException
     {
 
         if( !initialHandshakeComplete )
@@ -359,51 +411,6 @@
         return status;
     }
     
-    private void doEncrypt( ByteBuffer src ) throws SSLException
-    {
-        if( !initialHandshakeComplete )
-        {
-            throw new IllegalStateException();
-        }
-
-        // The data buffer is (must be) empty, we can reuse the entire
-        // buffer.
-        outNetBuffer.clear();
-
-        SSLEngineResult result;
-
-        // Loop until there is no more data in src
-        while ( src.hasRemaining() ) {
-
-            if ( src.remaining() > ( ( outNetBuffer.capacity() - outNetBuffer.position() ) / 2 ) ) {
-                // We have to expand outNetBuffer
-                // Note: there is no way to know the exact size required, but enrypted data
-                // shouln't need to be larger than twice the source data size?
-                outNetBuffer = SSLByteBufferPool.expandBuffer( outNetBuffer, src.capacity() * 2 );
-                if ( log.isDebugEnabled() ) {
-                    log.debug( session + " expanded outNetBuffer:" + outNetBuffer );
-                }
-            }
-
-            result = sslEngine.wrap( src, outNetBuffer );
-            if ( log.isDebugEnabled() ) {
-                log.debug( session + " Wrap res:" + result );
-            }
-
-            if ( result.getStatus() == SSLEngineResult.Status.OK ) {
-                if ( result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK ) {
-                    doTasks();
-                }
-            } else {
-                throw new SSLException( "SSLEngine error during encrypt: "
-                        + result.getStatus() +
-                        " src: " + src + "outNetBuffer: " + outNetBuffer);
-            }
-        }
-
-        outNetBuffer.flip();
-    }
-
     /**
      * Perform any handshaking processing.
      */
@@ -479,7 +486,7 @@
 
                 outNetBuffer.flip();
                 initialHandshakeStatus = result.getHandshakeStatus();
-                writeNetBuffer( nextFilter, session );
+                writeNetBuffer( nextFilter );
                 // return to allow data on out buffer being sent
                 // TODO: We might want to send more data immidiatley?
             }
@@ -491,7 +498,7 @@
         }
     }
 
-    public WriteFuture writeNetBuffer( NextFilter nextFilter, IoSession session ) throws SSLException
+    public synchronized WriteFuture writeNetBuffer( NextFilter nextFilter ) throws SSLException
     {
         // Check if any net data needed to be writen
         if( !getOutNetBuffer().hasRemaining() )
@@ -506,10 +513,7 @@
         
         // set flag that we are writing encrypted data
         // (used in SSLFilter.filterWrite())
-        synchronized( this )
-        {
-            setWritingEncryptedData( true );
-        }
+        writingEncryptedData = true;
         
         try
         {
@@ -555,10 +559,7 @@
         }
         finally
         {
-            synchronized( this )
-            {
-                setWritingEncryptedData( false );
-            }
+            writingEncryptedData = false;
         }
         
         if( writeFuture != null )
@@ -572,7 +573,7 @@
     }
     
     
-    SSLEngineResult.Status unwrap() throws SSLException
+    private SSLEngineResult.Status unwrap() throws SSLException
     {
         if( log.isDebugEnabled() )
         {
@@ -716,29 +717,6 @@
         return sslEngine.getHandshakeStatus();
     }
 
-    /**
-     * Begin the shutdown process.
-     */
-    void doShutdown() throws SSLException
-    {
-
-        if( !sslEngine.isOutboundDone() )
-        {
-            sslEngine.closeOutbound();
-        }
-
-        // By RFC 2616, we can "fire and forget" our close_notify
-        // message, so that's what we'll do here.
-
-        outNetBuffer.clear();
-        SSLEngineResult result = sslEngine.wrap( hsBB, outNetBuffer );
-        if( result.getStatus() != SSLEngineResult.Status.CLOSED )
-        {
-            throw new SSLException( "Improper close state: " + result );
-        }
-        outNetBuffer.flip();
-    }
-    
     private static class ScheduledWrite
     {
         private final NextFilter nextFilter;