You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ad...@apache.org on 2010/01/09 15:26:31 UTC

svn commit: r897460 [2/2] - in /mina/sandbox/adc/ahc: api/src/main/java/org/apache/ahc/api/ api/src/main/java/org/apache/ahc/api/listeners/ mina2/src/main/java/org/apache/ahc/mina2/ mina3/src/main/java/org/apache/ahc/mina3/ mina3/src/main/java/org/apac...

Added: mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/FinishedChannelState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/FinishedChannelState.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/FinishedChannelState.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/FinishedChannelState.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+package org.apache.mina.ssl;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import java.nio.ByteBuffer;
+
+import org.apache.mina.core.BaseChannelState;
+import org.apache.mina.core.IoBuffer;
+import org.apache.mina.core.IoProperty;
+import org.apache.mina.core.IoPropertyScope;
+import org.apache.mina.core.StateMachineChannel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: $ $Date: $
+ */
+public class FinishedChannelState extends BaseChannelState
+{
+    private final static Logger LOGGER = LoggerFactory.getLogger(FinishedChannelState.class);
+    private ByteBuffer byteBuffer;
+    private SSLEngine engine;
+
+    @IoProperty(name = "byteBuffer", scope = IoPropertyScope.SESSION)
+    public void setByteBuffer(ByteBuffer byteBuffer)
+    {
+        this.byteBuffer = byteBuffer;
+    }
+
+    @IoProperty(name = "engine", scope = IoPropertyScope.SESSION)
+    public void setEngine(SSLEngine engine)
+    {
+        this.engine = engine;
+    }
+
+    @Override
+    public Object send(StateMachineChannel stateMachine, Object message) throws Exception
+    {
+        IoBuffer ioBuffer = (IoBuffer) message;
+
+        engine.wrap(ioBuffer.getMessages(), byteBuffer);
+
+        return byteBuffer;
+    }
+
+    @Override
+    public Object receive(StateMachineChannel stateMachine, Object message) throws Exception
+    {
+        IoBuffer ioBuffer = (IoBuffer) message;
+
+        SSLEngineResult result = engine.unwrap(ioBuffer.getMessages()[0], byteBuffer);
+
+        if (result.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW)
+        {
+            return byteBuffer;
+        }
+        else
+        {
+            return null;
+        }
+    }
+}

Added: mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/HandshakeChannelState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/HandshakeChannelState.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/HandshakeChannelState.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/HandshakeChannelState.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+package org.apache.mina.ssl;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import java.nio.ByteBuffer;
+
+import org.apache.mina.core.BaseChannelState;
+import org.apache.mina.core.IoBuffer;
+import org.apache.mina.core.IoByteBufferFactory;
+import org.apache.mina.core.IoProperty;
+import org.apache.mina.core.IoPropertyScope;
+import org.apache.mina.core.StateMachineChannel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @version $Revision: $ $Date: $
+ */
+public class HandshakeChannelState extends BaseChannelState<SslStates>
+{
+    private final static Logger LOGGER = LoggerFactory.getLogger(HandshakeChannelState.class);
+    private IoByteBufferFactory factory;
+    private SSLEngine engine;
+
+    @IoProperty(name = "factory", scope = IoPropertyScope.GLOBAL)
+    public void setFactory(IoByteBufferFactory factory)
+    {
+        this.factory = factory;
+    }
+
+    @IoProperty(name = "engine", scope = IoPropertyScope.SESSION)
+    public void setEngine(SSLEngine engine)
+    {
+        this.engine = engine;
+    }
+
+    @Override
+    public Object send(StateMachineChannel<SslStates> stateMachine, Object message) throws Exception
+    {
+        IoBuffer ioBuffer = (IoBuffer) message;
+
+        ByteBuffer byteBuffer = factory.allocate(engine.getSession().getPacketBufferSize()).get();
+        SSLEngineResult result = engine.wrap(ioBuffer.getMessages(), byteBuffer);
+        if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
+        {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null)
+            {
+                LOGGER.trace("delegated task started");
+                runnable.run();
+                LOGGER.trace("delegated task completed");
+            }
+
+            SSLEngineResult.HandshakeStatus status = engine.getHandshakeStatus();
+            if (status == SSLEngineResult.HandshakeStatus.NEED_TASK)
+            {
+                throw new Exception("handshake shouldn't need additional tasks");
+            }
+            LOGGER.trace("handshake status: " + status);
+        }
+        factory.recycle(ioBuffer);
+
+        return byteBuffer;
+    }
+
+    @Override
+    public Object receive(StateMachineChannel<SslStates> stateMachine, Object message) throws Exception
+    {
+        IoBuffer ioBuffer = (IoBuffer) message;
+
+        ByteBuffer byteBuffer = factory.allocate(engine.getSession().getPacketBufferSize()).get();
+        SSLEngineResult result = engine.unwrap(ioBuffer.getMessages()[0], byteBuffer);
+        if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
+        {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null)
+            {
+                LOGGER.trace("delegated task started");
+                runnable.run();
+                LOGGER.trace("delegated task completed");
+            }
+
+            SSLEngineResult.HandshakeStatus status = engine.getHandshakeStatus();
+            if (status == SSLEngineResult.HandshakeStatus.NEED_TASK)
+            {
+                throw new Exception("handshake shouldn't need additional tasks");
+            }
+
+            LOGGER.trace("handshake status: " + status);
+        }
+        else if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP)
+        {
+            stateMachine.send(send(stateMachine, IoBuffer.EMPTY));
+        }
+        else if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED)
+        {
+            stateMachine.setState(SslStates.FINISHED);
+        }
+        factory.recycle(ioBuffer);
+
+        return byteBuffer;
+    }
+}

