Author: elecharny
Date: Fri Dec  9 17:54:12 2011
New Revision: 1212546

URL: http://svn.apache.org/viewvc?rev=1212546&view=rev
Log:
A better version of the SSLHandler. The Handshake seems to work pretty much, 
but we never get the FINSIHED status. Work in progress...

Modified:
    mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java
    
mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java
URL: 
http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java?rev=1212546&r1=1212545&r2=1212546&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java 
(original)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java Fri 
Dec  9 17:54:12 2011
@@ -25,6 +25,8 @@ import java.nio.ByteBuffer;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLSession;
 
@@ -78,7 +80,7 @@ public class SslHelper
     private ByteBuffer appBuffer;
 
     /** Incoming buffer accumulating bytes read from the channel */
-    private ByteBuffer sslInBuffer;
+    private ByteBuffer accBuffer;
     
     /**
      * Create a new SSL Handler.
@@ -163,33 +165,127 @@ public class SslHelper
     }
 
     public ByteBuffer getSslInBuffer(ByteBuffer inBuffer) {
-        if (sslInBuffer == null) {
-            sslInBuffer = inBuffer;
+        if (inBuffer == null) {
+            inBuffer = inBuffer;
         } else {
             addInBuffer(inBuffer);
         }
         
-        return sslInBuffer;
+        return inBuffer;
     }
 
     public void setInBuffer(ByteBuffer inBuffer) {
-        sslInBuffer = ByteBuffer.allocate(16*1024);
-        sslInBuffer.put(inBuffer);
+        inBuffer = ByteBuffer.allocate(16*1024);
+        inBuffer.put(inBuffer);
     }
 
-    public void addInBuffer(ByteBuffer inBuffer) {
-        if (sslInBuffer.capacity() - sslInBuffer.remaining() < 
inBuffer.remaining()) {
+    private void addInBuffer(ByteBuffer buffer) {
+        if (accBuffer.capacity() - accBuffer.limit() < buffer.remaining()) {
             // Increase the internal buffer
-            ByteBuffer newBuffer = ByteBuffer.allocate(sslInBuffer.capacity() 
+ inBuffer.remaining());
-            newBuffer.put(sslInBuffer);
-            newBuffer.put(inBuffer);
-            sslInBuffer = newBuffer;
+            ByteBuffer newBuffer = ByteBuffer.allocate(accBuffer.capacity() + 
buffer.remaining());
+            
+            // Copy the two buffers
+            newBuffer.put(accBuffer);
+            newBuffer.put(buffer);
+            
+            // And reset the position to the original position
+            newBuffer.flip();
+            
+            accBuffer = newBuffer;
         } else {
-            sslInBuffer.put(inBuffer);
+            accBuffer.put(buffer);
+            accBuffer.flip();
         }
     }
     
     public void releaseInBuffer() {
-        sslInBuffer = null;
+        accBuffer = null;
+    }
+    
+    /**
+     * Process the NEED_TASK action.
+     * 
+     * @param engine The SSLEngine instance
+     * @return The resulting HandshakeStatus
+     * @throws SSLException If we've got an error while processing the tasks
+     */
+    public HandshakeStatus processTasks(SSLEngine engine) throws SSLException {
+        Runnable runnable;
+        
+        while ((runnable = engine.getDelegatedTask()) != null) {
+            // TODO : we may have to use a thread pool here to improve the
+            // performances
+            runnable.run();
+        }
+
+        HandshakeStatus hsStatus = engine.getHandshakeStatus();
+        
+        return hsStatus;
+    }
+    
+    /**
+     * Process the NEED_UNWRAP action. We have to read the incoming buffer, 
and to feed
+     * the application buffer. We also have to cover the three special cases : 
<br/>
+     * <ul>
+     * <li>The incoming buffer does not contain enough data (then we need to 
read some
+     * more and to accumulate the bytes in a temporary buffer)</li>
+     * <li></li>
+     * </ul>
+     * 
+     * @param engine
+     * @param inBuffer
+     * @param appBuffer
+     * @return
+     * @throws SSLException
+     */
+    public Status processUnwrap(SSLEngine engine, ByteBuffer inBuffer, 
ByteBuffer appBuffer) throws SSLException {
+        ByteBuffer tempBuffer = null;
+        
+        // First work with either the new incoming buffer, or the accumulating 
buffer
+        if ((this.accBuffer != null) && (this.accBuffer.remaining() > 0)) {
+            // Add the new incoming data into the local buffer
+            addInBuffer(inBuffer);
+            tempBuffer = this.accBuffer;
+        } else {
+            tempBuffer = inBuffer;
+        }
+        
+        // Loop until we have processed the entire incoming buffer,
+        // or until we have to stop
+        while (true) {
+            SSLEngineResult result = engine.unwrap(tempBuffer, appBuffer);
+
+            switch (result.getStatus()) {
+                case OK :
+                    System.out.println( "------------------> OK" );
+                    accBuffer = null;
+                    
+                    return Status.OK;
+                    
+                case BUFFER_UNDERFLOW :
+                    System.out.println( "------------------> UNDERFLOW" );
+                    // We need to read some more data from the channel.
+                    if (this.accBuffer == null) {
+                        this.accBuffer = 
ByteBuffer.allocate(tempBuffer.capacity() + 4096);
+                        this.accBuffer.put(inBuffer);
+                    }
+                    
+                    inBuffer.clear();
+                    
+                    return Status.BUFFER_UNDERFLOW;
+    
+                case CLOSED :
+                    System.out.println( "------------------> CLOSED" );
+                    // Get out
+                    accBuffer = null;
+                    throw new IllegalStateException();
+    
+                case BUFFER_OVERFLOW :
+                    System.out.println( "------------------> OVERFLOW" );
+                    // We have to increase the appBuffer size. In any case
+                    // we aren't processing an handshake here. Read again.
+                    appBuffer = ByteBuffer.allocate(appBuffer.capacity() + 
4096 );
+            }
+        }
     }
 }

