You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/05/14 02:44:49 UTC

[3/4] mina-sshd git commit: [SSHD-459] Make Buffer an abstract class

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
index 95294da..38ea52f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
@@ -20,7 +20,7 @@ package org.apache.sshd.common.compression;
 
 import java.io.IOException;
 
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
  * Interface used to compress the stream of data between the

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionZlib.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionZlib.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionZlib.java
index 5e9a56c..4b50c3b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionZlib.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionZlib.java
@@ -23,7 +23,7 @@ import java.util.zip.DataFormatException;
 import java.util.zip.Deflater;
 import java.util.zip.Inflater;
 
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
  * ZLib based Compression.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
index cb68ea4..458b483 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
@@ -40,9 +40,10 @@ import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * TODO Add javadoc
@@ -68,6 +69,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
     // TcpIpForwarder implementation
     //
 
+    @Override
     public synchronized SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
         if (local == null) {
             throw new IllegalArgumentException("Local address is null");
@@ -89,12 +91,14 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         return bound;
     }
 
+    @Override
     public synchronized void stopLocalPortForwarding(SshdSocketAddress local) throws IOException {
         if (localToRemote.remove(local.getPort()) != null && acceptor != null) {
             acceptor.unbind(local.toInetSocketAddress());
         }
     }
 
+    @Override
     public synchronized SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_GLOBAL_REQUEST);
         buffer.putString("tcpip-forward");
@@ -111,6 +115,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         return new SshdSocketAddress(remote.getHostName(), port);
     }
 
+    @Override
     public synchronized void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
         if (remoteToLocal.remove(remote.getPort()) != null) {
             Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_GLOBAL_REQUEST);
@@ -122,6 +127,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         }
     }
 
