Improved logging and exception handling.
Now IllegalStateExceptions are thrown with a message. Methods needsFillInterest() and onIncompleteFlush() are now wrapped in try/catch to make sure the connection is closed in case of exceptions. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
a3451c9d6e
commit
ddd80deeb9
|
@ -519,7 +519,7 @@ public class SslConnection extends AbstractConnection
|
|||
return filled = 0;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
|
||||
}
|
||||
|
||||
if (_encryptedInput==null)
|
||||
|
@ -616,7 +616,7 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected unwrap result " + unwrap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -659,6 +659,8 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(SslConnection.this.toString(), x);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
|
@ -667,66 +669,76 @@ public class SslConnection extends AbstractConnection
|
|||
@Override
|
||||
protected void needsFillInterest()
|
||||
{
|
||||
boolean fillable;
|
||||
ByteBuffer write = null;
|
||||
boolean interest = false;
|
||||
synchronized(_decryptedEndPoint)
|
||||
try
|
||||
{
|
||||
boolean fillable;
|
||||
ByteBuffer write = null;
|
||||
boolean interest = false;
|
||||
synchronized(_decryptedEndPoint)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug(">needFillInterest uf={} {}", _underflown, SslConnection.this);
|
||||
LOG.debug("ei={} di={}",BufferUtil.toDetailString(_encryptedInput),BufferUtil.toDetailString(_decryptedInput));
|
||||
}
|
||||
|
||||
if (_fillState!=FillState.IDLE)
|
||||
return;
|
||||
|
||||
// Fillable if we have decrypted Input OR encrypted input that has not yet been underflown.
|
||||
fillable = BufferUtil.hasContent(_decryptedInput) || (BufferUtil.hasContent(_encryptedInput) && !_underflown);
|
||||
|
||||
HandshakeStatus status = _sslEngine.getHandshakeStatus();
|
||||
switch (status)
|
||||
{
|
||||
case NEED_TASK:
|
||||
// Pretend we are fillable
|
||||
fillable = true;
|
||||
break;
|
||||
|
||||
case NEED_UNWRAP:
|
||||
case NOT_HANDSHAKING:
|
||||
if (!fillable)
|
||||
{
|
||||
interest = true;
|
||||
_fillState = FillState.INTERESTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEED_WRAP:
|
||||
if (!fillable)
|
||||
{
|
||||
_fillState = FillState.WAIT_FOR_FLUSH;
|
||||
if (_flushState == FlushState.IDLE)
|
||||
{
|
||||
_flushState = FlushState.WRITING;
|
||||
write = BufferUtil.hasContent(_encryptedOutput) ? _encryptedOutput : BufferUtil.EMPTY_BUFFER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("<needFillInterest s={}/{} f={} i={} w={}",_flushState,_fillState,fillable,interest,BufferUtil.toDetailString(write));
|
||||
}
|
||||
|
||||
if (write!=null)
|
||||
getEndPoint().write(_incompleteWriteCallback, write);
|
||||
else if (fillable)
|
||||
getExecutor().execute(_runFillable);
|
||||
else if (interest)
|
||||
ensureFillInterested();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug(">needFillInterest uf={} {}", _underflown, SslConnection.this);
|
||||
LOG.debug("ei={} di={}",BufferUtil.toDetailString(_encryptedInput),BufferUtil.toDetailString(_decryptedInput));
|
||||
}
|
||||
|
||||
if (_fillState!=FillState.IDLE)
|
||||
return;
|
||||
|
||||
// Fillable if we have decrypted Input OR encrypted input that has not yet been underflown.
|
||||
fillable = BufferUtil.hasContent(_decryptedInput) || (BufferUtil.hasContent(_encryptedInput) && !_underflown);
|
||||
|
||||
switch(_sslEngine.getHandshakeStatus())
|
||||
{
|
||||
case NEED_TASK:
|
||||
// Pretend we are fillable
|
||||
fillable = true;
|
||||
break;
|
||||
|
||||
case NEED_UNWRAP:
|
||||
case NOT_HANDSHAKING:
|
||||
if (!fillable)
|
||||
{
|
||||
interest = true;
|
||||
_fillState = FillState.INTERESTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEED_WRAP:
|
||||
if (!fillable)
|
||||
{
|
||||
fillable = false;
|
||||
_fillState = FillState.WAIT_FOR_FLUSH;
|
||||
if (_flushState == FlushState.IDLE)
|
||||
{
|
||||
_flushState = FlushState.WRITING;
|
||||
write = BufferUtil.hasContent(_encryptedOutput) ? _encryptedOutput : BufferUtil.EMPTY_BUFFER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("<needFillInterest s={}/{} f={} i={} w={}",_flushState,_fillState,fillable,interest,BufferUtil.toDetailString(write));
|
||||
LOG.debug(SslConnection.this.toString(), x);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
|
||||
if (write!=null)
|
||||
getEndPoint().write(_incompleteWriteCallback, write);
|
||||
else if (fillable)
|
||||
getExecutor().execute(_runFillable);
|
||||
else if (interest)
|
||||
ensureFillInterested();
|
||||
}
|
||||
|
||||
private void handshakeSucceeded()
|
||||
|
@ -839,7 +851,7 @@ public class SslConnection extends AbstractConnection
|
|||
return result = false;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
|
||||
}
|
||||
|
||||
if (_encryptedOutput == null)
|
||||
|
@ -867,13 +879,16 @@ public class SslConnection extends AbstractConnection
|
|||
allConsumed=false;
|
||||
|
||||
// if we have net bytes, let's try to flush them
|
||||
boolean flushed = BufferUtil.hasContent(_encryptedOutput) ? getEndPoint().flush(_encryptedOutput) : true;
|
||||
boolean flushed = true;
|
||||
if (BufferUtil.hasContent(_encryptedOutput))
|
||||
flushed = getEndPoint().flush(_encryptedOutput);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("net flushed={}, ac={}", flushed, allConsumed);
|
||||
|
||||
// Now deal with the results returned from the wrap
|
||||
switch (wrapResult.getStatus())
|
||||
Status wrap = wrapResult.getStatus();
|
||||
switch (wrap)
|
||||
{
|
||||
case CLOSED:
|
||||
{
|
||||
|
@ -911,7 +926,7 @@ public class SslConnection extends AbstractConnection
|
|||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected wrap result " + wrap);
|
||||
}
|
||||
|
||||
if (getEndPoint().isOutputShutdown())
|
||||
|
@ -933,6 +948,8 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(SslConnection.this.toString(), x);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
|
@ -941,84 +958,94 @@ public class SslConnection extends AbstractConnection
|
|||
@Override
|
||||
protected void onIncompleteFlush()
|
||||
{
|
||||
boolean fillInterest = false;
|
||||
ByteBuffer write = null;
|
||||
synchronized(_decryptedEndPoint)
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(">onIncompleteFlush {} {}", SslConnection.this, BufferUtil.toDetailString(_encryptedOutput));
|
||||
|
||||
if (_flushState!=FlushState.IDLE)
|
||||
return;
|
||||
|
||||
while(true)
|
||||
boolean fillInterest = false;
|
||||
ByteBuffer write = null;
|
||||
synchronized(_decryptedEndPoint)
|
||||
{
|
||||
HandshakeStatus status = _sslEngine.getHandshakeStatus();
|
||||
switch(status)
|
||||
{
|
||||
case NEED_TASK:
|
||||
case NEED_WRAP:
|
||||
case NOT_HANDSHAKING:
|
||||
// write what we have or an empty buffer to reschedule a call to flush
|
||||
write = BufferUtil.hasContent(_encryptedOutput)?_encryptedOutput:BufferUtil.EMPTY_BUFFER;
|
||||
_flushState = FlushState.WRITING;
|
||||
break;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(">onIncompleteFlush {} {}", SslConnection.this, BufferUtil.toDetailString(_encryptedOutput));
|
||||
|
||||
case NEED_UNWRAP:
|
||||
// If we have something to write, then write it and ignore the needed unwrap for now.
|
||||
if (BufferUtil.hasContent(_encryptedOutput))
|
||||
{
|
||||
write = _encryptedOutput;
|
||||
if (_flushState!=FlushState.IDLE)
|
||||
return;
|
||||
|
||||
while(true)
|
||||
{
|
||||
HandshakeStatus status = _sslEngine.getHandshakeStatus();
|
||||
switch(status)
|
||||
{
|
||||
case NEED_TASK:
|
||||
case NEED_WRAP:
|
||||
case NOT_HANDSHAKING:
|
||||
// write what we have or an empty buffer to reschedule a call to flush
|
||||
write = BufferUtil.hasContent(_encryptedOutput)?_encryptedOutput:BufferUtil.EMPTY_BUFFER;
|
||||
_flushState = FlushState.WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fillState!=FillState.IDLE)
|
||||
{
|
||||
// Wait for a fill that is happening anyway
|
||||
|
||||
case NEED_UNWRAP:
|
||||
// If we have something to write, then write it and ignore the needed unwrap for now.
|
||||
if (BufferUtil.hasContent(_encryptedOutput))
|
||||
{
|
||||
write = _encryptedOutput;
|
||||
_flushState = FlushState.WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fillState!=FillState.IDLE)
|
||||
{
|
||||
// Wait for a fill that is happening anyway
|
||||
_flushState = FlushState.WAIT_FOR_FILL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Try filling ourselves
|
||||
try
|
||||
{
|
||||
int filled = fill(BufferUtil.EMPTY_BUFFER);
|
||||
// If this changed the status, let's try again
|
||||
if (_sslEngine.getHandshakeStatus()!=status)
|
||||
continue;
|
||||
if (filled < 0)
|
||||
throw new IOException("Broken pipe");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.debug(e);
|
||||
close(e);
|
||||
write = BufferUtil.EMPTY_BUFFER;
|
||||
_flushState = FlushState.WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we are fill interested.
|
||||
fillInterest = true;
|
||||
_fillState = FillState.INTERESTED;
|
||||
_flushState = FlushState.WAIT_FOR_FILL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Try filling ourselves
|
||||
try
|
||||
{
|
||||
int filled = fill(BufferUtil.EMPTY_BUFFER);
|
||||
// If this changed the status, let's try again
|
||||
if (_sslEngine.getHandshakeStatus()!=status)
|
||||
continue;
|
||||
if (filled < 0)
|
||||
throw new IOException("Broken pipe");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.debug(e);
|
||||
close(e);
|
||||
write = BufferUtil.EMPTY_BUFFER;
|
||||
_flushState = FlushState.WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we are fill interested.
|
||||
fillInterest = true;
|
||||
_fillState = FillState.INTERESTED;
|
||||
_flushState = FlushState.WAIT_FOR_FILL;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("<onIncompleteFlush s={}/{} fi={} w={}", _flushState, _fillState, fillInterest, BufferUtil.toDetailString(write));
|
||||
}
|
||||
|
||||
if (write!=null)
|
||||
getEndPoint().write(_incompleteWriteCallback, write);
|
||||
else if (fillInterest)
|
||||
ensureFillInterested();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("<onIncompleteFlush s={}/{} fi={} w={}", _flushState, _fillState, fillInterest, BufferUtil.toDetailString(write));
|
||||
}
|
||||
|
||||
if (write!=null)
|
||||
getEndPoint().write(_incompleteWriteCallback, write);
|
||||
else if (fillInterest)
|
||||
ensureFillInterested();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(SslConnection.this.toString(), x);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue