diff --git a/Foundation Web Core/src/com/foundation/web/server/ServerSocketContext.java b/Foundation Web Core/src/com/foundation/web/server/ServerSocketContext.java index f9ba543..33ee8f4 100644 --- a/Foundation Web Core/src/com/foundation/web/server/ServerSocketContext.java +++ b/Foundation Web Core/src/com/foundation/web/server/ServerSocketContext.java @@ -12,4 +12,7 @@ public class ServerSocketContext implements IChannelContext { super(); this.serviceListener = serviceListener; }//ServerSocketContext()// + public ServiceListener getServiceListener() { + return serviceListener; + }//getServiceListener()// }//ServerSocketContext// \ No newline at end of file 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 567c56c..551cab9 100644 --- a/Foundation Web Core/src/com/foundation/web/server/SocketContext.java +++ b/Foundation Web Core/src/com/foundation/web/server/SocketContext.java @@ -1125,7 +1125,11 @@ private boolean writeClientBoundPlainMessage(SocketChannel channel, MessageBuffe */ protected void readIncomingMessages() throws IOException { boolean requiresRead = true; - SocketChannel channel = (SocketChannel) key.channel(); + SocketChannel channel; + + synchronized(getLock()) { + channel = (SocketChannel) key.channel(); + }//synchronized// if(isSsl()) { int loopCount = 0; @@ -1134,7 +1138,7 @@ protected void readIncomingMessages() throws IOException { if(sslEngine == null) { SSLSession session = null; - if(parseFirstTlsMessage(this, channel)) { + if(parseFirstTlsMessage(channel)) { SSLContext sslContext = null; //Error checking.// @@ -1148,10 +1152,10 @@ protected void readIncomingMessages() throws IOException { //Synchronize to prevent another thread from altering the service's web applications while we are accessing it.// synchronized(getWebServer()) { if(tlsFailure) { - domain = serverSocketContext.serviceListener.getDefaultSslDomain(); + domain = serverSocketContext.getServiceListener().getDefaultSslDomain(); }//if// - webApplicationContainer = serverSocketContext.serviceListener.getWebApplicationContainer(domain); + webApplicationContainer = serverSocketContext.getServiceListener().getWebApplicationContainer(domain); }//synchronized// //Error checking.// @@ -1205,6 +1209,7 @@ protected void readIncomingMessages() throws IOException { IPassThroughDomain passThroughDomain = ((IPassThroughDomain) application); //Setup the pass through socket context (and socket channel). All data will be sent to this context to be sent to the remote process.// +// relatedSocketContext = new PassThroughSocketContext(getWebServer(), getNetworkListener(), this, passThroughDomain.getAddress(), passThroughDomain.getPort()); relatedSocketContext = new PassThroughSocketContext(this, passThroughDomain.getAddress(), passThroughDomain.getPort()); }//if// }//if// @@ -1257,7 +1262,7 @@ protected void readIncomingMessages() throws IOException { SSLEngineResult sslResult; //Sometimes the SSL Engine requires a partial read of the encrypted bytes, then a task, then reading the rest of the encrypted bytes.// - while(key.channel().isOpen() && encryptedReadBuffer.hasRemaining()) { + while(channel.isOpen() && encryptedReadBuffer.hasRemaining()) { //Reset the unencrypted read buffer prior to decrypting the next frame.// unencryptedReadBuffer.position(0); unencryptedReadBuffer.limit(unencryptedReadBuffer.capacity()); @@ -1272,7 +1277,7 @@ protected void readIncomingMessages() throws IOException { }//if// else if(sslResult.getStatus() == Status.BUFFER_OVERFLOW) { //Should never happen.// -// if(getWebServer().debug())) Debug.log(new RuntimeException("Unexpected ssl engine buffer overflow.")); +// if(debug) Debug.log(new RuntimeException("Unexpected ssl engine buffer overflow.")); close(); }//else if// else if(sslResult.getStatus() == Status.CLOSED) { @@ -1293,17 +1298,6 @@ protected void readIncomingMessages() throws IOException { if(sslResult.getHandshakeStatus() == HandshakeStatus.NEED_WRAP || sslResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { sslNeedsWrap = true; requiresRead = writeClientBoundMessage(channel, null); - /* - //Need to synchronize if this is a pass through socket so that multiple threads don't access pendingOutboundMessage or lastAddedMessageBuffer (via a call to passThrough(ByteBuffer) on another thread).// - if(getPassThroughSocketContext() == null) { - requiresRead = writeClientBoundMessage(); - }//if// - else { - synchronized(this) { - requiresRead = writeClientBoundMessage(); - }//synchronized// - }//else// - */ }//if// //If bytes were produced then process them.// @@ -1311,10 +1305,14 @@ protected void readIncomingMessages() throws IOException { //If we are not passing all content to another process then handle it by calling processClientRequest, otherwise pass it through.// if(getPassThroughSocketContext() == null) { if(isWebsocket) { - requiresRead = processWebsocketFrame(unencryptedReadBuffer, key); + requiresRead = processWebsocketFrame(unencryptedReadBuffer); }//if// else { - requiresRead = processClientRequest(unencryptedReadBuffer, key); + if(getWebServer().debug()) { + Debug.log(this.getId() + "|" + System.nanoTime() + "|SSL bytes decoded: " + unencryptedReadBuffer.remaining()); + }//if// + + requiresRead = processClientRequest(unencryptedReadBuffer); }//else// }//if// else { @@ -1358,7 +1356,7 @@ protected void readIncomingMessages() throws IOException { //Setup the pass through socket if the application is an instance of IPassThroughDomain.// if(count != -1 && isFirstUnencryptedMessage) { //Read enough of the header to identify the application.// - if(processRequestedHost(socketReadBuffer, key)) { + if(processRequestedHost(socketReadBuffer)) { //Create a pass through socket and context and attach it to this context if the application is setup as a pass through to another process.// IWebApplication application = webApplicationContainer.getWebApplication(); @@ -1366,6 +1364,7 @@ protected void readIncomingMessages() throws IOException { IPassThroughDomain passThroughDomain = ((IPassThroughDomain) application); //Setup the pass through socket context (and socket channel). All data will be sent to this context to be sent to the remote process.// + //relatedSocketContext = new PassThroughSocketContext(getWebServer(), getNetworkListener(), this, passThroughDomain.getAddress(), passThroughDomain.getPort()); relatedSocketContext = new PassThroughSocketContext(this, passThroughDomain.getAddress(), passThroughDomain.getPort()); }//if// @@ -1390,14 +1389,14 @@ protected void readIncomingMessages() throws IOException { }//if// }//else if// else if(isWebsocket) { - requiresRead = processWebsocketFrame(socketReadBuffer, key); + requiresRead = processWebsocketFrame(socketReadBuffer); if(socketReadBuffer.remaining() > 0) { Debug.log(new RuntimeException("Remaining bytes found on the read buffer!")); }//if// }//else if// else if(socketReadBuffer.hasRemaining()) { - requiresRead = processClientRequest(socketReadBuffer, key); + requiresRead = processClientRequest(socketReadBuffer); if(socketReadBuffer.remaining() > 0) { Debug.log(new RuntimeException("Remaining bytes found on the read buffer!")); @@ -1408,17 +1407,15 @@ protected void readIncomingMessages() throws IOException { }//else// }//while// }//else// -}//processRequest()// +}//readIncomingMessages()// /** * Processes a single websocket frame if there is enough data in the fragment. *
Will not return until all data is read from the frame or the socket is closed. - * @param context The context for the socket. * @param fragment The fragment of data off the socket. - * @param key The key for the socket. * @return Whether more data is required in order to process a single frame. * @throws IOException */ -private boolean processWebsocketFrame(ByteBuffer fragment, SelectionKey key) throws IOException { +private boolean processWebsocketFrame(ByteBuffer fragment) throws IOException { boolean isFrameFullyRead = false; while(fragment.remaining() > 0) { @@ -1634,10 +1631,9 @@ private boolean isCompleteHeader(StringBuffer buffer) { /** * Processes enough of the header of this first request to identify the application and set it for the socket. Used to forward unencrypted message to a remote server. * @param fragment - * @param key * @return Whether enough of the request could be read to identify the application. The caller should ignore the result if key.channel() is closed since the request was incomplete, incorrectly formatted, or the socket failed. */ -private boolean processRequestedHost(ByteBuffer fragment, SelectionKey key) throws IOException { +private boolean processRequestedHost(ByteBuffer fragment) throws IOException { boolean result = false; try { @@ -1711,10 +1707,9 @@ private boolean processRequestedHost(ByteBuffer fragment, SelectionKey key) thro /** * Processes the client request given the latest fragment of a message. * @param messageFragment The message fragment. - * @param key The socket's key. * @result Whether request is in a receive state. Will be false if the request generated a response that could not be completely transmitted. */ -private boolean processClientRequest(ByteBuffer fragment, SelectionKey key) throws IOException { +private boolean processClientRequest(ByteBuffer fragment) throws IOException { boolean result = true; try { @@ -2183,7 +2178,7 @@ private boolean processClientRequest(ByteBuffer fragment, SelectionKey key) thro //If we have a partial message left then process it if we can.// if(result && fragment.hasRemaining()) { - result = processClientRequest(fragment, key); + result = processClientRequest(fragment); }//if// }//if// }//try// @@ -2395,29 +2390,28 @@ private boolean internalProcessClientRequest(SelectionKey key, final IWebApplica }//internalProcessClientRequest()// /** * Parses the initial client hello message sent in the TLS protocol to identify which SSL context to use for the connection. - * @param context The connection context. * @param channel The socket channel to read from. * @return Whether the message could be parsed. If false, the method will be called again until true as new bytes arrive on the channel. */ -private boolean parseFirstTlsMessage(SocketContext context, SocketChannel channel) throws IOException { +private boolean parseFirstTlsMessage(SocketChannel channel) throws IOException { boolean result = false; ByteBuffer temp = ByteBuffer.allocate(500); StreamBuffer input; int originalInputSize; //Create the stream buffer for this operation if not already created.// - if(context.initialBuffer == null) { - context.initialBuffer = new StreamBuffer(); + if(initialBuffer == null) { + initialBuffer = new StreamBuffer(); }//if// //Simplify the code a bit with a local variable.// - input = context.initialBuffer; + input = initialBuffer; originalInputSize = input.getSize(); //Exit if the initial buffer size is rediculously large or if the channel is closed or has no additional bytes.// - while(channel.read(temp) > 0 && context.initialBuffer.getSize() < 10000) { + while(channel.read(temp) > 0 && initialBuffer.getSize() < 10000) { temp.flip(); - context.initialBuffer.writeBytes(temp); + initialBuffer.writeBytes(temp); }//while// //Ensure we have enough data to read the header.// @@ -2427,7 +2421,7 @@ private boolean parseFirstTlsMessage(SocketContext context, SocketChannel channe int lowVersion = input.getByte(2) & 0xFF; int length = input.getShort(3, StreamBuffer.NUMBER_MSF) & 0xFFFF; -// context.initialBuffer.getAsText(); +// initialBuffer.getAsText(); //Check the version.// if(highVersion != 3 || lowVersion > 3 || lowVersion < 1) { @@ -2535,8 +2529,8 @@ private boolean parseFirstTlsMessage(SocketContext context, SocketChannel channe name = input.readText(nameByteCount, "UTF8").toLowerCase(); // Debug.log(name); - if(context.domain == null) { - context.domain = name; + if(domain == null) { + domain = name; }//if// }//try// catch(UnsupportedEncodingException e) {