Return-Path: X-Original-To: apmail-hc-commits-archive@www.apache.org Delivered-To: apmail-hc-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C376210CF7 for ; Sat, 25 Jan 2014 11:17:12 +0000 (UTC) Received: (qmail 79126 invoked by uid 500); 25 Jan 2014 11:17:11 -0000 Delivered-To: apmail-hc-commits-archive@hc.apache.org Received: (qmail 79084 invoked by uid 500); 25 Jan 2014 11:17:05 -0000 Mailing-List: contact commits-help@hc.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "HttpComponents Project" Delivered-To: mailing list commits@hc.apache.org Received: (qmail 79077 invoked by uid 99); 25 Jan 2014 11:17:03 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 25 Jan 2014 11:17:03 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 25 Jan 2014 11:17:01 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id CD07C23888D7 for ; Sat, 25 Jan 2014 11:16:40 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1561282 - in /httpcomponents/httpcore/trunk: ./ httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ Date: Sat, 25 Jan 2014 11:16:40 -0000 To: commits@hc.apache.org From: olegk@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140125111640.CD07C23888D7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: olegk Date: Sat Jan 25 11:16:40 2014 New Revision: 1561282 URL: http://svn.apache.org/r1561282 Log: HTTPCORE-368: Customizable buffer management strategies for SSLIOSession. Contributed by offbynull Added: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java (with props) httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java (with props) httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java (with props) httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java (with props) Modified: httpcomponents/httpcore/trunk/RELEASE_NOTES.txt httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java Modified: httpcomponents/httpcore/trunk/RELEASE_NOTES.txt URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt?rev=1561282&r1=1561281&r2=1561282&view=diff ============================================================================== --- httpcomponents/httpcore/trunk/RELEASE_NOTES.txt (original) +++ httpcomponents/httpcore/trunk/RELEASE_NOTES.txt Sat Jan 25 11:16:40 2014 @@ -1,6 +1,15 @@ Changes since release 4.3.1 ------------------- +* [HTTPCORE-368] Customizable buffer management strategies for SSLIOSession. + Contributed by offbynull + +* [HTTPCORE-358] Added I/O reactor listener backlog parameter. + Contributed by Dmitry Potapov + +* [HTTPCORE-357] Avoid DNS lookups in SSLIOSession. + Contributed by Oleg Kalnichevski + * (Regression) Fixed synchronization issue in blocking and non-blocking connection pool implementations caused by HTTPCORE-362 Contributed by Oleg Kalnichevski Added: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java?rev=1561282&view=auto ============================================================================== --- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java (added) +++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java Sat Jan 25 11:16:40 2014 @@ -0,0 +1,73 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.nio.reactor.ssl; + +import java.nio.ByteBuffer; +import org.apache.http.util.Args; + +/** + * A {@link SSLBufferManagementStrategy} that never releases the underlying buffer. + */ +public class PermanentSSLBufferManagementStrategy implements SSLBufferManagementStrategy { + + @Override + public SSLBuffer constructBuffer(final int size) { + return new InternalBuffer(size); + } + + + private static final class InternalBuffer implements SSLBuffer { + + private final ByteBuffer buffer; + + public InternalBuffer(final int size) { + Args.positive(size, "size"); + buffer = ByteBuffer.allocate(size); + } + + @Override + public ByteBuffer acquire() { + return buffer; + } + + @Override + public void release() { + // do nothing + } + + @Override + public boolean isAcquired() { + return true; + } + + @Override + public boolean hasData() { + return buffer.position() > 0; + } + + } +} Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:keywords = Date Revision Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/PermanentSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java?rev=1561282&view=auto ============================================================================== --- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java (added) +++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java Sat Jan 25 11:16:40 2014 @@ -0,0 +1,78 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.nio.reactor.ssl; + +import java.nio.ByteBuffer; +import org.apache.http.util.Args; + +/** + * A {@link SSLBufferManagementStrategy} that releases the underlying buffer when deactivated. + */ +public class ReleasableSSLBufferManagementStrategy implements SSLBufferManagementStrategy { + + @Override + public SSLBuffer constructBuffer(final int size) { + return new InternalBuffer(size); + } + + + private static final class InternalBuffer implements SSLBuffer { + + private ByteBuffer wrapped; + private final int length; + + public InternalBuffer(final int size) { + Args.positive(size, "size"); + this.length = size; + } + + @Override + public ByteBuffer acquire() { + if (wrapped != null) { + return wrapped; + } + wrapped = ByteBuffer.allocate(length); + return wrapped; + } + + @Override + public void release() { + wrapped = null; + } + + @Override + public boolean isAcquired() { + return wrapped != null; + } + + @Override + public boolean hasData() { + return wrapped != null && wrapped.position() > 0; + } + + } +} Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:keywords = Date Revision Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/ReleasableSSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java?rev=1561282&view=auto ============================================================================== --- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java (added) +++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java Sat Jan 25 11:16:40 2014 @@ -0,0 +1,58 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.nio.reactor.ssl; + +import java.nio.ByteBuffer; + +/** + * Managed internal SSL buffer. + */ +public interface SSLBuffer { + /** + * Allocates the resources required for this buffer, or returns the resources already allocated for this buffer. + * Unless {@link #release() } is called, multiple invokations to this method must return the same + * {@link java.nio.ByteBuffer}. + * @return buffer + */ + ByteBuffer acquire(); + /** + * Releases the resources for this buffer. If the buffer has already been released, this method does nothing. + */ + void release(); + /** + * Tests to see if this buffer has been acquired. + * @return {@code true} if the buffer is acquired, otherwise {@code false} + */ + boolean isAcquired(); + /** + * Tests to make sure that the buffer has been acquired and the underlying buffer has a position larger than + * {@code 0}. Essentially the same as {@code isAquired() && acquire().position > 0}. + * @return {@code true} if the buffer has been acquired and the underlying buffer's position is {@code > 0}, + * otherwise {@code false} + */ + boolean hasData(); +} Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java ------------------------------------------------------------------------------ svn:keywords = Date Revision Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBuffer.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java?rev=1561282&view=auto ============================================================================== --- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java (added) +++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java Sat Jan 25 11:16:40 2014 @@ -0,0 +1,42 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.nio.reactor.ssl; + +/** + * Encapsulates logic to manager SSL input/output buffers. + */ +public interface SSLBufferManagementStrategy { + + /** + * Creates a {@link SSLBuffer} of {@code size}. + * @param size size of the buffer to create + * @return constructed buffer + * @throws IllegalArgumentException if {@code size} is not greater than {@code 0} + */ + SSLBuffer constructBuffer(int size); + +} Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:keywords = Date Revision Propchange: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLBufferManagementStrategy.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java?rev=1561282&r1=1561281&r2=1561282&view=diff ============================================================================== --- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java (original) +++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java Sat Jan 25 11:16:40 2014 @@ -77,12 +77,14 @@ public class SSLIOSession implements IOS */ public static final String SESSION_KEY = "http.session.ssl"; + private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); + private final IOSession session; private final SSLEngine sslEngine; - private final ByteBuffer inEncrypted; - private final ByteBuffer outEncrypted; - private final ByteBuffer inPlain; - private final ByteBuffer outPlain; + private final SSLBuffer inEncrypted; + private final SSLBuffer outEncrypted; + private final SSLBuffer inPlain; + private final SSLBuffer outPlain; private final InternalByteChannel channel; private final SSLSetupHandler handler; @@ -95,7 +97,8 @@ public class SSLIOSession implements IOS private volatile boolean initialized; /** - * Creates new instance of SSLIOSession class. + * Creates new instance of SSLIOSession class. The instances created uses a + * {@link PermanentSSLBufferManagementStrategy} to manage its buffers. * * @param session I/O session to be decorated with the TLS/SSL capabilities. * @param sslMode SSL mode (client or server) @@ -111,9 +114,30 @@ public class SSLIOSession implements IOS final HttpHost host, final SSLContext sslContext, final SSLSetupHandler handler) { + this(session, sslMode, host, sslContext, handler, new PermanentSSLBufferManagementStrategy()); + } + + /** + * Creates new instance of SSLIOSession class. + * + * @param session I/O session to be decorated with the TLS/SSL capabilities. + * @param sslMode SSL mode (client or server) + * @param host original host (applicable in client mode only) + * @param sslContext SSL context to use for this I/O session. + * @param handler optional SSL setup handler. May be null. + * @param bufferManagementStrategy buffer management strategy + */ + public SSLIOSession( + final IOSession session, + final SSLMode sslMode, + final HttpHost host, + final SSLContext sslContext, + final SSLSetupHandler handler, + final SSLBufferManagementStrategy bufferManagementStrategy) { super(); Args.notNull(session, "IO session"); Args.notNull(sslContext, "SSL context"); + Args.notNull(bufferManagementStrategy, "Buffer management strategy"); this.session = session; this.sslMode = sslMode; this.appEventMask = session.getEventMask(); @@ -131,13 +155,13 @@ public class SSLIOSession implements IOS // Allocate buffers for network (encrypted) data final int netBuffersize = this.sslEngine.getSession().getPacketBufferSize(); - this.inEncrypted = ByteBuffer.allocate(netBuffersize); - this.outEncrypted = ByteBuffer.allocate(netBuffersize); + this.inEncrypted = bufferManagementStrategy.constructBuffer(netBuffersize); + this.outEncrypted = bufferManagementStrategy.constructBuffer(netBuffersize); // Allocate buffers for application (unencrypted) data final int appBuffersize = this.sslEngine.getSession().getApplicationBufferSize(); - this.inPlain = ByteBuffer.allocate(appBuffersize); - this.outPlain = ByteBuffer.allocate(appBuffersize); + this.inPlain = bufferManagementStrategy.constructBuffer(appBuffersize); + this.outPlain = bufferManagementStrategy.constructBuffer(appBuffersize); } /** @@ -208,6 +232,12 @@ public class SSLIOSession implements IOS } this.initialized = true; this.sslEngine.beginHandshake(); + + this.inEncrypted.release(); + this.outEncrypted.release(); + this.inPlain.release(); + this.outPlain.release(); + doHandshake(); } @@ -263,23 +293,55 @@ public class SSLIOSession implements IOS switch (this.sslEngine.getHandshakeStatus()) { case NEED_WRAP: // Generate outgoing handshake data - this.outPlain.flip(); - result = doWrap(this.outPlain, this.outEncrypted); - this.outPlain.compact(); + + // Acquire buffers + ByteBuffer outPlainBuf = this.outPlain.acquire(); + final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire(); + + // Perform operations + outPlainBuf.flip(); + result = doWrap(outPlainBuf, outEncryptedBuf); + outPlainBuf.compact(); + + // Release outPlain if empty + if (outPlainBuf.position() == 0) { + this.outPlain.release(); + outPlainBuf = null; + } + + if (result.getStatus() != Status.OK) { handshaking = false; } break; case NEED_UNWRAP: // Process incoming handshake data - this.inEncrypted.flip(); - result = doUnwrap(this.inEncrypted, this.inPlain); - this.inEncrypted.compact(); - if (!this.inEncrypted.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { - throw new SSLException("Input buffer is full"); + + // Acquire buffers + ByteBuffer inEncryptedBuf = this.inEncrypted.acquire(); + ByteBuffer inPlainBuf = this.inPlain.acquire(); + + // Perform operations + inEncryptedBuf.flip(); + result = doUnwrap(inEncryptedBuf, inPlainBuf); + inEncryptedBuf.compact(); + + + try { + if (!inEncryptedBuf.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { + throw new SSLException("Input buffer is full"); + } + } finally { + // Release inEncrypted if empty + if (inEncryptedBuf.position() == 0) { + this.inEncrypted.release(); + inEncryptedBuf = null; + } } + if (this.status >= IOSession.CLOSING) { - this.inPlain.clear(); + this.inPlain.release(); + inPlainBuf = null; } if (result.getStatus() != Status.OK) { handshaking = false; @@ -341,7 +403,7 @@ public class SSLIOSession implements IOS } // Do we have encrypted data ready to be sent? - if (this.outEncrypted.position() > 0) { + if (this.outEncrypted.hasData()) { newMask = newMask | EventMask.WRITE; } @@ -352,9 +414,26 @@ public class SSLIOSession implements IOS } private int sendEncryptedData() throws IOException { - this.outEncrypted.flip(); - final int bytesWritten = this.session.channel().write(this.outEncrypted); - this.outEncrypted.compact(); + if (!this.outEncrypted.hasData()) { + // If the buffer isn't acquired or is empty, call write() with an empty buffer. + // This will ensure that tests performed by write() still take place without + // having to acquire and release an empty buffer (e.g. connection closed, + // interrupted thread, etc..) + return this.session.channel().write(EMPTY_BUFFER); + } + + // Acquire buffer + final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire(); + + // Perform operation + outEncryptedBuf.flip(); + final int bytesWritten = this.session.channel().write(outEncryptedBuf); + outEncryptedBuf.compact(); + + // Release if empty + if (outEncryptedBuf.position() == 0) { + this.outEncrypted.release(); + } return bytesWritten; } @@ -362,28 +441,52 @@ public class SSLIOSession implements IOS if (this.endOfStream) { return -1; } - return this.session.channel().read(this.inEncrypted); + + // Acquire buffer + final ByteBuffer inEncryptedBuf = this.inEncrypted.acquire(); + + // Perform operation + final int ret = this.session.channel().read(inEncryptedBuf); + + // Release if empty + if (inEncryptedBuf.position() == 0) { + this.inEncrypted.release(); + } + return ret; } private boolean decryptData() throws SSLException { boolean decrypted = false; - while (this.inEncrypted.position() > 0) { - this.inEncrypted.flip(); - final SSLEngineResult result = doUnwrap(this.inEncrypted, this.inPlain); - this.inEncrypted.compact(); - if (!this.inEncrypted.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { - throw new SSLException("Input buffer is full"); - } - if (result.getStatus() == Status.OK) { - decrypted = true; - } else { - break; - } - if (result.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) { - break; - } - if (this.endOfStream) { - break; + while (this.inEncrypted.hasData()) { + // Get buffers + final ByteBuffer inEncryptedBuf = this.inEncrypted.acquire(); + final ByteBuffer inPlainBuf = this.inPlain.acquire(); + + // Perform operations + inEncryptedBuf.flip(); + final SSLEngineResult result = doUnwrap(inEncryptedBuf, inPlainBuf); + inEncryptedBuf.compact(); + + try { + if (!inEncryptedBuf.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { + throw new SSLException("Input buffer is full"); + } + if (result.getStatus() == Status.OK) { + decrypted = true; + } else { + break; + } + if (result.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) { + break; + } + if (this.endOfStream) { + break; + } + } finally { + // Release inEncrypted if empty + if (this.inEncrypted.acquire().position() == 0) { + this.inEncrypted.release(); + } } } return decrypted; @@ -407,7 +510,7 @@ public class SSLIOSession implements IOS } // Some decrypted data is available or at the end of stream return (this.appEventMask & SelectionKey.OP_READ) > 0 - && (this.inPlain.position() > 0 + && (this.inPlain.hasData() || (this.appBufferStatus != null && this.appBufferStatus.hasBufferedInput()) || (this.endOfStream && this.status == ACTIVE)); } @@ -463,13 +566,25 @@ public class SSLIOSession implements IOS if (this.status != ACTIVE) { return -1; } - if (this.outPlain.position() > 0) { - this.outPlain.flip(); - doWrap(this.outPlain, this.outEncrypted); - this.outPlain.compact(); + if (this.outPlain.hasData()) { + // Acquire buffers + ByteBuffer outPlainBuf = this.outPlain.acquire(); + final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire(); + + // Perform operations + outPlainBuf.flip(); + doWrap(outPlainBuf, outEncryptedBuf); + outPlainBuf.compact(); + + // Release outPlain if empty + if (outPlainBuf.position() == 0) { + this.outPlain.release(); + outPlainBuf = null; + } } - if (this.outPlain.position() == 0) { - final SSLEngineResult result = doWrap(src, this.outEncrypted); + if (!this.outPlain.hasData()) { + final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire(); + final SSLEngineResult result = doWrap(src, outEncryptedBuf); if (result.getStatus() == Status.CLOSED) { this.status = CLOSED; } @@ -481,13 +596,23 @@ public class SSLIOSession implements IOS private synchronized int readPlain(final ByteBuffer dst) { Args.notNull(dst, "Byte buffer"); - if (this.inPlain.position() > 0) { - this.inPlain.flip(); - final int n = Math.min(this.inPlain.remaining(), dst.remaining()); + if (this.inPlain.hasData()) { + // Acquire buffer + ByteBuffer inPlainBuf = this.inPlain.acquire(); + + // Perform opertaions + inPlainBuf.flip(); + final int n = Math.min(inPlainBuf.remaining(), dst.remaining()); for (int i = 0; i < n; i++) { - dst.put(this.inPlain.get()); + dst.put(inPlainBuf.get()); + } + inPlainBuf.compact(); + + // Release if empty + if (inPlainBuf.position() == 0) { + this.inPlain.release(); + inPlainBuf = null; } - this.inPlain.compact(); return n; } else { if (this.endOfStream) { @@ -503,6 +628,9 @@ public class SSLIOSession implements IOS if (this.status >= CLOSING) { return; } + + // deactivating buffers in here causes failed tests + this.status = CLOSING; this.sslEngine.closeOutbound(); updateEventMask(); @@ -513,6 +641,12 @@ public class SSLIOSession implements IOS if (this.status == CLOSED) { return; } + + this.inEncrypted.release(); + this.outEncrypted.release(); + this.inPlain.release(); + this.outPlain.release(); + this.status = CLOSED; this.session.shutdown(); } @@ -578,15 +712,15 @@ public class SSLIOSession implements IOS @Override public synchronized boolean hasBufferedInput() { return (this.appBufferStatus != null && this.appBufferStatus.hasBufferedInput()) - || this.inEncrypted.position() > 0 - || this.inPlain.position() > 0; + || this.inEncrypted.hasData() + || this.inPlain.hasData(); } @Override public synchronized boolean hasBufferedOutput() { return (this.appBufferStatus != null && this.appBufferStatus.hasBufferedOutput()) - || this.outEncrypted.position() > 0 - || this.outPlain.position() > 0; + || this.outEncrypted.hasData() + || this.outPlain.hasData(); } @Override @@ -648,13 +782,13 @@ public class SSLIOSession implements IOS buffer.append("][EOF]["); } buffer.append("]["); - buffer.append(this.inEncrypted.position()); + buffer.append(!this.inEncrypted.hasData() ? 0 : inEncrypted.acquire().position()); buffer.append("]["); - buffer.append(this.inPlain.position()); + buffer.append(!this.inPlain.hasData() ? 0 : inPlain.acquire().position()); buffer.append("]["); - buffer.append(this.outEncrypted.position()); + buffer.append(!this.outEncrypted.hasData() ? 0 : outEncrypted.acquire().position()); buffer.append("]["); - buffer.append(this.outPlain.position()); + buffer.append(!this.outPlain.hasData() ? 0 : outPlain.acquire().position()); buffer.append("]"); return buffer.toString(); }