You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2014/01/25 12:16:40 UTC
svn commit: r1561282 - in /httpcomponents/httpcore/trunk: ./
httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/
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 <offbynull at gmail.com>
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 <offbynull at gmail.com>
+
+* [HTTPCORE-358] Added I/O reactor listener backlog parameter.
+ Contributed by Dmitry Potapov <potapov.d at gmail.com>
+
+* [HTTPCORE-357] Avoid DNS lookups in SSLIOSession.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
* (Regression) Fixed synchronization issue in blocking and non-blocking connection pool
implementations caused by HTTPCORE-362
Contributed by Oleg Kalnichevski <olegk at apache.org>
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
+ * <http://www.apache.org/>.
+ *
+ */
+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
+ * <http://www.apache.org/>.
+ *
+ */
+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
+ * <http://www.apache.org/>.
+ *
+ */
+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
+ * <http://www.apache.org/>.
+ *
+ */
+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 <tt>SSLIOSession</tt> class.
+ * Creates new instance of <tt>SSLIOSession</tt> 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 <tt>SSLIOSession</tt> 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 <code>null</code>.
+ * @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();
}