下面列出了javax.net.ssl.SSLEngineResult.Status#OK 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* performs the unwrap operation by unwrapping from {@link #inCrypt} to {@link #inData}
**/
private synchronized ByteBuffer unwrap() throws SSLException {
int rem;
//There are some ssl test suites, which get around the selector.select() call, which
// cause an infinite unwrap and 100% cpu usage (see #459 and #458)
if (readEngineResult.getStatus() == Status.CLOSED
&& sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
try {
close();
} catch (IOException e) {
//Not really interesting
}
}
do {
rem = inData.remaining();
readEngineResult = sslEngine.unwrap(inCrypt, inData);
} while (readEngineResult.getStatus() == Status.OK && (rem != inData.remaining()
|| sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP));
inData.flip();
return inData;
}
private Status encryptAndWriteFully(final BufferStateManager src) throws IOException {
SSLEngineResult result = null;
final ByteBuffer buff = src.prepareForRead(0);
final ByteBuffer outBuff = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize());
logger.trace("{} Encrypting {} bytes", this, buff.remaining());
while (buff.remaining() > 0) {
result = engine.wrap(buff, outBuff);
if (result.getStatus() == Status.OK) {
final ByteBuffer readableOutBuff = streamOutManager.prepareForRead(0);
writeFully(readableOutBuff);
streamOutManager.clear();
} else {
return result.getStatus();
}
}
return result.getStatus();
}
private Status encryptAndWriteFully(final BufferStateManager src) throws IOException {
SSLEngineResult result = null;
final ByteBuffer buff = src.prepareForRead(0);
final ByteBuffer outBuff = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize());
logger.trace("{} Encrypting {} bytes", this, buff.remaining());
while (buff.remaining() > 0) {
result = engine.wrap(buff, outBuff);
if (result.getStatus() == Status.OK) {
final ByteBuffer readableOutBuff = streamOutManager.prepareForRead(0);
writeFully(readableOutBuff);
streamOutManager.clear();
} else {
return result.getStatus();
}
}
return result.getStatus();
}
/**
* 打包并发送数据
*
* @param buffer 需要的数据缓冲区
* @return 返回成功执行的最后一个或者失败的那个 SSLEnginResult
* @throws IOException IO 异常
*/
public synchronized SSLEngineResult warpData(ByteBuffer buffer) throws IOException {
if (session.isConnected()) {
SSLEngineResult engineResult = null;
do {
synchronized (netData) {
if(!TByteBuffer.isReleased(netData)) {
netData.clear();
engineResult = engine.wrap(buffer, netData);
netData.flip();
if (session.isConnected() && engineResult.bytesProduced() > 0 && netData.limit() > 0) {
session.sendToBuffer(netData);
}
netData.clear();
} else {
return null;
}
}
} while (engineResult.getStatus() == Status.OK && buffer.hasRemaining());
return engineResult;
} else {
return null;
}
}
private Status unwrapHandshake(NextFilter nextFilter) throws Exception {
// Prepare the net data for reading.
if (inNetBuffer != null)
inNetBuffer.flip();
if ((inNetBuffer == null) || !inNetBuffer.hasRemaining())
return Status.BUFFER_UNDERFLOW; // Need more data
SSLEngineResult res = unwrap();
handshakeStatus = res.getHandshakeStatus();
checkStatus(res);
// If handshake finished, no data was produced, and the status is still ok, try to unwrap more
if (handshakeStatus == HandshakeStatus.FINISHED && res.getStatus() == Status.OK && inNetBuffer.hasRemaining()) {
res = unwrap();
// prepare to be written again
if (inNetBuffer.hasRemaining())
inNetBuffer.compact();
else {
inNetBuffer.free();
inNetBuffer = null;
}
renegotiateIfNeeded(nextFilter, res);
} else {
// prepare to be written again
if (inNetBuffer.hasRemaining())
inNetBuffer.compact();
else {
inNetBuffer.free();
inNetBuffer = null;
}
}
return res.getStatus();
}
private static void decryptOne(final SqSSL ssl, final ByteBuffer target) throws SSLException {
ssl.buffer.flip();
final SSLEngineResult result = unwrap(ssl, ssl.buffer, target);
checkStatus("Decrypt status", result, Status.OK, Status.BUFFER_UNDERFLOW, Status.CLOSED);
if (result.getStatus() == Status.OK || result.getStatus() == Status.BUFFER_UNDERFLOW) {
ssl.buffer.compact();
}
if (result.getStatus() == Status.CLOSED) {
connectionClosed(ssl);
}
}
@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);
}
}
/**
* 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);
}
static WrapperResult createOK() {
WrapperResult r = new WrapperResult();
r.buf = null;
r.result = new SSLEngineResult(Status.OK, NOT_HANDSHAKING, 0, 0);
return r;
}
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;
}
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;
}
}
public synchronized int read(ByteBuffer dst) throws IOException
{
if (socketChannel.socket().isInputShutdown())
{
throw new ClosedChannelException();
}
else if (initialized != 0)
{
handshake(SelectionKey.OP_READ);
return 0;
}
else if (shutdown)
{
shutdown();
return 0;
}
else if (sslEngine.isInboundDone())
{
return -1;
}
else if ((fill(inputBuffer[0]) < 0) && (inputBuffer[0].position() == 0))
{
return -1;
}
SSLEngineResult result;
Status status;
do
{
if (!prepare(inputCache, minCacheSize))
{
// Overflow!
break;
}
inputBuffer[0].flip();
try
{
result = sslEngine.unwrap(inputBuffer[0], inputCache[0]);
}
finally
{
inputBuffer[0].compact();
inputCache[0].flip();
}
status = result.getStatus();
if ((status == Status.OK) || (status == Status.BUFFER_UNDERFLOW))
{
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
{
runTasks();
}
}
else
{
if (status == Status.CLOSED)
{
shutdown();
}
throw new IOException("Read error '" + result.getStatus()
+ '\'');
}
} while ((inputBuffer[0].position() != 0)
&& (status != Status.BUFFER_UNDERFLOW));
int n = inputCache[0].remaining();
if (n > 0)
{
if (n > dst.remaining())
{
n = dst.remaining();
}
for (int i = 0; i < n; i++)
{
dst.put(inputCache[0].get());
}
}
return n;
}
/**
* 读取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;
}
@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);
}
}
/**
* Wrap the underlying transport's output, passing it to the output buffer.
*
* {@link #_outputBuffer} is assumed to be writeable on entry and is guaranteed to
* be still writeable on exit.
*/
private void wrapOutput() throws SSLException
{
while (true) {
int pending = _underlyingOutput.pending();
if (pending < 0) {
_head_closed = true;
}
ByteBuffer clearOutputBuffer = _underlyingOutput.head();
SSLEngineResult result = _sslEngine.wrap(clearOutputBuffer, _outputBuffer);
logEngineClientModeAndResult(result, "output");
int written = result.bytesConsumed();
_underlyingOutput.pop(written);
pending = _underlyingOutput.pending();
Status status = result.getStatus();
switch (status) {
case CLOSED:
_head_closed = true;
break;
case OK:
break;
case BUFFER_OVERFLOW:
ByteBuffer old = _outputBuffer;
_outputBuffer = newWriteableBuffer(_outputBuffer.capacity()*2);
_head = _outputBuffer.asReadOnlyBuffer();
old.flip();
_outputBuffer.put(old);
continue;
case BUFFER_UNDERFLOW:
throw new IllegalStateException("app buffer underflow");
}
HandshakeStatus hstatus = result.getHandshakeStatus();
switch (hstatus) {
case NEED_UNWRAP:
// wait for input data
if (_inputBuffer.position() == 0 && _tail_closed) {
_head_closed = true;
}
break;
case NEED_WRAP:
// keep looping
continue;
case NEED_TASK:
runDelegatedTasks(result);
continue;
case FINISHED:
updateCipherAndProtocolName(result);
// intentionally fall through
case NOT_HANDSHAKING:
if (pending > 0 && status == Status.OK) {
continue;
} else {
break;
}
}
break;
}
}
@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);
}
}
/**
* Converts <-A-><-B-><-C-> to a_. <> is special and decodes as z_
* Input such as "<A" will causes a {@link Status#BUFFER_UNDERFLOW} result status.
*/
@Override
public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst)
throws SSLException
{
_unwrapCount++;
if(_nextException != null)
{
throw _nextException;
}
Status resultStatus;
final int consumed;
final int produced;
if (src.remaining() >= SHORT_ENCODED_CHUNK_SIZE)
{
src.mark();
char begin = (char)src.get();
char nextChar = (char)src.get(); // Could be - or >
final int readSoFar = 2;
final char capitalisedChar;
if (nextChar != ENCODED_TEXT_END)
{
int remainingBytesForMaxLengthPacket = MAX_ENCODED_CHUNK_SIZE - readSoFar;
if (src.remaining() < remainingBytesForMaxLengthPacket )
{
src.reset();
resultStatus = Status.BUFFER_UNDERFLOW;
return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
else
{
char beginInner = nextChar;
capitalisedChar = (char)src.get();
char endInner = (char)src.get();
char end = (char)src.get();
consumed = MAX_ENCODED_CHUNK_SIZE;
validateEncoded(begin, beginInner, capitalisedChar, endInner, end);
}
}
else
{
assertEquals("Unexpected begin", Character.toString(ENCODED_TEXT_BEGIN), Character.toString(begin));
capitalisedChar = 'Z';
consumed = SHORT_ENCODED_CHUNK_SIZE;;
}
char lowerCaseChar = Character.toLowerCase(capitalisedChar);
dst.put((byte)lowerCaseChar);
dst.put((byte)CLEARTEXT_PADDING);
produced = CLEAR_CHUNK_SIZE;
resultStatus = Status.OK;
}
else
{
resultStatus = Status.BUFFER_UNDERFLOW;
consumed = 0;
produced = 0;
}
return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, consumed, produced);
}