dev@grizzly.java.net

Re: SelectionKey attachment unification

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Wed, 13 Feb 2008 13:47:16 -0500

Salut,

Oleksiy Stashok wrote:
> Hi,
>
> I wanted to post here changes for reviewing.
> Recently I figured out, that we have bug in SSL engine, because we tried
> to store SSL connection information in SSLSession, which is wrong, as
> session could be shared among several connections.

That sound strange they allow that, but their documentation is
clear...not sure I agree with their implementation :-)

  So, it means we need
> some other place, where connection info could be stored.
> IMHO SelectionKey attachment could be good place for it.

Performance wise, it can cause trouble so we need to be careful here:

http://weblogs.java.net/blog/jfarcand/archive/2006/06/tricks_and_tips.html

Unifying/improving our solution is great, we just have to make sure our
users knows that can have potential issues.

But currently
> in Grizzly we have non-clear attachment support implementation.

;-) My fault :-)

There
> are several attachments types, which we support internally and using
> if-else/instanceof to process each of attachment type.

Right, the reason was originally we didn't support ThreadAttachment and
only needed to support attachment via SSLEngine. I agree we you it needs
to be cleaned :-)


So I decided to
> create SelectionKey attachment class hierarchy. Here I'm attaching
> initial propose for that. Unfortunately with 1.x branch I can not apply
> all the changes I wanted, so I didn't change CallbackHandler to be
> subclass of SelectionKeyAttachment, however SSL support is completely
> reworked and should not have bug I mentioned above.

Great!

> Think, in 2.x branch we will be able to have clear and complete
> SelectionKey attachment implementation, which will include
> CallbackHandlers etc.


Like discussed at the meeting, I would propose we implement a complete
solution (event if we break compatibility). Let's works on the proposal!

A+

-- jeanfrancois


