Updated Branches:
  refs/heads/master 03aa3979d -> 488f4211f

[SSHD-222] Add pluggable global request handlers

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/488f4211
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/488f4211
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/488f4211

Branch: refs/heads/master
Commit: 488f4211fc878c97d6a4f981007c01f2b5e6c197
Parents: 03aa397
Author: Guillaume Nodet <[email protected]>
Authored: Wed Jan 29 13:57:01 2014 +0100
Committer: Guillaume Nodet <[email protected]>
Committed: Wed Jan 29 13:57:01 2014 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshServer.java    |  11 ++
 .../client/session/ClientConnectionService.java |  97 -----------
 .../sshd/common/AbstractFactoryManager.java     |   9 ++
 .../org/apache/sshd/common/FactoryManager.java  |   7 +
 .../sshd/common/GlobalRequestHandler.java       |  45 ++++++
 .../session/AbstractConnectionService.java      | 159 ++++++++++++++++++-
 .../sshd/common/session/AbstractSession.java    | 103 +-----------
 .../sshd/common/session/ConnectionService.java  |   3 +
 .../global/CancelTcpipForwardHandler.java       |  49 ++++++
 .../sshd/server/global/KeepAliveHandler.java    |  44 +++++
 .../server/global/NoMoreSessionsHandler.java    |  45 ++++++
 .../sshd/server/global/TcpipForwardHandler.java |  50 ++++++
 .../server/session/ServerConnectionService.java | 158 +-----------------
 13 files changed, 421 insertions(+), 359 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java 
b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index 56e84cd..90df02d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -41,6 +41,7 @@ import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.Compression;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.ForwardingFilter;
+import org.apache.sshd.common.GlobalRequestHandler;
 import org.apache.sshd.common.KeyExchange;
 import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
@@ -96,6 +97,10 @@ import org.apache.sshd.server.auth.gss.GSSAuthenticator;
 import org.apache.sshd.server.auth.gss.UserAuthGSS;
 import org.apache.sshd.server.channel.ChannelSession;
 import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.global.CancelTcpipForwardHandler;
+import org.apache.sshd.server.global.KeepAliveHandler;
+import org.apache.sshd.server.global.NoMoreSessionsHandler;
+import org.apache.sshd.server.global.TcpipForwardHandler;
 import org.apache.sshd.server.kex.DHG1;
 import org.apache.sshd.server.kex.DHG14;
 import org.apache.sshd.server.kex.DHGEX;
@@ -495,6 +500,12 @@ public class SshServer extends AbstractFactoryManager 
implements ServerFactoryMa
                 new TcpipServerChannel.DirectTcpipFactory()));
         sshd.setFileSystemFactory(new NativeFileSystemFactory());
         sshd.setTcpipForwarderFactory(new DefaultTcpipForwarderFactory());
+        sshd.setGlobalRequestHandlers(Arrays.<GlobalRequestHandler>asList(
+                new KeepAliveHandler(),
+                new NoMoreSessionsHandler(),
+                new TcpipForwardHandler(),
+                new CancelTcpipForwardHandler()
+        ));
         return sshd;
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
index bc9e316..d183284 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
@@ -99,43 +99,6 @@ public class ClientConnectionService extends 
AbstractConnectionService {
         }
     }
 