Copied: mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslChannel.java (from r892489, mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/core/SslChannel.java)
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslChannel.java?p2=mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslChannel.java&p1=mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/core/SslChannel.java&r1=892489&r2=897460&rev=897460&view=diff
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/core/SslChannel.java (original)
+++ mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslChannel.java Sat Jan  9 14:26:30 2010
@@ -16,41 +16,96 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.mina.core;
+package org.apache.mina.ssl;
 
-import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+
+import org.apache.mina.core.IoBuffer;
+import org.apache.mina.core.IoByteBufferFactory;
+import org.apache.mina.core.IoChannelState;
+import org.apache.mina.core.IoDown;
+import org.apache.mina.core.IoProperty;
+import org.apache.mina.core.IoPropertyScope;
+import org.apache.mina.core.StateMachineChannel;
 
 
 /**
  * @version $Revision: $ $Date: $
  */
-public class SslChannel extends AbstractIoChannel implements IoDown, IoUp
+public class SslChannel extends StateMachineChannel<SslStates>
 {
-    private final SSLContext context;
+    private SslConfig sslConfig;
+    private IoByteBufferFactory factory;
+    private ByteBuffer byteBuffer;
+    private SSLEngine engine;
 
-    public SslChannel(SSLContext context)
+    public SslChannel()
     {
-        if (context == null) throw new IllegalArgumentException("SSL context cannot be null");
-        this.context = context;
+        getStates().put(SslStates.HANDSHAKE, Collections.<IoChannelState>singletonList(new HandshakeChannelState()));
+        getStates().put(SslStates.FINISHED, Collections.<IoChannelState>singletonList(new FinishedChannelState()));
+        getStates().put(SslStates.CLOSING, Collections.<IoChannelState>singletonList(new ClosingChannelState()));
+        getStates().put(SslStates.CLOSED, Collections.<IoChannelState>singletonList(new ClosedChannelState()));
     }
 
+    @IoProperty(name = "sslConfig", scope = IoPropertyScope.GLOBAL)
+    public void setSslConfig(SslConfig sslConfig)
+    {
+        this.sslConfig = sslConfig;
+    }
+
+    @IoProperty(name = "factory", scope = IoPropertyScope.GLOBAL)
+    public void setFactory(IoByteBufferFactory factory)
+    {
+        this.factory = factory;
+    }
+
+    @Override
     public void init() throws Exception
     {
-        //Todo change body of implemented methods use File | Settings | File Templates.
+        sslConfig.getSslContext().init(sslConfig.getKeyManagers(), sslConfig.getTrustManagers(), sslConfig.getSecureRandom());
+
+        engine = sslConfig.getSslContext().createSSLEngine();
+
+        engine.setUseClientMode(sslConfig.isClientMode());
+        if (sslConfig.getSslProtocols() != null) engine.setEnabledProtocols(sslConfig.getSslProtocols());
+        if (sslConfig.getEnabledCipherSuites() != null) engine.setEnabledCipherSuites(sslConfig.getEnabledCipherSuites());
+
+        engine.beginHandshake();
+
+        byteBuffer = factory.allocate(engine.getSession().getPacketBufferSize()).get();
+
+        setState(SslStates.HANDSHAKE);
+
+        if (!sslConfig.isLazyHandshake())
+        {
+            HandshakeChannelState state = (HandshakeChannelState) getStates().get(SslStates.HANDSHAKE).get(0);
+            state.setByteBuffer(byteBuffer);
+            state.setEngine(engine);
+
+            IoBuffer message = (IoBuffer) state.send(this, IoBuffer.EMPTY);
+
+            for (IoDown down : getChildren()) down.send(message);
+        }
     }
 
+    @Override
     public void destroy() throws Exception
     {
-        //Todo change body of implemented methods use File | Settings | File Templates.
+        engine.closeInbound();
+        engine.closeOutbound();
     }
 
-    public void send(IoSession session, Object message) throws Exception
+    @IoProperty(name = "byteBuffer", scope = IoPropertyScope.SESSION)
+    public ByteBuffer getByteBuffer()
     {
-        //Todo change body of implemented methods use File | Settings | File Templates.
+        return byteBuffer;
     }
 
-    public void receive(IoSession session, Object message) throws Exception
+    @IoProperty(name = "engine", scope = IoPropertyScope.SESSION)
+    public SSLEngine getEngine()
     {
-        //Todo change body of implemented methods use File | Settings | File Templates.
+        return engine;
     }
 }