Modified: 
mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java
URL: 
http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java?rev=1212546&r1=1212545&r2=1212546&view=diff
==============================================================================
--- 
mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java
 (original)
+++ 
mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java
 Fri Dec  9 17:54:12 2011
@@ -38,6 +38,7 @@ import java.util.concurrent.locks.Reentr
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 
@@ -455,7 +456,8 @@ public class NioSelectorProcessor implem
             SocketChannel channel = session.getSocketChannel();
             readBuffer.clear();
             int readCount = channel.read(readBuffer);
-            
+            System.out.println( "------------------> read " + readCount + 
"bytes" );
+
             LOGGER.debug("read {} bytes", readCount);
 
             if (readCount < 0) {
@@ -485,10 +487,7 @@ public class NioSelectorProcessor implem
             
             SSLEngine engine = sslHelper.getEngine();
             HandshakeStatus hsStatus = engine.getHandshakeStatus();
-            ByteBuffer applicationBuffer = appBuffer;
             boolean processingData = true;
-            ByteBuffer sslBufferIn = sslHelper.getSslInBuffer(inBuffer);
-            boolean waitingForMore = false;
             
             // Start the Handshake
             engine.beginHandshake();
@@ -500,19 +499,13 @@ public class NioSelectorProcessor implem
                    processingData) {
                 switch (hsStatus) {
                     case NEED_TASK :
-                        Runnable runnable;
-                        
-                        while ((runnable = engine.getDelegatedTask()) != null) 
{
-                            // TODO : we may have to use a thread pool here to 
improve the
-                            // performances
-                            runnable.run();
-                        }
-
-                        hsStatus = engine.getHandshakeStatus();
+                        System.out.println( "------------------> NEED_TASK" );
+                        hsStatus = sslHelper.processTasks(engine);
                         
                         break;
                         
                     case NEED_WRAP :
+                        System.out.println( "------------------> NEED_WRAP" );
                         if ( LOGGER.isDebugEnabled()) {
                             LOGGER.debug("{} processing the NEED_WRAP state", 
session);
                         }
@@ -532,60 +525,30 @@ public class NioSelectorProcessor implem
         
                         outBuffer.flip();
                         session.write(outBuffer);
+                        processingData = false;
                         hsStatus = engine.getHandshakeStatus();
-                        
-                        // Now that we have written the response, we can exit 
if there is nothing else to do,
-                        if (engine.isOutboundDone()) {
-                            processingData = false;
-                        }
-                        
+
                         break;
                         
                     case NEED_UNWRAP :
-                        if (engine.isInboundDone()) {
-                            processingData = false;
-                            sslHelper.releaseInBuffer();
-                            break;
-                        }
+                        System.out.println( "------------------> NEED_UNWRAP" 
);
+                        Status status = sslHelper.processUnwrap(engine, 
inBuffer, EMPTY_BUFFER);
 
-                        // We will try to unwrap the incoming data, using the 
selector buffers.
-                        SSLEngineResult result = engine.unwrap(sslBufferIn, 
applicationBuffer);
-                        hsStatus = engine.getHandshakeStatus();
-
-                        switch (result.getStatus()) {
-                            case OK :
-                                // We have unwrapped the message. The inBuffer 
can contain
-                                // some more data to be unwrapped. Loop.
-                                break;
-                                
-                            case CLOSED :
-                                // We must exit immediately
-                                sslHelper.releaseInBuffer();
-                                throw new IllegalStateException();
-                                
-                            case BUFFER_OVERFLOW :
-                                // Not enough room in the appData : increase 
the buffer size
-                                ByteBuffer newBuffer = 
ByteBuffer.allocate(applicationBuffer.capacity() + 4 * 1024);
-                                applicationBuffer = newBuffer;
-                                
-                                // And now, try again.
-                                break;
-    
-                            case BUFFER_UNDERFLOW :
-                                // Not enough data in the received data. 
Accumulate and get some more.
-                                processingData = false;
-                                waitingForMore = true;
-                                sslHelper.addInBuffer(sslBufferIn);
-                                break;
+                        if ( status == Status.BUFFER_UNDERFLOW) {
+                            // Read more data
+                            processingData = false;
+                        } else {
+                            hsStatus = engine.getHandshakeStatus();
                         }
+                        
+                        break;
                 }
             }
             
-            if (!waitingForMore) {
-                sslHelper.releaseInBuffer();
-            }
+            System.out.println( "======================> " + hsStatus);
             
             if (hsStatus == HandshakeStatus.FINISHED) {
+                System.out.println( "------------------> FINISHED" );
                 if ( LOGGER.isDebugEnabled()) {
                     LOGGER.debug("{} processing the FINISHED state", session);
                 }
@@ -626,7 +589,9 @@ public class NioSelectorProcessor implem
                     ByteBuffer buf = (ByteBuffer) wreq.getMessage();
 
                     int wrote = session.getSocketChannel().write(buf);
-                    
+
+                    System.out.println( "------------------> Written" + 
buf.limit() + " bytes");
+
                     if (LOGGER.isDebugEnabled()) {
                         LOGGER.debug("wrote {} bytes to {}", wrote, session);
                     }


Reply via email to