-    public void process(SshConstants.Message cmd, Buffer buffer) throws 
Exception {
-        switch (cmd) {
-            case SSH_MSG_CHANNEL_OPEN:
-                channelOpen(buffer);
-                break;
-            case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
-                channelOpenConfirmation(buffer);
-                break;
-            case SSH_MSG_CHANNEL_OPEN_FAILURE:
-                channelOpenFailure(buffer);
-                break;
-            case SSH_MSG_CHANNEL_REQUEST:
-                channelRequest(buffer);
-                break;
-            case SSH_MSG_CHANNEL_DATA:
-                channelData(buffer);
-                break;
-            case SSH_MSG_CHANNEL_EXTENDED_DATA:
-                channelExtendedData(buffer);
-                break;
-            case SSH_MSG_CHANNEL_FAILURE:
-                channelFailure(buffer);
-                break;
-            case SSH_MSG_CHANNEL_WINDOW_ADJUST:
-                channelWindowAdjust(buffer);
-                break;
-            case SSH_MSG_CHANNEL_EOF:
-                channelEof(buffer);
-                break;
-            case SSH_MSG_CHANNEL_CLOSE:
-                channelClose(buffer);
-                break;
-            default:
-                throw new IllegalStateException("Unsupported command: " + cmd);
-        }
-    }
-
     // TODO: remove from interface
     public String initAgentForward() throws IOException {
         throw new IllegalStateException("Server side operation");
@@ -146,64 +109,4 @@ public class ClientConnectionService extends 
AbstractConnectionService {
         throw new IllegalStateException("Server side operation");
     }
 
-    private void channelOpen(Buffer buffer) throws Exception {
-        String type = buffer.getString();
-        final int id = buffer.getInt();
-        final int rwsize = buffer.getInt();
-        final int rmpsize = buffer.getInt();
-
-        log.info("Received SSH_MSG_CHANNEL_OPEN {}", type);
-
-        if (closing) {
-            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-            buf.putInt(id);
-            buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
-            buf.putString("SSH server is shutting down: " + type);
-            buf.putString("");
-            session.writePacket(buf);
-            return;
-        }
-
-        final Channel channel = 
NamedFactory.Utils.create(getSession().getFactoryManager().getChannelFactories(),
 type);
-        if (channel == null) {
-            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-            buf.putInt(id);
-            buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
-            buf.putString("Unsupported channel type: " + type);
-            buf.putString("");
-            session.writePacket(buf);
-            return;
-        }
-
-        final int channelId = registerChannel(channel);
-        channel.open(id, rwsize, rmpsize, buffer).addListener(new 
SshFutureListener<OpenFuture>() {
-            public void operationComplete(OpenFuture future) {
-                try {
-                    if (future.isOpened()) {
-                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
-                        buf.putInt(id);
-                        buf.putInt(channelId);
-                        buf.putInt(channel.getLocalWindow().getSize());
-                        buf.putInt(channel.getLocalWindow().getPacketSize());
-                        session.writePacket(buf);
-                    } else if (future.getException() != null) {
-                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-                        buf.putInt(id);
-                        if (future.getException() instanceof 
OpenChannelException) {
-                            
buf.putInt(((OpenChannelException)future.getException()).getReasonCode());
-                            buf.putString(future.getException().getMessage());
-                        } else {
-                            buf.putInt(0);
-                            buf.putString("Error opening channel: " + 
future.getException().getMessage());
-                        }
-                        buf.putString("");
-                        session.writePacket(buf);
-                    }
-                } catch (IOException e) {
-                    session.exceptionCaught(e);
-                }
-            }
-        });
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java 
b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index 450dce4..6c5bf4f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -60,6 +60,7 @@ public abstract class AbstractFactoryManager implements 
FactoryManager {
     protected ForwardingFilter tcpipForwardingFilter;
     protected FileSystemFactory fileSystemFactory;
     protected List<ServiceFactory> serviceFactories;
+    protected List<GlobalRequestHandler> globalRequestHandlers;
 
     protected AbstractFactoryManager() {
         loadVersion();
@@ -236,4 +237,12 @@ public abstract class AbstractFactoryManager implements 
FactoryManager {
     public void setServiceFactories(List<ServiceFactory> serviceFactories) {
         this.serviceFactories = serviceFactories;
     }
+
+    public List<GlobalRequestHandler> getGlobalRequestHandlers() {
+        return globalRequestHandlers;
+    }
+
+    public void setGlobalRequestHandlers(List<GlobalRequestHandler> 
globalRequestHandlers) {
+        this.globalRequestHandlers = globalRequestHandlers;
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java 
b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 86e0155..43df005 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -184,4 +184,11 @@ public interface FactoryManager {
      */
     List<ServiceFactory> getServiceFactories();
 
+    /**
+     * Retrieve the list of global request handlers.
+     *
+     * @return a list of named <code>GlobalRequestHandler</code>
+     */
+    List<GlobalRequestHandler> getGlobalRequestHandlers();
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/GlobalRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/GlobalRequestHandler.java 
b/sshd-core/src/main/java/org/apache/sshd/common/GlobalRequestHandler.java
new file mode 100644
index 0000000..5409a4f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/GlobalRequestHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.sshd.common;
+
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * A global request handler.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public interface GlobalRequestHandler {
+
+    /**
+     * Process the ssh-connection global request.
+     * If an exception is thrown, the ConnectionService will send a failure 
message if needed
+     * and the request will be considered handled.
+     *
+     * @param connectionService
+     * @param request
+     * @param wantReply
+     * @param buffer
+     * @return <code>true</code> if the request was handled
+     * @throws Exception
+     */
+    boolean process(ConnectionService connectionService, String request, 
boolean wantReply, Buffer buffer) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
index 2f7b070..54432a8 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
@@ -27,16 +27,19 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.sshd.agent.common.AgentForwardSupport;
 import org.apache.sshd.client.channel.AbstractClientChannel;
+import org.apache.sshd.client.future.OpenFuture;
 import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.GlobalRequestHandler;
+import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.TcpipForwarder;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultCloseFuture;
-import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.channel.OpenChannelException;
 import org.apache.sshd.server.x11.X11ForwardSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,6 +66,7 @@ public abstract class AbstractConnectionService implements 
ConnectionService {
     protected final X11ForwardSupport x11Forward;
     protected final CloseFuture closeFuture;
     protected volatile boolean closing;
+    protected boolean allowMoreSessions = true;
 
     protected AbstractConnectionService(Session session) {
         this.session = session;
@@ -97,8 +101,8 @@ public abstract class AbstractConnectionService implements 
ConnectionService {
                         final AtomicInteger latch = new 
AtomicInteger(channelToClose.size());
                         for (Channel channel : channelToClose) {
                             log.debug("Closing channel {}", channel.getId());
-                            channel.close(immediately).addListener(new 
SshFutureListener() {
-                                public void operationComplete(SshFuture 
sshFuture) {
+                            channel.close(immediately).addListener(new 
SshFutureListener<CloseFuture>() {
+                                public void operationComplete(CloseFuture 
future) {
                                     if (latch.decrementAndGet() == 0) {
                                         closeFuture.setClosed();
                                     }
@@ -125,7 +129,7 @@ public abstract class AbstractConnectionService implements 
ConnectionService {
      *
      * @param channel the channel to register
      * @return the id of this channel
-     * @throws Exception
+     * @throws IOException
      */
     public int registerChannel(Channel channel) throws IOException {
         int channelId = getNextChannelId();
@@ -143,6 +147,50 @@ public abstract class AbstractConnectionService implements 
ConnectionService {
         channels.remove(channel.getId());
     }
 
+    public void process(SshConstants.Message cmd, Buffer buffer) throws 
Exception {
+        switch (cmd) {
+            case SSH_MSG_CHANNEL_OPEN:
+                channelOpen(buffer);
+                break;
+            case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+                channelOpenConfirmation(buffer);
+                break;
+            case SSH_MSG_CHANNEL_OPEN_FAILURE:
+                channelOpenFailure(buffer);
+                break;
+            case SSH_MSG_CHANNEL_REQUEST:
+                channelRequest(buffer);
+                break;
+            case SSH_MSG_CHANNEL_DATA:
+                channelData(buffer);
+                break;
+            case SSH_MSG_CHANNEL_EXTENDED_DATA:
+                channelExtendedData(buffer);
+                break;
+            case SSH_MSG_CHANNEL_FAILURE:
+                channelFailure(buffer);
+                break;
+            case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+                channelWindowAdjust(buffer);
+                break;
+            case SSH_MSG_CHANNEL_EOF:
+                channelEof(buffer);
+                break;
+            case SSH_MSG_CHANNEL_CLOSE:
+                channelClose(buffer);
+                break;
+            case SSH_MSG_GLOBAL_REQUEST:
+                globalRequest(buffer);
+                break;
+            default:
+                throw new IllegalStateException("Unsupported command: " + cmd);
+        }
+    }
+
+    public void setAllowMoreSessions(boolean allow) {
+        allowMoreSessions = allow;
+    }
+
     public void channelOpenConfirmation(Buffer buffer) throws IOException {
         Channel channel = getChannel(buffer);
         log.debug("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel {}", 
channel.getId());
@@ -268,4 +316,107 @@ public abstract class AbstractConnectionService 
implements ConnectionService {
         return channel;
     }
 
+    protected void channelOpen(Buffer buffer) throws Exception {
+        String type = buffer.getString();
+        final int id = buffer.getInt();
+        final int rwsize = buffer.getInt();
+        final int rmpsize = buffer.getInt();
+
+        log.debug("Received SSH_MSG_CHANNEL_OPEN {}", type);
+
+        if (closing) {
+            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+            buf.putInt(id);
+            buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+            buf.putString("SSH server is shutting down: " + type);
+            buf.putString("");
+            session.writePacket(buf);
+            return;
+        }
+        if (!allowMoreSessions) {
+            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+            buf.putInt(id);
+            buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+            buf.putString("additional sessions disabled");
+            buf.putString("");
+            session.writePacket(buf);
+            return;
+        }
+
+        final Channel channel = 
NamedFactory.Utils.create(session.getFactoryManager().getChannelFactories(), 
type);
+        if (channel == null) {
+            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+            buf.putInt(id);
+            buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
+            buf.putString("Unsupported channel type: " + type);
+            buf.putString("");
+            session.writePacket(buf);
+            return;
+        }
+
+        final int channelId = registerChannel(channel);
+        channel.open(id, rwsize, rmpsize, buffer).addListener(new 
SshFutureListener<OpenFuture>() {
+            public void operationComplete(OpenFuture future) {
+                try {
+                    if (future.isOpened()) {
+                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
+                        buf.putInt(id);
+                        buf.putInt(channelId);
+                        buf.putInt(channel.getLocalWindow().getSize());
+                        buf.putInt(channel.getLocalWindow().getPacketSize());
+                        session.writePacket(buf);
+                    } else if (future.getException() != null) {
+                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+                        buf.putInt(id);
+                        if (future.getException() instanceof 
OpenChannelException) {
+                            buf.putInt(((OpenChannelException) 
future.getException()).getReasonCode());
+                            buf.putString(future.getException().getMessage());
+                        } else {
+                            buf.putInt(0);
+                            buf.putString("Error opening channel: " + 
future.getException().getMessage());
+                        }
+                        buf.putString("");
+                        session.writePacket(buf);
+                    }
+                } catch (IOException e) {
+                    session.exceptionCaught(e);
+                }
+            }
+        });
+    }
+
+    /**
+     * Process global requests
+     *
+     * @param buffer the request
+     * @throws Exception
+     */
+    protected void globalRequest(Buffer buffer) throws Exception {
+        String req = buffer.getString();
+        boolean wantReply = buffer.getBoolean();
+        log.debug("Received SSH_MSG_GLOBAL_REQUEST {}", req);
+        List<GlobalRequestHandler> handlers = 
session.getFactoryManager().getGlobalRequestHandlers();
+        if (handlers != null) {
+            for (GlobalRequestHandler handler : handlers) {
+                try {
+                    if (handler.process(this, req, wantReply, buffer)) {
+                        return;
+                    }
+                } catch (Exception e) {
+                    log.warn("Error processing global request " + req, e);
+                    if (wantReply) {
+                        buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
+                        session.writePacket(buffer);
+                    }
+                    return;
+                }
+            }
+        }
+        log.warn("Unknown global request: {}", req);
+        if (wantReply) {
+            buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
+            session.writePacket(buffer);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java 
b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index a7c6ec7..942809e 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -24,11 +24,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.sshd.client.channel.AbstractClientChannel;
-import org.apache.sshd.common.Channel;
 import org.apache.sshd.common.Cipher;
 import org.apache.sshd.common.Compression;
 import org.apache.sshd.common.Digest;
@@ -42,14 +39,12 @@ import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SessionListener;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.TcpipForwarder;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultCloseFuture;
-import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoCloseFuture;
-import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.BufferUtils;
 import org.apache.sshd.common.util.Readable;
@@ -337,7 +332,7 @@ public abstract class AbstractSession implements Session {
                     lock.notifyAll();
                 }
                 state = State.Closed;
-                log.info("Session {}@{} closed", s.getUsername(), 
s.getIoSession().getRemoteAddress());
+                log.info("SMessession {}@{} closed", s.getUsername(), 
s.getIoSession().getRemoteAddress());
                 // Fire 'close' event
                 final ArrayList<SessionListener> l = new 
ArrayList<SessionListener>(listeners);
                 for (SessionListener sl : l) {
@@ -998,100 +993,6 @@ public abstract class AbstractSession implements Session {
         }
     }
 
-
-    /*
-    protected int getNextChannelId() {
-        return nextChannelId.incrementAndGet();
-    }
-
-    public int registerChannel(Channel channel) throws IOException {
-        int channelId = getNextChannelId();
-        channel.init(this, session, channelId);
-        channels.put(channelId, channel);
-        return channelId;
-    }
-
-    public void channelOpenConfirmation(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        log.debug("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel {}", 
channel.getId());
-        int recipient = buffer.getInt();
-        int rwsize = buffer.getInt();
-        int rmpsize = buffer.getInt();
-        channel.handleOpenSuccess(recipient, rwsize, rmpsize, buffer);
-    }
-
-    public void channelOpenFailure(Buffer buffer) throws IOException {
-        AbstractClientChannel channel = (AbstractClientChannel) 
getChannel(buffer);
-        log.debug("Received SSH_MSG_CHANNEL_OPEN_FAILURE on channel {}", 
channel.getId());
-        channels.remove(channel.getId());
-        channel.handleOpenFailure(buffer);
-    }
-
-    public void channelData(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        channel.handleData(buffer);
-    }
-
-    public void channelExtendedData(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        channel.handleExtendedData(buffer);
-    }
-
-    public void channelWindowAdjust(Buffer buffer) throws IOException {
-        try {
-            Channel channel = getChannel(buffer);
-            channel.handleWindowAdjust(buffer);
-        } catch (SshException e) {
-            log.info(e.getMessage());
-        }
-    }
-
-    public void channelEof(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        channel.handleEof();
-    }
-
-    public void channelClose(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        channel.handleClose();
-        unregisterChannel(channel);
-    }
-
-    public void unregisterChannel(Channel channel) {
-        channels.remove(channel.getId());
-    }
-
-    public void channelRequest(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        String type = buffer.getString();
-        boolean wantReply = buffer.getBoolean();
-        boolean success = channel.handleRequest(type, buffer);
-        if (wantReply) {
-            Buffer replyBuffer = createBuffer(
-                    success ? SshConstants.Message.SSH_MSG_CHANNEL_SUCCESS
-                            : SshConstants.Message.SSH_MSG_CHANNEL_FAILURE, 0);
-            replyBuffer.putInt(channel.getRecipient());
-            writePacket(replyBuffer);
-        }
-    }
-
-    public void channelFailure(Buffer buffer) throws IOException {
-        Channel channel = getChannel(buffer);
-        channel.handleFailure();
-    }
-
-    protected Channel getChannel(Buffer buffer) throws IOException {
-        int recipient = buffer.getInt();
-        Channel channel = channels.get(recipient);
-        if (channel == null) {
-            buffer.rpos(buffer.rpos() - 5);
-            SshConstants.Message cmd = buffer.getCommand();
-            throw new SshException("Received " + cmd + " on unknown channel " 
+ recipient);
-        }
-        return channel;
-    }
-    */
-
     /**
      * Retrieve a configuration property as an integer
      *

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java 
b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
index 600986a..45c6266 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
@@ -60,4 +60,7 @@ public interface ConnectionService extends Service {
 
     // TODO: remove from interface, it's server side only
     String createX11Display(boolean singleConnection, String 
authenticationProtocol, String authenticationCookie, int screen) throws 
IOException;
+
+    void setAllowMoreSessions(boolean allow);
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
new file mode 100644
index 0000000..23c127d
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sshd.server.global;
+
+import org.apache.sshd.common.GlobalRequestHandler;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * Handler for cancel-tcpip-forward global request.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class CancelTcpipForwardHandler implements GlobalRequestHandler {
+
+    public boolean process(ConnectionService connectionService, String 
request, boolean wantReply, Buffer buffer) throws Exception {
+        if (request.equals("cancel-tcpip-forward")) {
+            String address = buffer.getString();
+            int port = buffer.getInt();
+            
connectionService.getTcpipForwarder().localPortForwardingCancelled(new 
SshdSocketAddress(address, port));
+            if (wantReply){
+                buffer = 
connectionService.getSession().createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS,
 0);
+                buffer.putInt(port);
+                connectionService.getSession().writePacket(buffer);
+            }
+            return true;
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java 
b/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
new file mode 100644
index 0000000..3371ed9
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/KeepAliveHandler.java
@@ -0,0 +1,44 @@
+/*
+ * 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.sshd.server.global;
+
+import org.apache.sshd.common.GlobalRequestHandler;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * Handler for keepalive@xxx global request.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class KeepAliveHandler implements GlobalRequestHandler {
+
+    public boolean process(ConnectionService connectionService, String 
request, boolean wantReply, Buffer buffer) throws Exception {
+        if (request.startsWith("keepalive@")) {
+            if (wantReply) {
+                buffer = 
connectionService.getSession().createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE,
 0);
+                connectionService.getSession().writePacket(buffer);
+            }
+            return true;
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
new file mode 100644
index 0000000..98fe3a3
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/NoMoreSessionsHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.sshd.server.global;
+
+import org.apache.sshd.common.GlobalRequestHandler;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * Handler for no-more-sessions@xxx global request.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class NoMoreSessionsHandler implements GlobalRequestHandler {
+
+    public boolean process(ConnectionService connectionService, String 
request, boolean wantReply, Buffer buffer) throws Exception {
+        if (request.startsWith("no-more-sessions@")) {
+            connectionService.setAllowMoreSessions(false);
+            if (wantReply) {
+                buffer = 
connectionService.getSession().createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE,
 0);
+                connectionService.getSession().writePacket(buffer);
+            }
+            return true;
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
new file mode 100644
index 0000000..01aa6a5
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
@@ -0,0 +1,50 @@
+/*
+ * 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.sshd.server.global;
+
+import org.apache.sshd.common.GlobalRequestHandler;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * Handler for tcpip-forward global request.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class TcpipForwardHandler implements GlobalRequestHandler {
+
+    public boolean process(ConnectionService connectionService, String 
request, boolean wantReply, Buffer buffer) throws Exception {
+        if (request.equals("tcpip-forward")) {
+            String address = buffer.getString();
+            int port = buffer.getInt();
+            SshdSocketAddress bound = 
connectionService.getTcpipForwarder().localPortForwardingRequested(new 
SshdSocketAddress(address, port));
+            port = bound.getPort();
+            if (wantReply){
+                buffer = 
connectionService.getSession().createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS,
 0);
+                buffer.putInt(port);
+                connectionService.getSession().writePacket(buffer);
+            }
+            return true;
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/488f4211/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
index b5a4461..50c0cf8 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 
 import org.apache.sshd.client.future.OpenFuture;
 import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.GlobalRequestHandler;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Service;
 import org.apache.sshd.common.ServiceFactory;
@@ -53,8 +54,6 @@ public class ServerConnectionService extends 
AbstractConnectionService {
     }
 
 
-    private boolean allowMoreSessions = true;
-
     protected ServerConnectionService(Session s) throws SshException {
         super(s);
         if (!(s instanceof ServerSession)) {
@@ -66,161 +65,6 @@ public class ServerConnectionService extends 
AbstractConnectionService {
         }
     }
 
-    public void process(SshConstants.Message cmd, Buffer buffer) throws 
Exception {
-        switch (cmd) {
-            case SSH_MSG_CHANNEL_OPEN:
-                channelOpen(buffer);
-                break;
-            case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
-                channelOpenConfirmation(buffer);
-                break;
-            case SSH_MSG_CHANNEL_OPEN_FAILURE:
-                channelOpenFailure(buffer);
-                break;
-            case SSH_MSG_CHANNEL_REQUEST:
-                channelRequest(buffer);
-                break;
-            case SSH_MSG_CHANNEL_DATA:
-                channelData(buffer);
-                break;
-            case SSH_MSG_CHANNEL_EXTENDED_DATA:
-                channelExtendedData(buffer);
-                break;
-            case SSH_MSG_CHANNEL_FAILURE:
-                channelFailure(buffer);
-                break;
-            case SSH_MSG_CHANNEL_WINDOW_ADJUST:
-                channelWindowAdjust(buffer);
-                break;
-            case SSH_MSG_CHANNEL_EOF:
-                channelEof(buffer);
-                break;
-            case SSH_MSG_CHANNEL_CLOSE:
-                channelClose(buffer);
-                break;
-            case SSH_MSG_GLOBAL_REQUEST:
-                globalRequest(buffer);
-                break;
-            default:
-                throw new IllegalStateException("Unsupported command: " + cmd);
-        }
-    }
-
-    private void channelOpen(Buffer buffer) throws Exception {
-        String type = buffer.getString();
-        final int id = buffer.getInt();
-        final int rwsize = buffer.getInt();
-        final int rmpsize = buffer.getInt();
-
-        log.debug("Received SSH_MSG_CHANNEL_OPEN {}", type);
-
-        if (closing) {
-            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-            buf.putInt(id);
-            buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
-            buf.putString("SSH server is shutting down: " + type);
-            buf.putString("");
-            session.writePacket(buf);
-            return;
-        }
-        if (!allowMoreSessions) {
-            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-            buf.putInt(id);
-            buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
-            buf.putString("additional sessions disabled");
-            buf.putString("");
-            session.writePacket(buf);
-            return;
-        }
-
-        final Channel channel = 
NamedFactory.Utils.create(session.getFactoryManager().getChannelFactories(), 
type);
-        if (channel == null) {
-            Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-            buf.putInt(id);
-            buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
-            buf.putString("Unsupported channel type: " + type);
-            buf.putString("");
-            session.writePacket(buf);
-            return;
-        }
-
-        final int channelId = registerChannel(channel);
-        channel.open(id, rwsize, rmpsize, buffer).addListener(new 
SshFutureListener<OpenFuture>() {
-            public void operationComplete(OpenFuture future) {
-                try {
-                    if (future.isOpened()) {
-                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
-                        buf.putInt(id);
-                        buf.putInt(channelId);
-                        buf.putInt(channel.getLocalWindow().getSize());
-                        buf.putInt(channel.getLocalWindow().getPacketSize());
-                        session.writePacket(buf);
-                    } else if (future.getException() != null) {
-                        Buffer buf = 
session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
-                        buf.putInt(id);
-                        if (future.getException() instanceof 
OpenChannelException) {
-                            buf.putInt(((OpenChannelException) 
future.getException()).getReasonCode());
-                            buf.putString(future.getException().getMessage());
-                        } else {
-                            buf.putInt(0);
-                            buf.putString("Error opening channel: " + 
future.getException().getMessage());
-                        }
-                        buf.putString("");
-                        session.writePacket(buf);
-                    }
-                } catch (IOException e) {
-                    session.exceptionCaught(e);
-                }
-            }
-        });
-    }
-
-    private void globalRequest(Buffer buffer) throws Exception {
-        String req = buffer.getString();
-        boolean wantReply = buffer.getBoolean();
-        log.debug("Received global request {}", req);
-        if (req.startsWith("keepalive@")) {
-            // Relatively standard KeepAlive directive, just wants failure
-        } else if (req.equals("[email protected]")) {
-            allowMoreSessions = false;
-        } else if (req.equals("tcpip-forward")) {
-            String address = buffer.getString();
-            int port = buffer.getInt();
-            try {
-                SshdSocketAddress bound = 
tcpipForwarder.localPortForwardingRequested(new SshdSocketAddress(address, 
port));
-                port = bound.getPort();
-                if (wantReply){
-                    buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
-                    buffer.putInt(port);
-                    session.writePacket(buffer);
-                }
-            } catch (Exception e) {
-                log.debug("Error starting tcpip forward", e);
-                if (wantReply) {
-                    buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
-                    session.writePacket(buffer);
-                }
-            }
-            return;
-        } else if (req.equals("cancel-tcpip-forward")) {
-            String address = buffer.getString();
-            int port = buffer.getInt();
-            tcpipForwarder.localPortForwardingCancelled(new 
SshdSocketAddress(address, port));
-            if (wantReply){
-                buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
-                session.writePacket(buffer);
-            }
-            return;
-        } else {
-            log.debug("Received SSH_MSG_GLOBAL_REQUEST {}", req);
-            log.warn("Unknown global request: {}", req);
-        }
-        if (wantReply) {
-            buffer = 
session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
-            session.writePacket(buffer);
-        }
-    }
-
     public String initAgentForward() throws IOException {
         return agentForward.initialize();
     }

Reply via email to