Added: mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslConfig.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslConfig.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslConfig.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslConfig.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,126 @@
+/**
+ * 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.
+ */
+package org.apache.mina.ssl;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import java.security.SecureRandom;
+
+import org.apache.mina.core.IoConfig;
+
+
+/**
+ * @version $Revision: $ $Date: $
+ */
+public class SslConfig implements IoConfig
+{
+    private boolean lazyHandshake;
+    private boolean clientMode;
+    private SSLContext sslContext;
+    private String[] sslProtocols;
+    private KeyManager[] keyManagers;
+    private TrustManager[] trustManagers;
+    private SecureRandom secureRandom;
+    private String[] enabledCipherSuites;
+
+    public boolean isLazyHandshake()
+    {
+        return lazyHandshake;
+    }
+
+    public void setLazyHandshake(boolean lazyHandshake)
+    {
+        this.lazyHandshake = lazyHandshake;
+    }
+
+    public boolean isClientMode()
+    {
+        return clientMode;
+    }
+
+    public void setClientMode(boolean clientMode)
+    {
+        this.clientMode = clientMode;
+    }
+
+    public SSLContext getSslContext()
+    {
+        return sslContext;
+    }
+
+    public void setSslContext(SSLContext sslContext)
+    {
+        this.sslContext = sslContext;
+    }
+
+    public String[] getSslProtocols()
+    {
+        return sslProtocols;
+    }
+
+    public void setSslProtocols(String[] sslProtocols)
+    {
+        this.sslProtocols = new String[sslProtocols.length];
+        System.arraycopy(sslProtocols, 0, this.sslProtocols, 0, sslProtocols.length);
+    }
+
+    public KeyManager[] getKeyManagers()
+    {
+        return keyManagers;
+    }
+
+    public void setKeyManagers(KeyManager[] keyManagers)
+    {
+        this.keyManagers = new KeyManager[keyManagers.length];
+        System.arraycopy(keyManagers, 0, this.keyManagers, 0, keyManagers.length);
+    }
+
+    public TrustManager[] getTrustManagers()
+    {
+        return trustManagers;
+    }
+
+    public void setTrustManagers(TrustManager[] trustManagers)
+    {
+        this.trustManagers = new TrustManager[trustManagers.length];
+        System.arraycopy(trustManagers, 0, this.trustManagers, 0, trustManagers.length);
+    }
+
+    public SecureRandom getSecureRandom()
+    {
+        return secureRandom;
+    }
+
+    public void setSecureRandom(SecureRandom secureRandom)
+    {
+        this.secureRandom = secureRandom;
+    }
+
+    public String[] getEnabledCipherSuites()
+    {
+        return enabledCipherSuites;
+    }
+
+    public void setEnabledCipherSuites(String[] enabledCipherSuites)
+    {
+        this.enabledCipherSuites = new String[enabledCipherSuites.length];
+        System.arraycopy(enabledCipherSuites, 0, this.enabledCipherSuites, 0, enabledCipherSuites.length);
+    }
+}

