use of javax.net.ssl.SSLEngineResult in project kafka by apache.
the class SslTransportLayer method read.
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* @param dst The buffer into which bytes are to be transferred
* @return The number of bytes read, possible zero or -1 if the channel has reached end-of-stream
* @throws IOException if some other I/O error occurs
*/
@Override
public int read(ByteBuffer dst) throws IOException {
if (closing)
return -1;
int read = 0;
if (!handshakeComplete)
return read;
//if we have unread decrypted data in appReadBuffer read that into dst buffer.
if (appReadBuffer.position() > 0) {
read = readFromAppBuffer(dst);
}
if (dst.remaining() > 0) {
netReadBuffer = Utils.ensureCapacity(netReadBuffer, netReadBufferSize());
if (netReadBuffer.remaining() > 0) {
int netread = socketChannel.read(netReadBuffer);
if (netread == 0 && netReadBuffer.position() == 0)
return read;
else if (netread < 0)
throw new EOFException("EOF during read");
}
do {
netReadBuffer.flip();
SSLEngineResult unwrapResult = sslEngine.unwrap(netReadBuffer, appReadBuffer);
netReadBuffer.compact();
// handle ssl renegotiation.
if (unwrapResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && unwrapResult.getStatus() == Status.OK) {
log.trace("SSLChannel Read begin renegotiation channelId {}, appReadBuffer pos {}, netReadBuffer pos {}, netWriteBuffer pos {}", channelId, appReadBuffer.position(), netReadBuffer.position(), netWriteBuffer.position());
renegotiate();
break;
}
if (unwrapResult.getStatus() == Status.OK) {
read += readFromAppBuffer(dst);
} else if (unwrapResult.getStatus() == Status.BUFFER_OVERFLOW) {
int currentApplicationBufferSize = applicationBufferSize();
appReadBuffer = Utils.ensureCapacity(appReadBuffer, currentApplicationBufferSize);
if (appReadBuffer.position() >= currentApplicationBufferSize) {
throw new IllegalStateException("Buffer overflow when available data size (" + appReadBuffer.position() + ") >= application buffer size (" + currentApplicationBufferSize + ")");
}
// we can break here.
if (dst.hasRemaining())
read += readFromAppBuffer(dst);
else
break;
} else if (unwrapResult.getStatus() == Status.BUFFER_UNDERFLOW) {
int currentNetReadBufferSize = netReadBufferSize();
netReadBuffer = Utils.ensureCapacity(netReadBuffer, currentNetReadBufferSize);
if (netReadBuffer.position() >= currentNetReadBufferSize) {
throw new IllegalStateException("Buffer underflow when available data size (" + netReadBuffer.position() + ") > packet buffer size (" + currentNetReadBufferSize + ")");
}
break;
} else if (unwrapResult.getStatus() == Status.CLOSED) {
// If data has been read and unwrapped, return the data. Close will be handled on the next poll.
if (appReadBuffer.position() == 0 && read == 0)
throw new EOFException();
else
break;
}
} while (netReadBuffer.position() != 0);
}
return read;
}
use of javax.net.ssl.SSLEngineResult in project kafka by apache.
the class SslTransportLayer method close.
/**
* Sends a SSL close message and closes socketChannel.
*/
@Override
public void close() throws IOException {
if (closing)
return;
closing = true;
sslEngine.closeOutbound();
try {
if (isConnected()) {
if (!flush(netWriteBuffer)) {
throw new IOException("Remaining data in the network buffer, can't send SSL close message.");
}
//prep the buffer for the close message
netWriteBuffer.clear();
//perform the close, since we called sslEngine.closeOutbound
SSLEngineResult wrapResult = sslEngine.wrap(emptyBuf, netWriteBuffer);
//we should be in a close state
if (wrapResult.getStatus() != SSLEngineResult.Status.CLOSED) {
throw new IOException("Unexpected status returned by SSLEngine.wrap, expected CLOSED, received " + wrapResult.getStatus() + ". Will not send close message to peer.");
}
netWriteBuffer.flip();
flush(netWriteBuffer);
}
} catch (IOException ie) {
log.warn("Failed to send SSL Close message ", ie);
} finally {
try {
socketChannel.socket().close();
socketChannel.close();
} finally {
key.attach(null);
key.cancel();
}
}
}
use of javax.net.ssl.SSLEngineResult in project http-kit by http-kit.
the class HttpsRequest method unwrapRead.
final int unwrapRead(ByteBuffer peerAppData) throws IOException {
// TODO, make sure peerNetData has remaining place
int read = ((SocketChannel) key.channel()).read(peerNetData), unwrapped = 0;
if (read > 0) {
peerNetData.flip();
SSLEngineResult res;
while ((res = engine.unwrap(peerNetData, peerAppData)).getStatus() == Status.OK) {
unwrapped += res.bytesProduced();
if (!peerNetData.hasRemaining())
break;
}
peerNetData.compact();
switch(res.getStatus()) {
case OK:
case // need more data
BUFFER_UNDERFLOW:
return unwrapped;
case CLOSED:
return unwrapped > 0 ? unwrapped : -1;
case BUFFER_OVERFLOW:
// can't => peerAppData is 64k
return -1;
}
return unwrapped;
} else {
return read;
}
}
use of javax.net.ssl.SSLEngineResult in project netty by netty.
the class SslHandler method wrap.
private SSLEngineResult wrap(ByteBufAllocator alloc, SSLEngine engine, ByteBuf in, ByteBuf out) throws SSLException {
ByteBuf newDirectIn = null;
try {
int readerIndex = in.readerIndex();
int readableBytes = in.readableBytes();
// We will call SslEngine.wrap(ByteBuffer[], ByteBuffer) to allow efficient handling of
// CompositeByteBuf without force an extra memory copy when CompositeByteBuffer.nioBuffer() is called.
final ByteBuffer[] in0;
if (in.isDirect() || !engineType.wantsDirectBuffer) {
// which is better then walking the composed ByteBuf in most cases.
if (!(in instanceof CompositeByteBuf) && in.nioBufferCount() == 1) {
in0 = singleBuffer;
// We know its only backed by 1 ByteBuffer so use internalNioBuffer to keep object allocation
// to a minimum.
in0[0] = in.internalNioBuffer(readerIndex, readableBytes);
} else {
in0 = in.nioBuffers();
}
} else {
// We could even go further here and check if its a CompositeByteBuf and if so try to decompose it and
// only replace the ByteBuffer that are not direct. At the moment we just will replace the whole
// CompositeByteBuf to keep the complexity to a minimum
newDirectIn = alloc.directBuffer(readableBytes);
newDirectIn.writeBytes(in, readerIndex, readableBytes);
in0 = singleBuffer;
in0[0] = newDirectIn.internalNioBuffer(newDirectIn.readerIndex(), readableBytes);
}
for (; ; ) {
ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
SSLEngineResult result = engine.wrap(in0, out0);
in.skipBytes(result.bytesConsumed());
out.writerIndex(out.writerIndex() + result.bytesProduced());
switch(result.getStatus()) {
case BUFFER_OVERFLOW:
out.ensureWritable(maxPacketBufferSize);
break;
default:
return result;
}
}
} finally {
// Null out to allow GC of ByteBuffer
singleBuffer[0] = null;
if (newDirectIn != null) {
newDirectIn.release();
}
}
}
use of javax.net.ssl.SSLEngineResult in project netty by netty.
the class SslHandler method wrap.
// This method will not call setHandshakeFailure(...) !
private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
ByteBuf out = null;
ChannelPromise promise = null;
ByteBufAllocator alloc = ctx.alloc();
boolean needUnwrap = false;
try {
// See https://github.com/netty/netty/issues/5860
while (!ctx.isRemoved()) {
Object msg = pendingUnencryptedWrites.current();
if (msg == null) {
break;
}
ByteBuf buf = (ByteBuf) msg;
if (out == null) {
out = allocateOutNetBuf(ctx, buf.readableBytes(), buf.nioBufferCount());
}
SSLEngineResult result = wrap(alloc, engine, buf, out);
if (result.getStatus() == Status.CLOSED) {
// SSLEngine has been closed already.
// Any further write attempts should be denied.
pendingUnencryptedWrites.removeAndFailAll(SSLENGINE_CLOSED);
return;
} else {
if (!buf.isReadable()) {
promise = pendingUnencryptedWrites.remove();
} else {
promise = null;
}
switch(result.getHandshakeStatus()) {
case NEED_TASK:
runDelegatedTasks();
break;
case FINISHED:
setHandshakeSuccess();
// deliberate fall-through
case NOT_HANDSHAKING:
setHandshakeSuccessIfStillHandshaking();
// deliberate fall-through
case NEED_WRAP:
finishWrap(ctx, out, promise, inUnwrap, false);
promise = null;
out = null;
break;
case NEED_UNWRAP:
needUnwrap = true;
return;
default:
throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
}
}
}
} finally {
finishWrap(ctx, out, promise, inUnwrap, needUnwrap);
}
}
Aggregations