Split sending message code into SSL and plain.

This commit is contained in:
wcrisman
2014-12-28 14:48:03 -08:00
parent 7f4d6702a0
commit 7a75ba30de

View File

@@ -554,22 +554,22 @@ public synchronized boolean sendHttpResponse(Response response) {
* @see com.foundation.web.server.WebServer.AbstractSocketContext#passThrough(java.nio.ByteBuffer) * @see com.foundation.web.server.WebServer.AbstractSocketContext#passThrough(java.nio.ByteBuffer)
*/ */
protected synchronized boolean passThrough(ByteBuffer buffer) { protected synchronized boolean passThrough(ByteBuffer buffer) {
ByteBuffer messageBytes = ByteBuffer.allocate(buffer.remaining()); // ByteBuffer messageBytes = ByteBuffer.allocate(buffer.remaining());
MessageBuffer message; // MessageBuffer message;
//
//Create a new buffer to hold the data so we don't modify the passed buffer (other than to update its position).// // //Create a new buffer to hold the data so we don't modify the passed buffer (other than to update its position).//
messageBytes = ByteBuffer.allocate(buffer.remaining()); // messageBytes = ByteBuffer.allocate(buffer.remaining());
messageBytes.put(buffer); // messageBytes.put(buffer);
message = new MessageBuffer(messageBytes); // message = new MessageBuffer(messageBytes);
//
//Chain the message into the linked list. // //Chain the message into the linked list.
if(lastOutboundMessage == null || currentOutboundMessage == null) { // if(lastOutboundMessage == null || currentOutboundMessage == null) {
currentOutboundMessage = lastOutboundMessage = message; // currentOutboundMessage = lastOutboundMessage = message;
}//if// // }//if//
else { // else {
lastOutboundMessage.setNext(message); // lastOutboundMessage.setNext(message);
lastOutboundMessage = message; // lastOutboundMessage = message;
}//else// // }//else//
return true; return true;
}//passThrough()// }//passThrough()//
@@ -578,18 +578,18 @@ protected synchronized boolean passThrough(ByteBuffer buffer) {
*/ */
protected void writeOutgoingMessages() throws IOException { protected void writeOutgoingMessages() throws IOException {
if(getPassThroughSocketContext() != null) { if(getPassThroughSocketContext() != null) {
//Synchronized to avoid multiple threads accessing the pendingOutboundMessage chain at one time and updating the write flag out of order (could happen if we enabled request chaining over a single socket).// // //Synchronized to avoid multiple threads accessing the pendingOutboundMessage chain at one time and updating the write flag out of order (could happen if we enabled request chaining over a single socket).//
synchronized(this) { // synchronized(this) {
writeClientBoundMessage(); // writeClientBoundMessage();
}//synchronized// // }//synchronized//
}//if// }//if//
else if(isWebsocket) { else if(isWebsocket) {
//Right after upgrading the socket we have one last HTTP response to process.// //Right after upgrading the socket we have one last HTTP response to process.//
if(currentResponse != null) { // if(currentResponse != null) {
internalProcessResponses(); // internalProcessResponses();
}//if// // }//if//
//
internalProcessWebsocketMessages(); // internalProcessWebsocketMessages();
}//else if// }//else if//
else { else {
//Go directly to writing the client response if we are just passing everything through to another process.// //Go directly to writing the client response if we are just passing everything through to another process.//
@@ -770,13 +770,23 @@ private synchronized void internalProcessResponses() {
private boolean writeClientBoundMessage() { private boolean writeClientBoundMessage() {
boolean sendMore = true; boolean sendMore = true;
// if(getWebServer().debug) { if(sslEngine != null) {
// debugBuffer.append("Starting a write cycle.\n"); sendMore = writeClientBoundSslMessage();
// }//if// }//if//
else {
sendMore = writeClientBoundPlainMessage();
}//else//
return sendMore;
}//writeClientBoundMessage()//
/**
* Sends a response to the client.
* @return Whether the response could be fully sent. This will be false if there is still more data to be written when the call returns.
*/
private boolean writeClientBoundSslMessage() {
boolean sendMore = true;
try { try {
//Process SSL output first.//
if(sslEngine != null) {
//If we have part of an SSL frame then try to send it first.// //If we have part of an SSL frame then try to send it first.//
if(encryptedWriteBuffer.hasRemaining()) { if(encryptedWriteBuffer.hasRemaining()) {
int remaining = encryptedWriteBuffer.remaining(); int remaining = encryptedWriteBuffer.remaining();
@@ -784,10 +794,6 @@ private boolean writeClientBoundMessage() {
//Write the bytes to the stream.// //Write the bytes to the stream.//
((SocketChannel) key.channel()).write(encryptedWriteBuffer); ((SocketChannel) key.channel()).write(encryptedWriteBuffer);
// if(getWebServer().debug) {
// debugBuffer.append("Wrote " + (remaining - encryptedWriteBuffer.remaining()) + " encrypted bytes to the stream. " + encryptedWriteBuffer.remaining() + " remain.\n");
// }//if//
//Check to see if we failed to send the whole frame.// //Check to see if we failed to send the whole frame.//
if(encryptedWriteBuffer.hasRemaining()) { if(encryptedWriteBuffer.hasRemaining()) {
sendMore = false; sendMore = false;
@@ -830,16 +836,8 @@ private boolean writeClientBoundMessage() {
//Write the bytes to the stream.// //Write the bytes to the stream.//
((SocketChannel) key.channel()).write(encryptedWriteBuffer); ((SocketChannel) key.channel()).write(encryptedWriteBuffer);
// if(getWebServer().debug) {
// debugBuffer.append("Sent " + (remaining - encryptedWriteBuffer.remaining()) + " encrypted bytes.\n");
// }//if//
//If not all the bytes could be written then we will need to wait until we can write more.// //If not all the bytes could be written then we will need to wait until we can write more.//
if(encryptedWriteBuffer.hasRemaining()) { if(encryptedWriteBuffer.hasRemaining()) {
// if(getWebServer().debug) {
// debugBuffer.append("Pausing due to a partially sent packet (while ssl handshaking). Bytes actually sent: " + encryptedWriteBuffer.position() + ". Bytes remaining: " + encryptedWriteBuffer.remaining() + ".\n");
// }//if//
//Leave the data in the encrypted write buffer for the writing operation to send it.// //Leave the data in the encrypted write buffer for the writing operation to send it.//
sendMore = false; sendMore = false;
}//if// }//if//
@@ -859,11 +857,6 @@ private boolean writeClientBoundMessage() {
}//else// }//else//
}//while// }//while//
// if(getWebServer().debug) {
// debugBuffer.append("End Handshaking SSL\n");
// }//if//
}//if//
if(sendMore && currentOutboundMessage != null) { if(sendMore && currentOutboundMessage != null) {
//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.// //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.getBuffer().hasRemaining()) {
@@ -884,25 +877,15 @@ private boolean writeClientBoundMessage() {
//If we have an application response pending then send it now.// //If we have an application response pending then send it now.//
if(sendMore && currentOutboundMessage.getBuffer().hasRemaining()) { if(sendMore && currentOutboundMessage.getBuffer().hasRemaining()) {
if(sslEngine != null) {
//Keep sending encrypted frames until the output buffer is full, or we run out of message to send.// //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()) { while(key.channel().isOpen() && sendMore && (currentOutboundMessage != null) && currentOutboundMessage.getBuffer().hasRemaining()) {
SSLEngineResult encryptResult; SSLEngineResult encryptResult;
// int offset = pendingOutboundMessage.getBuffer().position();
//TODO: Comment me.
//int rem = pendingOutboundMessage.getBuffer().remaining();
//Reset the encrypted write buffer.// //Reset the encrypted write buffer.//
encryptedWriteBuffer.compact(); encryptedWriteBuffer.compact();
//Encrypt the next message frame.// //Encrypt the next message frame.//
encryptResult = sslEngine.wrap(currentOutboundMessage.getBuffer(), encryptedWriteBuffer); encryptResult = sslEngine.wrap(currentOutboundMessage.getBuffer(), encryptedWriteBuffer);
encryptedWriteBuffer.flip(); encryptedWriteBuffer.flip();
//TODO: Comment me.
//Debug.log("Encrypting/Sending to client from Git " + (rem - pendingOutboundMessage.getBuffer().remaining()) + " bytes.");
// if(getWebServer().debug) {
// sentBytes += (pendingOutboundMessage.position() - offset);
// debugBuffer.append("Encrypted: " + (pendingOutboundMessage.position() - offset) + ". Total Encrypted: " + sentBytes + ". Encrypted size: " + encryptedWriteBuffer.limit() + ".\n");
// }//if//
if(encryptResult.getStatus() == Status.BUFFER_OVERFLOW) { if(encryptResult.getStatus() == Status.BUFFER_OVERFLOW) {
//Should never happen.// //Should never happen.//
@@ -971,17 +954,61 @@ private boolean writeClientBoundMessage() {
}//if// }//if//
}//while// }//while//
}//if// }//if//
}//if//
}//try//
catch(ClosedChannelException e) {
close();
}//catch//
catch(SSLException e) {
if(getWebServer().debug) {
Debug.log(e);
}//if//
close();
}//catch//
catch(IOException e) {
if(getWebServer().debug) {
Debug.log(e);
}//if//
close();
}//catch//
return sendMore;
}//writeClientBoundSslMessage()//
/**
* Sends a response to the client.
* @return Whether the response could be fully sent. This will be false if there is still more data to be written when the call returns.
*/
private boolean writeClientBoundPlainMessage() {
boolean sendMore = true;
try {
if(sendMore && currentOutboundMessage != null) {
//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()) {
if(currentOutboundMessage.getBuffer() == null && currentOutboundMessage.getNext() != null) {
currentOutboundMessage = currentOutboundMessage.getNext();
}//if//
else { else {
sendMore = false;
}//else//
}//if//
if(currentOutboundMessage.getBuffer() == null) {
currentOutboundMessage = null;
lastOutboundMessage = null;
}//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.// //Keep sending encrypted frames until the output buffer is full, or we run out of message to send.//
while(sendMore && (currentOutboundMessage != null) && currentOutboundMessage.getBuffer().hasRemaining()) { while(sendMore && (currentOutboundMessage != null) && currentOutboundMessage.getBuffer().hasRemaining()) {
//Write the bytes to the stream.// //Write the bytes to the stream.//
((SocketChannel) key.channel()).write(currentOutboundMessage.getBuffer()); ((SocketChannel) key.channel()).write(currentOutboundMessage.getBuffer());
// if(getWebServer().debug) {
// sentBytes += pendingOutboundMessage.position();
// debugBuffer.append("Wrote " + pendingOutboundMessage.position() + " bytes to the client. Total sent: " + sentBytes + "\n");
// }//if//
//If not all the bytes could be written then we will need to wait until we can write more.// //If not all the bytes could be written then we will need to wait until we can write more.//
if(currentOutboundMessage.getBuffer().hasRemaining()) { if(currentOutboundMessage.getBuffer().hasRemaining()) {
sendMore = false; sendMore = false;
@@ -1005,7 +1032,6 @@ private boolean writeClientBoundMessage() {
}//if// }//if//
}//else// }//else//
}//while// }//while//
}//else//
}//if// }//if//
}//if// }//if//
}//try// }//try//
@@ -1028,7 +1054,7 @@ private boolean writeClientBoundMessage() {
}//catch// }//catch//
return sendMore; return sendMore;
}//writeClientBoundMessage()// }//writeClientBoundPlainMessage()//
/* (non-Javadoc) /* (non-Javadoc)
* @see com.foundation.web.server.WebServer.AbstractSocketContext#processRequest() * @see com.foundation.web.server.WebServer.AbstractSocketContext#processRequest()
*/ */