+    @Override
     public synchronized SshdSocketAddress startDynamicPortForwarding(SshdSocketAddress local) throws IOException {
         if (local == null) {
             throw new IllegalArgumentException("Local address is null");
@@ -141,6 +147,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         return bound;
     }
 
+    @Override
     public synchronized void stopDynamicPortForwarding(SshdSocketAddress local) throws IOException {
         Closeable obj = dynamicLocal.remove(local.getPort());
         if (obj != null) {
@@ -149,10 +156,12 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         }
     }
 
+    @Override
     public synchronized SshdSocketAddress getForwardedPort(int remotePort) {
         return remoteToLocal.get(remotePort);
     }
 
+    @Override
     public synchronized SshdSocketAddress localPortForwardingRequested(SshdSocketAddress local) throws IOException {
         if (local == null) {
             throw new IllegalArgumentException("Local address is null");
@@ -169,6 +178,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         return bound;
     }
 
+    @Override
     public synchronized void localPortForwardingCancelled(SshdSocketAddress local) throws IOException {
         if (localForwards.remove(local) && acceptor != null) {
             acceptor.unbind(local.toInetSocketAddress());
@@ -209,6 +219,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
         }
     }
 
+    @Override
     public String toString() {
         return getClass().getSimpleName() + "[" + session + "]";
     }
@@ -219,6 +230,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
 
     class StaticIoHandler implements IoHandler {
 
+        @Override
         public void sessionCreated(final IoSession session) throws Exception {
             final TcpipClientChannel channel;
             int localPort = ((InetSocketAddress) session.getLocalAddress()).getPort();
@@ -231,6 +243,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
             session.setAttribute(TcpipClientChannel.class, channel);
             service.registerChannel(channel);
             channel.open().addListener(new SshFutureListener<OpenFuture>() {
+                @Override
                 public void operationComplete(OpenFuture future) {
                     Throwable t = future.getException();
                     if (t != null) {
@@ -241,6 +254,7 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
             });
         }
 
+        @Override
         public void sessionClosed(IoSession session) throws Exception {
             TcpipClientChannel channel = (TcpipClientChannel) session.getAttribute(TcpipClientChannel.class);
             if (channel != null) {
@@ -249,15 +263,17 @@ public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable
             }
         }
 
+        @Override
         public void messageReceived(IoSession session, Readable message) throws Exception {
             TcpipClientChannel channel = (TcpipClientChannel) session.getAttribute(TcpipClientChannel.class);
-            Buffer buffer = new Buffer();
+            Buffer buffer = new ByteArrayBuffer();
             buffer.putBuffer(message);
             channel.waitFor(ClientChannel.OPENED | ClientChannel.CLOSED, Long.MAX_VALUE);
             channel.getInvertedIn().write(buffer.array(), buffer.rpos(), buffer.available());
             channel.getInvertedIn().flush();
         }
 
+        @Override
         public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
             cause.printStackTrace();
             session.close(false);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
index bbe4fe7..a009144 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/SocksProxy.java
@@ -30,8 +30,9 @@ import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.CloseableUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * SOCKS proxy server, supporting simple socks4/5 protocols.
@@ -47,12 +48,14 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         this.service = service;
     }
 
+    @Override
     public void sessionCreated(IoSession session) throws Exception {
         if (isClosing()) {
             throw new SshException("SocksProxy is closing or closed");
         }
     }
 
+    @Override
     public void sessionClosed(IoSession session) throws Exception {
         Proxy proxy = proxies.remove(session);
         if (proxy != null) {
@@ -60,8 +63,9 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         }
     }
 
+    @Override
     public void messageReceived(final IoSession session, org.apache.sshd.common.util.Readable message) throws Exception {
-        Buffer buffer = new Buffer(message.available());
+        Buffer buffer = new ByteArrayBuffer(message.available());
         buffer.putBuffer(message);
         Proxy proxy = proxies.get(session);
         if (proxy == null) {
@@ -80,6 +84,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         }
     }
 
+    @Override
     public void exceptionCaught(IoSession ioSession, Throwable cause) throws Exception {
         log.warn("Exception caught, closing socks proxy", cause);
         ioSession.close(false);
@@ -142,6 +147,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
                 channel = new TcpipClientChannel(TcpipClientChannel.Type.Direct, session, remote);
                 service.registerChannel(channel);
                 channel.open().addListener(new SshFutureListener<OpenFuture>() {
+                    @Override
                     public void operationComplete(OpenFuture future) {
                         onChannelOpened(future);
                     }
@@ -152,7 +158,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
         }
 
         protected void onChannelOpened(OpenFuture future) {
-            Buffer buffer = new Buffer(8);
+            Buffer buffer = new ByteArrayBuffer(8);
             buffer.putByte((byte) 0x00);
             Throwable t = future.getException();
             if (t != null) {
@@ -201,7 +207,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
                 for (int i = 0; i < nbAuthMethods; i++) {
                     foundNoAuth |= authMethods[i] == 0;
                 }
-                buffer = new Buffer(8);
+                buffer = new ByteArrayBuffer(8);
                 buffer.putByte((byte) 0x05);
                 buffer.putByte((byte) (foundNoAuth ? 0x00 : 0xFF));
                 session.write(buffer);
@@ -248,6 +254,7 @@ public class SocksProxy extends CloseableUtils.AbstractCloseable implements IoHa
                 channel = new TcpipClientChannel(TcpipClientChannel.Type.Direct, session, remote);
                 service.registerChannel(channel);
                 channel.open().addListener(new SshFutureListener<OpenFuture>() {
+                    @Override
                     public void operationComplete(OpenFuture future) {
                         onChannelOpened(future);
                     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
index 0d95acf..cb93049 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java
@@ -29,12 +29,9 @@ import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.channel.ChannelOutputStream;
-import org.apache.sshd.common.future.CloseFuture;
-import org.apache.sshd.common.future.DefaultCloseFuture;
-import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.CloseableUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * TODO Add javadoc
@@ -64,6 +61,7 @@ public class TcpipClientChannel extends AbstractClientChannel {
         return openFuture;
     }
 
+    @Override
     public synchronized OpenFuture open() throws IOException {
         InetSocketAddress src = null, dst = null;
         switch (typeEnum) {
@@ -107,10 +105,11 @@ public class TcpipClientChannel extends AbstractClientChannel {
         return builder().sequential(serverSession, super.getInnerCloseable()).build();
     }
 
+    @Override
     protected synchronized void doWriteData(byte[] data, int off, int len) throws IOException {
         // Make sure we copy the data as the incoming buffer may be reused
-        Buffer buf = new Buffer(data, off, len);
-        buf = new Buffer(buf.getCompactData());
+        Buffer buf = new ByteArrayBuffer(data, off, len);
+        buf = new ByteArrayBuffer(buf.getCompactData());
         localWindow.consumeAndCheck(len);
         serverSession.write(buf);
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
index f2e0925..a828de6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
@@ -37,8 +37,9 @@ import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
 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.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.server.channel.AbstractServerChannel;
 import org.apache.sshd.server.channel.OpenChannelException;
 
@@ -51,10 +52,12 @@ public class TcpipServerChannel extends AbstractServerChannel {
 
     public static class DirectTcpipFactory implements NamedFactory<Channel> {
 
+        @Override
         public String getName() {
             return "direct-tcpip";
         }
 
+        @Override
         public Channel create() {
             return new TcpipServerChannel(Type.Direct);
         }
@@ -62,10 +65,12 @@ public class TcpipServerChannel extends AbstractServerChannel {
 
     public static class ForwardedTcpipFactory implements NamedFactory<Channel> {
 
+        @Override
         public String getName() {
             return "forwarded-tcpip";
         }
 
+        @Override
         public Channel create() {
             return new TcpipServerChannel(Type.Forwarded);
         }
@@ -85,6 +90,7 @@ public class TcpipServerChannel extends AbstractServerChannel {
         this.type = type;
     }
 
+    @Override
     protected OpenFuture doInit(Buffer buffer) {
         final OpenFuture f = new DefaultOpenFuture(this);
 
@@ -111,21 +117,25 @@ public class TcpipServerChannel extends AbstractServerChannel {
         // TODO: revisit for better threading. Use async io ?
         out = new ChannelOutputStream(this, remoteWindow, log, SshConstants.SSH_MSG_CHANNEL_DATA);
         IoHandler handler = new IoHandler() {
+            @Override
             public void messageReceived(IoSession session, Readable message) throws Exception {
                 if (isClosing()) {
                     log.debug("Ignoring write to channel {} in CLOSING state", id);
                 } else {
-                    Buffer buffer = new Buffer();
+                    Buffer buffer = new ByteArrayBuffer();
                     buffer.putBuffer(message);
                     out.write(buffer.array(), buffer.rpos(), buffer.available());
                     out.flush();
                 }
             }
+            @Override
             public void sessionCreated(IoSession session) throws Exception {
             }
+            @Override
             public void sessionClosed(IoSession session) throws Exception {
                 close(false);
             }
+            @Override
             public void exceptionCaught(IoSession ioSession, Throwable cause) throws Exception {
                 close(true);
             }
@@ -134,6 +144,7 @@ public class TcpipServerChannel extends AbstractServerChannel {
                 .createConnector(handler);
         IoConnectFuture future = connector.connect(address.toInetSocketAddress());
         future.addListener(new SshFutureListener<IoConnectFuture>() {
+            @Override
             public void operationComplete(IoConnectFuture future) {
                 if (future.isConnected()) {
                     ioSession = future.getSession();
@@ -176,19 +187,23 @@ public class TcpipServerChannel extends AbstractServerChannel {
         }.start();
     }
 
+    @Override
     public CloseFuture close(boolean immediately) {
         return super.close(immediately).addListener(new SshFutureListener<CloseFuture>() {
+            @Override
             public void operationComplete(CloseFuture sshFuture) {
                 closeImmediately0();
             }
         });
     }
 
+    @Override
     protected void doWriteData(byte[] data, int off, final int len) throws IOException {
         // Make sure we copy the data as the incoming buffer may be reused
-        Buffer buf = new Buffer(data, off, len);
-        buf = new Buffer(buf.getCompactData());
+        Buffer buf = new ByteArrayBuffer(data, off, len);
+        buf = new ByteArrayBuffer(buf.getCompactData());
         ioSession.write(buf).addListener(new SshFutureListener<IoWriteFuture>() {
+            @Override
             public void operationComplete(IoWriteFuture future) {
                 try {
                     localWindow.consumeAndCheck(len);
@@ -199,6 +214,7 @@ public class TcpipServerChannel extends AbstractServerChannel {
         });
     }
 
+    @Override
     protected void doWriteExtendedData(byte[] data, int off, int len) throws IOException {
         throw new UnsupportedOperationException(type + "Tcpip channel does not support extended data");
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/IoInputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoInputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoInputStream.java
index c585b67..d61419c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoInputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoInputStream.java
@@ -19,7 +19,7 @@
 package org.apache.sshd.common.io;
 
 import org.apache.sshd.common.Closeable;
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 public interface IoInputStream extends Closeable {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/IoOutputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoOutputStream.java
index f2b8994..104d5fb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoOutputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoOutputStream.java
@@ -19,7 +19,7 @@
 package org.apache.sshd.common.io;
 
 import org.apache.sshd.common.Closeable;
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 public interface IoOutputStream extends Closeable {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/IoReadFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoReadFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoReadFuture.java
index d4f07a9..ebf9c20 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoReadFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoReadFuture.java
@@ -20,7 +20,7 @@ package org.apache.sshd.common.io;
 
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.SshFuture;
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 public interface IoReadFuture extends SshFuture<IoReadFuture> {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
index caccfca..0158064 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
@@ -22,7 +22,7 @@ import java.net.SocketAddress;
 
 import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.future.CloseFuture;
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 public interface IoSession extends Closeable {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
index ed8f380..64d245c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
@@ -31,8 +31,8 @@ import org.apache.sshd.common.future.DefaultSshFuture;
 import org.apache.sshd.common.io.IoService;
 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.CloseableUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
  */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSupport.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSupport.java
index f9259f4..9b623e5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSupport.java
@@ -19,8 +19,8 @@
 package org.apache.sshd.common.io.mina;
 
 import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 public class MinaSupport {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
index 9822c2d..a0ceaf0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
@@ -39,9 +39,9 @@ import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoService;
 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.CloseableUtils;
 import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
  */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/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 6a709df..26f589e 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
@@ -37,8 +37,8 @@ import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.TcpipForwarder;
 import org.apache.sshd.common.future.SshFutureListener;
-import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.CloseableUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.server.channel.OpenChannelException;
 import org.apache.sshd.server.x11.X11ForwardSupport;
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/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 0903c39..378cce6 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
@@ -61,17 +61,18 @@ import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 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.CloseableUtils;
 import org.apache.sshd.common.util.EventListenerUtils;
 import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * The AbstractSession handles all the basic SSH protocol such as key exchange, authentication,
  * encoding and decoding. Both server side and client side sessions should inherit from this
  * abstract class. Some basic packet processing methods are defined but the actual call to these
- * methods should be done from the {@link #handleMessage(org.apache.sshd.common.util.Buffer)}
+ * methods should be done from the {@link #handleMessage(org.apache.sshd.common.util.buffer.Buffer)}
  * method, which is dependant on the state and side of this session.
  *
  * TODO: if there is any very big packet, decoderBuffer and uncompressBuffer will get quite big
@@ -139,7 +140,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     protected Compression inCompression;
     protected long seqi;
     protected long seqo;
-    protected Buffer decoderBuffer = new Buffer();
+    protected Buffer decoderBuffer = new ByteArrayBuffer();
     protected Buffer uncompressBuffer;
     protected int decoderState;
     protected int decoderLength;
@@ -228,10 +229,12 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         ioSession.setAttribute(SESSION, session);
     }
 
+    @Override
     public String getServerVersion() {
         return serverVersion;
     }
 
+    @Override
     public String getClientVersion() {
         return clientVersion;
     }
@@ -250,6 +253,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      *  
      * @return the mina session
      */
+    @Override
     public IoSession getIoSession() {
         return ioSession;
     }
@@ -259,10 +263,12 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      *
      * @return the factory manager for this session
      */
+    @Override
     public FactoryManager getFactoryManager() {
         return factoryManager;
     }
 
+    @Override
     public String getNegotiatedKexParameter(int paramType) {
     	if ((paramType < 0) || (negotiated == null) || (paramType >= negotiated.length)) {
     		return null;
@@ -447,6 +453,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * 
      * @param t the exception to process
      */
+    @Override
     public void exceptionCaught(Throwable t) {
         // Ignore exceptions that happen while closing
         synchronized (lock) {
@@ -488,6 +495,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         return currentService != null ? new Service[] { currentService } : new Service[0];
     }
 
+    @Override
     public <T extends Service> T getService(Class<T> clazz) {
         for (Service s : getServices()) {
             if (clazz.isInstance(s)) {
@@ -506,6 +514,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @return a future that can be used to check when the packet has actually been sent
      * @throws java.io.IOException if an error occured when encoding sending the packet
      */
+    @Override
     public IoWriteFuture writePacket(Buffer buffer) throws IOException {
         // While exchanging key, queue high level packets
         if (kexState.get() != KEX_STATE_DONE) {
@@ -571,6 +580,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @return <code>true</code> if the request was successful, <code>false</code> otherwise.
      * @throws java.io.IOException if an error occured when encoding sending the packet
      */
+    @Override
     public Buffer request(Buffer buffer) throws IOException {
         synchronized (requestLock) {
             try {
@@ -585,6 +595,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         }
     }
 
+    @Override
     public Buffer createBuffer(byte cmd) {
         return createBuffer(cmd, 0);
     }
@@ -597,10 +608,11 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @param len estimated number of bytes the buffer will hold, 0 if unknown.
      * @return a new buffer ready for write
      */
+    @Override
     public Buffer createBuffer(byte cmd, int len) {
         Buffer buffer;
         if (len <= 0) {
-            buffer = new Buffer();
+            buffer = new ByteArrayBuffer();
         } else {
             // Since the caller claims to know how many bytes they will need
             // increase their request to account for our headers/footers if
@@ -616,7 +628,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             if (outMac != null) {
                 len += outMac.getBlockSize();
             }
-            buffer = new Buffer(new byte[Math.max(len, Buffer.DEFAULT_SIZE)], false);
+            buffer = new ByteArrayBuffer(new byte[Math.max(len, ByteArrayBuffer.DEFAULT_SIZE)], false);
         }
         buffer.rpos(5);
         buffer.wpos(5);
@@ -637,7 +649,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             if (buffer.rpos() < 5) {
                 log.warn("Performance cost: when sending a packet, ensure that "
                            + "5 bytes are available in front of the buffer");
-                Buffer nb = new Buffer();
+                Buffer nb = new ByteArrayBuffer();
                 nb.wpos(5);
                 nb.putBuffer(buffer);
                 buffer = nb;
@@ -763,7 +775,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
                     // Decompress if needed
                     if (inCompression != null && (authed || !inCompression.isDelayed())) {
                         if (uncompressBuffer == null) {
-                            uncompressBuffer = new Buffer();
+                            uncompressBuffer = new ByteArrayBuffer();
                         } else {
                             uncompressBuffer.clear();
                         }
@@ -803,13 +815,13 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     protected void sendIdentification(String ident) {
         log.debug("Send identification: {}", ident);
         byte[] data = (ident + "\r\n").getBytes();
-        ioSession.write(new Buffer(data));
+        ioSession.write(new ByteArrayBuffer(data));
     }
 
     /**
      * Read the other side identification.
      * This method is specific to the client or server side, but both should call
-     * {@link #doReadIdentification(org.apache.sshd.common.util.Buffer,boolean)} and
+     * {@link #doReadIdentification(org.apache.sshd.common.util.buffer.Buffer,boolean)} and
      * store the result in the needed property.
      *
      * @param buffer the buffer containing the remote identification
@@ -983,7 +995,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             System.arraycopy(H, 0, sessionId, 0, H.length);
         }
 
-        Buffer buffer = new Buffer();
+        Buffer buffer = new ByteArrayBuffer();
         buffer.putMPInt(K);
         buffer.putRawBytes(H);
         buffer.putByte((byte) 0x41);
@@ -1079,7 +1091,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      */
     private byte[] resizeKey(byte[] E, int blockSize, Digest hash, byte[] K, byte[] H) throws Exception {
         while (blockSize > E.length) {
-            Buffer buffer = new Buffer();
+            Buffer buffer = new ByteArrayBuffer();
             buffer.putMPInt(K);
             buffer.putRawBytes(H);
             buffer.putRawBytes(E);
@@ -1111,6 +1123,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         // Write the packet with a timeout to ensure a timely close of the session
         // in case the consumer does not read packets anymore.
         writePacket(buffer, disconnectTimeoutMs, TimeUnit.MILLISECONDS).addListener(new SshFutureListener<IoWriteFuture>() {
+            @Override
             public void operationComplete(IoWriteFuture future) {
                 close(true);
             }
@@ -1188,7 +1201,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
 
     protected void requestSuccess(Buffer buffer) throws Exception{
         synchronized (requestResult) {
-            requestResult.set(new Buffer(buffer.getCompactData()));
+            requestResult.set(new ByteArrayBuffer(buffer.getCompactData()));
             resetIdleTimeout();
             requestResult.notify();
         }
@@ -1209,6 +1222,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @param defaultValue the default value
      * @return the value of the configuration property or the default value if not found
      */
+    @Override
     public int getIntProperty(String name, int defaultValue) {
         try {
             String v = factoryManager.getProperties().get(name);
@@ -1239,6 +1253,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @param key the key of the attribute; must not be null.
      * @return <tt>null</tt> if there is no attribute with the specified key
      */
+    @Override
     @SuppressWarnings("unchecked")
     public <T> T getAttribute(AttributeKey<T> key) {
         return (T)attributes.get(key);
@@ -1251,11 +1266,13 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * @param value the value of the attribute; must not be null.
      * @return The old value of the attribute.  <tt>null</tt> if it is new.
      */
+    @Override
     @SuppressWarnings("unchecked")
     public <T, E extends T> T setAttribute(AttributeKey<T> key, E value) {
         return (T)attributes.put(key, value);
     }
 
+    @Override
     public String getUsername() {
         return username;
     }
@@ -1267,6 +1284,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addListener(SessionListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException();
@@ -1277,6 +1295,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     /**
      * {@inheritDoc}
      */
+    @Override
     public void removeListener(SessionListener listener) {
         this.listeners.remove(listener);
     }
@@ -1288,6 +1307,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     /**
      * {@inheritDoc}
      */
+    @Override
     public SshFuture reExchangeKeys() throws IOException {
         if (kexState.compareAndSet(KEX_STATE_DONE, KEX_STATE_INIT)) {
             log.info("Initiating key re-exchange");
@@ -1331,6 +1351,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         }
     }
 
+    @Override
     public void resetIdleTimeout() {
         this.idleTimeoutTimestamp = System.currentTimeMillis() + idleTimeoutMs;
     }
@@ -1339,6 +1360,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * Check if timeout has occurred.
      * @return
      */
+    @Override
     public TimeoutStatus getTimeoutStatus() {
         return timeoutStatus.get();
     }
@@ -1347,6 +1369,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * What is timeout value in milliseconds for authentication stage
      * @return
      */
+    @Override
     public long getAuthTimeout() {
         return authTimeoutMs;
     }
@@ -1355,6 +1378,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
      * What is timeout value in milliseconds for communication
      * @return
      */
+    @Override
     public long getIdleTimeout() {
         return idleTimeoutMs;
     }
@@ -1376,6 +1400,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             return buffer;
         }
 
+        @Override
         public void verify() throws SshException {
             try {
                 await();
@@ -1388,10 +1413,12 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             }
         }
 
+        @Override
         public boolean isWritten() {
             return getValue() instanceof Boolean;
         }
 
+        @Override
         public Throwable getException() {
             Object v = getValue();
             return v instanceof Throwable ? (Throwable) v : null;
@@ -1408,6 +1435,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
             setValue(cause);
         }
 
+        @Override
         public void operationComplete(IoWriteFuture future) {
             if (future.isWritten()) {
                 setWritten();
@@ -1417,6 +1445,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         }
     }
 
+    @Override
     public String toString() {
         return getClass().getSimpleName() + "[" + getUsername() + "@" + getIoSession().getRemoteAddress() + "]";
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
index 5801801..2fdef4e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
@@ -20,7 +20,9 @@ package org.apache.sshd.common.signature;
 
 import java.io.IOException;
 import java.math.BigInteger;
-import org.apache.sshd.common.util.Buffer;
+
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * Signature algorithm for EC keys using ECDSA. There 
@@ -61,7 +63,7 @@ public class SignatureECDSA extends AbstractSignature {
         BigInteger s = new BigInteger(sArray);
 
         // Write the <r,s> to its own types writer.
-        Buffer rsBuf = new Buffer();
+        Buffer rsBuf = new ByteArrayBuffer();
         rsBuf.putMPInt(r);
         rsBuf.putMPInt(s);
 
@@ -72,7 +74,7 @@ public class SignatureECDSA extends AbstractSignature {
     public boolean verify(byte[] sig) throws Exception {
         sig = extractSig(sig);
 
-        Buffer rsBuf = new Buffer(sig);
+        Buffer rsBuf = new ByteArrayBuffer(sig);
         byte[] rArray = rsBuf.getMPIntAsBytes();
         byte[] sArray = rsBuf.getMPIntAsBytes();
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/Buffer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/Buffer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/Buffer.java
deleted file mode 100644
index 9697bb3..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/Buffer.java
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * 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.util;
-
-import java.math.BigInteger;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECPoint;
-import java.security.spec.ECPrivateKeySpec;
-import java.security.spec.ECPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-
-import org.apache.sshd.common.KeyPairProvider;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.cipher.ECCurves;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class Buffer implements Readable {
-
-    public static final int DEFAULT_SIZE = 256;
-    public static final int MAX_LEN = 65536;
-
-    private byte[] data;
-    private int rpos;
-    private int wpos;
-
-    public Buffer() {
-        this(DEFAULT_SIZE);
-    }
-
-    public Buffer(int size) {
-        this(new byte[getNextPowerOf2(size)], false);
-    }
-
-    public Buffer(byte[] data) {
-        this(data, 0, data.length, true);
-    }
-
-    public Buffer(byte[] data, boolean read) {
-        this(data, 0, data.length, read);
-    }
-
-    public Buffer(byte[] data, int off, int len) {
-        this(data, off, len, true);
-    }
-
-    public Buffer(byte[] data, int off, int len, boolean read) {
-        this.data = data;
-        this.rpos = off;
-        this.wpos = (read ? len : 0) + off;
-    }
-
-    @Override
-    public String toString() {
-        return "Buffer [rpos=" + rpos + ", wpos=" + wpos + ", size=" + data.length + "]";
-    }
-
-    /*======================
-      Global methods
-    ======================*/
-
-    public int rpos() {
-        return rpos;
-    }
-
-    public void rpos(int rpos) {
-        this.rpos = rpos;
-    }
-
-    public int wpos() {
-        return wpos;
-    }
-
-    public void wpos(int wpos) {
-        ensureCapacity(wpos - this.wpos);
-        this.wpos = wpos;
-    }
-
-    public int available() {
-        return wpos - rpos;
-    }
-
-    public int capacity() {
-        return data.length - wpos;
-    }
-
-    public byte[] array() {
-        return data;
-    }
-
-    public void compact() {
-        if (available() > 0) {
-            System.arraycopy(data, rpos, data, 0, wpos - rpos);
-        }
-        wpos -= rpos;
-        rpos = 0;
-    }
-
-    public byte[] getCompactData() {
-        int l = available();
-        if (l > 0) {
-            byte[] b = new byte[l];
-            System.arraycopy(data, rpos, b, 0, l);
-            return b;
-        } else {
-            return new byte[0];
-        }
-    }
-
-    public void clear() {
-        rpos = 0;
-        wpos = 0;
-    }
-
-    public String printHex() {
-        return BufferUtils.printHex(array(), rpos(), available());
-    }
-
-    /*======================
-       Read methods
-     ======================*/
-
-    public byte getByte() {
-        ensureAvailable(1);
-        return data[rpos++];
-    }
-
-    public int getInt() {
-        return (int) getUInt();
-    }
-
-    public long getUInt()
-    {
-        ensureAvailable(4);
-        long l = ((data[rpos++] << 24) & 0xff000000L)|
-                 ((data[rpos++] << 16) & 0x00ff0000L)|
-                 ((data[rpos++] <<  8) & 0x0000ff00L)|
-                 ((data[rpos++]      ) & 0x000000ffL);
-        return l;        
-    }
-
-    public long getLong()
-    {
-        ensureAvailable(8);
-        long l = (((long) data[rpos++] << 56) & 0xff00000000000000L)|
-                 (((long) data[rpos++] << 48) & 0x00ff000000000000L)|
-                 (((long) data[rpos++] << 40) & 0x0000ff0000000000L)|
-                 (((long) data[rpos++] << 32) & 0x000000ff00000000L)|
-                 (((long) data[rpos++] << 24) & 0x00000000ff000000L)|
-                 (((long) data[rpos++] << 16) & 0x0000000000ff0000L)|
-                 (((long) data[rpos++] <<  8) & 0x000000000000ff00L)|
-                 (((long) data[rpos++]      ) & 0x00000000000000ffL);
-        return l;
-    }
-
-    public boolean getBoolean() {
-        return getByte() != 0;
-    }
-
-    public String getString() {
-        return getString(StandardCharsets.UTF_8);
-    }
-
-    public String getString(Charset charset) {
-        int len = getInt();
-        if (len < 0) {
-            throw new IllegalStateException("Bad item length: " + len);
-        }
-        ensureAvailable(len);
-        String s = new String(data, rpos, len, charset);
-        rpos += len;
-        return s;
-    }
-
-    public byte[] getStringAsBytes() {
-        return getBytes();
-    }
-
-    public BigInteger getMPInt() {
-        return new BigInteger(getMPIntAsBytes());
-    }
-
-    public byte[] getMPIntAsBytes() {
-        return getBytes();
-    }
-
-    public byte[] getBytes() {
-        int len = getInt();
-        if (len < 0) {
-            throw new IllegalStateException("Bad item length: " + len);
-        }
-        ensureAvailable(len);
-        byte[] b = new byte[len];
-        getRawBytes(b);
-        return b;
-    }
-
-    public void getRawBytes(byte[] buf) {
-        getRawBytes(buf, 0, buf.length);
-    }
-
-    public void getRawBytes(byte[] buf, int off, int len) {
-        ensureAvailable(len);
-        System.arraycopy(data, rpos, buf, off, len);
-        rpos += len;
-    }
-
-    public PublicKey getPublicKey() throws SshException {
-        int ow = wpos;
-        int len = getInt();
-        wpos = rpos + len;
-        try {
-            return getRawPublicKey();
-        } finally {
-            wpos = ow;
-        }
-    }
-
-    public PublicKey getRawPublicKey() throws SshException {
-        try {
-            PublicKey key;
-            String keyAlg = getString();
-            if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
-                BigInteger e = getMPInt();
-                BigInteger n = getMPInt();
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
-                key = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
-            } else if (KeyPairProvider.SSH_DSS.equals(keyAlg)) {
-                BigInteger p = getMPInt();
-                BigInteger q = getMPInt();
-                BigInteger g = getMPInt();
-                BigInteger y = getMPInt();
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
-                key = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP256.equals(keyAlg)) {
-                key = getRawECKey("nistp256", ECCurves.EllipticCurves.nistp256);
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP384.equals(keyAlg)) {
-                key = getRawECKey("nistp384", ECCurves.EllipticCurves.nistp384);
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP521.equals(keyAlg)) {
-                key = getRawECKey("nistp521", ECCurves.EllipticCurves.nistp521);
-            } else {
-                throw new IllegalStateException("Unsupported algorithm: " + keyAlg);
-            }
-            return key;
-        } catch (InvalidKeySpecException e) {
-            throw new SshException(e);
-        } catch (NoSuchAlgorithmException e) {
-            throw new SshException(e);
-        } catch (NoSuchProviderException e) {
-            throw new SshException(e);
-        }
-    }
-
-    private PublicKey getRawECKey(String expectedCurve, ECParameterSpec spec) throws InvalidKeySpecException,
-            SshException, NoSuchAlgorithmException, NoSuchProviderException {
-        String curveName = getString();
-        if (!expectedCurve.equals(curveName)) {
-            throw new InvalidKeySpecException("Curve name does not match expected: " + curveName + " vs "
-                    + expectedCurve);
-        }
-        ECPoint w = ECCurves.decodeECPoint(getStringAsBytes(), spec.getCurve());
-        KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
-        return keyFactory.generatePublic(new ECPublicKeySpec(w, spec));
-    }
-
-    public KeyPair getKeyPair() throws SshException {
-        try {
-            PublicKey pub;
-            PrivateKey prv;
-            String keyAlg = getString();
-            if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
-                BigInteger e = getMPInt();
-                BigInteger n = getMPInt();
-                BigInteger d = getMPInt();
-                BigInteger qInv = getMPInt();
-                BigInteger q = getMPInt();
-                BigInteger p = getMPInt();
-                BigInteger dP = d.remainder(p.subtract(BigInteger.valueOf(1)));
-                BigInteger dQ = d.remainder(q.subtract(BigInteger.valueOf(1)));
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
-                pub = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
-                prv = keyFactory.generatePrivate(new RSAPrivateCrtKeySpec(n, e, d, p, q, dP, dQ, qInv));
-            } else if (KeyPairProvider.SSH_DSS.equals(keyAlg)) {
-                BigInteger p = getMPInt();
-                BigInteger q = getMPInt();
-                BigInteger g = getMPInt();
-                BigInteger y = getMPInt();
-                BigInteger x = getMPInt();
-                KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
-                pub = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
-                prv = keyFactory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g));
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP256.equals(keyAlg)) {
-                return extractEC("nistp256", ECCurves.EllipticCurves.nistp256);
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP384.equals(keyAlg)) {
-                return extractEC("nistp384", ECCurves.EllipticCurves.nistp384);
-            } else if (KeyPairProvider.ECDSA_SHA2_NISTP521.equals(keyAlg)) {
-                return extractEC("nistp521", ECCurves.EllipticCurves.nistp521);
-            } else {
-                throw new IllegalStateException("Unsupported algorithm: " + keyAlg);
-            }
-            return new KeyPair(pub, prv);
-        } catch (InvalidKeySpecException e) {
-            throw new SshException(e);
-        } catch (NoSuchAlgorithmException e) {
-            throw new SshException(e);
-        } catch (NoSuchProviderException e) {
-            throw new SshException(e);
-        }
-    }
-
-    private KeyPair extractEC(String expectedCurveName, ECParameterSpec spec) throws NoSuchAlgorithmException,
-            NoSuchProviderException, InvalidKeySpecException, SshException {
-        String curveName = getString();
-        byte[] groupBytes = getStringAsBytes();
-        BigInteger exponent = getMPInt();
-
-        if (!expectedCurveName.equals(curveName)) {
-            throw new SshException("Expected curve " + expectedCurveName + " but was " + curveName);
-        }
-
-        ECPoint group = ECCurves.decodeECPoint(groupBytes, spec.getCurve());
-        if (group == null) {
-            throw new InvalidKeySpecException("Couldn't decode EC group");
-        }
-
-        KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
-        PublicKey pubKey = keyFactory.generatePublic(new ECPublicKeySpec(group, spec));
-        PrivateKey privKey = keyFactory.generatePrivate(new ECPrivateKeySpec(exponent, spec));
-        return new KeyPair(pubKey, privKey);
-    }
-
-    private void ensureAvailable(int a) {
-        if (available() < a) {
-            throw new BufferException("Underflow");
-        }
-    }
-
-    /*======================
-       Write methods
-     ======================*/
-
-    public void putByte(byte b) {
-        ensureCapacity(1);
-        data[wpos++] = b;
-    }
-
-    public void putBuffer(Readable buffer) {
-        putBuffer(buffer, true);
-    }
-
-    public int putBuffer(Readable buffer, boolean expand) {
-        int r = expand ? buffer.available() : Math.min(buffer.available(), capacity());
-        ensureCapacity(r);
-        buffer.getRawBytes(data, wpos, r);
-        wpos += r;
-        return r;
-    }
-
-    /**
-     * Writes 16 bits
-     * @param i
-     */
-    public void putShort(int i) {
-        ensureCapacity(2);
-        data[wpos++] = (byte) (i >>  8);
-        data[wpos++] = (byte) (i      );
-    }
-
-    /**
-     * Writes 32 bits
-     * @param i
-     */
-    public void putInt(long i) {
-        ensureCapacity(4);
-        data[wpos++] = (byte) (i >> 24);
-        data[wpos++] = (byte) (i >> 16);
-        data[wpos++] = (byte) (i >>  8);
-        data[wpos++] = (byte) (i      );
-    }
-
-    /**
-     * Writes 64 bits
-     * @param i
-     */
-    public void putLong(long i) {
-        ensureCapacity(8);
-        data[wpos++] = (byte) (i >> 56);
-        data[wpos++] = (byte) (i >> 48);
-        data[wpos++] = (byte) (i >> 40);
-        data[wpos++] = (byte) (i >> 32);
-        data[wpos++] = (byte) (i >> 24);
-        data[wpos++] = (byte) (i >> 16);
-        data[wpos++] = (byte) (i >>  8);
-        data[wpos++] = (byte) (i      );
-    }
-
-    public void putBoolean(boolean b) {
-        putByte(b ? (byte) 1 : (byte) 0);
-    }
-
-    public void putBytes(byte[] b) {
-        putBytes(b, 0, b.length);
-    }
-
-    public void putBytes(byte[] b, int off, int len) {
-        putInt(len);
-        ensureCapacity(len);
-        System.arraycopy(b, off, data, wpos, len);
-        wpos += len;
-    }
-
-    public void putString(String string) {
-        putString(string, Charset.defaultCharset());
-    }
-
-    public void putString(String string, Charset charset) {
-        putString(string.getBytes(charset));
-    }
-
-    public void putString(byte[] str) {
-        putInt(str.length);
-        putRawBytes(str);
-    }
-
-    public void putMPInt(BigInteger bi) {
-        putMPInt(bi.toByteArray());
-    }
-
-    public void putMPInt(byte[] foo) {
-        int i = foo.length;
-        if ((foo[0] & 0x80) != 0) {
-            i++;
-            putInt(i);
-            putByte((byte)0);
-        } else {
-            putInt(i);
-        }
-        putRawBytes(foo);
-    }
-
-    public void putRawBytes(byte[] d) {
-        putRawBytes(d, 0, d.length);
-    }
-
-    public void putRawBytes(byte[] d, int off, int len) {
-        ensureCapacity(len);
-        System.arraycopy(d, off, data, wpos, len);
-        wpos += len;
-    }
-
-    public void putPublicKey(PublicKey key) {
-        int ow = wpos;
-        putInt(0);
-        int ow1 = wpos;
-        putRawPublicKey(key);
-        int ow2 = wpos;
-        wpos = ow;
-        putInt(ow2 - ow1);
-        wpos = ow2;
-    }
-
-    public void putRawPublicKey(PublicKey key) {
-        if (key instanceof RSAPublicKey) {
-            putString(KeyPairProvider.SSH_RSA);
-            putMPInt(((RSAPublicKey) key).getPublicExponent());
-            putMPInt(((RSAPublicKey) key).getModulus());
-        } else if (key instanceof DSAPublicKey) {
-            putString(KeyPairProvider.SSH_DSS);
-            putMPInt(((DSAPublicKey) key).getParams().getP());
-            putMPInt(((DSAPublicKey) key).getParams().getQ());
-            putMPInt(((DSAPublicKey) key).getParams().getG());
-            putMPInt(((DSAPublicKey) key).getY());
-        } else if (key instanceof ECPublicKey) {
-            ECPublicKey ecKey = (ECPublicKey) key;
-            ECParameterSpec ecParams = ecKey.getParams();
-            String curveName = ECCurves.getCurveName(ecParams);
-            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
-            putString(curveName);
-            putBytes(ECCurves.encodeECPoint(ecKey.getW(), ecParams.getCurve()));
-        } else {
-            throw new IllegalStateException("Unsupported algorithm: " + key.getAlgorithm());
-        }
-    }
-
-    public void putKeyPair(KeyPair key) {
-        if (key.getPrivate() instanceof RSAPrivateCrtKey) {
-            putString(KeyPairProvider.SSH_RSA);
-            putMPInt(((RSAPublicKey) key.getPublic()).getPublicExponent());
-            putMPInt(((RSAPublicKey) key.getPublic()).getModulus());
-            putMPInt(((RSAPrivateCrtKey) key.getPrivate()).getPrivateExponent());
-            putMPInt(((RSAPrivateCrtKey) key.getPrivate()).getCrtCoefficient());
-            putMPInt(((RSAPrivateCrtKey) key.getPrivate()).getPrimeQ());
-            putMPInt(((RSAPrivateCrtKey) key.getPrivate()).getPrimeP());
-        } else if (key.getPublic() instanceof DSAPublicKey) {
-            putString(KeyPairProvider.SSH_DSS);
-            putMPInt(((DSAPublicKey) key.getPublic()).getParams().getP());
-            putMPInt(((DSAPublicKey) key.getPublic()).getParams().getQ());
-            putMPInt(((DSAPublicKey) key.getPublic()).getParams().getG());
-            putMPInt(((DSAPublicKey) key.getPublic()).getY());
-            putMPInt(((DSAPrivateKey) key.getPrivate()).getX());
-        } else if (key.getPublic() instanceof ECPublicKey) {
-            ECPublicKey ecPub = (ECPublicKey) key.getPublic();
-            ECPrivateKey ecPriv = (ECPrivateKey) key.getPrivate();
-            ECParameterSpec ecParams = ecPub.getParams();
-            String curveName = ECCurves.getCurveName(ecParams);
-
-            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
-            putString(curveName);
-            putString(ECCurves.encodeECPoint(ecPub.getW(), ecParams.getCurve()));
-            putMPInt(ecPriv.getS());
-        } else {
-            throw new IllegalStateException("Unsupported algorithm: " + key.getPublic().getAlgorithm());
-        }
-    }
-
-    private void ensureCapacity(int capacity) {
-        if (data.length - wpos < capacity) {
-            int cw = wpos + capacity;
-            byte[] tmp = new byte[getNextPowerOf2(cw)];
-            System.arraycopy(data, 0, tmp, 0, data.length);
-            data = tmp;
-        }
-    }
-
-    public static class BufferException extends RuntimeException {
-        public BufferException(String message) {
-            super(message);
-        }
-    }
-
-    private static int getNextPowerOf2(int i) {
-        int j = 1;
-        while (j < i) {
-            j <<= 1;
-        }
-        return j;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/BufferUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/BufferUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/BufferUtils.java
deleted file mode 100644
index dde95e6..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/BufferUtils.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.util;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class BufferUtils {
-
-    public static String printHex(byte[] array) {
-        return printHex(array, 0, array.length);
-    }
-
-    public static String printHex(byte[] array, int offset, int len) {
-        return printHex(array, offset, len, ' ');
-    }
-
-    public static String printHex(byte[] array, int offset, int len, char sep) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < len; i++) {
-            byte b = array[offset + i];
-            if (sb.length() > 0) {
-                sb.append(sep);
-            }
-            sb.append(digits[(b >> 4) & 0x0F]);
-            sb.append(digits[b & 0x0F]);
-        }
-        return sb.toString();
-    }
-
-    public static boolean equals(byte[] a1, byte[] a2) {
-        if (a1.length != a2.length) {
-            return false;
-        }
-        return equals(a1, 0, a2, 0, a1.length);
-    }
-
-    public static boolean equals(byte[] a1, int a1Offset, byte[] a2, int a2Offset, int length) {
-        if (a1.length < a1Offset + length || a2.length < a2Offset + length) {
-            return false;
-        }
-        while (length-- > 0) {
-            if (a1[a1Offset++] != a2[a2Offset++]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    final static char[] digits = {
-	    '0' , '1' , '2' , '3' , '4' , '5' ,
-	    '6' , '7' , '8' , '9' , 'a' , 'b' ,
-	    'c' , 'd' , 'e' , 'f'
-    };
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index ebc600a..0fad1b7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -36,6 +36,7 @@ import java.util.TreeSet;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public class GenericUtils {
+    public static final byte[]      EMPTY_BYTE_ARRAY={ };
     public static final String[]    EMPTY_STRING_ARRAY={ };
     public static final Object[]    EMPTY_OBJECT_ARRAY={ };
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
index 6c7800a..d86c024 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
@@ -30,6 +30,9 @@ import org.apache.sshd.common.Digest;
 import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.cipher.ECCurves;
 import org.apache.sshd.common.digest.BuiltinDigests;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 
 /**
  * Utility class for keys
@@ -46,7 +49,7 @@ public class KeyUtils {
      */
     public static String getFingerPrint(PublicKey key) {
         try {
-            Buffer buffer = new Buffer();
+            Buffer buffer = new ByteArrayBuffer();
             buffer.putRawPublicKey(key);
             Digest md5 = BuiltinDigests.md5.create();
             md5.init();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
new file mode 100644
index 0000000..93d006c
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
@@ -0,0 +1,489 @@
+/*
+ * 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.util.buffer;
+
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.SecurityUtils;
+
+/**
+ * Provides an abstract message buffer for encoding SSH messages
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class Buffer implements Readable {
+
+    // TODO use Long.BYTES in JDK-8
+    protected final byte[]  workBuf = new byte[Long.SIZE / Byte.SIZE];
+
+    protected Buffer() {
+        super();
+    }
+
+    /*======================
+      Global methods
+    ======================*/
+
+    public abstract int rpos();
+    public abstract void rpos(int rpos);
+
+    public abstract int wpos();
+
+    public abstract void wpos(int wpos);
+
+    public abstract int capacity();
+    public abstract byte[] array();
+
+    public abstract void compact();
+
+    public byte[] getCompactData() {
+        int l = available();
+        if (l > 0) {
+            byte[] b = new byte[l];
+            System.arraycopy(array(), rpos(), b, 0, l);
+            return b;
+        } else {
+            return GenericUtils.EMPTY_BYTE_ARRAY;
+        }
+    }
+
+    public abstract void clear();
+
+    public String printHex() {
+        return BufferUtils.printHex(array(), rpos(), available());
+    }
+
+    /*======================
+       Read methods
+     ======================*/
+
+    public byte getByte() {
+        // TODO use Byte.BYTES for JDK-8
+        ensureAvailable(Byte.SIZE / Byte.SIZE);
+        getRawBytes(workBuf, 0, Byte.SIZE / Byte.SIZE);
+        return workBuf[0];
+    }
+
+    public int getInt() {
+        return (int) getUInt();
+    }
+
+    public long getUInt() {
+        // TODO use Integer.BYTES for JDK-8
+        ensureAvailable(Integer.SIZE / Byte.SIZE);
+        getRawBytes(workBuf, 0, Integer.SIZE / Byte.SIZE);
+        long l = ((workBuf[0] << 24) & 0xff000000L)|
+                 ((workBuf[1] << 16) & 0x00ff0000L)|
+                 ((workBuf[2] <<  8) & 0x0000ff00L)|
+                 ((workBuf[3]      ) & 0x000000ffL);
+        return l;        
+    }
+
+    public long getLong() {
+        // TODO use Long.BYTES for JDK-8
+        ensureAvailable(Long.SIZE / Byte.SIZE);
+        getRawBytes(workBuf, 0, Long.SIZE / Byte.SIZE);
+        @SuppressWarnings("cast")
+        long l = (((long) workBuf[0] << 56) & 0xff00000000000000L)|
+                 (((long) workBuf[1] << 48) & 0x00ff000000000000L)|
+                 (((long) workBuf[2] << 40) & 0x0000ff0000000000L)|
+                 (((long) workBuf[3] << 32) & 0x000000ff00000000L)|
+                 (((long) workBuf[4] << 24) & 0x00000000ff000000L)|
+                 (((long) workBuf[5] << 16) & 0x0000000000ff0000L)|
+                 (((long) workBuf[6] <<  8) & 0x000000000000ff00L)|
+                 (((long) workBuf[7]      ) & 0x00000000000000ffL);
+        return l;
+    }
+
+    public boolean getBoolean() {
+        return getByte() != 0;
+    }
+
+    public String getString() {
+        return getString(StandardCharsets.UTF_8);
+    }
+
+    public abstract String getString(Charset charset);
+
+    public byte[] getStringAsBytes() {
+        return getBytes();
+    }
+
+    public BigInteger getMPInt() {
+        return new BigInteger(getMPIntAsBytes());
+    }
+
+    public byte[] getMPIntAsBytes() {
+        return getBytes();
+    }
+
+    public byte[] getBytes() {
+        int len = getInt();
+        if (len < 0) {
+            throw new BufferException("Bad item length: " + len);
+        }
+        ensureAvailable(len);
+        byte[] b = new byte[len];
+        getRawBytes(b);
+        return b;
+    }
+
+    public void getRawBytes(byte[] buf) {
+        getRawBytes(buf, 0, buf.length);
+    }
+
+    public PublicKey getPublicKey() throws SshException {
+        int ow = wpos();
+        int len = getInt();
+        wpos(rpos() + len);
+        try {
+            return getRawPublicKey();
+        } finally {
+            wpos(ow);
+        }
+    }
+
+    public PublicKey getRawPublicKey() throws SshException {
+        try {
+            PublicKey key;
+            String keyAlg = getString();
+            if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
+                BigInteger e = getMPInt();
+                BigInteger n = getMPInt();
+                KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
+                key = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
+            } else if (KeyPairProvider.SSH_DSS.equals(keyAlg)) {
+                BigInteger p = getMPInt();
+                BigInteger q = getMPInt();
+                BigInteger g = getMPInt();
+                BigInteger y = getMPInt();
+                KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
+                key = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP256.equals(keyAlg)) {
+                key = getRawECKey("nistp256", ECCurves.EllipticCurves.nistp256);
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP384.equals(keyAlg)) {
+                key = getRawECKey("nistp384", ECCurves.EllipticCurves.nistp384);
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP521.equals(keyAlg)) {
+                key = getRawECKey("nistp521", ECCurves.EllipticCurves.nistp521);
+            } else {
+                throw new NoSuchAlgorithmException("Unsupported raw public algorithm: " + keyAlg);
+            }
+            return key;
+        } catch (GeneralSecurityException e) {
+            throw new SshException(e);
+        }
+    }
+
+    protected PublicKey getRawECKey(String expectedCurve, ECParameterSpec spec) throws GeneralSecurityException, SshException {
+        String curveName = getString();
+        if (!expectedCurve.equals(curveName)) {
+            throw new InvalidKeySpecException("Curve name does not match expected: " + curveName + " vs "
+                    + expectedCurve);
+        }
+        ECPoint w = ECCurves.decodeECPoint(getStringAsBytes(), spec.getCurve());
+        KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
+        return keyFactory.generatePublic(new ECPublicKeySpec(w, spec));
+    }
+
+    public KeyPair getKeyPair() throws SshException {
+        try {
+            PublicKey pub;
+            PrivateKey prv;
+            String keyAlg = getString();
+            if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
+                BigInteger e = getMPInt();
+                BigInteger n = getMPInt();
+                BigInteger d = getMPInt();
+                BigInteger qInv = getMPInt();
+                BigInteger q = getMPInt();
+                BigInteger p = getMPInt();
+                BigInteger dP = d.remainder(p.subtract(BigInteger.valueOf(1)));
+                BigInteger dQ = d.remainder(q.subtract(BigInteger.valueOf(1)));
+                KeyFactory keyFactory = SecurityUtils.getKeyFactory("RSA");
+                pub = keyFactory.generatePublic(new RSAPublicKeySpec(n, e));
+                prv = keyFactory.generatePrivate(new RSAPrivateCrtKeySpec(n, e, d, p, q, dP, dQ, qInv));
+            } else if (KeyPairProvider.SSH_DSS.equals(keyAlg)) {
+                BigInteger p = getMPInt();
+                BigInteger q = getMPInt();
+                BigInteger g = getMPInt();
+                BigInteger y = getMPInt();
+                BigInteger x = getMPInt();
+                KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
+                pub = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
+                prv = keyFactory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g));
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP256.equals(keyAlg)) {
+                return extractEC("nistp256", ECCurves.EllipticCurves.nistp256);
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP384.equals(keyAlg)) {
+                return extractEC("nistp384", ECCurves.EllipticCurves.nistp384);
+            } else if (KeyPairProvider.ECDSA_SHA2_NISTP521.equals(keyAlg)) {
+                return extractEC("nistp521", ECCurves.EllipticCurves.nistp521);
+            } else {
+                throw new NoSuchAlgorithmException("Unsupported key pair algorithm: " + keyAlg);
+            }
+            return new KeyPair(pub, prv);
+        } catch (GeneralSecurityException e) {
+            throw new SshException(e);
+        }
+    }
+
+    protected KeyPair extractEC(String expectedCurveName, ECParameterSpec spec) throws GeneralSecurityException, SshException {
+        String curveName = getString();
+        byte[] groupBytes = getStringAsBytes();
+        BigInteger exponent = getMPInt();
+
+        if (!expectedCurveName.equals(curveName)) {
+            throw new SshException("Expected curve " + expectedCurveName + " but was " + curveName);
+        }
+
+        ECPoint group = ECCurves.decodeECPoint(groupBytes, spec.getCurve());
+        if (group == null) {
+            throw new InvalidKeySpecException("Couldn't decode EC group");
+        }
+
+        KeyFactory keyFactory = SecurityUtils.getKeyFactory("EC");
+        PublicKey pubKey = keyFactory.generatePublic(new ECPublicKeySpec(group, spec));
+        PrivateKey privKey = keyFactory.generatePrivate(new ECPrivateKeySpec(exponent, spec));
+        return new KeyPair(pubKey, privKey);
+    }
+
+    public void ensureAvailable(int a) throws BufferException {
+        if (available() < a) {
+            throw new BufferException("Underflow");
+        }
+    }
+
+    /*======================
+       Write methods
+     ======================*/
+
+    public void putByte(byte b) {
+        // TODO use Byte.BYTES in JDK-8
+        ensureCapacity(Byte.SIZE / Byte.SIZE);
+        workBuf[0] = b;
+        putRawBytes(workBuf, 0, Byte.SIZE / Byte.SIZE);
+    }
+
+    public void putBuffer(Readable buffer) {
+        putBuffer(buffer, true);
+    }
+
+    public abstract int putBuffer(Readable buffer, boolean expand);
+
+    /**
+     * Writes 16 bits
+     * @param i
+     */
+    public void putShort(int i) {
+        // TODO use Short.BYTES for JDK-8
+        ensureCapacity(Short.SIZE / Byte.SIZE);
+        workBuf[0] = (byte) (i >>  8);
+        workBuf[1] = (byte) (i      );
+        putRawBytes(workBuf, 0, Short.SIZE / Byte.SIZE);
+    }
+
+    /**
+     * Writes 32 bits
+     * @param i
+     */
+    public void putInt(long i) {
+        // TODO use Integer.BYTES for JDK-8
+        ensureCapacity(Integer.SIZE / Byte.SIZE);
+        workBuf[0] = (byte) (i >> 24);
+        workBuf[1] = (byte) (i >> 16);
+        workBuf[2] = (byte) (i >>  8);
+        workBuf[3] = (byte) (i      );
+        putRawBytes(workBuf, 0, Integer.SIZE / Byte.SIZE);
+    }
+
+    /**
+     * Writes 64 bits
+     * @param i
+     */
+    public void putLong(long i) {
+        // TODO use Long.BYTES for JDK-8
+        ensureCapacity(Long.SIZE / Byte.SIZE);
+        workBuf[0] = (byte) (i >> 56);
+        workBuf[1] = (byte) (i >> 48);
+        workBuf[2] = (byte) (i >> 40);
+        workBuf[3] = (byte) (i >> 32);
+        workBuf[4] = (byte) (i >> 24);
+        workBuf[5] = (byte) (i >> 16);
+        workBuf[6] = (byte) (i >>  8);
+        workBuf[7] = (byte) (i      );
+        putRawBytes(workBuf, 0, Long.SIZE / Byte.SIZE);
+    }
+
+    public void putBoolean(boolean b) {
+        putByte(b ? (byte) 1 : (byte) 0);
+    }
+
+    public void putBytes(byte[] b) {
+        putBytes(b, 0, b.length);
+    }
+
+    public void putBytes(byte[] b, int off, int len) {
+        putInt(len);
+        putRawBytes(b, off, len);
+    }
+
+    public void putString(String string) {
+        putString(string, StandardCharsets.UTF_8);
+    }
+
+    public void putString(String string, Charset charset) {
+        putBytes(string.getBytes(charset));
+    }
+
+    public void putMPInt(BigInteger bi) {
+        putMPInt(bi.toByteArray());
+    }
+
+    public void putMPInt(byte[] foo) {
+        int i = foo.length;
+        if ((foo[0] & 0x80) != 0) {
+            i++;
+            putInt(i);
+            putByte((byte)0);
+        } else {
+            putInt(i);
+        }
+        putRawBytes(foo);
+    }
+
+    public void putRawBytes(byte[] d) {
+        putRawBytes(d, 0, d.length);
+    }
+
+    public abstract void putRawBytes(byte[] d, int off, int len);
+
+    public void putPublicKey(PublicKey key) {
+        int ow = wpos();
+        putInt(0);
+        int ow1 = wpos();
+        putRawPublicKey(key);
+        int ow2 = wpos();
+        wpos(ow);
+        putInt(ow2 - ow1);
+        wpos(ow2);
+    }
+
+    public void putRawPublicKey(PublicKey key) {
+        if (key instanceof RSAPublicKey) {
+            RSAPublicKey rsaPub = (RSAPublicKey) key;
+
+            putString(KeyPairProvider.SSH_RSA);
+            putMPInt(rsaPub.getPublicExponent());
+            putMPInt(rsaPub.getModulus());
+        } else if (key instanceof DSAPublicKey) {
+            DSAPublicKey    dsaPub = (DSAPublicKey) key;
+            DSAParams       dsaParams = dsaPub.getParams();
+
+            putString(KeyPairProvider.SSH_DSS);
+            putMPInt(dsaParams.getP());
+            putMPInt(dsaParams.getQ());
+            putMPInt(dsaParams.getG());
+            putMPInt(dsaPub.getY());
+        } else if (key instanceof ECPublicKey) {
+            ECPublicKey     ecKey = (ECPublicKey) key;
+            ECParameterSpec ecParams = ecKey.getParams();
+            String          curveName = ECCurves.getCurveName(ecParams);
+            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
+            putString(curveName);
+            putBytes(ECCurves.encodeECPoint(ecKey.getW(), ecParams.getCurve()));
+        } else {
+            throw new BufferException("Unsupported raw public key algorithm: " + key.getAlgorithm());
+        }
+    }
+
+    public void putKeyPair(KeyPair kp) {
+        PublicKey   pubKey = kp.getPublic();
+        PrivateKey  prvKey = kp.getPrivate();
+        if (prvKey instanceof RSAPrivateCrtKey) {
+            RSAPublicKey        rsaPub = (RSAPublicKey) pubKey;
+            RSAPrivateCrtKey    rsaPrv = (RSAPrivateCrtKey) prvKey;
+
+            putString(KeyPairProvider.SSH_RSA);
+            putMPInt(rsaPub.getPublicExponent());
+            putMPInt(rsaPub.getModulus());
+            putMPInt(rsaPrv.getPrivateExponent());
+            putMPInt(rsaPrv.getCrtCoefficient());
+            putMPInt(rsaPrv.getPrimeQ());
+            putMPInt(rsaPrv.getPrimeP());
+        } else if (pubKey instanceof DSAPublicKey) {
+            DSAPublicKey    dsaPub = (DSAPublicKey) pubKey;
+            DSAParams       dsaParams = dsaPub.getParams();
+            DSAPrivateKey   dsaPrv = (DSAPrivateKey) prvKey;
+
+            putString(KeyPairProvider.SSH_DSS);
+            putMPInt(dsaParams.getP());
+            putMPInt(dsaParams.getQ());
+            putMPInt(dsaParams.getG());
+            putMPInt(dsaPub.getY());
+            putMPInt(dsaPrv.getX());
+        } else if (pubKey instanceof ECPublicKey) {
+            ECPublicKey     ecPub = (ECPublicKey) pubKey;
+            ECPrivateKey    ecPriv = (ECPrivateKey) prvKey;
+            ECParameterSpec ecParams = ecPub.getParams();
+            String          curveName = ECCurves.getCurveName(ecParams);
+
+            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
+            putString(curveName);
+            putBytes(ECCurves.encodeECPoint(ecPub.getW(), ecParams.getCurve()));
+            putMPInt(ecPriv.getS());
+        } else {
+            throw new BufferException("Unsupported key pair algorithm: " + kp.getPublic().getAlgorithm());
+        }
+    }
+
+    protected abstract void ensureCapacity(int capacity);
+    protected abstract int size();
+
+    @Override
+    public String toString() {
+        return "Buffer [rpos=" + rpos() + ", wpos=" + wpos() + ", size=" + size() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9f0bb1bc/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/BufferException.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/BufferException.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/BufferException.java
new file mode 100644
index 0000000..e8d298d
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/BufferException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.util.buffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class BufferException extends RuntimeException {
+    private static final long serialVersionUID = 658645233475011039L;
+
+    public BufferException(String message) {
+        super(message);
+    }
+}
\ No newline at end of file