Added: mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslStates.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslStates.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslStates.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/main/java/org/apache/mina/ssl/SslStates.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+package org.apache.mina.ssl;
+
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+
+/**
+ * @version $Revision: $ $Date: $
+ */
+public enum SslStates
+{
+    HANDSHAKE,
+    FINISHED,
+    CLOSING,
+    CLOSED;
+}

Added: mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/BenchMark.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/BenchMark.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/BenchMark.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/BenchMark.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,183 @@
+/**
+ * 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.
+ */
+package org.apache.ahc;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLSession;
+import java.nio.ByteBuffer;
+
+import org.apache.ahc.mina3.EquipmentStack;
+import org.junit.Test;
+
+
+/**
+ * @version $Revision: $ $Date: $
+ */
+public class BenchMark
+{
+    @Test
+    public void test()
+    {
+        EquipmentStack stack = new EquipmentStack();
+
+        for (int i = 0; i < 1000; i++) stack.equipWith("" + i, new Object());
+
+        long start = System.currentTimeMillis();
+        final int COUNT = 100000;
+        for (int i = 0; i < COUNT; i++)
+        {
+            stack.push();
+            stack.pop();
+        }
+        long end = System.currentTimeMillis();
+        System.err.println("Time " + (double)(end - start) / 1000d + "s " + (double)(end - start) / (double)COUNT * 1000d + "us");
+    }
+
+    @Test
+    public void testSsl() throws Exception
+    {
+        SSLEngine clientEngine = generateEngine(true);
+        SSLEngine serverEngine = generateEngine(false);
+
+        ByteBuffer in = ByteBuffer.wrap(new byte[]{(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe});
+        in.flip();
+        ByteBuffer out = ByteBuffer.allocate(1024);
+
+        SSLSession session = clientEngine.getSession();
+
+        ByteBuffer myAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
+        ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize());
+        ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
+        ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());
+
+        doHandshake(clientEngine, serverEngine, in, peerNetData);
+//        SSLEngineResult result = engine.wrap(in, out);
+    }
+
+    void doHandshake(SSLEngine fromEngine, SSLEngine toEngine, ByteBuffer myAppData, ByteBuffer peerNetData) throws Exception
+    {
+        int appBufferSize = fromEngine.getSession().getApplicationBufferSize();
+        ByteBuffer myNetData = ByteBuffer.allocate(appBufferSize);
+        ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
+
+        // Begin handshake
+        fromEngine.beginHandshake();
+        SSLEngineResult.HandshakeStatus hs = fromEngine.getHandshakeStatus();
+
+        // Process handshaking message
+        while ((hs = fromEngine.getHandshakeStatus()) != SSLEngineResult.HandshakeStatus.FINISHED &&
+               (hs = fromEngine.getHandshakeStatus()) != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
+        {
+
+            switch (hs)
+            {
+
+                case NEED_UNWRAP:
+                    // Receive handshaking data from peer
+//                    if (socketChannel.read(peerNetData) < 0)
+//                    {
+//                        // Handle closed channel
+//                    }
+
+                    // Process incoming handshaking data
+                    peerNetData.flip();
+                    SSLEngineResult res = fromEngine.unwrap(peerNetData, peerAppData);
+                    peerNetData.compact();
+                    hs = res.getHandshakeStatus();
+
+
+                    // Check status
+                    switch (res.getStatus())
+                    {
+                        case OK:
+                            //	 if( hs == SSLEngineResult.HandshakeStatus.FINISHED ){
+                            //	 break myio;
+                            //	 }
+                            break;
+                        case BUFFER_OVERFLOW:
+                            System.out.println("---------overflow-------");
+                            break;
+                        case BUFFER_UNDERFLOW:
+                            System.out.println("---------underflow-------");
+                            break;
+
+                        // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED
+                        //...
+                    }
+                    break;
+
+                case NEED_WRAP:
+                    // Empty the local network packet buffer.
+                    myNetData.clear();
+
+                    // Generate handshaking data
+                    res = fromEngine.wrap(myAppData, myNetData);
+                    hs = res.getHandshakeStatus();
+                    //HandshakeStatus hs2 = engine.getHandshakeStatus();
+                    // Check status
+                    switch (res.getStatus())
+                    {
+                        case OK:
+                            //	 if( hs == SSLEngineResult.HandshakeStatus.FINISHED ){
+                            //	 break myio;
+                            //	 }
+                            myNetData.flip();
+
+                            // Send the handshaking data to peer
+                            while (!myNetData.hasRemaining())
+                            {
+//                                if (socketChannel.write(myNetData) < 0)
+//                                {
+//                                    // Handle closed channel
+//                                }
+                            }
+
+                            break;
+
+                        // Handle other status: BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
+                        //...
+                    }
+                    break;
+
+                case NEED_TASK:
+                    new Thread(fromEngine.getDelegatedTask()).start();
+                    // Handle blocking tasks
+                    break;
+
+                // Handle other status: // FINISHED or NOT_HANDSHAKING
+                //...
+            }
+        }
+
+        // Processes after handshaking
+        //...
+    }
+
+    SSLEngine generateEngine(boolean isClient) throws Exception
+    {
+        SSLContext context = SSLContext.getInstance("TLS");
+        context.init(null, null, null);
+        SSLEngine engine = context.createSSLEngine();
+        engine.setUseClientMode(isClient);
+
+        return engine;
+    }
+}