>
> Thanks.
>
> WBR,
> Alexey.
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\Grizzly\trunk\modules\grizzly\src
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java
> --- main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Base (BASE)
> +++ main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,7 +23,7 @@
>
> package com.sun.grizzly.async;
>
> -import com.sun.grizzly.ContextTask;
> +import com.sun.grizzly.SelectionKeyContextTask;
> import java.nio.channels.SelectionKey;
>
>
> @@ -35,11 +35,11 @@
> *
> * @author Alexey Stashok
> */
> -public class AsyncQueueReaderContextTask extends ContextTask {
> +public class AsyncQueueReaderContextTask extends SelectionKeyContextTask {
> private static final TaskPool<AsyncQueueReaderContextTask> taskPool =
> new TaskPool<AsyncQueueReaderContextTask>() {
> @Override
> - public AsyncQueueReaderContextTask newTask() {
> + public AsyncQueueReaderContextTask newInstance() {
> return new AsyncQueueReaderContextTask();
> }
> };
> @@ -55,7 +55,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + public Object doCall() throws Exception {
> try {
> SelectionKey selectionKey = context.getSelectionKey();
> if (selectionKey == null) {
> Index: main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java
> --- main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Base (BASE)
> +++ main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,7 +23,7 @@
>
> package com.sun.grizzly.async;
>
> -import com.sun.grizzly.ContextTask;
> +import com.sun.grizzly.SelectionKeyContextTask;
> import java.nio.channels.SelectionKey;
>
>
> @@ -35,11 +35,11 @@
> *
> * @author Alexey Stashok
> */
> -public class AsyncQueueWriterContextTask extends ContextTask {
> +public class AsyncQueueWriterContextTask extends SelectionKeyContextTask {
> private static final TaskPool<AsyncQueueWriterContextTask> taskPool =
> new TaskPool<AsyncQueueWriterContextTask>() {
> @Override
> - public AsyncQueueWriterContextTask newTask() {
> + public AsyncQueueWriterContextTask newInstance() {
> return new AsyncQueueWriterContextTask();
> }
> };
> @@ -55,7 +55,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + protected Object doCall() throws Exception {
> try {
> SelectionKey selectionKey = context.getSelectionKey();
> if (selectionKey == null) {
> Index: main/java/com/sun/grizzly/CallbackHandlerContextTask.java
> --- main/java/com/sun/grizzly/CallbackHandlerContextTask.java Base (BASE)
> +++ main/java/com/sun/grizzly/CallbackHandlerContextTask.java Locally Modified (Based On LOCAL)
> @@ -33,11 +33,11 @@
> *
> * @author Alexey Stashok
> */
> -public class CallbackHandlerContextTask extends ContextTask {
> +public class CallbackHandlerContextTask extends SelectionKeyContextTask {
> private static final TaskPool<CallbackHandlerContextTask> taskPool =
> new TaskPool<CallbackHandlerContextTask>() {
> @Override
> - public CallbackHandlerContextTask newTask() {
> + public CallbackHandlerContextTask newInstance() {
> return new CallbackHandlerContextTask();
> }
> };
> @@ -53,7 +53,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + protected Object doCall() throws Exception {
> IOEvent ioEvent = context.getIOEvent();
> OpType currentOpType = context.getCurrentOpType();
>
> @@ -93,6 +93,4 @@
> callBackHandler = null;
> super.recycle();
> }
> -
> -
> }
> Index: main/java/com/sun/grizzly/Context.java
> --- main/java/com/sun/grizzly/Context.java Base (BASE)
> +++ main/java/com/sun/grizzly/Context.java Locally Modified (Based On LOCAL)
> @@ -32,6 +32,7 @@
> import com.sun.grizzly.async.AsyncReadCondition;
> import com.sun.grizzly.async.AsyncWriteCallbackHandler;
> import com.sun.grizzly.util.AttributeHolder;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.IOException;
> import java.net.SocketAddress;
> import java.nio.ByteBuffer;
> @@ -373,7 +374,7 @@
> // If a IOEvent has been defined, invoke it first and
> // let its associated CallbackHandler decide if the ProtocolChain
> // be invoked or not.
> - Object attachment = key.attachment();
> + Object attachment = SelectionKeyAttachment.getAttachment(key);
> if (ioEvent != null && (attachment instanceof CallbackHandler)) {
> CallbackHandlerContextTask task = CallbackHandlerContextTask.poll();
> task.setCallBackHandler((CallbackHandler) attachment);
> Index: main/java/com/sun/grizzly/ContextTask.java
> --- main/java/com/sun/grizzly/ContextTask.java Base (BASE)
> +++ main/java/com/sun/grizzly/ContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,6 +23,7 @@
>
> package com.sun.grizzly;
>
> +import com.sun.grizzly.util.ConcurrentLinkedQueuePool;
> import java.util.concurrent.Callable;
> import java.util.concurrent.ConcurrentLinkedQueue;
>
> @@ -47,24 +48,13 @@
> context = null;
> }
>
> - protected abstract static class TaskPool<E extends ContextTask> {
> - private ConcurrentLinkedQueue<E> pool =
> - new ConcurrentLinkedQueue<E>();
> + protected abstract static class TaskPool<E extends ContextTask>
> + extends ConcurrentLinkedQueuePool<E> {
>
> - public abstract E newTask();
> -
> - public E poll() {
> - E task = pool.poll();
> - if (task == null) {
> - task = newTask();
> - }
> -
> - return task;
> - }
> -
> + @Override
> public void offer(E task) {
> task.recycle();
> - pool.offer(task);
> + super.offer(task);
> }
> }
> }
> Index: main/java/com/sun/grizzly/Controller.java
> --- main/java/com/sun/grizzly/Controller.java Base (BASE)
> +++ main/java/com/sun/grizzly/Controller.java Locally Modified (Based On LOCAL)
> @@ -25,6 +25,7 @@
>
> import com.sun.grizzly.util.AttributeHolder;
> import com.sun.grizzly.util.Cloner;
> +import com.sun.grizzly.util.ConcurrentLinkedQueuePool;
> import com.sun.grizzly.util.Copyable;
> import com.sun.grizzly.util.State;
> import com.sun.grizzly.util.StateHolder;
> @@ -135,7 +136,7 @@
> /**
> * A cached list of Context. Context are by default stateless.
> */
> - private ConcurrentLinkedQueue<Context> contexts;
> + private ConcurrentLinkedQueuePool<Context> contexts;
>
>
> /**
> @@ -239,7 +240,13 @@
> * Controller constructor
> */
> public Controller() {
> - contexts = new ConcurrentLinkedQueue<Context>();
> + contexts = new ConcurrentLinkedQueuePool<Context>() {
> + @Override
> + public Context newInstance() {
> + return new Context();
> + }
> + };
> +
> stateHolder = new StateHolder<State>(true);
> }
>
> @@ -262,10 +269,8 @@
> ProtocolChainInstanceHandler pciHandler = null;
> ProtocolChain protocolChain = null;
> Context serverCtx = contexts.poll();
> - if (serverCtx == null){
> - serverCtx = new Context();
> serverCtx.setController(this);
> - }
> +
> serverCtx.setSelectorHandler(selectorHandler);
>
> try {
> @@ -474,9 +479,6 @@
> */
> public Context pollContext(SelectionKey key){
> Context ctx = contexts.poll();
> - if (ctx == null){
> - ctx = new Context();
> - }
> ctx.setController(this);
> ctx.setSelectionKey(key);
> return ctx;
> Index: main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java
> --- main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Base (BASE)
> +++ main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Locally Modified (Based On LOCAL)
> @@ -23,8 +23,9 @@
>
> package com.sun.grizzly;
>
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> +import com.sun.grizzly.util.SelectionKeyActionAttachment;
> import com.sun.grizzly.util.Copyable;
> -import com.sun.grizzly.util.ThreadAttachment;
> import java.io.IOException;
> import java.net.Socket;
> import java.nio.channels.ClosedChannelException;
> @@ -34,11 +35,7 @@
> import java.util.Iterator;
> import java.util.logging.Level;
> import java.util.logging.Logger;
> -import javax.net.ssl.SSLEngine;
> -import javax.net.ssl.SSLSession;
>
> -import static com.sun.grizzly.filter.SSLReadFilter.EXPIRE_TIME;
> -import com.sun.grizzly.util.WorkerThread;
> import java.nio.channels.Selector;
>
> /**
> @@ -103,6 +100,12 @@
> * {_at_inheritDoc}
> */
> public void process(SelectionKey key) {
> + Object attachment = key.attachment();
> +
> + if (attachment instanceof SelectionKeyActionAttachment) {
> + ((SelectionKeyActionAttachment) attachment).process(key);
> + }
> +
> removeExpirationStamp(key);
> }
>
> @@ -238,6 +241,11 @@
> closeChannel(key.channel());
> }
>
> + Object attachment = key.attachment();
> + if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).release();
> + }
> +
> key.attach(null);
> key.cancel();
> key = null;
> @@ -309,13 +317,8 @@
> if (attachment != null) {
> if (attachment instanceof Long) {
> key.attach(null);
> - } else if (attachment instanceof ThreadAttachment) {
> - ((WorkerThread) Thread.currentThread()).attach(
> - (ThreadAttachment) attachment);
> - key.attach(null);
> - } else if (attachment instanceof SSLEngine) {
> - SSLEngine sslEngine = (SSLEngine) attachment;
> - sslEngine.getSession().removeValue(EXPIRE_TIME);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).setTimeout(null);
> }
> }
> }
> @@ -331,11 +334,8 @@
> Object attachment = key.attachment();
> if (attachment == null) {
> key.attach(currentTime);
> - } else if (attachment instanceof ThreadAttachment) {
> - ((ThreadAttachment) attachment).setTimeout(currentTime);
> - } else if (attachment instanceof SSLEngine) {
> - SSLEngine sslEngine = (SSLEngine) attachment;
> - sslEngine.getSession().putValue(EXPIRE_TIME,currentTime);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).setTimeout(currentTime);
> }
> }
>
> @@ -356,17 +356,9 @@
> // can't predict the type of the attached object.
> if (attachment instanceof Long) {
> return (Long) attachment;
> - } else if (attachment instanceof SSLEngine) {
> - SSLSession sslSession = ((SSLEngine) attachment).getSession();
> - if (sslSession != null &&
> - sslSession.getValue(EXPIRE_TIME) != null) {
> - return (Long) sslSession.getValue(EXPIRE_TIME);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + return ((SelectionKeyAttachment) attachment).getTimeout();
> }
> -
> - return null;
> - } else if (attachment instanceof ThreadAttachment) {
> - return ((ThreadAttachment) attachment).getTimeout();
> - }
> } catch (ClassCastException ex) {
> if (logger.isLoggable(Level.FINEST)) {
> logger.log(Level.FINEST,
> Index: main/java/com/sun/grizzly/filter/SSLReadFilter.java
> --- main/java/com/sun/grizzly/filter/SSLReadFilter.java Base (BASE)
> +++ main/java/com/sun/grizzly/filter/SSLReadFilter.java Locally Modified (Based On LOCAL)
> @@ -27,7 +27,9 @@
> import com.sun.grizzly.Controller;
> import com.sun.grizzly.ProtocolFilter;
> import com.sun.grizzly.SSLConfig;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.SSLUtils;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import com.sun.grizzly.util.WorkerThreadImpl;
> import java.io.EOFException;
> import java.io.IOException;
> @@ -49,14 +51,6 @@
> * @author Jeanfrancois Arcand
> */
> public class SSLReadFilter implements ProtocolFilter{
> -
> - public final static String HANDSHAKE = "handshake";
> - public final static String DATA_DECODED = "dataDecoded";
> - public final static String INPUT_BB_REMAINDER = "inputBBRemainder";
> - public final static String OUTPUT_BB_REMAINDER = "outputBBRemainder";
> -
> -
> -
> /**
> * The <code>SSLContext</code> associated with the SSL implementation
> * we are running on.
> @@ -95,12 +89,6 @@
>
>
> /**
> - * Session keep-alive flag.
> - */
> - public final static String EXPIRE_TIME = "expireTime";
> -
> -
> - /**
> * Has the enabled protocol configured.
> */
> private boolean isProtocolConfigured = false;
> @@ -125,7 +113,6 @@
> public boolean execute(Context ctx) throws IOException {
> boolean result = true;
> int count = 0;
> - boolean isCopied = false;
> Throwable exception = null;
> SelectionKey key = ctx.getSelectionKey();
> WorkerThreadImpl workerThread;
> @@ -137,22 +124,16 @@
>
> SSLEngine sslEngine = newSSLEngine(key);
> workerThread.setSSLEngine(sslEngine);
> - key.attach(sslEngine);
> + SSLSelectionKeyAttachment.attach(key, sslEngine);
>
> - boolean hasHandshake = Boolean.TRUE.equals(
> - sslEngine.getSession().getValue(HANDSHAKE));
> -
> - restoreSecuredBufferRemainders(sslEngine);
> + boolean hasHandshake = sslEngine.getSession().isValid();
> try {
> allocateBuffers();
> - isCopied = copyByteBufferToInputBB(sslEngine,
> - workerThread.getByteBuffer(), workerThread.getInputBB());
>
> if (hasHandshake) {
> count = doRead(key);
> } else if (doHandshake(key, SSLUtils.getReadTimeout())) {
> hasHandshake = true;
> - sslEngine.getSession().putValue(HANDSHAKE, Boolean.TRUE);
>
> // set "no available data" for secured output buffer
> ByteBuffer outputBB = workerThread.getOutputBB();
> @@ -168,12 +149,6 @@
> log("SSLReadFilter.execute",ex);
> } finally {
> if (exception != null || count == -1){
> - if (isCopied) {
> - /* if some data was copied from ByteBuffer,
> - * but connection got closed - clean inputBB */
> - workerThread.getInputBB().clear();
> - }
> -
> ctx.setAttribute(Context.THROWABLE,exception);
> ctx.setKeyRegistrationState(
> Context.KeyRegistrationState.CANCEL);
> @@ -199,8 +174,7 @@
> cancel(ctx.getSelectionKey());
> } else if (ctx.getKeyRegistrationState()
> == Context.KeyRegistrationState.REGISTER){
> - SSLEngine sslEngine = (SSLEngine) ctx.getSelectionKey().attachment();
> - saveSecuredBufferRemainders(sslEngine);
> + saveSecuredBufferRemainders(ctx.getSelectionKey());
> ctx.getSelectorHandler().register(ctx.getSelectionKey(),
> SelectionKey.OP_READ);
> ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE);
> @@ -295,20 +269,20 @@
> }
>
>
> - private static int doRead(SelectionKey key){
> + private static int doRead(SelectionKey key) {
> final WorkerThreadImpl workerThread =
> - (WorkerThreadImpl)Thread.currentThread();
> + (WorkerThreadImpl) Thread.currentThread();
> ByteBuffer byteBuffer = workerThread.getByteBuffer();
> ByteBuffer outputBB = workerThread.getOutputBB();
> ByteBuffer inputBB = workerThread.getInputBB();
> SSLEngine sslEngine = workerThread.getSSLEngine();
>
> int count = -1;
> - try{
> + try {
> // Read first bytes to avoid continuing if the client
> // closed the connection.
> - count = ((SocketChannel)key.channel()).read(inputBB);
> - if (count != -1){
> + count = ((SocketChannel) key.channel()).read(inputBB);
> + if (count != -1) {
> // Decrypt the bytes we just read.
> if (Controller.logger().isLoggable(Level.FINE)) {
> Controller.logger().log(Level.FINE,
> @@ -318,21 +292,20 @@
> }
>
> byteBuffer =
> - SSLUtils.unwrapAll(byteBuffer,inputBB,sslEngine);
> + SSLUtils.unwrapAll(byteBuffer, inputBB, sslEngine);
> workerThread.setInputBB(inputBB);
> workerThread.setOutputBB(outputBB);
> workerThread.setByteBuffer(byteBuffer);
> }
> return count;
> - } catch(IOException ex){
> + } catch (IOException ex) {
> log("Exception during SSL read.", ex);
> return -1;
> } finally {
> - if (count == -1){
> - try{
> + if (count == -1) {
> + try {
> sslEngine.closeInbound();
> - } catch (SSLException ex){
> - ;
> + } catch (SSLException ex) {
> }
> }
> }
> @@ -399,13 +372,12 @@
> SSLEngine sslEngine = null;
> if (key.attachment() == null){
> sslEngine = newSSLEngine();
> - } else if (key.attachment() instanceof SSLEngine){
> - sslEngine = (SSLEngine)key.attachment();
> + } else if (key.attachment() instanceof SSLSelectionKeyAttachment){
> + sslEngine = ((SSLSelectionKeyAttachment) SelectionKeyAttachment.getAttachment(key)).getSslEngine();
> } else {
> sslEngine = newSSLEngine();
> }
> sslEngine.setWantClientAuth(wantClientAuth);
> - sslEngine.getSession().removeValue(EXPIRE_TIME);
> sslEngine.setNeedClientAuth(needClientAuth);
> return sslEngine;
> }
> @@ -613,78 +585,28 @@
> return ciphers;
> }
>
> - /**
> - * If bytebuffer is not empty it means that previous
> - * <code>ProtocolFilter</code>s has read some data already. This data
> - * should be copied to the inputBB.
> - */
> - private static boolean copyByteBufferToInputBB(SSLEngine sslEngine,
> - ByteBuffer byteBuffer, ByteBuffer inputBB) {
> - if (byteBuffer.position() > 0) {
> - Boolean isDataDecoded =
> - (Boolean) sslEngine.getSession().getValue(DATA_DECODED);
> + private void saveSecuredBufferRemainders(SelectionKey selectionKey) {
> + SSLSelectionKeyAttachment attachment =
> + (SSLSelectionKeyAttachment) selectionKey.attachment();
>
> - if (!Boolean.TRUE.equals(isDataDecoded)) {
> - byteBuffer.flip();
> - inputBB.put(byteBuffer);
> - byteBuffer.clear();
> - return true;
> - } else if (isDataDecoded != null) {
> - sslEngine.getSession().removeValue(DATA_DECODED);
> - }
> - }
> -
> - return false;
> - }
> -
> - /**
> - * Restores (if required) secure buffers, associated with <code>SSLEngine</code>,
> - * which were saved during previous SSLReadFilter execution.
> - * It makes possible data, which wasn't processed on previous cycle to be processed now
> - */
> - private void restoreSecuredBufferRemainders(SSLEngine sslEngine) {
> - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> -
> - ByteBuffer inputBBRemainder = (ByteBuffer) sslEngine.getSession().
> - getValue(INPUT_BB_REMAINDER);
> - if (inputBBRemainder != null) {
> - sslEngine.getSession().removeValue(INPUT_BB_REMAINDER);
> - workerThread.setInputBB(inputBBRemainder);
> - }
> -
> - ByteBuffer outputBBRemainder = (ByteBuffer) sslEngine.getSession().
> - getValue(OUTPUT_BB_REMAINDER);
> - if (outputBBRemainder != null) {
> - sslEngine.getSession().removeValue(OUTPUT_BB_REMAINDER);
> - workerThread.setOutputBB(outputBBRemainder);
> - }
> - }
> -
> - /**
> - * Saves (if required) secure buffers, associated with <code>SSLEngine</code>
> - * If secured data, associated with <code>SSLEngine</code>, is not completely
> - * processed now (may be additional data is required) - then it could be processed
> - * on next SSLReadFilter execution.
> - */
> - private void saveSecuredBufferRemainders(SSLEngine sslEngine) {
> - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> -
> - if (sslEngine == null) {
> + if (attachment == null) {
> Controller.logger().log(Level.FINE,
> - "SSLEngine is NULL, when saving buffers");
> + "SelectionKey attachment is NULL, when saving buffers");
> return;
> }
>
> + WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> +
> ByteBuffer inputBB = workerThread.getInputBB();
> if (inputBB != null && inputBB.hasRemaining()) {
> - sslEngine.getSession().putValue(INPUT_BB_REMAINDER, inputBB);
> workerThread.setInputBB(null);
> + attachment.setInputBB(inputBB);
> }
>
> ByteBuffer outputBB = workerThread.getOutputBB();
> if (outputBB != null && outputBB.hasRemaining()) {
> - sslEngine.getSession().putValue(OUTPUT_BB_REMAINDER, outputBB);
> workerThread.setOutputBB(null);
> + attachment.setOutputBB(outputBB);
> }
> }
>
> Index: main/java/com/sun/grizzly/ProtocolChainContextTask.java
> --- main/java/com/sun/grizzly/ProtocolChainContextTask.java Base (BASE)
> +++ main/java/com/sun/grizzly/ProtocolChainContextTask.java Locally Modified (Based On LOCAL)
> @@ -24,8 +24,6 @@
>
> package com.sun.grizzly;
>
> -import java.nio.channels.SelectionKey;
> -
> /**
> * <code>ProtocolChain</code> task, which will be executed by
> * <code>Context</code>, when Context.execute(<code>ContextTask</code>)
> @@ -33,11 +31,11 @@
> *
> * @author Alexey Stashok
> */
> -public class ProtocolChainContextTask extends ContextTask {
> +public class ProtocolChainContextTask extends SelectionKeyContextTask {
> private static final TaskPool<ProtocolChainContextTask> taskPool =
> new TaskPool<ProtocolChainContextTask>() {
> @Override
> - public ProtocolChainContextTask newTask() {
> + public ProtocolChainContextTask newInstance() {
> return new ProtocolChainContextTask();
> }
> };
> @@ -51,16 +49,10 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> - SelectionKey currentKey = context.getSelectionKey();
> - SelectionKeyHandler selectionKeyHandler = context.
> - getSelectorHandler().getSelectionKeyHandler();
> -
> - selectionKeyHandler.process(currentKey);
> + protected Object doCall() throws Exception {
> try {
> context.getProtocolChain().execute(context);
> } finally {
> - selectionKeyHandler.postProcess(currentKey);
> offer(this);
> }
>
> Index: main/java/com/sun/grizzly/SelectionKeyContextTask.java
> --- main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New
> +++ main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New
> @@ -0,0 +1,66 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Basic class for all <code>ContextTask</code>s, which are dealing with
> + * <code>SelectionKey</code>s
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyContextTask extends ContextTask {
> +
> + public final Object call() throws Exception {
> + Object result = null;
> + SelectionKey currentKey = context.getSelectionKey();
> + SelectionKeyHandler selectionKeyHandler = context.
> + getSelectorHandler().getSelectionKeyHandler();
> +
> + selectionKeyHandler.process(currentKey);
> + try {
> + result = doCall();
> + } finally {
> + selectionKeyHandler.postProcess(currentKey);
> + }
> +
> + return result;
> + }
> +
> + protected abstract Object doCall() throws Exception;
> +}
> Index: main/java/com/sun/grizzly/TCPSelectorHandler.java
> --- main/java/com/sun/grizzly/TCPSelectorHandler.java Base (BASE)
> +++ main/java/com/sun/grizzly/TCPSelectorHandler.java Locally Modified (Based On LOCAL)
> @@ -31,6 +31,7 @@
> import com.sun.grizzly.async.TCPAsyncQueueReader;
> import com.sun.grizzly.util.Cloner;
> import com.sun.grizzly.util.Copyable;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import com.sun.grizzly.util.SelectionKeyOP;
> import com.sun.grizzly.util.SelectionKeyOP.ConnectSelectionKeyOP;
> import com.sun.grizzly.util.State;
> @@ -610,7 +611,7 @@
> throws IOException{
> // disable OP_READ on key before doing anything else
> key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
> - Object attach = key.attachment();
> + Object attach = SelectionKeyAttachment.getAttachment(key);
>
> if (asyncQueueReader.isAsyncQueueReaderEnabledFor(key)) {
> final Context context = pollContext(ctx, key);
> @@ -646,7 +647,8 @@
> context.setCurrentOpType(Context.OpType.OP_WRITE);
> invokeAsyncQueueWriter(context);
> return false;
> - } else if ((attach = key.attachment()) instanceof CallbackHandler){
> + } else if ((attach = SelectionKeyAttachment.getAttachment(key))
> + instanceof CallbackHandler){
> final Context context = pollContext(ctx, key);
> context.setCurrentOpType(Context.OpType.OP_WRITE);
> invokeCallbackHandler((CallbackHandler) attach, context);
> @@ -671,7 +673,7 @@
> key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
> key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
>
> - Object attach = key.attachment();
> + Object attach = SelectionKeyAttachment.getAttachment(key);
> if (attach instanceof CallbackHandler){
> final Context context = pollContext(ctx, key);
> context.setCurrentOpType(Context.OpType.OP_CONNECT);
> Index: main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java
> --- main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New
> +++ main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New
> @@ -0,0 +1,60 @@
> +/*
> + * The contents of this file are subject to the terms
> + * of the Common Development and Distribution License
> + * (the License). You may not use this file except in
> + * compliance with the License.
> + *
> + * You can obtain a copy of the license at
> + * https://glassfish.dev.java.net/public/CDDLv1.0.html or
> + * glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * See the License for the specific language governing
> + * permissions and limitations under the License.
> + *
> + * When distributing Covered Code, include this CDDL
> + * Header Notice in each file and include the License file
> + * at glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * If applicable, add the following below the CDDL Header,
> + * with the fields enclosed by brackets [] replaced by
> + * you own identifying information:
> + * "Portions Copyrighted [year] [name of copyright owner]"
> + *
> + * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.util.concurrent.ConcurrentLinkedQueue;
> +
> +/**
> + * <code>ObjectPool</code> implementation based on <code>ConcurrentLinkedQueue</code>
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class ConcurrentLinkedQueuePool<E> implements ObjectPool<E> {
> + private volatile ConcurrentLinkedQueue<E> pool;
> +
> + public abstract E newInstance();
> +
> + public E poll() {
> + if (pool == null) {
> + synchronized(this) {
> + if (pool == null) {
> + pool = new ConcurrentLinkedQueue<E>();
> + }
> + }
> + }
> +
> + E object = pool.poll();
> + if (object == null) {
> + object = newInstance();
> + }
> +
> + return object;
> + }
> +
> + public void offer(E object) {
> + if (pool != null) {
> + pool.offer(object);
> + }
> + }
> +}
> Index: main/java/com/sun/grizzly/util/ObjectPool.java
> --- main/java/com/sun/grizzly/util/ObjectPool.java Locally New
> +++ main/java/com/sun/grizzly/util/ObjectPool.java Locally New
> @@ -0,0 +1,35 @@
> +/*
> + * The contents of this file are subject to the terms
> + * of the Common Development and Distribution License
> + * (the License). You may not use this file except in
> + * compliance with the License.
> + *
> + * You can obtain a copy of the license at
> + * https://glassfish.dev.java.net/public/CDDLv1.0.html or
> + * glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * See the License for the specific language governing
> + * permissions and limitations under the License.
> + *
> + * When distributing Covered Code, include this CDDL
> + * Header Notice in each file and include the License file
> + * at glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * If applicable, add the following below the CDDL Header,
> + * with the fields enclosed by brackets [] replaced by
> + * you own identifying information:
> + * "Portions Copyrighted [year] [name of copyright owner]"
> + *
> + * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +/**
> + * Basic interface for object pool implementations
> + *
> + * @author Alexey Stashok
> + */
> +public interface ObjectPool<E> {
> + public E poll();
> +
> + public void offer(E object);
> +}
> Index: main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java
> --- main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New
> +++ main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New
> @@ -0,0 +1,50 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Class represents extended version of <code>SelectionKeyAttachment</code>,
> + * and introduces process method, which will be called by framework once
> + * <code>SelectionKey</code> has some ready event, before actual event processing.
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyActionAttachment extends SelectionKeyAttachment {
> + public abstract void process(SelectionKey selectionKey);
> +}
> Index: main/java/com/sun/grizzly/util/SelectionKeyAttachment.java
> --- main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New
> +++ main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New
> @@ -0,0 +1,70 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Basic class for all SelectionKey attachments.
> + * Custom attachments should be inherited from it.
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyAttachment {
> + private Long timeout;
> +
> + public static Object getAttachment(SelectionKey key) {
> + Object attachment = key.attachment();
> + if (attachment instanceof SelectionKeyAttachmentWrapper) {
> + return ((SelectionKeyAttachmentWrapper) attachment).getAttachment();
> + }
> +
> + return attachment;
> + }
> +
> + public Long getTimeout() {
> + return timeout;
> + }
> +
> + public void setTimeout(Long timeout) {
> + this.timeout = timeout;
> + }
> +
> + public void release() {
> + timeout = null;
> + }
> +}
> Index: main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java
> --- main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New
> +++ main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New
> @@ -0,0 +1,70 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * <code>SelectionKey</code> attachment utility class.
> + * This class could be used as wrapper for custom <code>SelectionKey</code>
> + * attachments, which are not subclasses of <code>SelectionKeyAttachment</code>
> + * class.
> + *
> + * @author Alexey Stashok
> + */
> +public class SelectionKeyAttachmentWrapper<E> extends SelectionKeyActionAttachment {
> + private E attachment;
> +
> + public E getAttachment() {
> + return attachment;
> + }
> +
> + public void setAttachment(E attachment) {
> + this.attachment = attachment;
> + }
> +
> + @Override
> + public void process(SelectionKey selectionKey) {
> + // Do nothing by default
> + }
> +
> + @Override
> + public void release() {
> + attachment = null;
> + super.release();
> + }
> +}
> Index: main/java/com/sun/grizzly/util/SelectionKeyOP.java
> --- main/java/com/sun/grizzly/util/SelectionKeyOP.java Base (BASE)
> +++ main/java/com/sun/grizzly/util/SelectionKeyOP.java Locally Modified (Based On LOCAL)
> @@ -27,7 +27,6 @@
> import java.net.SocketAddress;
> import java.nio.channels.SelectableChannel;
> import java.nio.channels.SelectionKey;
> -import java.util.concurrent.ConcurrentLinkedQueue;
>
> /**
> *
> @@ -38,27 +37,29 @@
> private SelectionKey key;
> private SelectableChannel channel;
>
> - private static ConcurrentLinkedQueue<SelectionKeyOP> readWritePool =
> - new ConcurrentLinkedQueue<SelectionKeyOP>();
> + private static ConcurrentLinkedQueuePool<SelectionKeyOP> readWritePool =
> + new ConcurrentLinkedQueuePool<SelectionKeyOP>() {
> + @Override
> + public SelectionKeyOP newInstance() {
> + return new SelectionKeyOP();
> + }
> + };
>
> - private static ConcurrentLinkedQueue<SelectionKeyOP> connectPool =
> - new ConcurrentLinkedQueue<SelectionKeyOP>();
> + private static ConcurrentLinkedQueuePool<SelectionKeyOP> connectPool =
> + new ConcurrentLinkedQueuePool<SelectionKeyOP>() {
> + @Override
> + public SelectionKeyOP newInstance() {
> + return new ConnectSelectionKeyOP();
> + }
> + };
>
> public static SelectionKeyOP aquireSelectionKeyOP(int op) {
> if (op == SelectionKey.OP_READ || op == SelectionKey.OP_WRITE ||
> op == (SelectionKey.OP_WRITE | SelectionKey.OP_READ)) {
> SelectionKeyOP operation = readWritePool.poll();
> - if (operation == null) {
> - operation = new SelectionKeyOP();
> - }
> -
> return operation;
> } else if (op == SelectionKey.OP_CONNECT) {
> SelectionKeyOP operation = connectPool.poll();
> - if (operation == null) {
> - operation = new ConnectSelectionKeyOP();
> - }
> -
> \ No newline at end of file
> return operation;
> }
>
> Index: main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java
> --- main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New
> +++ main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New
> @@ -0,0 +1,145 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.ByteBuffer;
> +import java.nio.channels.SelectionKey;
> +import javax.net.ssl.SSLEngine;
> +
> +/**
> + * <code>SelectionKeyAttachment</code> implementation, which is targeted for SSL
> + * support.
> + *
> + * @author Alexey Stashok
> + */
> +public class SSLSelectionKeyAttachment extends SelectionKeyActionAttachment {
> +
> + private static ConcurrentLinkedQueuePool<SSLSelectionKeyAttachment> pool =
> + new ConcurrentLinkedQueuePool<SSLSelectionKeyAttachment>() {
> +
> + @Override
> + public SSLSelectionKeyAttachment newInstance() {
> + return new SSLSelectionKeyAttachment();
> + }
> + };
> + private SSLEngine sslEngine;
> + private ByteBuffer inputBB;
> + private ByteBuffer outputBB;
> +
> + /**
> + * Saves (if required) secure buffers, associated with <code>SSLEngine</code>
> + * If secured data, associated with <code>SSLEngine</code>, is not completely
> + * processed now (may be additional data is required) - then it could be processed
> + * on next SSLReadFilter execution.
> + */
> + public static void attach(SelectionKey key, SSLEngine sslEngine) {
> + SSLSelectionKeyAttachment attachment = null;
> + Object currentAttachment = key.attachment();
> + if (currentAttachment != null &&
> + currentAttachment instanceof SSLSelectionKeyAttachment) {
> + attachment = (SSLSelectionKeyAttachment) currentAttachment;
> + } else {
> + attachment = pool.poll();
> + }
> +
> + attachment.setInputBB(null);
> + attachment.setOutputBB(null);
> +
> + attachment.setSslEngine(sslEngine);
> + key.attach(attachment);
> + }
> +
> + public ByteBuffer getInputBB() {
> + return inputBB;
> + }
> +
> + public void setInputBB(ByteBuffer inputBB) {
> + this.inputBB = inputBB;
> + }
> +
> + public ByteBuffer getOutputBB() {
> + return outputBB;
> + }
> +
> + public void setOutputBB(ByteBuffer outputBB) {
> + this.outputBB = outputBB;
> + }
> +
> + public SSLEngine getSslEngine() {
> + return sslEngine;
> + }
> +
> + public void setSslEngine(SSLEngine sslEngine) {
> + this.sslEngine = sslEngine;
> + }
> +
> + /**
> + * Restores (if required) secure buffers, associated with <code>SSLEngine</code>,
> + * which were saved during previous SSLReadFilter execution.
> + * It makes possible data, which wasn't processed on previous cycle to be processed now
> + */
> + @Override
> + public void process(SelectionKey selectionKey) {
> + WorkerThreadImpl workerThread;
> + try {
> + workerThread = (WorkerThreadImpl) Thread.currentThread();
> + } catch (ClassCastException ex) {
> + throw new IllegalStateException(ex.getMessage());
> + }
> +
> + if (inputBB != null) {
> + workerThread.setInputBB(inputBB);
> + inputBB = null;
> + }
> +
> + if (outputBB != null) {
> + workerThread.setOutputBB(outputBB);
> + outputBB = null;
> + }
> +
> + workerThread.setSSLEngine(sslEngine);
> + }
> +
> + @Override
> + public void release() {
> + sslEngine = null;
> + inputBB = null;
> + outputBB = null;
> + super.release();
> + pool.offer(this);
> + }
> + }
> Index: main/java/com/sun/grizzly/util/ThreadAttachment.java
> --- main/java/com/sun/grizzly/util/ThreadAttachment.java Base (BASE)
> +++ main/java/com/sun/grizzly/util/ThreadAttachment.java Locally Modified (Based On LOCAL)
> @@ -23,6 +23,7 @@
> package com.sun.grizzly.util;
>
> import java.nio.ByteBuffer;
> +import java.nio.channels.SelectionKey;
> import java.util.WeakHashMap;
> import javax.net.ssl.SSLEngine;
>
> @@ -32,12 +33,9 @@
> *
> * @author Jeanfrancois Arcand
> */
> -public class ThreadAttachment {
> +public class ThreadAttachment extends SelectionKeyActionAttachment {
>
>
> - private long timeout;
> -
> -
> private String threadId;
>
>
> @@ -169,22 +167,13 @@
> this.threadId = threadId;
> }
>
> -
> /**
> - * Set the timeout used by the SelectionKeyHandler to times out an idle
> - * connection.
> + * SelectionKey attachment processing
> + * @param selectionKey
> */
> - public void setTimeout(long timeout){
> - this.timeout = timeout;
> + public void process(SelectionKey selectionKey) {
> + ((WorkerThread) Thread.currentThread()).attach(
> + (ThreadAttachment) this);
> + selectionKey.attach(null);
> }
> -
> -
> - /**
> - * Return the timeout used by the SelectionKeyHandler to times out an idle
> - * connection.
> - */
> - public long getTimeout(){
> - return timeout;
> }
> -
> -}
> Index: main/java/com/sun/grizzly/util/WorkerThreadImpl.java
> --- main/java/com/sun/grizzly/util/WorkerThreadImpl.java Base (BASE)
> +++ main/java/com/sun/grizzly/util/WorkerThreadImpl.java Locally Modified (Based On LOCAL)
> @@ -294,11 +294,11 @@
> * @return a new ThreadAttachment
> */
> public ThreadAttachment detach(boolean copyState) {
> - if (threadAttachment == null){
> + if (threadAttachment == null) {
> threadAttachment = new ThreadAttachment();
> }
>
> - try{
> + try {
> threadAttachment.setByteBuffer(byteBuffer);
> threadAttachment.setSSLEngine(sslEngine);
> threadAttachment.setInputBB(inputBB);
> @@ -308,7 +308,7 @@
> } finally {
> // We cannot cache/re-use this object as it might be referenced
> // by more than one thread.
> - if (copyState){
> + if (copyState) {
> // Re-create a new ByteBuffer
> byteBuffer = ByteBufferFactory.allocate(byteBufferType,
> initialByteBufferSize);
>
>
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\Grizzly\trunk\modules\portunif\src
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java
> --- main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java Base (BASE)
> +++ main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java Locally Modified (Based On LOCAL)
> @@ -26,8 +26,9 @@
> import com.sun.grizzly.Context;
> import com.sun.grizzly.Controller;
> import com.sun.grizzly.SSLConfig;
> -import com.sun.grizzly.filter.SSLReadFilter;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.SSLUtils;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.EOFException;
> import java.io.IOException;
> import java.nio.ByteBuffer;
> @@ -50,12 +51,7 @@
>
> private static final String TMP_DECODED_BUFFER ="TMP_DECODED_BUFFER";
>
> - /**
> - * Decrypted ByteBuffer default size.
> - */
> - private final static int appBBSize = 5 * 4096;
>
> -
> /**
> * The <code>SSLContext</code> associated with the SSL implementation
> * we are running on.
> @@ -108,14 +104,14 @@
>
>
> SSLEngine sslEngine = null;
> - Object attachment = key.attachment();
> - if (attachment == null || !(attachment instanceof SSLEngine)) {
> + Object attachment = SelectionKeyAttachment.getAttachment(key);
> + if (attachment == null || !(attachment instanceof SSLSelectionKeyAttachment)) {
> sslEngine = sslContext.createSSLEngine();
> sslEngine.setUseClientMode(false);
> sslEngine.setNeedClientAuth(needClientAuth);
> sslEngine.setWantClientAuth(wantClientAuth);
> } else {
> - sslEngine = (SSLEngine) attachment;
> + sslEngine = ((SSLSelectionKeyAttachment) attachment).getSslEngine();
> }
>
> ByteBuffer inputBB = protocolRequest.getSecuredInputByteBuffer();
> @@ -146,8 +142,7 @@
> inputBB.put((ByteBuffer) byteBuffer.flip());
> byteBuffer.clear();
>
> - boolean OK = Boolean.TRUE.equals(
> - sslEngine.getSession().getValue(SSLReadFilter.HANDSHAKE));
> + boolean OK = sslEngine.getSession().isValid();
>
> if (!OK) { // Handshake wasn't completed on prev step
> HandshakeStatus handshakeStatus = HandshakeStatus.NEED_UNWRAP;
> @@ -156,8 +151,7 @@
> byteBuffer = SSLUtils.doHandshake(channel, byteBuffer,
> inputBB, outputBB, sslEngine, handshakeStatus,
> SSLUtils.getReadTimeout(), inputBB.position() > 0);
> - sslEngine.getSession().putValue(SSLReadFilter.HANDSHAKE, true);
> - key.attach(sslEngine);
> + SSLSelectionKeyAttachment.attach(key, sslEngine);
> protocolRequest.setSSLEngine(sslEngine);
> // set "no available data" for secured output buffer
> outputBB.limit(outputBB.position());
> @@ -196,8 +190,6 @@
> if (byteRead > -1) {
> byteBuffer = SSLUtils.unwrapAll(byteBuffer, inputBB, sslEngine);
> protocolRequest.setByteBuffer(byteBuffer);
> - sslEngine.getSession().putValue(SSLReadFilter.DATA_DECODED,
> - Boolean.TRUE);
> } else {
> throw new EOFException();
> }
> Index: test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java
> --- test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java Base (BASE)
> +++ test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java Locally Modified (Based On LOCAL)
> @@ -25,13 +25,14 @@
>
> import com.sun.grizzly.Context;
> import com.sun.grizzly.Controller;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.OutputWriter;
> import com.sun.grizzly.util.SSLOutputWriter;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.IOException;
> import java.nio.ByteBuffer;
> import java.nio.channels.SelectionKey;
> import java.util.logging.Level;
> -import javax.net.ssl.SSLEngine;
>
> /**
> * @author Alexey Stashok
> @@ -78,9 +79,9 @@
> buffer.position(pos);
> }
>
> - Object attachment = protocolRequest.getSelectionKey().attachment();
> - if (attachment instanceof SSLEngine) {
> - protocolRequest.setSSLEngine((SSLEngine) attachment);
> + Object attachment = SelectionKeyAttachment.getAttachment(protocolRequest.getSelectionKey());
> + if (attachment instanceof SSLSelectionKeyAttachment) {
> + protocolRequest.setSSLEngine(((SSLSelectionKeyAttachment) attachment).getSslEngine());
> allocateBuffers(protocolRequest);
> } else {
> protocolRequest.setSSLEngine(null);
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net