From bd3e9ac5cc6cddfec55def9a3037524a2d330b21 Mon Sep 17 00:00:00 2001 From: wcrisman Date: Sun, 28 Dec 2014 17:45:22 -0800 Subject: [PATCH] Changed code in SocketContext.writeClientBoundSslMessage() to sync it up with the master branch (they are now identical (or nearly). --- .../foundation/web/server/SocketContext.java | 157 ++++++++++-------- 1 file changed, 91 insertions(+), 66 deletions(-) diff --git a/Foundation Web Core/src/com/foundation/web/server/SocketContext.java b/Foundation Web Core/src/com/foundation/web/server/SocketContext.java index fee6239..8c760cc 100644 --- a/Foundation Web Core/src/com/foundation/web/server/SocketContext.java +++ b/Foundation Web Core/src/com/foundation/web/server/SocketContext.java @@ -897,79 +897,104 @@ private boolean writeClientBoundSslMessage(SocketChannel channel, MessageBuffer }//while// if(sendMore && currentOutboundMessage != null && !currentOutboundMessage.isClosed()) { - //Check to see if the outbound message is prepared to send more content. For chunked transfers the outbound message may be waiting for additional content from another stream and we should return later.// - if(!currentOutboundMessage.getBuffer().hasRemaining()) { - if(!currentOutboundMessage.loadBuffer()) { - sendMore = false; + //Initialize the outbound message.// + if(!currentOutboundMessage.initialize()) { + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Couldn't initialize the currentOutboundMessage."); }//if// - if(currentOutboundMessage.getBuffer() == null) { - currentOutboundMessage = null; + close(); + }//if// + else { + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Loading the current outbound message's buffer."); }//if// - }//if// - - //If we have an application response pending then send it now.// - if(sendMore && currentOutboundMessage.getBuffer().hasRemaining()) { - //Keep sending encrypted frames until the output buffer is full, or we run out of message to send.// - while(key.channel().isOpen() && sendMore && (currentOutboundMessage != null) && currentOutboundMessage.getBuffer().hasRemaining()) { - SSLEngineResult encryptResult; - - //Reset the encrypted write buffer.// - encryptedWriteBuffer.compact(); - //Encrypt the next message frame.// - encryptResult = sslEngine.wrap(currentOutboundMessage.getBuffer(), encryptedWriteBuffer); - encryptedWriteBuffer.flip(); - - if(encryptResult.getStatus() == Status.BUFFER_OVERFLOW) { - //Should never happen.// - Debug.log(new RuntimeException("Unexpected ssl engine buffer overflow.")); - }//if// - else if(encryptResult.getStatus() == Status.BUFFER_UNDERFLOW) { - //Should never happen.// - Debug.log(new RuntimeException("Unexpected ssl engine buffer underflow.")); - }//else if// - else if(encryptResult.getStatus() == Status.CLOSED) { - //Should never happen.// -// Debug.log(new RuntimeException("Unexpected ssl engine closed.")); - //TODO: Handle this closure without an infinate loop... - //Close the socket.// - try {channel.close();} catch(Throwable e2) {} - }//else if// - else if(encryptResult.getStatus() == Status.OK) { - //Write the bytes to the stream.// - try { - channel.write(encryptedWriteBuffer); - }//try// - catch(IOException e) { - //Caught if the channel is forcably closed by the client. We will ignore it.// - }//catch// + + //Check to see if the outbound message is prepared to send more content. For chunked transfers the outbound message may be waiting for additional content from another stream and we should return later.// + if(!currentOutboundMessage.getBuffer().hasRemaining()) { + //Load the buffer for the current outbound message so it is full of bytes to be sent.// + currentOutboundMessage.loadBuffer(); + }//if// + + //If we have an application response pending then send it now.// + if(!currentOutboundMessage.isClosed()) { //currentOutboundMessage.getBuffer().hasRemaining() + //Keep sending encrypted frames until the output buffer is full, or we run out of message to send.// + while(channel.isOpen() && sendMore && !currentOutboundMessage.isClosed() && currentOutboundMessage.getBuffer().hasRemaining()) { + SSLEngineResult encryptResult; + int remaining = currentOutboundMessage.getBuffer().remaining(); - //If not all the bytes could be written then we will need to wait until we can write more.// - if(encryptedWriteBuffer.hasRemaining()) { - //Leave the data in the encrypted write buffer for the writing operation to send it.// - sendMore = false; - }//if// - }//else if// - else { - //Should never happen.// - Debug.log(new RuntimeException("Unexpected ssl engine status code.")); - }//else// - - //Add more content to the buffer.// - //Note: Do this even if the last encrypted write buffer could not be fully sent - so that when it is sent there will be outbound message content.// - if(channel.isOpen() && currentOutboundMessage != null) { - if(!currentOutboundMessage.loadBuffer()) { - //Wait until additional message bytes are available.// - sendMore = false; + //Reset the encrypted write buffer.// + encryptedWriteBuffer.compact(); + //Encrypt the next message frame.// + encryptResult = sslEngine.wrap(currentOutboundMessage.getBuffer(), encryptedWriteBuffer); + encryptedWriteBuffer.flip(); + + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Encrypted " + (remaining - currentOutboundMessage.getBuffer().remaining()) + " bytes; " + currentOutboundMessage.getBuffer().remaining() + " bytes left to encrypt; Encrypted bytes available to be written: " + (encryptedWriteBuffer.remaining()) + "."); }//if// - //If the message end has been reached then the buffer will be null.// - if(currentOutboundMessage.getBuffer() == null) { - currentOutboundMessage = null; + if(encryptResult.getStatus() == Status.BUFFER_OVERFLOW) { + //Should never happen.// + Debug.log(new RuntimeException("Unexpected ssl engine buffer overflow.")); }//if// - }//if// - }//while// - }//if// + else if(encryptResult.getStatus() == Status.BUFFER_UNDERFLOW) { + //Should never happen.// + Debug.log(new RuntimeException("Unexpected ssl engine buffer underflow.")); + }//else if// + else if(encryptResult.getStatus() == Status.CLOSED) { + //Should never happen.// +// Debug.log(new RuntimeException("Unexpected ssl engine closed.")); + //TODO: Handle this closure without an infinate loop... + //Close the socket.// + try {channel.close();} catch(Throwable e2) {} + }//else if// + else if(encryptResult.getStatus() == Status.OK) { + //Write the bytes to the stream.// + try { + int writeCount = 0; + + writeCount = channel.write(encryptedWriteBuffer); + + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Sent " + writeCount + " encrypted bytes."); + }//if// + }//try// + catch(IOException e) { + //Caught if the channel is forcably closed by the client. We will ignore it.// + }//catch// + + //If not all the bytes could be written then we will need to wait until we can write more.// + if(encryptedWriteBuffer.hasRemaining()) { + //Leave the data in the encrypted write buffer for the writing operation to send it.// + sendMore = false; + + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Couldn't send all the encrypted bytes in the packet, will wait for another write event in the listener."); + }//if// + }//if// + }//else if// + else { + //Should never happen.// + Debug.log(new RuntimeException("Unexpected ssl engine status code.")); + }//else// + + //Add more content to the buffer.// + //Note: Do this even if the last encrypted write buffer could not be fully sent - so that when it is sent there will be outbound message content.// + if(sendMore && channel.isOpen() && !currentOutboundMessage.isClosed()) { + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|Loading the next buffer of data to be sent."); + }//if// + + currentOutboundMessage.loadBuffer(); + sendMore = !currentOutboundMessage.isClosed() && currentOutboundMessage.getBuffer().hasRemaining(); + + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|" + (currentOutboundMessage.isClosed() ? "The current message is closed." : "Remaining bytes on the current outbound message: " + currentOutboundMessage.getBuffer().remaining() + ".")); + }//if// + }//if// + }//while// + }//if// + }//else// }//if// }//try// catch(ClosedChannelException e) {