directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From trus...@apache.org
Subject svn commit: r169259 [2/5] - in /directory/network/branches/api_integration/src: examples/org/apache/mina/examples/echoserver/ examples/org/apache/mina/examples/httpserver/ examples/org/apache/mina/examples/netcat/ examples/org/apache/mina/examples/reverser/ examples/org/apache/mina/examples/tennis/ java/org/apache/mina/common/ java/org/apache/mina/filter/ java/org/apache/mina/filter/codec/ java/org/apache/mina/handler/ java/org/apache/mina/io/ java/org/apache/mina/io/datagram/ java/org/apache/mina/io/filter/ java/org/apache/mina/io/handler/ java/org/apache/mina/io/socket/ java/org/apache/mina/protocol/ java/org/apache/mina/protocol/codec/ java/org/apache/mina/protocol/filter/ java/org/apache/mina/protocol/handler/ java/org/apache/mina/protocol/io/ java/org/apache/mina/protocol/vmpipe/ java/org/apache/mina/registry/ java/org/apache/mina/transport/ java/org/apache/mina/transport/socket/ java/org/apache/mina/transport/socket/bio/ java/org/apache/mina/transport/socket/nio/ java/org/apache/mina/transport/vmpipe/ java/org/apache/mina/util/ test/org/apache/mina/examples/echoserver/ test/org/apache/mina/io/ test/org/apache/mina/io/datagram/ test/org/apache/mina/io/socket/ test/org/apache/mina/protocol/ test/org/apache/mina/protocol/codec/ test/org/apache/mina/util/
Date Mon, 09 May 2005 09:21:54 GMT
Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoFilterChain.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoFilterChain.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoFilterChain.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoFilterChain.java Mon May  9 02:21:50 2005
@@ -0,0 +1,16 @@
+package org.apache.mina.common;
+
+import java.util.List;
+
+
+public interface IoFilterChain {
+    IoFilter getChild( String name );
+    List getChildren();
+    List getChildrenReversed();
+    void addFirst( String name, IoFilter filter );
+    void addLast( String name, IoFilter filter );
+    void addBefore( String baseName, String name, IoFilter filter );
+    void addAfter( String baseName, String name, IoFilter filter );
+    void remove( String name );
+    void clear();
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoFilterChain.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandler.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandler.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandler.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandler.java Mon May  9 02:21:50 2005
@@ -0,0 +1,82 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+import java.io.IOException;
+
+/**
+ * Handles all protocol events fired by MINA.
+ * There are 6 event handler methods, and they are all invoked by MINA
+ * automatically.
+ * <p>
+ * Please refer to
+ * <a href="../../../../../xref-examples/org/apache/mina/examples/reverser/ReverseIoHandler.html"><code>ReverseIoHandler</code></a>
+ * example.
+ * 
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ * 
+ * @see IoHandlerAdapter
+ */
+public interface IoHandler
+{
+    /**
+     * Invoked when the session is created.  Initialize default socket
+     * parameters and user-defined attributes here.
+     */
+    void sessionCreated( IoSession session ) throws Exception;
+    
+    /**
+     * Invoked when the connection is opened.  This method is not invoked if the
+     * transport type is UDP.
+     */
+    void sessionOpened( IoSession session ) throws Exception;
+
+    /**
+     * Invoked when the connection is closed.  This method is not invoked if the
+     * transport type is UDP.
+     */
+    void sessionClosed( IoSession session ) throws Exception;
+
+    /**
+     * Invoked when the connection is idle.  Refer to {@link IdleStatus}.  This
+     * method is not invoked if the transport type is UDP.
+     */
+    void sessionIdle( IoSession session, IdleStatus status ) throws Exception;
+
+    /**
+     * Invoked when any exception is thrown by user {@link IoHandler}
+     * implementation or by MINA.  If <code>cause</code> is instanceof
+     * {@link IOException}, MINA will close the connection automatically.
+     */
+    void exceptionCaught( IoSession session, Throwable cause ) throws Exception;
+
+    /**
+     * Invoked when protocol message is received.  Implement your protocol flow
+     * here.
+     */
+    void messageReceived( IoSession session, Object message ) throws Exception;
+
+    /**
+     * Invoked when protocol message that user requested by
+     * {@link IoSession#write(Object)} is sent out actually.
+     */
+    void messageSent( IoSession session, Object message ) throws Exception;
+}
\ No newline at end of file

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandler.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandlerAdapter.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandlerAdapter.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandlerAdapter.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandlerAdapter.java Mon May  9 02:21:50 2005
@@ -0,0 +1,61 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+import org.apache.mina.util.SessionUtil;
+
+/**
+ * An abstract adapter class for {@link IoHandler}.  You can extend this
+ * class and selectively override required event handler methods only.  All
+ * methods do nothing by default. 
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public class IoHandlerAdapter implements IoHandler
+{
+    public void sessionCreated( IoSession session ) throws Exception
+    {
+        SessionUtil.initialize( session );
+    }
+
+    public void sessionOpened( IoSession session ) throws Exception
+    {
+    }
+
+    public void sessionClosed( IoSession session ) throws Exception
+    {
+    }
+
+    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
+    {
+    }
+
+    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
+    {
+    }
+
+    public void messageReceived( IoSession session, Object message ) throws Exception
+    {
+    }
+
+    public void messageSent( IoSession session, Object message ) throws Exception
+    {
+    }
+}
\ No newline at end of file

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoHandlerAdapter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSession.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSession.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSession.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSession.java Mon May  9 02:21:50 2005
@@ -0,0 +1,168 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+import java.net.SocketAddress;
+import java.util.Set;
+
+/**
+ * A handle which represents connection between two endpoints regardless of 
+ * transport types.
+ * <p>
+ * Session provides user-defined attributes.  User-defined attributes are
+ * application-specific data which is associated with a session.
+ * It often contains objects that represents the state of a higher-level protocol
+ * and becomes a way to exchange data between filters and handlers.
+ *   
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface IoSession {
+
+    /**
+     * Returns the {@link IoHandler} which handles this session.
+     */
+    IoHandler getHandler();
+
+    /**
+     * Returns the filter chain that only affects this session.
+     */
+    IoFilterChain getFilterChain();
+
+    /**
+     * Writes the specified <code>message</code> to remote peer.  This operation
+     * is asynchronous; {@link IoHandler#messageSent(IoSession, Object)}
+     * will be invoked when the message is actually sent to remote peer.
+     */
+    void write( Object message );
+
+    /**
+     * Closes this session immediately.  Calling method is identical with
+     * calling <tt>close( false )</tt>.
+     */
+    void close();
+
+    /**
+     * Closes this session immediately.
+     * 
+     * @param wait <tt>true</tt> if you want to wait until closing process is
+     *             complete.
+     */
+    void close( boolean wait );
+    
+    /**
+     * Returns an attachment of this session.
+     * This method is identical with <tt>getAttribute( "" )</tt>.
+     */
+    Object getAttachment();
+
+    /**
+     * Sets an attachment of this session.
+     * This method is identical with <tt>setAttribute( "", attachment )</tt>.
+     * 
+     * @return Old attachment.  <tt>null</tt> if it is new.
+     */
+    Object setAttachment( Object attachment );
+    
+    /**
+     * Returns the value of user-defined attribute of this session.
+     * 
+     * @param key the key of the attribute
+     * @return <tt>null</tt> if there is no attribute with the specified key
+     */
+    Object getAttribute( String key );
+    
+    /**
+     * Sets a user-defined attribute.
+     * 
+     * @param key the key of the attribute
+     * @param value the value of the attribute
+     * @return The old value of the attribute.  <tt>null</tt> if it is new.
+     */
+    Object setAttribute( String key, Object value );
+    
+    /**
+     * Removes a user-defined attribute with the specified key.
+     * 
+     * @return The old value of the attribute.  <tt>null</tt> if not found.
+     */
+    Object removeAttribute( String key );
+    
+    /**
+     * Returns the set of keys of all user-defined attributes.
+     */
+    Set getAttributeKeys();
+    
+    /**
+     * Returns transport type of this session.
+     */
+    TransportType getTransportType();
+
+    /**
+     * Returns <code>true</code> if this session is connected with remote peer.
+     */
+    boolean isConnected();
+
+    /**
+     * Returns the configuration of this session.
+     */
+    IoSessionConfig getConfig();
+
+    /**
+     * Returns the socket address of remote peer. 
+     */
+    SocketAddress getRemoteAddress();
+
+    /**
+     * Returns the socket address of local machine which is associated with this
+     * session.
+     */
+    SocketAddress getLocalAddress();
+
+    /**
+     * Returns the total number of bytes which were read from this session.
+     */
+    long getReadBytes();
+
+    /**
+     * Returns the total number of bytes which were written to this session.
+     */
+    long getWrittenBytes();
+
+    /**
+     * Returns the time in millis when I/O occurred lastly.
+     */
+    long getLastIoTime();
+
+    /**
+     * Returns the time in millis when read operation occurred lastly.
+     */
+    long getLastReadTime();
+
+    /**
+     * Returns the time in millis when write operation occurred lastly.
+     */
+    long getLastWriteTime();
+
+    /**
+     * Returns <code>true</code> if this session is idle for the specified 
+     * {@link IdleStatus}.
+     */
+    boolean isIdle( IdleStatus status );
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSession.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionConfig.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionConfig.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionConfig.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionConfig.java Mon May  9 02:21:50 2005
@@ -0,0 +1,82 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+import org.apache.mina.transport.socket.nio.DatagramSessionConfig;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+
+/**
+ * Provides general or {@link TransportType}-specific configuration.
+ * <p>
+ * <ul>
+ *   <li><code>idleTime</code> (secs) - <code>sessionIdle</code> event is
+ *       enabled if this value is greater than 0.
+ *   <li><code>writeTimeout</code> (secs) - {@link WriteTimeoutException} is
+ *       thrown when the write buffer of session is full for the specified
+ *       time.</li>
+ * </ul>
+ * <p>
+ * Please refer to {@link SocketSessionConfig} and {@link DatagramSessionConfig}
+ * for {@link TransportType}-specific configurations.
+ * <p>
+ * {@link IoSessionConfig} can be obtained by {@link IoSession#getConfig()} and
+ * by {@link IoSession#getConfig()}.  To adjust
+ * {@link TransportType}-specific settings, please downcast it:
+ * <pre>
+ * public void sessionOpened( IoSession s )
+ * {
+ *     ( ( SocketSessionConfig ) s.getConfig() ).setReuseAddress( true );
+ * }
+ * </pre>
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface IoSessionConfig
+{
+    /**
+     * Returns idle time for the specified type of idleness in seconds.
+     */
+    int getIdleTime( IdleStatus status );
+
+    /**
+     * Returnd idle time for the specified type of idleness in milliseconds.
+     */
+    long getIdleTimeInMillis( IdleStatus status );
+
+    /**
+     * Sets idle time for the specified type of idleness in seconds.
+     */
+    void setIdleTime( IdleStatus status, int idleTime );
+
+    /**
+     * Returns write timeout in seconds.
+     */
+    int getWriteTimeout();
+
+    /**
+     * Returns write timeout in milliseconds.
+     */
+    long getWriteTimeoutInMillis();
+
+    /**
+     * Sets write timeout in seconds.
+     */
+    void setWriteTimeout( int writeTimeout );
+}
\ No newline at end of file

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionConfig.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionFilterChain.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionFilterChain.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionFilterChain.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionFilterChain.java Mon May  9 02:21:50 2005
@@ -0,0 +1,44 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+/**
+ * An {@link IoFilterChain} that forwards <tt>filterWrite</tt>
+ * requests to the specified {@link IoSessionManagerFilterChain}.
+ * <p>
+ * This filter chain is used by implementations of {@link IoSession}s.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public class IoSessionFilterChain extends AbstractIoFilterChain {
+
+    private final IoSessionManagerFilterChain managerChain;
+
+    public IoSessionFilterChain( IoSessionManagerFilterChain managerChain )
+    {
+        this.managerChain = managerChain;
+    }
+
+    protected void doWrite( IoSession session, Object message )
+    {
+        managerChain.filterWrite( session, message );
+    }
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionFilterChain.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManager.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManager.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManager.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManager.java Mon May  9 02:21:50 2005
@@ -0,0 +1,53 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+/**
+ * Base interface for all acceptors and connectors that manage
+ * sessions.
+ * <p>
+ * You can monitor any uncaught exceptions by setting {@link ExceptionMonitor}
+ * by calling {@link #setExceptionMonitor(ExceptionMonitor)}.  The default
+ * monitor is {@link DefaultExceptionMonitor}.
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface IoSessionManager {
+    
+    /**
+     * Returns the filter chain that filters all events which is related
+     * with sessions this manager manages.
+     */
+    IoFilterChain getFilterChain();
+    
+    /**
+     * Returns the current exception monitor.
+     */
+    ExceptionMonitor getExceptionMonitor();
+
+    /**
+     * Sets the uncaught exception monitor.  If <code>null</code> is specified,
+     * a new instance of {@link DefaultExceptionMonitor} will be set.
+     * 
+     * @param monitor A new instance of {@link DefaultExceptionMonitor} is set
+     *                if <tt>null</tt> is specified.
+     */
+    void setExceptionMonitor( ExceptionMonitor monitor );
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManager.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManagerFilterChain.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManagerFilterChain.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManagerFilterChain.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManagerFilterChain.java Mon May  9 02:21:50 2005
@@ -0,0 +1,91 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+/**
+ * An {@link IoFilterChain} that forwards all events
+ * except <tt>filterWrite</tt> to the {@link IoSessionFilterChain}
+ * of the recipient session.
+ * <p>
+ * This filter chain is used by implementations of {@link IoSessionManager}s.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public abstract class IoSessionManagerFilterChain extends AbstractIoFilterChain {
+
+    private final IoSessionManager manager;
+
+    protected IoSessionManagerFilterChain( IoSessionManager manager )
+    {
+        this.manager = manager;
+    }
+    
+    public IoSessionManager getManager()
+    {
+        return manager;
+    }
+    
+    protected IoFilter createTailFilter()
+    {
+        return new IoFilter()
+        {
+            public void sessionOpened( NextFilter nextFilter, IoSession session )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).sessionOpened( session );
+            }
+
+            public void sessionClosed( NextFilter nextFilter, IoSession session )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).sessionClosed( session );
+            }
+
+            public void sessionIdle( NextFilter nextFilter, IoSession session,
+                                    IdleStatus status )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).sessionIdle( session, status );
+            }
+
+            public void exceptionCaught( NextFilter nextFilter,
+                                        IoSession session, Throwable cause )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).exceptionCaught( session, cause );
+            }
+
+            public void messageReceived( NextFilter nextFilter, IoSession session,
+                                         Object message )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).messageReceived( session, message );
+            }
+
+            public void messageSent( NextFilter nextFilter, IoSession session,
+                                     Object message )
+            {
+                ( ( IoSessionFilterChain ) session.getFilterChain() ).messageSent( session, message );
+            }
+
+            public void filterWrite( NextFilter nextFilter,
+                                     IoSession session, Object message )
+            {
+                nextFilter.filterWrite( session, message );
+            }
+        };
+    }
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/IoSessionManagerFilterChain.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/common/WriteTimeoutException.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/common/WriteTimeoutException.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/common/WriteTimeoutException.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/common/WriteTimeoutException.java Mon May  9 02:21:50 2005
@@ -0,0 +1,49 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.common;
+
+import java.io.IOException;
+
+/**
+ * An {@link IOException} which is thrown when write buffer is not flushed for
+ * {@link SessionConfig#getWriteTimeout()} seconds.
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$, 
+ */
+public class WriteTimeoutException extends IOException
+{
+    private static final long serialVersionUID = 3906931157944579121L;
+
+	/**
+     * Creates a new exception.
+     */
+    public WriteTimeoutException()
+    {
+        super();
+    }
+
+    /**
+     * Creates a new exception.
+     */
+    public WriteTimeoutException( String s )
+    {
+        super( s );
+    }
+}
\ No newline at end of file

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/common/WriteTimeoutException.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/filter/BlacklistFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/filter/BlacklistFilter.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/filter/BlacklistFilter.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/filter/BlacklistFilter.java Mon May  9 02:21:50 2005
@@ -0,0 +1,103 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.filter;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.mina.common.IoFilter;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+/**
+ * A {@link IoFilter} which blocks connections from blacklisted remote
+ * address.
+ * 
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ */
+public class BlacklistFilter extends IoFilterAdapter
+{
+    private final Set blacklist = new HashSet();
+
+    /**
+     * Blocks the specified endpoint.
+     */
+    public synchronized void block( InetAddress address )
+    {
+        blacklist.add( address );
+    }
+
+    /**
+     * Unblocks the specified endpoint.
+     */
+    public synchronized void unblock( InetAddress address )
+    {
+        blacklist.remove( address );
+    }
+
+    /**
+     * Forwards event if and if only the remote address of session is not
+     * blacklisted.
+     */
+    public void messageReceived( NextFilter nextFilter, IoSession session,
+                                 Object message ) throws Exception
+    {
+        if( !isBlocked( session ) )
+        {
+            // forward if not blocked
+            super.messageReceived( nextFilter, session, message );
+        }
+    }
+
+    /**
+     * Close connection immediately if the remote address of session is
+     * blacklisted.
+     */
+    public void sessionOpened( NextFilter nextFilter, IoSession session ) throws Exception
+    {
+        if( isBlocked( session ) )
+        {
+            // Close immediately if blocked
+            session.close();
+        }
+        else
+        {
+            super.sessionOpened( nextFilter, session );
+        }
+    }
+
+    private boolean isBlocked( IoSession session )
+    {
+        SocketAddress remoteAddress = session.getRemoteAddress();
+        if( remoteAddress instanceof InetSocketAddress )
+        {
+            if( blacklist.contains( ( ( InetSocketAddress ) remoteAddress )
+                    .getAddress() ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/filter/BlacklistFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/filter/LoggingFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/filter/LoggingFilter.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/filter/LoggingFilter.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/filter/LoggingFilter.java Mon May  9 02:21:50 2005
@@ -0,0 +1,119 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.filter;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.SessionLog;
+
+/**
+ * Logs all MINA protocol events to {@link Logger}.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @author Trustin Lee (trustin@apache.org)
+ * @version $Rev$, $Date$
+ * 
+ * @see SessionLog
+ */
+public class LoggingFilter implements IoFilter
+{
+    /**
+     * Session attribute key: prefix string
+     */
+    public static final String PREFIX = SessionLog.PREFIX;
+
+    /**
+     * Session attribute key: {@link Logger}
+     */
+    public static final String LOGGER = SessionLog.LOGGER;
+    
+    private Level defaultLevel = Level.INFO;
+    
+    /**
+     * Creates a new instance.
+     */
+    public LoggingFilter()
+    {
+    }
+    
+    
+    /**
+     * Returns the default level of log entry this filter logs. 
+     */
+    public Level getDefaultLevel() {
+        return defaultLevel;
+    }
+    
+    /**
+     * Sets the default level of log entry this filter logs. 
+     */
+    public void setDefaultLevel(Level defaultLevel) {
+        if( defaultLevel == null )
+        {
+            defaultLevel = Level.INFO;
+        }
+        this.defaultLevel = defaultLevel;
+    }
+    
+    public void sessionOpened( NextFilter nextFilter, IoSession session )
+    {
+        SessionLog.log( defaultLevel, session, "OPENED" );
+        nextFilter.sessionOpened( session );
+    }
+
+    public void sessionClosed( NextFilter nextFilter, IoSession session )
+    {
+        SessionLog.log( defaultLevel, session, "CLOSED" );
+        nextFilter.sessionClosed( session );
+    }
+
+    public void sessionIdle( NextFilter nextFilter, IoSession session, IdleStatus status )
+    {
+        SessionLog.log( defaultLevel, session, "IDLE: " + status );
+        nextFilter.sessionIdle( session, status );
+    }
+
+    public void exceptionCaught( NextFilter nextFilter, IoSession session, Throwable cause )
+    {
+        SessionLog.log( defaultLevel, session, "EXCEPTION:", cause );
+        nextFilter.exceptionCaught( session, cause );
+    }
+
+    public void messageReceived( NextFilter nextFilter, IoSession session, Object message )
+    {
+        SessionLog.log( defaultLevel, session, "RECEIVED: " + message );
+        nextFilter.messageReceived( session, message );
+    }
+
+    public void messageSent( NextFilter nextFilter, IoSession session, Object message )
+    {
+        SessionLog.log( defaultLevel, session, "SENT: " + message );
+        nextFilter.messageSent( session, message );
+    }
+
+    public void filterWrite( NextFilter nextFilter, IoSession session, Object message)
+    {
+        SessionLog.log( defaultLevel, session, "WRITE: " + message );
+        nextFilter.filterWrite( session, message );
+    }
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/filter/LoggingFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLByteBufferPool.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLByteBufferPool.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLByteBufferPool.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLByteBufferPool.java Mon May  9 02:21:50 2005
@@ -0,0 +1,194 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.filter;
+
+import java.nio.ByteBuffer;
+
+import javax.net.ssl.SSLEngine;
+
+import org.apache.mina.util.Stack;
+
+/**
+ * Simple ByteBuffer pool used by SSLHandler.
+ * ByteBuffers are by default allocated as direct byte buffers. To use non-direct
+ * ByteBuffers, set system property mina.sslfilter.directbuffer to false.
+ *
+ * @author Jan Andersson (janne@minq.se)
+ * @version $Rev$, $Date$
+ */
+class SSLByteBufferPool
+{
+    private static final int PACKET_BUFFER_INDEX = 0;
+
+    private static final int APPLICATION_BUFFER_INDEX = 1;
+
+    private static boolean initiated = false;
+
+    private static final String DIRECT_MEMORY_PROP = "mina.sslfilter.directbuffer";
+
+    private static boolean useDirectAllocatedBuffers = true;
+
+    private static int packetBufferSize;
+
+    private static int appBufferSize;
+
+    private static int[] bufferStackSizes;
+
+    private static final Stack[] bufferStacks = new Stack[] { new Stack(),
+                                                             new Stack(), };
+
+    /**
+     * Initiate buffer pool and buffer sizes from SSLEngine session.
+     *
+     * @param sslEngine SSLEngine
+     */
+    static synchronized void initiate( SSLEngine sslEngine )
+    {
+        if( !initiated )
+        {
+            // Use direct allocated memory or not?
+            String prop = System.getProperty( DIRECT_MEMORY_PROP );
+            if( prop != null )
+            {
+                useDirectAllocatedBuffers = Boolean
+                        .getBoolean( DIRECT_MEMORY_PROP );
+            }
+            
+            // init buffer sizes from SSLEngine
+            packetBufferSize = sslEngine.getSession().getPacketBufferSize();
+
+            // application buffer size has been doubled because SSLEngine
+            // returns BUFFER_OVERFLOW even if there is enough room for the buffer.
+            // So for now we use a size double the packet size as a workaround.
+            appBufferSize = packetBufferSize * 2;
+            initiateBufferStacks();
+            initiated = true;
+        }
+    }
+
+    /**
+     * Get bytebuffer with size the size of the largest SSL/TLS packet that may occur
+     * (as defined by SSLSession).
+     */
+    static ByteBuffer getPacketBuffer()
+    {
+        if( !initiated )
+        {
+            throw new IllegalStateException( "Not initialized" );
+        }
+        return allocate( PACKET_BUFFER_INDEX );
+    }
+
+    /**
+     * Get ByteBuffer with the size of the largest application buffer that may occur
+     * (as defined by SSLSession).
+     */
+    static ByteBuffer getApplicationBuffer()
+    {
+        if( !initiated )
+        {
+            throw new IllegalStateException( "Not initialized" );
+        }
+        return allocate( APPLICATION_BUFFER_INDEX );
+    }
+
+    /**
+     * Allocate or get the buffer which is capable of the specified size.
+     */
+    private static ByteBuffer allocate( int idx )
+    {
+        Stack stack = bufferStacks[ idx ];
+
+        ByteBuffer buf;
+        synchronized( stack )
+        {
+            buf = ( ByteBuffer ) stack.pop();
+            if( buf == null )
+            {
+                buf = createBuffer( bufferStackSizes[ idx ] );
+            }
+        }
+
+        buf.clear();
+        return buf;
+    }
+
+    /**
+     * Releases the specified buffer to buffer pool.
+     */
+    public static void release( ByteBuffer buf )
+    {
+        int stackIndex =getBufferStackIndex( buf.capacity() );
+        if ( stackIndex >= PACKET_BUFFER_INDEX ) {
+            Stack stack = bufferStacks[getBufferStackIndex( buf.capacity() )];
+            synchronized ( stack ) {
+                stack.push( buf );
+            }
+        }
+    }
+
+    /**
+     * Expand size of provided buffer
+     * @param buf buffer to be expande
+     * @param newCapacity new capacity
+     */
+    public static ByteBuffer expandBuffer( ByteBuffer buf, int newCapacity )
+    {
+        ByteBuffer newBuf = createBuffer( newCapacity );
+        buf.flip();
+        newBuf.put( buf );
+        release(buf);
+        return newBuf;
+    }
+
+    private static void initiateBufferStacks()
+    {
+        bufferStackSizes = new int[ 2 ];
+        bufferStackSizes[ PACKET_BUFFER_INDEX ] = packetBufferSize;
+        bufferStackSizes[ APPLICATION_BUFFER_INDEX ] = appBufferSize;
+    }
+
+    private static int getBufferStackIndex( int size )
+    {
+        if( size == packetBufferSize )
+            return PACKET_BUFFER_INDEX;
+        if( size == appBufferSize )
+            return APPLICATION_BUFFER_INDEX;
+        return -1;  // not reused
+    }
+
+    private static ByteBuffer createBuffer( int capacity )
+    {
+        if( useDirectAllocatedBuffers )
+        {
+            try
+            {
+                return ByteBuffer.allocateDirect( capacity );
+            }
+            catch( OutOfMemoryError e )
+            {
+                useDirectAllocatedBuffers = false;
+                System.err
+                        .println( "OutOfMemoryError: No more direct buffers available; trying heap buffer instead" );
+            }
+        }
+        return ByteBuffer.allocate( capacity );
+    }
+
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLByteBufferPool.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLFilter.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLFilter.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLFilter.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLFilter.java Mon May  9 02:21:50 2005
@@ -0,0 +1,520 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.filter;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoSession;
+
+/**
+ * An SSL filter that encrypts and decrypts the data exchanged in the session.
+ * This filter uses an {@link SSLEngine} which was introduced in Java 5, so 
+ * Java version 5 or above is mandatory to use this filter. And please note that
+ * this filter only works for TCP/IP connections.
+ * <p>
+ * This filter logs debug information in {@link Level#FINEST} using {@link Logger}.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class SSLFilter extends IoFilterAdapter
+{
+    private static final Logger log = Logger.getLogger( SSLFilter.class.getName() );
+    /**
+     * A marker which is passed with {@link IoHandler#messageSent(IoSession, Object)}
+     * when <tt>SSLFilter</tt> writes data other then user actually requested.
+     */
+    public static final Object SSL_MARKER = new Object()
+    {
+        public String toString()
+        {
+            return "SSL_MARKER";
+        }
+    };
+    
+    // SSL Context
+    private SSLContext sslContext;
+
+    // Map used to map SSLHandler objects per session (key is IoSession)
+    private Map sslSessionHandlerMap = new IdentityHashMap();
+
+    private boolean client;
+    private boolean needClientAuth;
+    private boolean wantClientAuth;
+    private String[] enabledCipherSuites;
+    private String[] enabledProtocols;
+
+    /**
+     * Creates a new SSL filter using the specified {@link SSLContext}.
+     */
+    public SSLFilter( SSLContext sslContext )
+    {
+        if( sslContext == null )
+        {
+            throw new NullPointerException( "sslContext" );
+        }
+
+        this.sslContext = sslContext;
+    }
+
+    /**
+     * Returns <tt>true</tt> if the engine is set to use client mode
+     * when handshaking.
+     */
+    public boolean isUseClientMode()
+    {
+        return client;
+    }
+    
+    /**
+     * Configures the engine to use client (or server) mode when handshaking.
+     */
+    public void setUseClientMode( boolean clientMode )
+    {
+        this.client = clientMode;
+    }
+    
+    /**
+     * Returns <tt>true</tt> if the engine will <em>require</em> client authentication.
+     * This option is only useful to engines in the server mode.
+     */
+    public boolean isNeedClientAuth()
+    {
+        return needClientAuth;
+    }
+
+    /**
+     * Configures the engine to <em>require</em> client authentication.
+     * This option is only useful for engines in the server mode.
+     */
+    public void setNeedClientAuth( boolean needClientAuth )
+    {
+        this.needClientAuth = needClientAuth;
+    }
+    
+    
+    /**
+     * Returns <tt>true</tt> if the engine will <em>request</em> client authentication.
+     * This option is only useful to engines in the server mode.
+     */
+    public boolean isWantClientAuth()
+    {
+        return wantClientAuth;
+    }
+    
+    /**
+     * Configures the engine to <em>request</em> client authentication.
+     * This option is only useful for engines in the server mode.
+     */
+    public void setWantClientAuth( boolean wantClientAuth )
+    {
+        this.wantClientAuth = wantClientAuth;
+    }
+    
+    /**
+     * Returns the list of cipher suites to be enabled when {@link SSLEngine}
+     * is initialized.
+     * 
+     * @return <tt>null</tt> means 'use {@link SSLEngine}'s default.'
+     */
+    public String[] getEnabledCipherSuites()
+    {
+        return enabledCipherSuites;
+    }
+    
+    /**
+     * Sets the list of cipher suites to be enabled when {@link SSLEngine}
+     * is initialized.
+     * 
+     * @param cipherSuites <tt>null</tt> means 'use {@link SSLEngine}'s default.'
+     */
+    public void setEnabledCipherSuites( String[] cipherSuites )
+    {
+        this.enabledCipherSuites = cipherSuites;
+    }
+
+    /**
+     * Returns the list of protocols to be enabled when {@link SSLEngine}
+     * is initialized.
+     * 
+     * @return <tt>null</tt> means 'use {@link SSLEngine}'s default.'
+     */
+    public String[] getEnabledProtocols()
+    {
+        return enabledProtocols;
+    }
+    
+    /**
+     * Sets the list of protocols to be enabled when {@link SSLEngine}
+     * is initialized.
+     * 
+     * @param protocols <tt>null</tt> means 'use {@link SSLEngine}'s default.'
+     */
+    public void setEnabledProtocols( String[] protocols )
+    {
+        this.enabledProtocols = protocols;
+    }
+
+    // IoFilter impl.
+
+    public void sessionOpened( NextFilter nextFilter, IoSession session ) throws SSLException
+    {
+        // Create an SSL handler
+        createSSLSessionHandler( session );
+        nextFilter.sessionOpened( session );
+    }
+
+    public void sessionClosed( NextFilter nextFilter, IoSession session )
+    {
+        SSLHandler sslHandler = getSSLSessionHandler( session );
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " Closed: " + sslHandler );
+        }
+        if( sslHandler != null )
+        {
+            synchronized( sslHandler )
+            {
+               // Start SSL shutdown process
+               try
+               {
+                  // shut down
+                  sslHandler.shutdown();
+                  
+                  // there might be data to write out here?
+                  writeNetBuffer( session, sslHandler );
+               }
+               catch( SSLException ssle )
+               {
+                  nextFilter.exceptionCaught( session, ssle );
+               }
+               finally
+               {
+                  // notify closed session
+                  nextFilter.sessionClosed( session );
+                  
+                  // release buffers
+                  sslHandler.release();
+                  removeSSLSessionHandler( session );
+               }
+            }
+        }
+    }
+   
+    public void messageReceived( NextFilter nextFilter, IoSession session,
+                                 Object message )
+    {
+        ByteBuffer buf = ( ByteBuffer ) message;
+        SSLHandler sslHandler = getSSLSessionHandler( session );
+        if( sslHandler != null )
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " Data Read: " + sslHandler + " (" + buf+ ')' );
+            }
+            synchronized( sslHandler )
+            {
+                try
+                {
+                    // forward read encrypted data to SSL handler
+                    sslHandler.messageReceived( buf.buf() );
+
+                    // Handle data to be forwarded to application or written to net
+                    handleSSLData( nextFilter, session, sslHandler );
+
+                    if( sslHandler.isClosed() )
+                    {
+                        if( log.isLoggable( Level.FINEST ) )
+                        {
+                            log.log( Level.FINEST,
+                                     session + " SSL Session closed. Closing connection.." );
+                        }
+                        session.close();
+                    }
+                }
+                catch( SSLException ssle )
+                {
+                    if( !sslHandler.isInitialHandshakeComplete() )
+                    {
+                        SSLException newSSLE = new SSLHandshakeException(
+                                "Initial SSL handshake failed." );
+                        newSSLE.initCause( ssle );
+                        ssle = newSSLE;
+                    }
+
+                    nextFilter.exceptionCaught( session, ssle );
+                }
+            }
+        }
+        else
+        {
+            nextFilter.messageReceived( session, buf );
+        }
+    }
+
+    public void messageSent( NextFilter nextFilter, IoSession session,
+                             Object message )
+    {
+        nextFilter.messageSent( session, message );
+    }
+
+    public void filterWrite( NextFilter nextFilter, IoSession session, Object message ) throws SSLException
+    {
+        ByteBuffer buf = ( ByteBuffer ) message;
+
+        SSLHandler handler = createSSLSessionHandler( session );
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " Filtered Write: " + handler );
+        }
+
+        synchronized( handler )
+        {
+            if( handler.isWritingEncryptedData() )
+            {
+                // data already encrypted; simply return buffer
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + "   already encrypted: " + buf );
+                }
+                nextFilter.filterWrite( session, buf );
+                return;
+            }
+            
+            if( handler.isInitialHandshakeComplete() )
+            {
+                // SSL encrypt
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + " encrypt: " + buf );
+                }
+                handler.encrypt( buf.buf() );
+                ByteBuffer encryptedBuffer = copy( handler
+                        .getOutNetBuffer() );
+
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + " encrypted buf: " + encryptedBuffer);
+                }
+                buf.release();
+                nextFilter.filterWrite( session, encryptedBuffer );
+                return;
+            }
+            else
+            {
+                if( !session.isConnected() )
+                {
+                    if( log.isLoggable( Level.FINEST ) )
+                    {
+                        log.log( Level.FINEST, session + " Write request on closed session." );
+                    }
+                }
+                else
+                {
+                    if( log.isLoggable( Level.FINEST ) )
+                    {
+                        log.log( Level.FINEST, session + " Handshaking is not complete yet. Buffering write request." );
+                    }
+                    handler.scheduleWrite( nextFilter, buf );
+                }
+            }
+        }
+    }
+
+    // Utiliities
+
+    private void handleSSLData( NextFilter nextFilter, IoSession session,
+                               SSLHandler handler ) throws SSLException
+    {
+        // Flush any buffered write requests occurred before handshaking.
+        if( handler.isInitialHandshakeComplete() )
+        {
+            handler.flushScheduledWrites();
+        }
+
+        // Write encrypted data to be written (if any)
+        writeNetBuffer( session, handler );
+
+        // handle app. data read (if any)
+        handleAppDataRead( nextFilter, session, handler );
+    }
+
+    private void handleAppDataRead( NextFilter nextFilter, IoSession session,
+                                   SSLHandler sslHandler )
+    {
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " appBuffer: " + sslHandler.getAppBuffer() );
+        }
+        if( sslHandler.getAppBuffer().hasRemaining() )
+        {
+            // forward read app data
+            ByteBuffer readBuffer = copy( sslHandler.getAppBuffer() );
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " app data read: " + readBuffer + " (" + readBuffer.getHexDump() + ')' );
+            }
+            nextFilter.messageReceived( session, readBuffer );
+        }
+    }
+
+    void writeNetBuffer( IoSession session, SSLHandler sslHandler )
+            throws SSLException
+    {
+        // Check if any net data needed to be writen
+        if( !sslHandler.getOutNetBuffer().hasRemaining() )
+        {
+            // no; bail out
+            return;
+        }
+
+        // write net data
+
+        // set flag that we are writing encrypted data
+        // (used in filterWrite() above)
+        synchronized( sslHandler )
+        {
+            sslHandler.setWritingEncryptedData( true );
+        }
+
+        try
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " write outNetBuffer: " +
+                                   sslHandler.getOutNetBuffer() );
+            }
+            ByteBuffer writeBuffer = copy( sslHandler.getOutNetBuffer() );
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " session write: " + writeBuffer );
+            }
+            //debug("outNetBuffer (after copy): {0}", sslHandler.getOutNetBuffer());
+            session.write( writeBuffer );
+
+            // loop while more writes required to complete handshake
+            while( sslHandler.needToCompleteInitialHandshake() )
+            {
+                try
+                {
+                    sslHandler.continueHandshake();
+                }
+                catch( SSLException ssle )
+                {
+                    SSLException newSSLE = new SSLHandshakeException(
+                            "Initial SSL handshake failed." );
+                    newSSLE.initCause( ssle );
+                    throw newSSLE;
+                }
+                if( sslHandler.getOutNetBuffer().hasRemaining() )
+                {
+                    if( log.isLoggable( Level.FINEST ) )
+                    {
+                        log.log( Level.FINEST, session + " write outNetBuffer2: " +
+                                           sslHandler.getOutNetBuffer() );
+                    }
+                    ByteBuffer writeBuffer2 = copy( sslHandler
+                            .getOutNetBuffer() );
+                    session.write( writeBuffer2 );
+                }
+            }
+        }
+        finally
+        {
+            synchronized( sslHandler )
+            {
+                sslHandler.setWritingEncryptedData( false );
+            }
+        }
+    }
+
+    /**
+     * Creates a new Mina byte buffer that is a deep copy of the remaining bytes
+     * in the given buffer (between index buf.position() and buf.limit())
+     *
+     * @param src the buffer to copy
+     * @return the new buffer, ready to read from
+     */
+    private static ByteBuffer copy( java.nio.ByteBuffer src )
+    {
+        ByteBuffer copy = ByteBuffer.allocate( src.remaining() );
+        copy.put( src );
+        copy.flip();
+        return copy;
+    }
+
+    // Utilities to mainpulate SSLHandler based on IoSession
+
+    private SSLHandler createSSLSessionHandler( IoSession session ) throws SSLException
+    {
+        SSLHandler handler = ( SSLHandler ) sslSessionHandlerMap.get( session );
+        if( handler == null )
+        {
+            synchronized( sslSessionHandlerMap )
+            {
+                handler = ( SSLHandler ) sslSessionHandlerMap.get( session );
+                if( handler == null )
+                {
+                    boolean done = false;
+                    try
+                    {
+                        handler =
+                            new SSLHandler( this, sslContext, session );
+                        sslSessionHandlerMap.put( session, handler );
+                        handler.doHandshake();
+                        done = true;
+                    }
+                    finally 
+                    {
+                        if( !done )
+                        {
+                            sslSessionHandlerMap.remove( session );
+                        }
+                    }
+                }
+            }
+        }
+        
+        return handler;
+    }
+
+    private SSLHandler getSSLSessionHandler( IoSession session )
+    {
+        return ( SSLHandler ) sslSessionHandlerMap.get( session );
+    }
+
+    private void removeSSLSessionHandler( IoSession session )
+    {
+        synchronized( sslSessionHandlerMap )
+        {
+            sslSessionHandlerMap.remove( session );
+        }
+    }
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLHandler.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLHandler.java?rev=169259&view=auto
==============================================================================
--- directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLHandler.java (added)
+++ directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLHandler.java Mon May  9 02:21:50 2005
@@ -0,0 +1,664 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.filter;
+
+import java.nio.ByteBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoFilter.NextFilter;
+import org.apache.mina.util.Queue;
+
+/**
+ * A helper class using the SSLEngine API to decrypt/encrypt data.
+ * <p>
+ * Each connection has a SSLEngine that is used through the lifetime of the connection.
+ * We allocate byte buffers for use as the outbound and inbound network buffers.
+ * These buffers handle all of the intermediary data for the SSL connection. To make things easy,
+ * we'll require outNetBuffer be completely flushed before trying to wrap any more data.
+ *
+ * @author Jan Andersson (janne@minq.se)
+ * @version $Rev$, $Date$
+ */
+class SSLHandler
+{
+    private static final Logger log = Logger.getLogger( SSLFilter.class.getName() );
+
+    private final SSLFilter parent;
+
+    private final IoSession session;
+    
+    private final Queue nextFilterQueue = new Queue();
+    
+    private final Queue writeBufferQueue = new Queue();
+
+    private SSLEngine sslEngine;
+
+    /**
+     * Encrypted data from the net
+     */
+    private ByteBuffer inNetBuffer;
+
+    /**
+     * Encrypted data to be written to the net
+     */
+    private ByteBuffer outNetBuffer;
+
+    /**
+     * Applicaton cleartext data to be read by application
+     */
+    private ByteBuffer appBuffer;
+
+    /**
+     * Empty buffer used during initial handshake and close operations
+     */
+    private ByteBuffer hsBB = ByteBuffer.allocate( 0 );
+
+    /**
+     * Handshake status
+     */
+    private SSLEngineResult.HandshakeStatus initialHandshakeStatus;
+
+    /**
+     * Initial handshake complete?
+     */
+    private boolean initialHandshakeComplete;
+
+    /**
+     * We have received the shutdown request by our caller, and have
+     * closed our outbound side.
+     */
+    private boolean shutdown = false;
+
+    private boolean closed = false;
+
+    private boolean isWritingEncryptedData = false;
+    
+    /**
+     * Constuctor.
+     *
+     * @param sslc
+     * @throws SSLException 
+     */
+    SSLHandler( SSLFilter parent, SSLContext sslc, IoSession session ) throws SSLException
+    {
+        this.parent = parent;
+        this.session = session;
+        sslEngine = sslc.createSSLEngine();
+        sslEngine.setUseClientMode( parent.isUseClientMode() );
+        sslEngine.setNeedClientAuth( parent.isNeedClientAuth() );
+        sslEngine.setWantClientAuth( parent.isWantClientAuth() );
+  
+        if( parent.getEnabledCipherSuites() != null )
+        {
+            sslEngine.setEnabledCipherSuites( parent.getEnabledCipherSuites() );
+        }
+        
+        if( parent.getEnabledProtocols() != null )
+        {
+            sslEngine.setEnabledProtocols( parent.getEnabledProtocols() );
+        }
+
+        sslEngine.beginHandshake();   
+        initialHandshakeStatus = sslEngine.getHandshakeStatus();//SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
+        initialHandshakeComplete = false;
+        //SSLSession sslSession = sslEngine.getSession
+        
+        SSLByteBufferPool.initiate( sslEngine );
+
+        appBuffer = SSLByteBufferPool.getApplicationBuffer();
+
+        inNetBuffer = SSLByteBufferPool.getPacketBuffer();
+        outNetBuffer = SSLByteBufferPool.getPacketBuffer();
+        outNetBuffer.position( 0 );
+        outNetBuffer.limit( 0 );
+    }
+
+    /**
+     * Indicate that we are writing encrypted data.
+     * Only used as a flag by IoSSLFiler
+     */
+    public void setWritingEncryptedData( boolean flag )
+    {
+        isWritingEncryptedData = flag;
+    }
+
+    /**
+     * Check we are writing encrypted data.
+     */
+    public boolean isWritingEncryptedData()
+    {
+        return isWritingEncryptedData;
+    }
+
+    /**
+     * Check if initial handshake is completed.
+     */
+    public boolean isInitialHandshakeComplete()
+    {
+        return initialHandshakeComplete;
+    }
+
+    /**
+     * Check if SSL sesssion closed
+     */
+    public boolean isClosed()
+    {
+        return closed;
+    }
+
+    /**
+     * Check if there is any need to complete initial handshake.
+     */
+    public boolean needToCompleteInitialHandshake()
+    {
+        return ( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !closed );
+    }
+    
+    public synchronized void scheduleWrite( NextFilter nextFilter, org.apache.mina.common.ByteBuffer buf )
+    {
+        nextFilterQueue.push( nextFilter );
+        writeBufferQueue.push( buf );
+    }
+    
+    public synchronized void flushScheduledWrites() throws SSLException
+    {
+        NextFilter nextFilter;
+        org.apache.mina.common.ByteBuffer scheduledBuf;
+        Object scheduledMarker;
+        
+        while( ( scheduledBuf = ( org.apache.mina.common.ByteBuffer ) writeBufferQueue.pop() ) != null )
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " Flushing buffered write request: " + scheduledBuf );
+            }
+            nextFilter = ( NextFilter ) nextFilterQueue.pop();
+            parent.filterWrite( nextFilter, session, scheduledBuf );
+        }
+    }
+
+    /**
+     * Call when data read from net. Will perform inial hanshake or decrypt provided
+     * Buffer.
+     * Decrytpted data reurned by getAppBuffer(), if any.
+     *
+     * @param buf buffer to decrypt
+     * @throws SSLException on errors
+     */
+    public void messageReceived( ByteBuffer buf ) throws SSLException
+    {
+        if ( buf.limit() > inNetBuffer.remaining() ) {
+            // We have to expand inNetBuffer
+            inNetBuffer = SSLByteBufferPool.expandBuffer( inNetBuffer,
+                inNetBuffer.capacity() + ( buf.limit() * 2 ) );
+            // We also expand app. buffer (twice the size of in net. buffer)
+            appBuffer = SSLByteBufferPool.expandBuffer( appBuffer, inNetBuffer.capacity() * 2);
+            appBuffer.position( 0 );
+            appBuffer.limit( 0 );
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + 
+                                    " expanded inNetBuffer:" + inNetBuffer );
+                log.log( Level.FINEST, session + 
+                                    " expanded appBuffer:" + appBuffer );
+            }
+        }
+
+        // append buf to inNetBuffer
+        inNetBuffer.put( buf );
+        if( !initialHandshakeComplete )
+        {
+            doHandshake();
+        }
+        else
+        {
+            doDecrypt();
+        }
+    }
+
+    /**
+     * Continue initial SSL handshake.
+     *
+     * @throws SSLException on errors
+     */
+    public void continueHandshake() throws SSLException
+    {
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " continueHandshake()" );
+        }
+        doHandshake();
+    }
+
+    /**
+     * Get decrypted application data.
+     *
+     * @return buffer with data
+     */
+    public ByteBuffer getAppBuffer()
+    {
+        return appBuffer;
+    }
+
+    /**
+     * Get encrypted data to be sent.
+     *
+     * @return buffer with data
+     */
+    public ByteBuffer getOutNetBuffer()
+    {
+        return outNetBuffer;
+    }
+
+    /**
+     * Encrypt provided buffer. Encytpted data reurned by getOutNetBuffer().
+     *
+     * @param buf data to encrypt
+     * @throws SSLException on errors
+     */
+    public void encrypt( ByteBuffer buf ) throws SSLException
+    {
+        doEncrypt( buf );
+    }
+
+    /**
+     * Start SSL shutdown process
+     *
+     * @throws SSLException on errors
+     */
+    public void shutdown() throws SSLException
+    {
+        if( !shutdown )
+        {
+            doShutdown();
+        }
+    }
+
+    /**
+     * Release allocated ByteBuffers.
+     */
+    public void release()
+    {
+        SSLByteBufferPool.release( appBuffer );
+        SSLByteBufferPool.release( inNetBuffer );
+        SSLByteBufferPool.release( outNetBuffer );
+    }
+
+    /**
+     * Decrypt in net buffer. Result is stored in app buffer.
+     *
+     * @throws SSLException
+     */
+    private void doDecrypt() throws SSLException
+    {
+
+        if( !initialHandshakeComplete )
+        {
+            throw new IllegalStateException();
+        }
+
+        if( appBuffer.hasRemaining() )
+        {
+             if ( log.isLoggable( Level.FINEST ) ) {
+                 log.log( Level.FINEST, session + " Error: appBuffer not empty!" );
+             }
+            //still app data in buffer!?
+            throw new IllegalStateException();
+        }
+
+        unwrap();
+    }
+
+    /**
+     * @param status
+     * @throws SSLException
+     */
+    private SSLEngineResult.Status checkStatus( SSLEngineResult.Status status ) throws SSLException
+    {
+        if( status != SSLEngineResult.Status.OK &&
+            status != SSLEngineResult.Status.CLOSED &&
+            status != SSLEngineResult.Status.BUFFER_UNDERFLOW )
+        {
+            throw new SSLException( "SSLEngine error during decrypt: " +
+                                    status +
+                                    " inNetBuffer: " + inNetBuffer + "appBuffer: " + appBuffer);
+        }
+        
+        return status;
+    }
+    
+    private void doEncrypt( ByteBuffer src ) throws SSLException
+    {
+        if( !initialHandshakeComplete )
+        {
+            throw new IllegalStateException();
+        }
+
+        // The data buffer is (must be) empty, we can reuse the entire
+        // buffer.
+        outNetBuffer.clear();
+
+        SSLEngineResult result;
+
+        // Loop until there is no more data in src
+        while ( src.hasRemaining() ) {
+
+            if ( src.remaining() > ( ( outNetBuffer.capacity() - outNetBuffer.position() ) / 2 ) ) {
+                // We have to expand outNetBuffer
+                // Note: there is no way to know the exact size required, but enrypted data
+                // shouln't need to be larger than twice the source data size?
+                outNetBuffer = SSLByteBufferPool.expandBuffer( outNetBuffer, src.capacity() * 2 );
+                if ( log.isLoggable( Level.FINEST ) ) {
+                    log.log( Level.FINEST, session + " expanded outNetBuffer:" + outNetBuffer );
+                }
+            }
+
+            result = sslEngine.wrap( src, outNetBuffer );
+            if ( log.isLoggable( Level.FINEST ) ) {
+                log.log( Level.FINEST, session + " Wrap res:" + result );
+            }
+
+            if ( result.getStatus() == SSLEngineResult.Status.OK ) {
+                if ( result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK ) {
+                    doTasks();
+                }
+            } else {
+                throw new SSLException( "SSLEngine error during encrypt: "
+                        + result.getStatus() +
+                        " src: " + src + "outNetBuffer: " + outNetBuffer);
+            }
+        }
+
+        outNetBuffer.flip();
+    }
+
+    /**
+     * Perform any handshaking processing.
+     */
+    synchronized void doHandshake() throws SSLException
+    {
+
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " doHandshake()" );
+        }
+
+        while( !initialHandshakeComplete )
+        {
+            if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED )
+            {
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    SSLSession sslSession = sslEngine.getSession();
+                    log.log( Level.FINEST, session + "  initialHandshakeStatus=FINISHED" );
+                    log.log( Level.FINEST, session + "  sslSession CipherSuite used " + sslSession.getCipherSuite());
+                }
+                initialHandshakeComplete = true;
+                return;
+            }
+            else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_TASK )
+            {
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + "  initialHandshakeStatus=NEED_TASK" );
+                }
+                initialHandshakeStatus = doTasks();
+            }
+            else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP )
+            {
+                // we need more data read
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session +
+                             "  initialHandshakeStatus=NEED_UNWRAP" );
+                }
+                SSLEngineResult.Status status = unwrapHandshake();
+                if( ( initialHandshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED 
+                		&&  status == SSLEngineResult.Status.BUFFER_UNDERFLOW )
+                        || closed )
+                {
+                    // We need more data or the session is closed
+                    return;
+                }
+            }
+            else if( initialHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP )
+            {
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + "  initialHandshakeStatus=NEED_WRAP" );
+                }
+                // First make sure that the out buffer is completely empty. Since we
+                // cannot call wrap with data left on the buffer
+                if( outNetBuffer.hasRemaining() )
+                {
+                    if( log.isLoggable( Level.FINEST ) )
+                    {
+                        log.log( Level.FINEST, session + "  Still data in out buffer!" );
+                    }
+                    return;
+                }
+                outNetBuffer.clear();
+                SSLEngineResult result = sslEngine.wrap( hsBB, outNetBuffer );
+                if( log.isLoggable( Level.FINEST ) )
+                {
+                    log.log( Level.FINEST, session + " Wrap res:" + result );
+                }
+
+                outNetBuffer.flip();
+                initialHandshakeStatus = result.getHandshakeStatus();
+                parent.writeNetBuffer( session, this );
+                // return to allow data on out buffer being sent
+                // TODO: We might want to send more data immidiatley?
+            }
+            else
+            {
+                throw new IllegalStateException( "Invalid Handshaking State"
+                        + initialHandshakeStatus );
+            }
+        }
+    }
+
+    SSLEngineResult.Status unwrap() throws SSLException
+    {
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " unwrap()" );
+        }
+        // Prepare the application buffer to receive decrypted data
+        appBuffer.clear();
+
+        // Prepare the net data for reading.
+        inNetBuffer.flip();
+
+        SSLEngineResult res;
+        do
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + "   inNetBuffer: " + inNetBuffer );
+                log.log( Level.FINEST, session + "   appBuffer: " + appBuffer );
+            }
+            res = sslEngine.unwrap( inNetBuffer, appBuffer );
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " Unwrap res:" + res );
+            }
+        }
+        while( res.getStatus() == SSLEngineResult.Status.OK );
+
+        // If we are CLOSED, set flag
+        if( res.getStatus() == SSLEngineResult.Status.CLOSED )
+        {
+            closed = true;
+        }
+
+        // prepare to be written again
+        inNetBuffer.compact();
+        // prepare app data to be read
+        appBuffer.flip();
+
+        /*
+         * The status may be:
+         * OK - Normal operation
+         * OVERFLOW - Should never happen since the application buffer is
+         *      sized to hold the maximum packet size.
+         * UNDERFLOW - Need to read more data from the socket. It's normal.
+         * CLOSED - The other peer closed the socket. Also normal.
+         */
+        return checkStatus( res.getStatus() );
+    }
+
+    private SSLEngineResult.Status unwrapHandshake() throws SSLException
+    {
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + " unwrapHandshake()" );
+        }
+        // Prepare the application buffer to receive decrypted data
+        appBuffer.clear();
+
+        // Prepare the net data for reading.
+        inNetBuffer.flip();
+
+        SSLEngineResult res;
+        do
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + "   inNetBuffer: " + inNetBuffer );
+                log.log( Level.FINEST, session + "   appBuffer: " + appBuffer );
+            }
+            res = sslEngine.unwrap( inNetBuffer, appBuffer );
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + " Unwrap res:" + res );
+            }
+
+        }
+        while( res.getStatus() == SSLEngineResult.Status.OK &&
+               res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP );
+
+        initialHandshakeStatus = res.getHandshakeStatus();
+	
+	// If handshake finished, no data was produced, and the status is still ok,
+		// try to unwrap more
+		if (initialHandshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED
+				&& appBuffer.position() == 0
+				&& res.getStatus() == SSLEngineResult.Status.OK
+				&& inNetBuffer.hasRemaining()) {
+			do {
+				if (log.isLoggable( Level.FINEST )) {
+					log.log( Level.FINEST, session + "  extra handshake unwrap" );
+                    log.log( Level.FINEST, session + "   inNetBuffer: " + inNetBuffer );
+                    log.log( Level.FINEST, session + "   appBuffer: " + appBuffer );
+				}
+				res = sslEngine.unwrap(inNetBuffer, appBuffer);
+				if (log.isLoggable( Level.FINEST )) {
+                    log.log( Level.FINEST, session + " Unwrap res:" + res );
+				}
+			} while (res.getStatus() == SSLEngineResult.Status.OK);
+		}
+
+        // If we are CLOSED, set flag
+        if( res.getStatus() == SSLEngineResult.Status.CLOSED )
+        {
+            closed = true;
+        }
+        
+        // prepare to be written again
+        inNetBuffer.compact();
+
+        // prepare app data to be read
+        appBuffer.flip();
+
+        /*
+         * The status may be:
+         * OK - Normal operation
+         * OVERFLOW - Should never happen since the application buffer is
+         *      sized to hold the maximum packet size.
+         * UNDERFLOW - Need to read more data from the socket. It's normal.
+         * CLOSED - The other peer closed the socket. Also normal.
+         */
+        //initialHandshakeStatus = res.getHandshakeStatus();
+        return checkStatus( res.getStatus() );
+    }
+
+    /**
+     * Do all the outstanding handshake tasks in the current Thread.
+     */
+    private SSLEngineResult.HandshakeStatus doTasks()
+    {
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + "   doTasks()" );
+        }
+
+        /*
+         * We could run this in a separate thread, but I don't see the need
+         * for this when used from IoSSLFilter.Use thread filters in Mina instead?
+         */
+        Runnable runnable;
+        while( ( runnable = sslEngine.getDelegatedTask() ) != null )
+        {
+            if( log.isLoggable( Level.FINEST ) )
+            {
+                log.log( Level.FINEST, session + "    doTask: " + runnable );
+            }
+            runnable.run();
+        }
+        if( log.isLoggable( Level.FINEST ) )
+        {
+            log.log( Level.FINEST, session + "   doTasks(): "
+                    + sslEngine.getHandshakeStatus() );
+        }
+        return sslEngine.getHandshakeStatus();
+    }
+
+    /**
+     * Begin the shutdown process.
+     */
+    void doShutdown() throws SSLException
+    {
+
+        if( !shutdown )
+        {
+            sslEngine.closeOutbound();
+            shutdown = true;
+        }
+
+        // By RFC 2616, we can "fire and forget" our close_notify
+        // message, so that's what we'll do here.
+
+        outNetBuffer.clear();
+        SSLEngineResult result = sslEngine.wrap( hsBB, outNetBuffer );
+        if( result.getStatus() != SSLEngineResult.Status.CLOSED )
+        {
+            throw new SSLException( "Improper close state: " + result );
+        }
+        outNetBuffer.flip();
+    }
+}

Propchange: directory/network/branches/api_integration/src/java/org/apache/mina/filter/SSLHandler.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision



Mime
View raw message