下面列出了javax.net.ssl.SSLEngineResult#bytesProduced ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void checkResult(SSLEngineResult result, boolean wrap)
throws SSLException {
handshakeStatus = result.getHandshakeStatus();
resultStatus = result.getStatus();
if (resultStatus != Status.OK &&
(wrap || resultStatus != Status.BUFFER_UNDERFLOW)) {
throw new SSLException(
sm.getString("asyncChannelWrapperSecure.check.notOk", resultStatus));
}
if (wrap && result.bytesConsumed() != 0) {
throw new SSLException(sm.getString("asyncChannelWrapperSecure.check.wrap"));
}
if (!wrap && result.bytesProduced() != 0) {
throw new SSLException(sm.getString("asyncChannelWrapperSecure.check.unwrap"));
}
}
private void wrap() throws IOException {
ArrayList<ByteBuffer> wrapped = new ArrayList<>();
while (true) {
// TODO(bgallagher) buffer pooling
ByteBuffer out = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
SSLEngineResult result = engine.wrap(pending(), out);
if (result.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
throw new SSLException("renegotiation not supported");
}
if (result.bytesProduced() > 0) {
out.flip();
wrapped.add(out);
} else {
break;
}
}
setPending(wrapped.toArray(new ByteBuffer[wrapped.size()]));
}
private void checkResult(SSLEngineResult result, boolean wrap)
throws SSLException {
handshakeStatus = result.getHandshakeStatus();
resultStatus = result.getStatus();
if (resultStatus != Status.OK &&
(wrap || resultStatus != Status.BUFFER_UNDERFLOW)) {
throw new SSLException("TODO");
}
if (wrap && result.bytesConsumed() != 0) {
throw new SSLException("TODO");
}
if (!wrap && result.bytesProduced() != 0) {
throw new SSLException("TODO");
}
}
private void emitPlainData(SSLEngineResult result)
{
if (result.bytesProduced() > 0) {
ByteBuffer internalPlainBuffer = _buffers.get(BufferType.IN_PLAIN);
_sslListener.onPlainData(makeExternalBuffer(internalPlainBuffer));
}
}
private void emitWrappedData(SSLEngineResult result)
{
if (result.bytesProduced() > 0) {
ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
_sslListener.onWrappedData(makeExternalBuffer(internalCipherBuffer));
}
}
private void emitWrappedData(SSLEngineResult result)
{
if (result.bytesProduced() > 0) {
ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
_sslListener.onWrappedData(makeExternalBuffer(internalCipherBuffer));
}
}
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);
}
}
}
private void emitWrappedData(SslVo sslVo, SSLEngineResult result) {
if (result.bytesProduced() > 0) {
ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
sslVo.setByteBuffer(makeExternalBuffer(internalCipherBuffer));
_sslListener.onWrappedData(sslVo);
}
}
private boolean handshakeUnwrap() throws IOException {
SSLEngineResult result = sslEngineUnwrap(handshakeDummyBuffer);
switch (result.getStatus()) {
case OK:
if (result.bytesProduced() > 0) throw new SSLException("Got application data in handshake unwrap");
return true;
case BUFFER_UNDERFLOW:
return false;
default:
throw unexpectedStatusException(result.getStatus());
}
}
private int applicationDataUnwrap(ByteBuffer dst) throws IOException {
SSLEngineResult result = sslEngineUnwrap(dst);
if (result.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) throw new SSLException("Renegotiation detected");
switch (result.getStatus()) {
case OK:
return result.bytesProduced();
case BUFFER_OVERFLOW:
case BUFFER_UNDERFLOW:
return 0;
default:
throw unexpectedStatusException(result.getStatus());
}
}
@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);
}
}
@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 (RuntimeException | ReadBufferOverflowException | SSLException | EOFException |
ExecutionException | InterruptedException e) {
reading.set(false);
future.fail(e);
}
}
/**
* This method will not call
* {@link #setHandshakeFailure(ChannelHandlerContext, Throwable, boolean, boolean, boolean)} or
* {@link #setHandshakeFailure(ChannelHandlerContext, Throwable)}.
* @return {@code true} if this method ends on {@link SSLEngineResult.HandshakeStatus#NOT_HANDSHAKING}.
*/
private boolean wrapNonAppData(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
ByteBuf out = null;
ByteBufAllocator alloc = ctx.alloc();
try {
// Only continue to loop if the handler was not removed in the meantime.
// See https://github.com/netty/netty/issues/5860
while (!ctx.isRemoved()) {
if (out == null) {
// As this is called for the handshake we have no real idea how big the buffer needs to be.
// That said 2048 should give us enough room to include everything like ALPN / NPN data.
// If this is not enough we will increase the buffer in wrap(...).
out = allocateOutNetBuf(ctx, 2048, 1);
}
SSLEngineResult result = wrap(alloc, engine, Unpooled.EMPTY_BUFFER, out);
if (result.bytesProduced() > 0) {
ctx.write(out);
if (inUnwrap) {
needsFlush = true;
}
out = null;
}
switch (result.getHandshakeStatus()) {
case FINISHED:
setHandshakeSuccess();
return false;
case NEED_TASK:
runDelegatedTasks();
break;
case NEED_UNWRAP:
if (inUnwrap) {
// If we asked for a wrap, the engine requested an unwrap, and we are in unwrap there is
// no use in trying to call wrap again because we have already attempted (or will after we
// return) to feed more data to the engine.
return false;
}
unwrapNonAppData(ctx);
break;
case NEED_WRAP:
break;
case NOT_HANDSHAKING:
setHandshakeSuccessIfStillHandshaking();
// Workaround for TLS False Start problem reported at:
// https://github.com/netty/netty/issues/1108#issuecomment-14266970
if (!inUnwrap) {
unwrapNonAppData(ctx);
}
return true;
default:
throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
}
if (result.bytesProduced() == 0) {
break;
}
// It should not consume empty buffers when it is not handshaking
// Fix for Android, where it was encrypting empty buffers even when not handshaking
if (result.bytesConsumed() == 0 && result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
break;
}
}
} finally {
if (out != null) {
out.release();
}
}
return false;
}
@Test
public void testPartialPacketUnwrapJDKCompatabilityModeOff() throws Exception {
SelfSignedCertificate cert = new SelfSignedCertificate();
clientSslCtx = SslContextBuilder
.forClient()
.trustManager(cert.cert())
.sslProvider(sslClientProvider())
.build();
SSLEngine client = clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();
serverSslCtx = SslContextBuilder
.forServer(cert.certificate(), cert.privateKey())
.sslProvider(sslServerProvider())
.build();
SSLEngine server = serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();
try {
ByteBuffer plainClient = allocateBuffer(1024);
ByteBuffer plainClient2 = allocateBuffer(512);
ByteBuffer plainClientTotal = allocateBuffer(plainClient.capacity() + plainClient2.capacity());
plainClientTotal.put(plainClient);
plainClientTotal.put(plainClient2);
plainClient.clear();
plainClient2.clear();
plainClientTotal.flip();
ByteBuffer encClientToServer = allocateBuffer(client.getSession().getPacketBufferSize());
ByteBuffer plainServer = allocateBuffer(server.getSession().getApplicationBufferSize());
handshake(client, server);
SSLEngineResult result = client.wrap(plainClient, encClientToServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), plainClient.capacity());
final int encClientLen = result.bytesProduced();
result = client.wrap(plainClient2, encClientToServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), plainClient2.capacity());
final int encClientLen2 = result.bytesProduced();
// Flip so we can read it.
encClientToServer.flip();
// Consume a partial TLS packet.
ByteBuffer encClientFirstHalf = encClientToServer.duplicate();
encClientFirstHalf.limit(encClientLen / 2);
result = server.unwrap(encClientFirstHalf, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), encClientLen / 2);
encClientToServer.position(result.bytesConsumed());
// We now have half of the first packet and the whole second packet, so lets decode all but the last byte.
ByteBuffer encClientAllButLastByte = encClientToServer.duplicate();
final int encClientAllButLastByteLen = encClientAllButLastByte.remaining() - 1;
encClientAllButLastByte.limit(encClientAllButLastByte.limit() - 1);
result = server.unwrap(encClientAllButLastByte, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), encClientAllButLastByteLen);
encClientToServer.position(encClientToServer.position() + result.bytesConsumed());
// Read the last byte and verify the original content has been decrypted.
result = server.unwrap(encClientToServer, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), 1);
plainServer.flip();
assertEquals(plainClientTotal, plainServer);
} finally {
cert.delete();
cleanupClientSslEngine(client);
cleanupServerSslEngine(server);
}
}
@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);
}
}
private synchronized boolean wrap(final Buffer buffer) throws IOException
{
ByteBuffer bbuf=extractByteBuffer(buffer);
final SSLEngineResult result;
synchronized(bbuf)
{
_outbound.compact();
ByteBuffer out_buffer=_outbound.getByteBuffer();
synchronized(out_buffer)
{
try
{
bbuf.position(buffer.getIndex());
bbuf.limit(buffer.putIndex());
out_buffer.position(_outbound.putIndex());
out_buffer.limit(out_buffer.capacity());
result=_engine.wrap(bbuf,out_buffer);
if (_logger.isDebugEnabled())
_logger.debug("{} wrap {} {} consumed={} produced={}",
_session,
result.getStatus(),
result.getHandshakeStatus(),
result.bytesConsumed(),
result.bytesProduced());
buffer.skip(result.bytesConsumed());
_outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced());
}
catch(SSLException e)
{
_logger.debug(String.valueOf(_endp), e);
_endp.close();
throw e;
}
finally
{
out_buffer.position(0);
out_buffer.limit(out_buffer.capacity());
bbuf.position(0);
bbuf.limit(bbuf.capacity());
}
}
}
switch(result.getStatus())
{
case BUFFER_UNDERFLOW:
throw new IllegalStateException();
case BUFFER_OVERFLOW:
break;
case OK:
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_handshook=true;
break;
case CLOSED:
_logger.debug("wrap CLOSE {} {}",this,result);
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_endp.close();
break;
default:
_logger.debug("{} wrap default {}",_session,result);
throw new IOException(result.toString());
}
return result.bytesConsumed()>0 || result.bytesProduced()>0;
}
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);
}
}
}
@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);
}
}
private synchronized boolean wrap(final Buffer buffer) throws IOException
{
ByteBuffer bbuf=extractByteBuffer(buffer);
final SSLEngineResult result;
synchronized(bbuf)
{
_outbound.compact();
ByteBuffer out_buffer=_outbound.getByteBuffer();
synchronized(out_buffer)
{
try
{
bbuf.position(buffer.getIndex());
bbuf.limit(buffer.putIndex());
out_buffer.position(_outbound.putIndex());
out_buffer.limit(out_buffer.capacity());
result=_engine.wrap(bbuf,out_buffer);
if (_logger.isDebugEnabled())
_logger.debug("{} wrap {} {} consumed={} produced={}",
_session,
result.getStatus(),
result.getHandshakeStatus(),
result.bytesConsumed(),
result.bytesProduced());
buffer.skip(result.bytesConsumed());
_outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced());
}
catch(SSLException e)
{
_logger.debug(String.valueOf(_endp), e);
_endp.close();
throw e;
}
finally
{
out_buffer.position(0);
out_buffer.limit(out_buffer.capacity());
bbuf.position(0);
bbuf.limit(bbuf.capacity());
}
}
}
switch(result.getStatus())
{
case BUFFER_UNDERFLOW:
throw new IllegalStateException();
case BUFFER_OVERFLOW:
break;
case OK:
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_handshook=true;
break;
case CLOSED:
_logger.debug("wrap CLOSE {} {}",this,result);
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_endp.close();
break;
default:
_logger.debug("{} wrap default {}",_session,result);
throw new IOException(result.toString());
}
return result.bytesConsumed()>0 || result.bytesProduced()>0;
}