Added: mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/SSLEngineSimpleDemo.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/SSLEngineSimpleDemo.java?rev=897460&view=auto
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/SSLEngineSimpleDemo.java (added)
+++ mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/SSLEngineSimpleDemo.java Sat Jan  9 14:26:30 2010
@@ -0,0 +1,400 @@
+/**
+ * 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.
+ */
+package org.apache.ahc;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.FileInputStream;
+import java.nio.ByteBuffer;
+import java.security.KeyStore;
+
+
+/**
+ * A SSLEngine usage example which simplifies the presentation
+ * by removing the I/O and multi-threading concerns.
+ * <p/>
+ * The demo creates two SSLEngines, simulating a client and server.
+ * The "transport" layer consists two ByteBuffers:  think of them
+ * as directly connected pipes.
+ * <p/>
+ * Note, this is a *very* simple example: real code will be much more
+ * involved.  For example, different threading and I/O models could be
+ * used, transport mechanisms could close unexpectedly, and so on.
+ * <p/>
+ * When this application runs, notice that several messages
+ * (wrap/unwrap) pass before any application data is consumed or
+ * produced.  (For more information, please see the SSL/TLS
+ * specifications.)  There may several steps for a successful handshake,
+ * so it's typical to see the following series of operations:
+ * <p/>
+ * client		server		message
+ * ======		======		=======
+ * wrap()		...	    	ClientHello
+ * ...		    unwrap()	ClientHello
+ * ...		    wrap()		ServerHello/Certificate
+ * unwrap()	    ...		    ServerHello/Certificate
+ * wrap()		...		    ClientKeyExchange
+ * wrap()		...	    	ChangeCipherSpec
+ * wrap()		...		    Finished
+ * ...		    unwrap()	ClientKeyExchange
+ * ...		    unwrap()	ChangeCipherSpec
+ * ...		    unwrap()	Finished
+ * ...		    wrap()		ChangeCipherSpec
+ * ...		    wrap()		Finished
+ * unwrap()	    ...	    	ChangeCipherSpec
+ * unwrap()	    ... 		Finished
+ *
+ * @version $Revision: $ $Date: $
+ */
+public class SSLEngineSimpleDemo
+{
+    /*
+     * Enables logging of the SSLEngine operations.
+     */
+    private static boolean logging = true;
+
+    /*
+     * Enables the JSSE system debugging system property:
+     *
+     *     -Djavax.net.debug=all
+     *
+     * This gives a lot of low-level information about operations underway,
+     * including specific handshake messages, and might be best examined
+     * after gaining some familiarity with this application.
+     */
+    private static boolean debug = false;
+
+    private SSLContext sslc;
+
+    private SSLEngine clientEngine;    // client Engine
+    private ByteBuffer clientOut;    // write side of clientEngine
+    private ByteBuffer clientIn;    // read side of clientEngine
+
+    private SSLEngine serverEngine;    // server Engine
+    private ByteBuffer serverOut;    // write side of serverEngine
+    private ByteBuffer serverIn;    // read side of serverEngine
+
+    /*
+     * For data transport, this example uses local ByteBuffers.  This
+     * isn't really useful, but the purpose of this example is to show
+     * SSLEngine concepts, not how to do network transport.
+     */
+    private ByteBuffer cTOs;        // "reliable" transport client->server
+    private ByteBuffer sTOc;        // "reliable" transport server->client
+
+    /*
+     * The following is to set up the keystores.
+     */
+    private static String keyStoreFile = "testkeys";
+    private static String trustStoreFile = "testkeys";
+    private static String passwd = "passphrase";
+
+    /*
+     * Main entry point for this demo.
+     */
+
+    public static void main(String args[]) throws Exception
+    {
+        if (debug)
+        {
+            System.setProperty("javax.net.debug", "all");
+        }
+
+        SSLEngineSimpleDemo demo = new SSLEngineSimpleDemo();
+        demo.runDemo();
+
+        System.out.println("Demo Completed.");
+    }
+
+    /*
+     * Create an initialized SSLContext to use for this demo.
+     */
+
+    public SSLEngineSimpleDemo() throws Exception
+    {
+        KeyStore ks = KeyStore.getInstance("JKS");
+        KeyStore ts = KeyStore.getInstance("JKS");
+
+        char[] passphrase = "passphrase".toCharArray();
+
+        ks.load(new FileInputStream(keyStoreFile), passphrase);
+        ts.load(new FileInputStream(trustStoreFile), passphrase);
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(ks, passphrase);
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ts);
+
+        SSLContext sslCtx = SSLContext.getInstance("TLS");
+
+        sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+        sslc = sslCtx;
+    }
+
+    /*
+     * Run the demo.
+     *
+     * Sit in a tight loop, both engines calling wrap/unwrap regardless
+     * of whether data is available or not.  We do this until both engines
+     * report back they are closed.
+     *
+     * The main loop handles all of the I/O phases of the SSLEngine's
+     * lifetime:
+     *
+     *     initial handshaking
+     *     application data transfer
+     *     engine closing
+     *
+     * One could easily separate these phases into separate
+     * sections of code.
+     */
+
+    private void runDemo() throws Exception
+    {
+        boolean dataDone = false;
+
+        createSSLEngines();
+        createBuffers();
+
+        SSLEngineResult clientResult;    // results from client's last operation
+        SSLEngineResult serverResult;    // results from server's last operation
+
+        /*
+       * Examining the SSLEngineResults could be much more involved,
+       * and may alter the overall flow of the application.
+       *
+       * For example, if we received a BUFFER_OVERFLOW when trying
+       * to write to the output pipe, we could reallocate a larger
+       * pipe, but instead we wait for the peer to drain it.
+       */
+        while (!isEngineClosed(clientEngine) ||
+               !isEngineClosed(serverEngine))
+        {
+
+            log("================");
+
+            clientResult = clientEngine.wrap(clientOut, cTOs);
+            log("client wrap: ", clientResult);
+            runDelegatedTasks(clientResult, clientEngine);
+
+            serverResult = serverEngine.wrap(serverOut, sTOc);
+            log("server wrap: ", serverResult);
+            runDelegatedTasks(serverResult, serverEngine);
+
+            cTOs.flip();
+            sTOc.flip();
+
+            log("----");
+
+            clientResult = clientEngine.unwrap(sTOc, clientIn);
+            log("client unwrap: ", clientResult);
+            runDelegatedTasks(clientResult, clientEngine);
+
+            serverResult = serverEngine.unwrap(cTOs, serverIn);
+            log("server unwrap: ", serverResult);
+            runDelegatedTasks(serverResult, serverEngine);
+
+            cTOs.compact();
+            sTOc.compact();
+
+            /*
+            * After we've transfered all application data between the client
+            * and server, we close the clientEngine's outbound stream.
+            * This generates a close_notify handshake message, which the
+            * server engine receives and responds by closing itself.
+            *
+            * In normal operation, each SSLEngine should call
+            * closeOutbound().  To protect against truncation attacks,
+            * SSLEngine.closeInbound() should be called whenever it has
+            * determined that no more input data will ever be
+            * available (say a closed input stream).
+            */
+            if (!dataDone && (clientOut.limit() == serverIn.position()) &&
+                (serverOut.limit() == clientIn.position()))
+            {
+
+                /*
+             * A sanity check to ensure we got what was sent.
+             */
+                checkTransfer(serverOut, clientIn);
+                checkTransfer(clientOut, serverIn);
+
+                log("\tClosing clientEngine's *OUTBOUND*...");
+                clientEngine.closeOutbound();
+                // serverEngine.closeOutbound();
+                dataDone = true;
+            }
+        }
+    }
+
+    /*
+     * Using the SSLContext created during object creation,
+     * create/configure the SSLEngines we'll use for this demo.
+     */
+
+    private void createSSLEngines() throws Exception
+    {
+        /*
+       * Configure the serverEngine to act as a server in the SSL/TLS
+       * handshake.  Also, require SSL client authentication.
+       */
+        serverEngine = sslc.createSSLEngine();
+        serverEngine.setUseClientMode(false);
+        serverEngine.setNeedClientAuth(true);
+
+        /*
+       * Similar to above, but using client mode instead.
+       */
+        clientEngine = sslc.createSSLEngine("client", 80);
+        clientEngine.setUseClientMode(true);
+    }
+
+    /*
+     * Create and size the buffers appropriately.
+     */
+
+    private void createBuffers()
+    {
+        /*
+       * We'll assume the buffer sizes are the same
+       * between client and server.
+       */
+        SSLSession session = clientEngine.getSession();
+        int appBufferMax = session.getApplicationBufferSize();
+        int netBufferMax = session.getPacketBufferSize();
+
+        /*
+       * We'll make the input buffers a bit bigger than the max needed
+       * size, so that unwrap()s following a successful data transfer
+       * won't generate BUFFER_OVERFLOWS.
+       *
+       * We'll use a mix of direct and indirect ByteBuffers for
+       * tutorial purposes only.  In reality, only use direct
+       * ByteBuffers when they give a clear performance enhancement.
+       */
+        clientIn = ByteBuffer.allocate(appBufferMax + 50);
+        serverIn = ByteBuffer.allocate(appBufferMax + 50);
+
+        cTOs = ByteBuffer.allocateDirect(netBufferMax);
+        sTOc = ByteBuffer.allocateDirect(netBufferMax);
+
+        clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
+        serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());
+    }
+
+    /*
+     * If the result indicates that we have outstanding tasks to do,
+     * go ahead and run them in this thread.
+     */
+
+    private static void runDelegatedTasks(SSLEngineResult result,
+                                          SSLEngine engine) throws Exception
+    {
+
+        if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
+        {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null)
+            {
+                log("\trunning delegated task...");
+                runnable.run();
+            }
+            SSLEngineResult.HandshakeStatus hsStatus = engine.getHandshakeStatus();
+            if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK)
+            {
+                throw new Exception(
+                        "handshake shouldn't need additional tasks");
+            }
+            log("\tnew HandshakeStatus: " + hsStatus);
+        }
+    }
+
+    private static boolean isEngineClosed(SSLEngine engine)
+    {
+        return (engine.isOutboundDone() && engine.isInboundDone());
+    }
+
+    /*
+     * Simple check to make sure everything came across as expected.
+     */
+
+    private static void checkTransfer(ByteBuffer a, ByteBuffer b)
+            throws Exception
+    {
+        a.flip();
+        b.flip();
+
+        if (!a.equals(b))
+        {
+            throw new Exception("Data didn't transfer cleanly");
+        }
+        else
+        {
+            log("\tData transferred cleanly");
+        }
+
+        a.position(a.limit());
+        b.position(b.limit());
+        a.limit(a.capacity());
+        b.limit(b.capacity());
+    }
+
+    /*
+     * Logging code
+     */
+    private static boolean resultOnce = true;
+
+    private static void log(String str, SSLEngineResult result)
+    {
+        if (!logging)
+        {
+            return;
+        }
+        if (resultOnce)
+        {
+            resultOnce = false;
+            System.out.println("The format of the SSLEngineResult is: \n" +
+                               "\t\"getStatus() / getHandshakeStatus()\" +\n" +
+                               "\t\"bytesConsumed() / bytesProduced()\"\n");
+        }
+        SSLEngineResult.HandshakeStatus hsStatus = result.getHandshakeStatus();
+        log(str +
+            result.getStatus() + "/" + hsStatus + ", " +
+            result.bytesConsumed() + "/" + result.bytesProduced() +
+            " bytes");
+        if (hsStatus == SSLEngineResult.HandshakeStatus.FINISHED)
+        {
+            log("\t...ready for application data");
+        }
+    }
+
+    private static void log(String str)
+    {
+        if (logging)
+        {
+            System.out.println(str);
+        }
+    }
+}
\ No newline at end of file

