diff --git a/src/main/java/org/jboss/netty/handler/ssl/SslBufferPool.java b/src/main/java/org/jboss/netty/handler/ssl/SslBufferPool.java index 376c395388..95a5891fe2 100644 --- a/src/main/java/org/jboss/netty/handler/ssl/SslBufferPool.java +++ b/src/main/java/org/jboss/netty/handler/ssl/SslBufferPool.java @@ -24,12 +24,26 @@ package org.jboss.netty.handler.ssl; import java.nio.ByteBuffer; +import javax.net.ssl.SSLEngine; + /** + * A {@link ByteBuffer} pool dedicated for {@link SslHandler} performance + * improvement. + *
+ * In most cases, you won't need to create a new pool instance because + * {@link SslHandler} has a default pool instance internally. + *
+ * The reason why {@link SslHandler} requires a buffer pool is because the + * current {@link SSLEngine} implementation always requires a 17KiB buffer for + * the 'wrap' and 'unwrap' operation. In most cases, the size of the required + * buffer is much smaller than that, and therefore allocating a 17KiB buffer + * for every 'wrap' and 'unwrap' operation wastes a lot of memory bandwidth, + * resulting in the application performance degradation. + * * @author The Netty Project (netty-dev@lists.jboss.org) * @author Trustin Lee (tlee@redhat.com) * * @version $Rev$, $Date$ - * */ public class SslBufferPool { @@ -41,29 +55,49 @@ public class SslBufferPool { private final int maxBufferCount; private int index; + /** + * Creates a new buffer pool whose size is {@code 18113536}, which can + * hold {@code 1024} buffers. + */ public SslBufferPool() { this(DEFAULT_POOL_SIZE); } - public SslBufferPool(int poolSize) { - if (poolSize <= 0) { - throw new IllegalArgumentException("poolSize: " + poolSize); + /** + * Creates a new buffer pool. + * + * @param maxPoolSize the maximum number of bytes that this pool can hold + */ + public SslBufferPool(int maxPoolSize) { + if (maxPoolSize <= 0) { + throw new IllegalArgumentException("maxPoolSize: " + maxPoolSize); } - int maxBufferCount = poolSize / MAX_PACKET_SIZE; - if (poolSize % MAX_PACKET_SIZE != 0) { + int maxBufferCount = maxPoolSize / MAX_PACKET_SIZE; + if (maxPoolSize % MAX_PACKET_SIZE != 0) { maxBufferCount ++; } - poolSize = maxBufferCount * MAX_PACKET_SIZE; + maxPoolSize = maxBufferCount * MAX_PACKET_SIZE; pool = new ByteBuffer[maxBufferCount]; this.maxBufferCount = maxBufferCount; } + /** + * Returns the maximum size of this pool in byte unit. The returned value + * can be somewhat different from what was specified in the constructor. + */ public int getMaxPoolSize() { return maxBufferCount * MAX_PACKET_SIZE; } + /** + * Returns the number of bytes which were allocated but not acquired yet. + * You can estimate how optimal the specified maximum pool size is from + * this value. If it keeps returning {@code 0}, it means the pool is + * getting exhausted. If it keeps returns a unnecessarily big value, it + * means the pool is wasting the heap space. + */ public synchronized int getUnacquiredPoolSize() { return index * MAX_PACKET_SIZE; } diff --git a/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java b/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java index ec7e8a3e14..4f7f13be20 100644 --- a/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java +++ b/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java @@ -44,6 +44,7 @@ import org.jboss.netty.channel.ChannelEvent; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.MessageEvent; @@ -51,6 +52,42 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.jboss.netty.util.ImmediateExecutor; /** + * Adds SSL + * · TLS and StartTLS support to a {@link Channel}. Please refer + * to the "SecureChat" example in the distribution or the web + * site for the detailed usage. + * + *
+ * A user should make sure not to write a message while the + * {@linkplain #handshake(Channel) handshake} is in progress unless it's a + * renegotiation. You will be notified by the {@link ChannelFuture} which is + * returned by the {@link #handshake(Channel)} method when the handshake + * process succeeds or fails. + * + *
+ * Once the initial handshake is done successfully. You can always call + * {@link #handshake(Channel)} again to renegotiate the SSL session parameters. + * + *
+ * To close the SSL session, the {@link #close(Channel)} method should be + * called to send the {@code close_notify} message to the remote peer. One + * exception is when you close the {@link Channel} - {@link SslHandler} + * intercepts the close request and send the {@code close_notify} message + * before the channel closure automatically. Once the SSL session is closed, + * it's not reusable, and consequently you should create a new + * {@link SslHandler} with a new {@link SSLEngine} as explained in the + * following section. + * + *
+ * To restart the SSL session, you must remove the existing closed
+ * {@link SslHandler} from the {@link ChannelPipeline}, insert a new
+ * {@link SslHandler} with a new {@link SSLEngine} into the pipeline,
+ * and start the handshake process as described in the first section.
+ *
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
*
@@ -65,7 +102,11 @@ public class SslHandler extends FrameDecoder implements ChannelDownstreamHandler
private static SslBufferPool defaultBufferPool;
- private static synchronized SslBufferPool getDefaultBufferPool() {
+ /**
+ * Returns the default {@link SslBufferPool} used when no pool is
+ * specified in the constructor.
+ */
+ public static synchronized SslBufferPool getDefaultBufferPool() {
if (defaultBufferPool == null) {
defaultBufferPool = new SslBufferPool();
}
@@ -88,34 +129,110 @@ public class SslHandler extends FrameDecoder implements ChannelDownstreamHandler
private final Queue