Copied SocketContext.readIncommingMessages() from the master tree and updated as required to fix errors.
This commit is contained in:
@@ -12,4 +12,7 @@ public class ServerSocketContext implements IChannelContext {
|
|||||||
super();
|
super();
|
||||||
this.serviceListener = serviceListener;
|
this.serviceListener = serviceListener;
|
||||||
}//ServerSocketContext()//
|
}//ServerSocketContext()//
|
||||||
|
public ServiceListener getServiceListener() {
|
||||||
|
return serviceListener;
|
||||||
|
}//getServiceListener()//
|
||||||
}//ServerSocketContext//
|
}//ServerSocketContext//
|
||||||
@@ -1125,7 +1125,11 @@ private boolean writeClientBoundPlainMessage(SocketChannel channel, MessageBuffe
|
|||||||
*/
|
*/
|
||||||
protected void readIncomingMessages() throws IOException {
|
protected void readIncomingMessages() throws IOException {
|
||||||
boolean requiresRead = true;
|
boolean requiresRead = true;
|
||||||
SocketChannel channel = (SocketChannel) key.channel();
|
SocketChannel channel;
|
||||||
|
|
||||||
|
synchronized(getLock()) {
|
||||||
|
channel = (SocketChannel) key.channel();
|
||||||
|
}//synchronized//
|
||||||
|
|
||||||
if(isSsl()) {
|
if(isSsl()) {
|
||||||
int loopCount = 0;
|
int loopCount = 0;
|
||||||
@@ -1134,7 +1138,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
if(sslEngine == null) {
|
if(sslEngine == null) {
|
||||||
SSLSession session = null;
|
SSLSession session = null;
|
||||||
|
|
||||||
if(parseFirstTlsMessage(this, channel)) {
|
if(parseFirstTlsMessage(channel)) {
|
||||||
SSLContext sslContext = null;
|
SSLContext sslContext = null;
|
||||||
|
|
||||||
//Error checking.//
|
//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.//
|
//Synchronize to prevent another thread from altering the service's web applications while we are accessing it.//
|
||||||
synchronized(getWebServer()) {
|
synchronized(getWebServer()) {
|
||||||
if(tlsFailure) {
|
if(tlsFailure) {
|
||||||
domain = serverSocketContext.serviceListener.getDefaultSslDomain();
|
domain = serverSocketContext.getServiceListener().getDefaultSslDomain();
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
webApplicationContainer = serverSocketContext.serviceListener.getWebApplicationContainer(domain);
|
webApplicationContainer = serverSocketContext.getServiceListener().getWebApplicationContainer(domain);
|
||||||
}//synchronized//
|
}//synchronized//
|
||||||
|
|
||||||
//Error checking.//
|
//Error checking.//
|
||||||
@@ -1205,6 +1209,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
IPassThroughDomain passThroughDomain = ((IPassThroughDomain) application);
|
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.//
|
//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());
|
relatedSocketContext = new PassThroughSocketContext(this, passThroughDomain.getAddress(), passThroughDomain.getPort());
|
||||||
}//if//
|
}//if//
|
||||||
}//if//
|
}//if//
|
||||||
@@ -1257,7 +1262,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
SSLEngineResult sslResult;
|
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.//
|
//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.//
|
//Reset the unencrypted read buffer prior to decrypting the next frame.//
|
||||||
unencryptedReadBuffer.position(0);
|
unencryptedReadBuffer.position(0);
|
||||||
unencryptedReadBuffer.limit(unencryptedReadBuffer.capacity());
|
unencryptedReadBuffer.limit(unencryptedReadBuffer.capacity());
|
||||||
@@ -1272,7 +1277,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
}//if//
|
}//if//
|
||||||
else if(sslResult.getStatus() == Status.BUFFER_OVERFLOW) {
|
else if(sslResult.getStatus() == Status.BUFFER_OVERFLOW) {
|
||||||
//Should never happen.//
|
//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();
|
close();
|
||||||
}//else if//
|
}//else if//
|
||||||
else if(sslResult.getStatus() == Status.CLOSED) {
|
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) {
|
if(sslResult.getHandshakeStatus() == HandshakeStatus.NEED_WRAP || sslResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
|
||||||
sslNeedsWrap = true;
|
sslNeedsWrap = true;
|
||||||
requiresRead = writeClientBoundMessage(channel, null);
|
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//
|
||||||
|
|
||||||
//If bytes were produced then process them.//
|
//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 we are not passing all content to another process then handle it by calling processClientRequest, otherwise pass it through.//
|
||||||
if(getPassThroughSocketContext() == null) {
|
if(getPassThroughSocketContext() == null) {
|
||||||
if(isWebsocket) {
|
if(isWebsocket) {
|
||||||
requiresRead = processWebsocketFrame(unencryptedReadBuffer, key);
|
requiresRead = processWebsocketFrame(unencryptedReadBuffer);
|
||||||
}//if//
|
}//if//
|
||||||
else {
|
else {
|
||||||
requiresRead = processClientRequest(unencryptedReadBuffer, key);
|
if(getWebServer().debug()) {
|
||||||
|
Debug.log(this.getId() + "|" + System.nanoTime() + "|SSL bytes decoded: " + unencryptedReadBuffer.remaining());
|
||||||
|
}//if//
|
||||||
|
|
||||||
|
requiresRead = processClientRequest(unencryptedReadBuffer);
|
||||||
}//else//
|
}//else//
|
||||||
}//if//
|
}//if//
|
||||||
else {
|
else {
|
||||||
@@ -1358,7 +1356,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
//Setup the pass through socket if the application is an instance of IPassThroughDomain.//
|
//Setup the pass through socket if the application is an instance of IPassThroughDomain.//
|
||||||
if(count != -1 && isFirstUnencryptedMessage) {
|
if(count != -1 && isFirstUnencryptedMessage) {
|
||||||
//Read enough of the header to identify the application.//
|
//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.//
|
//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();
|
IWebApplication application = webApplicationContainer.getWebApplication();
|
||||||
|
|
||||||
@@ -1366,6 +1364,7 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
IPassThroughDomain passThroughDomain = ((IPassThroughDomain) application);
|
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.//
|
//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());
|
relatedSocketContext = new PassThroughSocketContext(this, passThroughDomain.getAddress(), passThroughDomain.getPort());
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
@@ -1390,14 +1389,14 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
}//if//
|
}//if//
|
||||||
}//else if//
|
}//else if//
|
||||||
else if(isWebsocket) {
|
else if(isWebsocket) {
|
||||||
requiresRead = processWebsocketFrame(socketReadBuffer, key);
|
requiresRead = processWebsocketFrame(socketReadBuffer);
|
||||||
|
|
||||||
if(socketReadBuffer.remaining() > 0) {
|
if(socketReadBuffer.remaining() > 0) {
|
||||||
Debug.log(new RuntimeException("Remaining bytes found on the read buffer!"));
|
Debug.log(new RuntimeException("Remaining bytes found on the read buffer!"));
|
||||||
}//if//
|
}//if//
|
||||||
}//else if//
|
}//else if//
|
||||||
else if(socketReadBuffer.hasRemaining()) {
|
else if(socketReadBuffer.hasRemaining()) {
|
||||||
requiresRead = processClientRequest(socketReadBuffer, key);
|
requiresRead = processClientRequest(socketReadBuffer);
|
||||||
|
|
||||||
if(socketReadBuffer.remaining() > 0) {
|
if(socketReadBuffer.remaining() > 0) {
|
||||||
Debug.log(new RuntimeException("Remaining bytes found on the read buffer!"));
|
Debug.log(new RuntimeException("Remaining bytes found on the read buffer!"));
|
||||||
@@ -1408,17 +1407,15 @@ protected void readIncomingMessages() throws IOException {
|
|||||||
}//else//
|
}//else//
|
||||||
}//while//
|
}//while//
|
||||||
}//else//
|
}//else//
|
||||||
}//processRequest()//
|
}//readIncomingMessages()//
|
||||||
/**
|
/**
|
||||||
* Processes a single websocket frame if there is enough data in the fragment.
|
* Processes a single websocket frame if there is enough data in the fragment.
|
||||||
* <br/>Will not return until all data is read from the frame or the socket is closed.
|
* <br/>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 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.
|
* @return Whether more data is required in order to process a single frame.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private boolean processWebsocketFrame(ByteBuffer fragment, SelectionKey key) throws IOException {
|
private boolean processWebsocketFrame(ByteBuffer fragment) throws IOException {
|
||||||
boolean isFrameFullyRead = false;
|
boolean isFrameFullyRead = false;
|
||||||
|
|
||||||
while(fragment.remaining() > 0) {
|
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.
|
* 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 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.
|
* @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;
|
boolean result = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1711,10 +1707,9 @@ private boolean processRequestedHost(ByteBuffer fragment, SelectionKey key) thro
|
|||||||
/**
|
/**
|
||||||
* Processes the client request given the latest fragment of a message.
|
* Processes the client request given the latest fragment of a message.
|
||||||
* @param messageFragment The message fragment.
|
* @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.
|
* @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;
|
boolean result = true;
|
||||||
|
|
||||||
try {
|
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 we have a partial message left then process it if we can.//
|
||||||
if(result && fragment.hasRemaining()) {
|
if(result && fragment.hasRemaining()) {
|
||||||
result = processClientRequest(fragment, key);
|
result = processClientRequest(fragment);
|
||||||
}//if//
|
}//if//
|
||||||
}//if//
|
}//if//
|
||||||
}//try//
|
}//try//
|
||||||
@@ -2395,29 +2390,28 @@ private boolean internalProcessClientRequest(SelectionKey key, final IWebApplica
|
|||||||
}//internalProcessClientRequest()//
|
}//internalProcessClientRequest()//
|
||||||
/**
|
/**
|
||||||
* Parses the initial client hello message sent in the TLS protocol to identify which SSL context to use for the connection.
|
* 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.
|
* @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.
|
* @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;
|
boolean result = false;
|
||||||
ByteBuffer temp = ByteBuffer.allocate(500);
|
ByteBuffer temp = ByteBuffer.allocate(500);
|
||||||
StreamBuffer input;
|
StreamBuffer input;
|
||||||
int originalInputSize;
|
int originalInputSize;
|
||||||
|
|
||||||
//Create the stream buffer for this operation if not already created.//
|
//Create the stream buffer for this operation if not already created.//
|
||||||
if(context.initialBuffer == null) {
|
if(initialBuffer == null) {
|
||||||
context.initialBuffer = new StreamBuffer();
|
initialBuffer = new StreamBuffer();
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
//Simplify the code a bit with a local variable.//
|
//Simplify the code a bit with a local variable.//
|
||||||
input = context.initialBuffer;
|
input = initialBuffer;
|
||||||
originalInputSize = input.getSize();
|
originalInputSize = input.getSize();
|
||||||
|
|
||||||
//Exit if the initial buffer size is rediculously large or if the channel is closed or has no additional bytes.//
|
//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();
|
temp.flip();
|
||||||
context.initialBuffer.writeBytes(temp);
|
initialBuffer.writeBytes(temp);
|
||||||
}//while//
|
}//while//
|
||||||
|
|
||||||
//Ensure we have enough data to read the header.//
|
//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 lowVersion = input.getByte(2) & 0xFF;
|
||||||
int length = input.getShort(3, StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
int length = input.getShort(3, StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||||
|
|
||||||
// context.initialBuffer.getAsText();
|
// initialBuffer.getAsText();
|
||||||
|
|
||||||
//Check the version.//
|
//Check the version.//
|
||||||
if(highVersion != 3 || lowVersion > 3 || lowVersion < 1) {
|
if(highVersion != 3 || lowVersion > 3 || lowVersion < 1) {
|
||||||
@@ -2535,8 +2529,8 @@ private boolean parseFirstTlsMessage(SocketContext context, SocketChannel channe
|
|||||||
name = input.readText(nameByteCount, "UTF8").toLowerCase();
|
name = input.readText(nameByteCount, "UTF8").toLowerCase();
|
||||||
// Debug.log(name);
|
// Debug.log(name);
|
||||||
|
|
||||||
if(context.domain == null) {
|
if(domain == null) {
|
||||||
context.domain = name;
|
domain = name;
|
||||||
}//if//
|
}//if//
|
||||||
}//try//
|
}//try//
|
||||||
catch(UnsupportedEncodingException e) {
|
catch(UnsupportedEncodingException e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user