下面列出了javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Performs raw unwrap from network read buffer.
*
* @return Result.
* @throws SSLException If SSL exception occurs.
*/
private SSLEngineResult unwrap0() throws SSLException {
SSLEngineResult res;
do {
res = sslEngine.unwrap(inNetBuf, appBuf);
if (log.isDebugEnabled())
log.debug("Unwrapped raw data [status=" + res.getStatus() + ", handshakeStatus=" +
res.getHandshakeStatus() + ']');
if (res.getStatus() == Status.BUFFER_OVERFLOW)
appBuf = expandBuffer(appBuf, appBuf.capacity() * 2);
}
while ((res.getStatus() == OK || res.getStatus() == Status.BUFFER_OVERFLOW) &&
(handshakeFinished && res.getHandshakeStatus() == NOT_HANDSHAKING
|| res.getHandshakeStatus() == NEED_UNWRAP));
return res;
}
/**
* Start SSL shutdown process.
*
* @return <tt>true</tt> if shutdown process is started.
* <tt>false</tt> if shutdown process is already finished.
* @throws SSLException on errors
*/
boolean closeOutbound() throws SSLException {
if (sslEngine == null || sslEngine.isOutboundDone())
return false;
sslEngine.closeOutbound();
createOutNetBuffer(0);
for (;;) {
SSLEngineResult result = sslEngine.wrap(SimpleBufferAllocator.emptyBuffer.buf(), outNetBuffer.buf());
if (result.getStatus() != Status.BUFFER_OVERFLOW) {
if (result.getStatus() != Status.CLOSED)
throw new SSLException("improper close state: " + result);
break;
}
outNetBuffer = IoBuffer.reallocate(outNetBuffer, outNetBuffer.capacity() << 1);
outNetBuffer.limit(outNetBuffer.capacity());
}
outNetBuffer.flip();
return true;
}
private UnwrapResult unwrapLoop(Optional<ByteBufferSet> dest, HandshakeStatus statusCondition, boolean closing)
throws SSLException {
ByteBufferSet effDest = dest.orElseGet(() -> {
inPlain.prepare();
return new ByteBufferSet(inPlain.buffer);
});
while (true) {
Util.assertTrue(inPlain.nullOrEmpty());
SSLEngineResult result = callEngineUnwrap(effDest);
/*
* Note that data can be returned even in case of overflow, in that
* case, just return the data.
*/
if (result.bytesProduced() > 0 || result.getStatus() == Status.BUFFER_UNDERFLOW
|| !closing && result.getStatus() == Status.CLOSED
|| result.getHandshakeStatus() != statusCondition) {
boolean wasClosed = result.getStatus() == Status.CLOSED;
return new UnwrapResult(result.bytesProduced(), result.getHandshakeStatus(), wasClosed);
}
if (result.getStatus() == Status.BUFFER_OVERFLOW) {
if (dest.isPresent() && effDest == dest.get()) {
/*
* The client-supplier buffer is not big enough. Use the
* internal inPlain buffer, also ensure that it is bigger
* than the too-small supplied one.
*/
inPlain.prepare();
ensureInPlainCapacity(Math.min(((int) dest.get().remaining()) * 2, maxTlsPacketSize));
} else {
inPlain.enlarge();
}
// inPlain changed, re-create the wrapper
effDest = new ByteBufferSet(inPlain.buffer);
}
}
}
/**
* Decrypt the incoming buffer and move the decrypted data to an application buffer.
*/
private SSLEngineResult unwrap() throws SSLException {
// We first have to create the application buffer if it does not exist
if (appBuffer == null)
appBuffer = IoBuffer.allocate(inNetBuffer.remaining());
else {
// We already have one, just add the new data into it
appBuffer = IoBuffer.reallocateRemain(appBuffer, inNetBuffer.remaining());
}
SSLEngineResult res;
Status status;
HandshakeStatus localHandshakeStatus;
do {
// Decode the incoming data
res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf());
status = res.getStatus();
// We can be processing the Handshake
localHandshakeStatus = res.getHandshakeStatus();
if (status == Status.BUFFER_OVERFLOW) {
// We have to grow the target buffer, it's too small. Then we can call the unwrap method again
int newCapacity = sslEngine.getSession().getApplicationBufferSize();
if (appBuffer.remaining() >= newCapacity) {
// The buffer is already larger than the max buffer size suggested by the SSL engine.
// Raising it any more will not make sense and it will end up in an endless loop. Throwing an error is safer
throw new SSLException("SSL buffer overflow");
}
appBuffer = IoBuffer.reallocateRemain(appBuffer, newCapacity);
}
} while ((status == Status.OK || status == Status.BUFFER_OVERFLOW) &&
(localHandshakeStatus == HandshakeStatus.NOT_HANDSHAKING || localHandshakeStatus == HandshakeStatus.NEED_UNWRAP));
return res;
}
/**
* Encrypt provided buffer. Encrypted data returned by getOutNetBuffer().
*
* @param src data to encrypt
* @throws SSLException on errors
*/
void encrypt(ByteBuffer src) throws SSLException {
if (!handshakeComplete)
throw new IllegalStateException();
if (!src.hasRemaining()) {
if (outNetBuffer == null)
outNetBuffer = IoBuffer.allocate(0);
return;
}
createOutNetBuffer(src.remaining());
// Loop until there is no more data in src
while (src.hasRemaining()) {
SSLEngineResult result = sslEngine.wrap(src, outNetBuffer.buf());
if (result.getStatus() == Status.OK) {
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
doTasks();
} else if (result.getStatus() == Status.BUFFER_OVERFLOW) {
outNetBuffer = IoBuffer.reallocate(outNetBuffer, outNetBuffer.capacity() << 1);
outNetBuffer.limit(outNetBuffer.capacity());
} else
throw new SSLException("SSLEngine error during encrypt: " + result.getStatus() + " src: " + src + "outNetBuffer: " + outNetBuffer);
}
outNetBuffer.flip();
}
@Override
public void run() {
long written = 0;
try {
for (int i = offset; i < offset + length; i++) {
ByteBuffer src = srcs[i];
while (src.hasRemaining()) {
socketWriteBuffer.clear();
// Encrypt the data
SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
written += r.bytesConsumed();
Status s = r.getStatus();
if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
// Need to write out the bytes and may need to read from
// the source again to empty it
} else {
// Status.BUFFER_UNDERFLOW - only happens on unwrap
// Status.CLOSED - unexpected
throw new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.statusWrap"));
}
// Check for tasks
if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable = sslEngine.getDelegatedTask();
while (runnable != null) {
runnable.run();
runnable = sslEngine.getDelegatedTask();
}
}
socketWriteBuffer.flip();
// Do the write
int toWrite = r.bytesProduced();
while (toWrite > 0) {
Future<Integer> f =
socketChannel.write(socketWriteBuffer);
Integer socketWrite = f.get();
toWrite -= socketWrite.intValue();
}
}
}
if (writing.compareAndSet(true, false)) {
future.complete(Long.valueOf(written));
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateWrite")));
}
} catch (Exception e) {
writing.set(false);
future.fail(e);
}
}
/**
* Perform any handshaking processing.
*/
void handshake(NextFilter nextFilter) throws Exception {
for (;;) {
switch (handshakeStatus) {
case FINISHED:
// LOGGER.debug("{} processing the FINISHED state", SslFilter.getSessionInfo(session));
handshakeComplete = true;
// Send the SECURE message only if it's the first SSL handshake
if (firstSSLNegociation) {
firstSSLNegociation = false;
if (session.containsAttribute(SslFilter.USE_NOTIFICATION))
scheduleMessageReceived(nextFilter, SslFilter.SESSION_SECURED);
}
// if (!isOutboundDone()) {
// LOGGER.debug("{} is now secured", SslFilter.getSessionInfo(session));
// } else {
// LOGGER.debug("{} is not secured yet", SslFilter.getSessionInfo(session));
// }
return;
case NEED_TASK:
// LOGGER.debug("{} processing the NEED_TASK state", SslFilter.getSessionInfo(session));
handshakeStatus = doTasks();
break;
case NEED_UNWRAP:
// LOGGER.debug("{} processing the NEED_UNWRAP state", SslFilter.getSessionInfo(session));
// we need more data read
if (unwrapHandshake(nextFilter) == Status.BUFFER_UNDERFLOW && handshakeStatus != HandshakeStatus.FINISHED || isInboundDone())
return; // We need more data or the session is closed
break;
case NEED_WRAP:
case NOT_HANDSHAKING:
// LOGGER.debug("{} processing the NEED_WRAP state", SslFilter.getSessionInfo(session));
// First make sure that the out buffer is completely empty.
// Since we cannot call wrap with data left on the buffer
if (outNetBuffer != null && outNetBuffer.hasRemaining())
return;
createOutNetBuffer(0);
for (;;) { //NOSONAR
SSLEngineResult result = sslEngine.wrap(SimpleBufferAllocator.emptyBuffer.buf(), outNetBuffer.buf());
if (result.getStatus() != Status.BUFFER_OVERFLOW) {
handshakeStatus = result.getHandshakeStatus();
break;
}
outNetBuffer = IoBuffer.reallocate(outNetBuffer, outNetBuffer.capacity() << 1);
outNetBuffer.limit(outNetBuffer.capacity());
}
outNetBuffer.flip();
writeNetBuffer(nextFilter, false);
break;
default:
String msg = "invalid handshaking state" + handshakeStatus + " while processing the handshake for session " + session.getId();
ExceptionMonitor.getInstance().error(msg);
throw new IllegalStateException(msg);
}
}
}
SSLStreams.WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
Status status = Status.OK;
SSLStreams.WrapperResult r = SSLStreams.this.new WrapperResult();
r.buf = dst;
if (this.closed) {
throw new IOException("Engine is closed");
} else {
boolean needData;
if (this.u_remaining > 0) {
this.unwrap_src.compact();
this.unwrap_src.flip();
needData = false;
} else {
this.unwrap_src.clear();
needData = true;
}
Object var5 = this.unwrapLock;
synchronized(this.unwrapLock) {
do {
if (needData) {
int x;
do {
x = this.chan.read(this.unwrap_src);
} while(x == 0);
if (x == -1) {
throw new IOException("connection closed for reading");
}
this.unwrap_src.flip();
}
r.result = this.engine.unwrap(this.unwrap_src, r.buf);
status = r.result.getStatus();
if (status == Status.BUFFER_UNDERFLOW) {
if (this.unwrap_src.limit() == this.unwrap_src.capacity()) {
this.unwrap_src = SSLStreams.this.realloc(this.unwrap_src, false, SSLStreams.BufType.PACKET);
} else {
this.unwrap_src.position(this.unwrap_src.limit());
this.unwrap_src.limit(this.unwrap_src.capacity());
}
needData = true;
} else if (status == Status.BUFFER_OVERFLOW) {
r.buf = SSLStreams.this.realloc(r.buf, true, SSLStreams.BufType.APPLICATION);
needData = false;
} else if (status == Status.CLOSED) {
this.closed = true;
r.buf.flip();
return r;
}
} while(status != Status.OK);
}
this.u_remaining = this.unwrap_src.remaining();
return r;
}
}
SSLStreams.WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
Status status = Status.OK;
SSLStreams.WrapperResult r = SSLStreams.this.new WrapperResult();
r.buf = dst;
if (this.closed) {
throw new IOException("Engine is closed");
} else {
boolean needData;
if (this.u_remaining > 0) {
this.unwrap_src.compact();
this.unwrap_src.flip();
needData = false;
} else {
this.unwrap_src.clear();
needData = true;
}
synchronized(this.unwrapLock) {
do {
if (needData) {
int x;
do {
x = this.chan.read(this.unwrap_src);
} while(x == 0);
if (x == -1) {
throw new IOException("connection closed for reading");
}
this.unwrap_src.flip();
}
r.result = this.engine.unwrap(this.unwrap_src, r.buf);
status = r.result.getStatus();
if (status == Status.BUFFER_UNDERFLOW) {
if (this.unwrap_src.limit() == this.unwrap_src.capacity()) {
this.unwrap_src = SSLStreams.this.realloc(this.unwrap_src, false, SSLStreams.BufType.PACKET);
} else {
this.unwrap_src.position(this.unwrap_src.limit());
this.unwrap_src.limit(this.unwrap_src.capacity());
}
needData = true;
} else if (status == Status.BUFFER_OVERFLOW) {
r.buf = SSLStreams.this.realloc(r.buf, true, SSLStreams.BufType.APPLICATION);
needData = false;
} else if (status == Status.CLOSED) {
this.closed = true;
r.buf.flip();
return r;
}
} while(status != Status.OK);
}
this.u_remaining = this.unwrap_src.remaining();
return r;
}
}
SSLStreams.WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
Status status = Status.OK;
SSLStreams.WrapperResult r = SSLStreams.this.new WrapperResult();
r.buf = dst;
if (this.closed) {
throw new IOException("Engine is closed");
} else {
boolean needData;
if (this.u_remaining > 0) {
this.unwrap_src.compact();
this.unwrap_src.flip();
needData = false;
} else {
this.unwrap_src.clear();
needData = true;
}
Object var5 = this.unwrapLock;
synchronized(this.unwrapLock) {
do {
if (needData) {
int x;
do {
x = this.chan.read(this.unwrap_src);
} while(x == 0);
if (x == -1) {
throw new IOException("connection closed for reading");
}
this.unwrap_src.flip();
}
r.result = this.engine.unwrap(this.unwrap_src, r.buf);
status = r.result.getStatus();
if (status == Status.BUFFER_UNDERFLOW) {
if (this.unwrap_src.limit() == this.unwrap_src.capacity()) {
this.unwrap_src = SSLStreams.this.realloc(this.unwrap_src, false, SSLStreams.BufType.PACKET);
} else {
this.unwrap_src.position(this.unwrap_src.limit());
this.unwrap_src.limit(this.unwrap_src.capacity());
}
needData = true;
} else if (status == Status.BUFFER_OVERFLOW) {
r.buf = SSLStreams.this.realloc(r.buf, true, SSLStreams.BufType.APPLICATION);
needData = false;
} else if (status == Status.CLOSED) {
this.closed = true;
r.buf.flip();
return r;
}
} while(status != Status.OK);
}
this.u_remaining = this.unwrap_src.remaining();
return r;
}
}
SSLStreams.WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
Status status = Status.OK;
SSLStreams.WrapperResult r = SSLStreams.this.new WrapperResult();
r.buf = dst;
if (this.closed) {
throw new IOException("Engine is closed");
} else {
boolean needData;
if (this.u_remaining > 0) {
this.unwrap_src.compact();
this.unwrap_src.flip();
needData = false;
} else {
this.unwrap_src.clear();
needData = true;
}
Object var5 = this.unwrapLock;
synchronized(this.unwrapLock) {
do {
if (needData) {
int x;
do {
x = this.chan.read(this.unwrap_src);
} while(x == 0);
if (x == -1) {
throw new IOException("connection closed for reading");
}
this.unwrap_src.flip();
}
r.result = this.engine.unwrap(this.unwrap_src, r.buf);
status = r.result.getStatus();
if (status == Status.BUFFER_UNDERFLOW) {
if (this.unwrap_src.limit() == this.unwrap_src.capacity()) {
this.unwrap_src = SSLStreams.this.realloc(this.unwrap_src, false, SSLStreams.BufType.PACKET);
} else {
this.unwrap_src.position(this.unwrap_src.limit());
this.unwrap_src.limit(this.unwrap_src.capacity());
}
needData = true;
} else if (status == Status.BUFFER_OVERFLOW) {
r.buf = SSLStreams.this.realloc(r.buf, true, SSLStreams.BufType.APPLICATION);
needData = false;
} else if (status == Status.CLOSED) {
this.closed = true;
r.buf.flip();
return r;
}
} while(status != Status.OK);
}
this.u_remaining = this.unwrap_src.remaining();
return r;
}
}
private void performHandshake() throws IOException {
// Generate handshake message
final byte[] emptyMessage = new byte[0];
handshaking = true;
logger.debug("{} Performing Handshake", this);
try {
while (true) {
switch (engine.getHandshakeStatus()) {
case FINISHED:
return;
case NEED_WRAP: {
final ByteBuffer appDataOut = ByteBuffer.wrap(emptyMessage);
final ByteBuffer outboundBuffer = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize());
final SSLEngineResult wrapHelloResult = engine.wrap(appDataOut, outboundBuffer);
if (wrapHelloResult.getStatus() == Status.BUFFER_OVERFLOW) {
streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize());
continue;
}
if (wrapHelloResult.getStatus() != Status.OK) {
throw new SSLHandshakeException("Could not generate SSL Handshake information: SSLEngineResult: "
+ wrapHelloResult.toString());
}
logger.trace("{} Handshake response after wrapping: {}", this, wrapHelloResult);
final ByteBuffer readableStreamOut = streamOutManager.prepareForRead(1);
final int bytesToSend = readableStreamOut.remaining();
writeFully(readableStreamOut);
logger.trace("{} Sent {} bytes of wrapped data for handshake", this, bytesToSend);
streamOutManager.clear();
}
continue;
case NEED_UNWRAP: {
final ByteBuffer readableDataIn = streamInManager.prepareForRead(0);
final ByteBuffer appData = appDataManager.prepareForWrite(engine.getSession().getApplicationBufferSize());
// Read handshake response from other side
logger.trace("{} Unwrapping: {} to {}", this, readableDataIn, appData);
SSLEngineResult handshakeResponseResult = engine.unwrap(readableDataIn, appData);
logger.trace("{} Handshake response after unwrapping: {}", this, handshakeResponseResult);
if (handshakeResponseResult.getStatus() == Status.BUFFER_UNDERFLOW) {
final ByteBuffer writableDataIn = streamInManager.prepareForWrite(engine.getSession().getPacketBufferSize());
final int bytesRead = readData(writableDataIn);
if (bytesRead > 0) {
logger.trace("{} Read {} bytes for handshake", this, bytesRead);
}
if (bytesRead < 0) {
throw new SSLHandshakeException("Reached End-of-File marker while performing handshake");
}
} else if (handshakeResponseResult.getStatus() == Status.CLOSED) {
throw new IOException("Channel was closed by peer during handshake");
} else {
streamInManager.compact();
appDataManager.clear();
}
}
break;
case NEED_TASK:
performTasks();
continue;
case NOT_HANDSHAKING:
return;
}
}
} finally {
handshaking = false;
}
}
@Override
public void run() {
long written = 0;
try {
for (int i = offset; i < offset + length; i++) {
ByteBuffer src = srcs[i];
while (src.hasRemaining()) {
socketWriteBuffer.clear();
// Encrypt the data
SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
written += r.bytesConsumed();
Status s = r.getStatus();
if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
// Need to write out the bytes and may need to read from
// the source again to empty it
} else {
// Status.BUFFER_UNDERFLOW - only happens on unwrap
// Status.CLOSED - unexpected
throw new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.statusWrap"));
}
// Check for tasks
if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable = sslEngine.getDelegatedTask();
while (runnable != null) {
runnable.run();
runnable = sslEngine.getDelegatedTask();
}
}
socketWriteBuffer.flip();
// Do the write
int toWrite = r.bytesProduced();
while (toWrite > 0) {
Future<Integer> f =
socketChannel.write(socketWriteBuffer);
Integer socketWrite = f.get();
toWrite -= socketWrite.intValue();
}
}
}
if (writing.compareAndSet(true, false)) {
future.complete(Long.valueOf(written));
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateWrite")));
}
} catch (Exception e) {
future.fail(e);
}
}
@Override
public void run() {
int read = 0;
boolean forceRead = false;
try {
while (read == 0) {
socketReadBuffer.compact();
if (forceRead) {
Future<Integer> f =
socketChannel.read(socketReadBuffer);
Integer socketRead = f.get();
if (socketRead.intValue() == -1) {
throw new EOFException(sm.getString(
"asyncChannelWrapperSecure.eof"));
}
}
socketReadBuffer.flip();
if (socketReadBuffer.hasRemaining()) {
// Decrypt the data in the buffer
SSLEngineResult r =
sslEngine.unwrap(socketReadBuffer, dest);
read += r.bytesProduced();
Status s = r.getStatus();
if (s == Status.OK) {
// Bytes available for reading and there may be
// sufficient data in the socketReadBuffer to
// support further reads without reading from the
// socket
} else if (s == Status.BUFFER_UNDERFLOW) {
// There is partial data in the socketReadBuffer
if (read == 0) {
// Need more data before the partial data can be
// processed and some output generated
forceRead = true;
}
// else return the data we have and deal with the
// partial data on the next read
} else if (s == Status.BUFFER_OVERFLOW) {
// Not enough space in the destination buffer to
// store all of the data. We could use a bytes read
// value of -bufferSizeRequired to signal the new
// buffer size required but an explicit exception is
// clearer.
if (reading.compareAndSet(true, false)) {
throw new ReadBufferOverflowException(sslEngine.
getSession().getApplicationBufferSize());
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateRead")));
}
} else {
// Status.CLOSED - unexpected
throw new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.statusUnwrap"));
}
// Check for tasks
if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable = sslEngine.getDelegatedTask();
while (runnable != null) {
runnable.run();
runnable = sslEngine.getDelegatedTask();
}
}
} else {
forceRead = true;
}
}
if (reading.compareAndSet(true, false)) {
future.complete(Integer.valueOf(read));
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateRead")));
}
} catch (Exception e) {
future.fail(e);
}
}
WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
Status status;
WrapperResult r = new WrapperResult();
r.buf = dst;
if (closed) {
throw new IOException ("Engine is closed");
}
boolean needData;
if (u_remaining > 0) {
unwrap_src.compact();
unwrap_src.flip();
needData = false;
} else {
unwrap_src.clear();
needData = true;
}
synchronized (unwrapLock) {
int x;
do {
if (needData) {
x = chan.read (unwrap_src);
if (x == -1) {
throw new IOException ("connection closed for reading");
}
unwrap_src.flip();
}
r.result = engine.unwrap (unwrap_src, r.buf);
status = r.result.getStatus();
if (status == Status.BUFFER_UNDERFLOW) {
if (unwrap_src.limit() == unwrap_src.capacity()) {
/* buffer not big enough */
unwrap_src = realloc (
unwrap_src, false, BufType.PACKET
);
} else {
/* Buffer not full, just need to read more
* data off the channel. Reset pointers
* for reading off SocketChannel
*/
unwrap_src.position (unwrap_src.limit());
unwrap_src.limit (unwrap_src.capacity());
}
needData = true;
} else if (status == Status.BUFFER_OVERFLOW) {
r.buf = realloc (r.buf, true, BufType.APPLICATION);
needData = false;
} else if (status == Status.CLOSED) {
closed = true;
r.buf.flip();
return r;
}
} while (status != Status.OK);
}
u_remaining = unwrap_src.remaining();
return r;
}
@Override
public void run() {
long written = 0;
try {
for (int i = offset; i < offset + length; i++) {
ByteBuffer src = srcs[i];
while (src.hasRemaining()) {
socketWriteBuffer.clear();
// Encrypt the data
SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
written += r.bytesConsumed();
Status s = r.getStatus();
if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
// Need to write out the bytes and may need to read from
// the source again to empty it
} else {
// Status.BUFFER_UNDERFLOW - only happens on unwrap
// Status.CLOSED - unexpected
throw new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.statusWrap"));
}
// Check for tasks
if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable = sslEngine.getDelegatedTask();
while (runnable != null) {
runnable.run();
runnable = sslEngine.getDelegatedTask();
}
}
socketWriteBuffer.flip();
// Do the write
int toWrite = r.bytesProduced();
while (toWrite > 0) {
Future<Integer> f =
socketChannel.write(socketWriteBuffer);
Integer socketWrite = f.get();
toWrite -= socketWrite.intValue();
}
}
}
if (writing.compareAndSet(true, false)) {
future.complete(Long.valueOf(written));
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateWrite")));
}
} catch (Exception e) {
future.fail(e);
}
}
@Override
public void run() {
int read = 0;
boolean forceRead = false;
try {
while (read == 0) {
socketReadBuffer.compact();
if (forceRead) {
forceRead = false;
Future<Integer> f = socketChannel.read(socketReadBuffer);
Integer socketRead = f.get();
if (socketRead.intValue() == -1) {
throw new EOFException(sm.getString(
"asyncChannelWrapperSecure.eof"));
}
}
socketReadBuffer.flip();
if (socketReadBuffer.hasRemaining()) {
// Decrypt the data in the buffer
SSLEngineResult r =
sslEngine.unwrap(socketReadBuffer, dest);
read += r.bytesProduced();
Status s = r.getStatus();
if (s == Status.OK) {
// Bytes available for reading and there may be
// sufficient data in the socketReadBuffer to
// support further reads without reading from the
// socket
} else if (s == Status.BUFFER_UNDERFLOW) {
// There is partial data in the socketReadBuffer
if (read == 0) {
// Need more data before the partial data can be
// processed and some output generated
forceRead = true;
}
// else return the data we have and deal with the
// partial data on the next read
} else if (s == Status.BUFFER_OVERFLOW) {
// Not enough space in the destination buffer to
// store all of the data. We could use a bytes read
// value of -bufferSizeRequired to signal the new
// buffer size required but an explicit exception is
// clearer.
if (reading.compareAndSet(true, false)) {
throw new ReadBufferOverflowException(sslEngine.
getSession().getApplicationBufferSize());
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateRead")));
}
} else {
// Status.CLOSED - unexpected
throw new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.statusUnwrap"));
}
// Check for tasks
if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable = sslEngine.getDelegatedTask();
while (runnable != null) {
runnable.run();
runnable = sslEngine.getDelegatedTask();
}
}
} else {
forceRead = true;
}
}
if (reading.compareAndSet(true, false)) {
future.complete(Integer.valueOf(read));
} else {
future.fail(new IllegalStateException(sm.getString(
"asyncChannelWrapperSecure.wrongStateRead")));
}
} catch (Exception e) {
future.fail(e);
}
}
/**
* Converts a_ to <-A->. z_ is special and encodes as <> (to give us packets of different lengths).
* If dst is not sufficiently large ({@value #SHORT_ENCODED_CHUNK_SIZE} in our encoding), we return
* {@link Status#BUFFER_OVERFLOW}, and the src and dst ByteBuffers are unchanged.
*/
@Override
public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst)
throws SSLException
{
int consumed = 0;
int produced = 0;
final Status resultStatus;
if (src.remaining() >= CLEAR_CHUNK_SIZE)
{
src.mark();
char uncapitalisedChar = (char) src.get();
char underscore = (char) src.get();
validateClear(uncapitalisedChar, underscore);
boolean useShortEncoding = uncapitalisedChar == 'z';
int encodingLength = useShortEncoding ? SHORT_ENCODED_CHUNK_SIZE : MAX_ENCODED_CHUNK_SIZE;
boolean overflow = dst.remaining() < encodingLength;
if (overflow)
{
src.reset();
resultStatus = Status.BUFFER_OVERFLOW;
}
else
{
consumed = CLEAR_CHUNK_SIZE;
char capitalisedChar = Character.toUpperCase(uncapitalisedChar);
dst.put((byte)ENCODED_TEXT_BEGIN);
if (!useShortEncoding)
{
dst.put((byte)ENCODED_TEXT_INNER_CHAR);
dst.put((byte)capitalisedChar);
dst.put((byte)ENCODED_TEXT_INNER_CHAR);
}
dst.put((byte)ENCODED_TEXT_END);
produced = encodingLength;
resultStatus = Status.OK;
}
}
else
{
resultStatus = Status.OK;
}
return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, consumed, produced);
}
private void unwrapLoop(HandshakeStatus originalStatus) throws SSLException {
ByteBufferSet effDest;
if (suppliedInPlain != null) {
effDest = suppliedInPlain;
} else {
inPlain.prepare();
effDest = new ByteBufferSet(inPlain.buffer);
}
while (true) {
Util.assertTrue(inPlain.nullOrEmpty());
SSLEngineResult result = callEngineUnwrap(effDest);
/*
* Note that data can be returned even in case of overflow, in that
* case, just return the data.
*/
if (result.bytesProduced() > 0
|| result.getStatus() == Status.BUFFER_UNDERFLOW
|| result.getStatus() == Status.CLOSED
|| result.getHandshakeStatus() != originalStatus) {
bytesToReturn = result.bytesProduced();
if (result.getStatus() == Status.CLOSED) {
shutdownReceived = true;
}
return;
}
if (result.getStatus() == Status.BUFFER_OVERFLOW) {
if (suppliedInPlain != null && effDest == suppliedInPlain) {
/*
* The client-supplier buffer is not big enough. Use the
* internal inPlain buffer, also ensure that it is bigger
* than the too-small supplied one.
*/
inPlain.prepare();
ensureInPlainCapacity(
Math.min(((int) suppliedInPlain.remaining()) * 2, maxTlsPacketSize));
} else {
inPlain.enlarge();
}
// inPlain changed, re-create the wrapper
effDest = new ByteBufferSet(inPlain.buffer);
}
}
}
/**
* 读取SSL消息到缓冲区
*
* @return 接收数据大小
* @throws IOException IO异常
*/
public synchronized int unWarpByteBufferChannel() throws IOException {
ByteBufferChannel appByteBufferChannel = session.getReadByteBufferChannel();
if(!isEnoughToUnwarp()) {
return 0;
}
int readSize = 0;
if (session.isConnected() && sslByteBufferChannel.size() > 0) {
SSLEngineResult engineResult = null;
try {
while (true) {
appData.clear();
ByteBuffer byteBuffer = sslByteBufferChannel.getByteBuffer();;
try {
engineResult = unwarpData(byteBuffer, appData);
} finally {
sslByteBufferChannel.compact();
}
if (engineResult == null) {
throw new SSLException("unWarpByteBufferChannel: Socket is disconnect");
}
appData.flip();
appByteBufferChannel.writeEnd(appData);
if (engineResult != null &&
engineResult.getStatus() == Status.OK &&
byteBuffer.remaining() == 0) {
break;
}
if (engineResult != null &&
(engineResult.getStatus() == Status.BUFFER_OVERFLOW ||
engineResult.getStatus() == Status.BUFFER_UNDERFLOW ||
engineResult.getStatus() == Status.CLOSED)
) {
break;
}
}
}catch (MemoryReleasedException e){
if(!session.isConnected()) {
throw new SSLException("unWarpByteBufferChannel ", e);
}
}
}
return readSize;
}