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);
}