Modified: mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/api/ClientTest.java
URL: http://svn.apache.org/viewvc/mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/api/ClientTest.java?rev=897460&r1=897459&r2=897460&view=diff
==============================================================================
--- mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/api/ClientTest.java (original)
+++ mina/sandbox/adc/ahc/mina3/src/test/java/org/apache/ahc/api/ClientTest.java Sat Jan  9 14:26:30 2010
@@ -38,6 +38,8 @@
 import com.acme.ahc.listeners.AcmeSslBenchmarkListener;
 import com.acme.ahc.listeners.AcmeSslCertificatManager;
 import org.apache.ahc.api.listeners.MimeContentListener;
+import org.apache.ahc.mina3.AsyncHttpClient;
+import org.apache.ahc.mina3.AsyncHttpRequest;
 import org.junit.Test;
 
 
@@ -49,7 +51,7 @@
     @Test
     void testBatch() throws Exception
     {
-        HttpClient client = new AcmeHttpClient();
+        HttpClient client = new AsyncHttpClient();
         client.equipWith(new AcmeSslCertificatManager());
         client.equipWith("CLIENT_ID", "92341");
 
@@ -83,7 +85,7 @@
     @Test
     void testSend() throws Exception
     {
-        HttpClient client = new AcmeHttpClient();
+        HttpClient client = new AsyncHttpClient();
 
         HttpResponse response = client.get("http://rest.acme.com/rest/student/41134?token=dFWEGV8ss63dmcs0245c")
                 .register(new FutureListener<HttpResponse>()
@@ -104,9 +106,9 @@
     @Test
     void testSendMultipleAttachments() throws Exception
     {
-        HttpClient client = new AcmeHttpClient();
+        HttpClient client = new AsyncHttpClient();
 
-        HttpRequest request = new AcmeHttpRequest();
+        HttpRequest request = new AsyncHttpRequest();
 
         request.setUrl(new URL("http://rest.acme.com/rest/student/41134?token=dFWEGV8ss63dmcs0245"))
                 .addMimeContent(generateXml())
@@ -118,9 +120,9 @@
     @Test
     void testReceiveMultipleAttachments() throws Exception
     {
-        HttpClient client = new AcmeHttpClient();
+        HttpClient client = new AsyncHttpClient();
 
-        HttpRequest request = new AcmeHttpRequest();
+        HttpRequest request = new AsyncHttpRequest();
 
         request.setUrl(new URL("http://rest.acme.com/rest/student/41134?token=dFWEGV8ss63dmcs0245"))
                 .addMimeContentListener(new MimeContentListener()