diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java
index 8d38f4f579be8216e1c1f9bda4630cb00dfb4a87..018655d8b8a0e92763cf2f63a85dfd72d4b6a468 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java
@@ -13,6 +13,14 @@ import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.Properties;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+
+import net.i2p.data.Destination;
+import net.i2p.data.DataFormatException;
+import net.i2p.data.PrivateKey;
+import net.i2p.data.SigningPrivateKey;
 
 import net.i2p.util.I2PThread;
 import net.i2p.util.Log;
@@ -27,11 +35,16 @@ public class SAMBridge implements Runnable {
     private final static Log _log = new Log(SAMBridge.class);
     private ServerSocket serverSocket;
     private Properties i2cpProps;
+    /** 
+     * app designated destination name to the base64 of the I2P formatted 
+     * destination keys (Destination+PrivateKey+SigningPrivateKey)
+     */
+    private Map nameToPrivKeys = Collections.synchronizedMap(new HashMap(8));
 
     private boolean acceptConnections = true;
 
     private final static int SAM_LISTENPORT = 7656;
-
+    
     private SAMBridge() {}
     
     /**
@@ -63,6 +76,46 @@ public class SAMBridge implements Runnable {
         this.i2cpProps = i2cpProps;
     }
 
+    /**
+     * Retrieve the destination associated with the given name
+     *
+     * @return null if the name does not exist, or if it is improperly formatted
+     */
+    public Destination getDestination(String name) {
+        String val = (String)nameToPrivKeys.get(name);
+        if (val == null) return null;
+        try {
+            Destination d = new Destination();
+            d.fromBase64(val);
+            return d;
+        } catch (DataFormatException dfe) {
+            _log.error("Error retrieving the destination from " + name, dfe);
+            nameToPrivKeys.remove(name);
+            return null;
+        }
+    }
+    
+    /**
+     * Retrieve the I2P private keystream for the given name, formatted
+     * as a base64 string (Destination+PrivateKey+SessionPrivateKey, as I2CP 
+     * stores it).
+     *
+     * @return null if the name does not exist, else the stream
+     */
+    public String getKeystream(String name) {
+        String val = (String)nameToPrivKeys.get(name);
+        if (val == null) return null;
+        return val;
+    }
+
+    /**
+     * Specify that the given keystream should be used for the given name
+     *
+     */
+    public void addKeystream(String name, String stream) {
+        nameToPrivKeys.put(name, stream);
+    }
+    
     /**
      * Usage:
      *  <pre>SAMBridge [[listenHost ]listenPort[ name=val]*]</pre>
@@ -140,10 +193,18 @@ public class SAMBridge implements Runnable {
                         } catch (IOException e) {}
                         continue;
                     }
+                    handler.setBridge(this);
                     handler.startHandling();
                 } catch (SAMException e) {
                     if (_log.shouldLog(Log.ERROR))
                         _log.error("SAM error: " + e.getMessage(), e);
+                    try {
+                        String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n";
+                        s.getOutputStream().write(reply.getBytes("ISO-8859-1"));
+                    } catch (IOException ioe) {
+                        if (_log.shouldLog(Log.ERROR))
+                            _log.error("SAM Error sending error reply", ioe);
+                    }
                     s.close();
                 }
             }
diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java
index 3eb9492cc904d6d934b987d46cff3be9db009799..757f137f9e840058c20639edd601e8a5f014f2b6 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java
@@ -30,6 +30,7 @@ import net.i2p.util.Log;
 public class SAMDatagramSession extends SAMMessageSession {
 
     private final static Log _log = new Log(SAMDatagramSession.class);
+    public static int DGRAM_SIZE_MAX = 31*1024;
 
     private SAMDatagramReceiver recv = null;
 
@@ -43,7 +44,8 @@ public class SAMDatagramSession extends SAMMessageSession {
      * @param recv Object that will receive incoming data
      */
     public SAMDatagramSession(String dest, Properties props,
-                         SAMDatagramReceiver recv) throws IOException, DataFormatException, I2PSessionException {
+                              SAMDatagramReceiver recv) throws IOException, 
+                              DataFormatException, I2PSessionException {
         super(dest, props);
 
         this.recv = recv;
@@ -58,7 +60,8 @@ public class SAMDatagramSession extends SAMMessageSession {
      * @param recv Object that will receive incoming data
      */
     public SAMDatagramSession(InputStream destStream, Properties props,
-                         SAMDatagramReceiver recv) throws IOException, DataFormatException, I2PSessionException {
+                              SAMDatagramReceiver recv) throws IOException, 
+                              DataFormatException, I2PSessionException {
         super(destStream, props);
 
         this.recv = recv;
@@ -73,6 +76,9 @@ public class SAMDatagramSession extends SAMMessageSession {
      * @return True if the data was sent, false otherwise
      */
     public boolean sendBytes(String dest, byte[] data) throws DataFormatException {
+        if (data.length > DGRAM_SIZE_MAX)
+            throw new DataFormatException("Datagram size exceeded (" + data.length + ")");
+        
         byte[] dgram = dgramMaker.makeI2PDatagram(data);
 
         return sendBytesThroughMessageSession(dest, dgram);
diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java
index f1084316c8f973ea0b7442dd656225223b191a71..bba48361a7fc1651fd068d9319325d1b2a43ca6c 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java
@@ -30,6 +30,7 @@ public abstract class SAMHandler implements Runnable {
     private final static Log _log = new Log(SAMHandler.class);
 
     protected I2PThread thread = null;
+    protected SAMBridge bridge = null;
 
     private Object socketWLock = new Object(); // Guards writings on socket
     private Socket socket = null;
@@ -71,6 +72,8 @@ public abstract class SAMHandler implements Runnable {
         thread.start();
     }
     
+    public void setBridge(SAMBridge bridge) { this.bridge = bridge; }
+    
     /**
      * Actually handle the SAM protocol.
      *
@@ -124,7 +127,9 @@ public abstract class SAMHandler implements Runnable {
      *
      */
     protected final void closeClientSocket() throws IOException {
-        socket.close();
+        if (socket != null)
+            socket.close();
+        socket = null;
     }
 
     /**
diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
index 6bb6f6d8642d170a852a849eff385e168c4dbfcc..8adb573fd3a27621a9182dca52c065275e4dde59 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
@@ -32,8 +32,8 @@ public class SAMHandlerFactory {
      *
      * @param s Socket attached to SAM client
      * @param i2cpProps config options for our i2cp connection
-     *
-     * @return A SAM protocol handler
+     * @throws SAMException if the connection handshake (HELLO message) was malformed
+     * @return A SAM protocol handler, or null if the client closed before the handshake
      */
     public static SAMHandler createSAMHandler(Socket s, Properties i2cpProps) throws SAMException {
         BufferedReader br;
@@ -66,8 +66,8 @@ public class SAMHandlerFactory {
         {
             String opcode;
             if (!(opcode = tok.nextToken()).equals("VERSION")) {
-                throw new SAMException("Unrecognized HELLO message opcode: \""
-                                       + opcode + "\"");
+                throw new SAMException("Unrecognized HELLO message opcode: '"
+                                       + opcode + "'");
             }
         }
 
@@ -88,22 +88,8 @@ public class SAMHandlerFactory {
         }
 
         String ver = chooseBestVersion(minVer, maxVer);
-        if (ver == null) {
-            // Let's answer negatively
-            try {
-                OutputStream out = s.getOutputStream();
-                out.write("HELLO REPLY RESULT=NOVERSION\n".getBytes("ISO-8859-1"));
-                return null;
-            } catch (UnsupportedEncodingException e) {
-                _log.error("Caught UnsupportedEncodingException ("
-                           + e.getMessage() + ")");
-                throw new SAMException("Character encoding error: "
-                                       + e.getMessage());
-            } catch (IOException e) {
-                throw new SAMException("Error reading from socket: "
-                                       + e.getMessage());
-            }
-        }
+        if (ver == null)
+            throw new SAMException("No version specified");
 
         // Let's answer positively
         try {
@@ -135,8 +121,8 @@ public class SAMHandlerFactory {
                 throw new SAMException("BUG! (in handler instantiation)");
             }
         } catch (IOException e) {
-            _log.error("IOException caught during SAM handler instantiation");
-            return null;
+            _log.error("Error creating the v1 handler", e);
+            throw new SAMException("IOException caught during SAM handler instantiation");
         }
         return handler;
     }
diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java
index 13b4785c00cca2d028ecee577f6a78e5cbc53db0..33dbe37963ceebb6a4d3453ef55825e44f50ad19 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java
@@ -26,6 +26,7 @@ import net.i2p.util.Log;
 public class SAMRawSession extends SAMMessageSession {
 
     private final static Log _log = new Log(SAMRawSession.class);
+    public static final int RAW_SIZE_MAX = 32*1024;
 
     private SAMRawReceiver recv = null;
     /**
@@ -64,6 +65,8 @@ public class SAMRawSession extends SAMMessageSession {
      * @return True if the data was sent, false otherwise
      */
     public boolean sendBytes(String dest, byte[] data) throws DataFormatException {
+        if (data.length > RAW_SIZE_MAX)
+            throw new DataFormatException("Data size limit exceeded (" + data.length + ")");
         return sendBytesThroughMessageSession(dest, data);
     }
 
diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
index f845b843354c07957debfe9bee45b89a2b1ab2c9..d3151a096b8b898813d58d0bbbd0a97cfd302f99 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
@@ -101,7 +101,6 @@ public class SAMStreamSession {
         allprops.putAll(System.getProperties());
         allprops.putAll(props);
 
-        // FIXME: we should setup I2CP host and port, too
         String i2cpHost = allprops.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
         int i2cpPort = 7654;
         String port = allprops.getProperty(I2PClient.PROP_TCP_PORT, "7654");
@@ -113,6 +112,7 @@ public class SAMStreamSession {
         // streams MUST be mode=guaranteed (though i think the socket manager 
         // enforces this anyway...
         allprops.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED);
+
         _log.debug("Creating I2PSocketManager...");
         socketMgr = I2PSocketManagerFactory.createManager(destStream,
                                                           i2cpHost,
diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
index 09dce27f3d3dd9aaa06045cba63b893b5a81201c..0ae440764160b8026828133ea1c30c35dce1b3cd 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
@@ -33,7 +33,6 @@ import net.i2p.I2PAppContext;
 public class SAMUtils {
 
     private final static Log _log = new Log(SAMUtils.class);
-    private static I2PAppContext _context = new I2PAppContext();
 
     /**
      * Generate a random destination key
@@ -86,7 +85,7 @@ public class SAMUtils {
      * @return the Destination for the specified hostname, or null if not found
      */
     public static Destination lookupHost(String name, OutputStream pubKey) {
-        NamingService ns = _context.namingService();
+        NamingService ns = I2PAppContext.getGlobalContext().namingService();
         Destination dest = ns.lookup(name);
 
         if ((pubKey != null) && (dest != null)) {
@@ -144,13 +143,13 @@ public class SAMUtils {
 
     /* Dump a Properties object in an human-readable form */
     private static String dumpProperties(Properties props) {
-        Enumeration enum = props.propertyNames();
+        Enumeration names = props.propertyNames();
         String msg = "";
         String key, val;
         boolean firstIter = true;
         
-        while (enum.hasMoreElements()) {
-            key = (String)enum.nextElement();
+        while (names.hasMoreElements()) {
+            key = (String)names.nextElement();
             val = props.getProperty(key);
             
             if (!firstIter) {
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
index d4fd7350b025f6b438b30158b5b3f5ee267ea420..b9eea3d353c340a9bb58514ab23a65eda6e84016 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
@@ -154,10 +154,10 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
             }
         } catch (UnsupportedEncodingException e) {
             _log.error("Caught UnsupportedEncodingException ("
-                       + e.getMessage() + ")");
+                       + e.getMessage() + ")", e);
         } catch (IOException e) {
             _log.debug("Caught IOException ("
-                       + e.getMessage() + ")");
+                       + e.getMessage() + ")", e);
         } catch (Exception e) {
             _log.error("Unexpected exception", e);
         } finally {
@@ -189,32 +189,47 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
                 if ((rawSession != null) || (datagramSession != null)
                     || (streamSession != null)) {
                     _log.debug("Trying to create a session, but one still exists");
-                    return false;
+                    return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n");
                 }
                 if (props == null) {
                     _log.debug("No parameters specified in SESSION CREATE message");
-                    return false;
+                    return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n");
                 }
                 
                 dest = props.getProperty("DESTINATION");
                 if (dest == null) {
                     _log.debug("SESSION DESTINATION parameter not specified");
-                    return false;
+                    return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n");
                 }
                 props.remove("DESTINATION");
-
+                
+                String destKeystream = null;
+                
                 if (dest.equals("TRANSIENT")) {
                     _log.debug("TRANSIENT destination requested");
-                    ByteArrayOutputStream priv = new ByteArrayOutputStream();
+                    ByteArrayOutputStream priv = new ByteArrayOutputStream(640);
                     SAMUtils.genRandomKey(priv, null);
                     
-                    dest = Base64.encode(priv.toByteArray());
+                    destKeystream = Base64.encode(priv.toByteArray());
+                } else {
+                    destKeystream = bridge.getKeystream(dest);
+                    if (destKeystream == null) {
+                        if (_log.shouldLog(Log.DEBUG))
+                            _log.debug("Custom destination specified [" + dest + "] but it isnt know, creating a new one");
+                        ByteArrayOutputStream baos = new ByteArrayOutputStream(640);
+                        SAMUtils.genRandomKey(baos, null);
+                        destKeystream = Base64.encode(baos.toByteArray());
+                        bridge.addKeystream(dest, destKeystream);
+                    } else {
+                        if (_log.shouldLog(Log.DEBUG))
+                            _log.debug("Custom destination specified [" + dest + "] and it is already known");
+                    }
                 }
                 
                 String style = props.getProperty("STYLE");
                 if (style == null) {
                     _log.debug("SESSION STYLE parameter not specified");
-                    return false;
+                    return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n");
                 }
                 props.remove("STYLE");
                 
@@ -231,34 +246,34 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
                     if (!dir.equals("CREATE") && !dir.equals("RECEIVE")
                         && !dir.equals("BOTH")) {
                         _log.debug("Unknow DIRECTION parameter value: [" + dir + "]");
-                        return false;
+                        return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown DIRECTION parameter\"\n");
                     }
                     props.remove("DIRECTION");
                 
-                    streamSession = new SAMStreamSession(dest, dir,props,this);
+                    streamSession = new SAMStreamSession(destKeystream, dir,props,this);
                 } else {
                     _log.debug("Unrecognized SESSION STYLE: \"" + style +"\"");
-                    return false;
+                    return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n");
                 }
                 return writeString("SESSION STATUS RESULT=OK DESTINATION="
                                    + dest + "\n");
             } else {
                 _log.debug("Unrecognized SESSION message opcode: \""
                            + opcode + "\"");
-                return false;
+                return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n");
             }
         } catch (DataFormatException e) {
             _log.debug("Invalid destination specified");
-            return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + "\n");
+            return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
         } catch (I2PSessionException e) {
             _log.debug("I2P error when instantiating session", e);
-            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + "\n");
+            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
         } catch (SAMException e) {
             _log.error("Unexpected SAM error", e);
-            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + "\n");
+            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
         } catch (IOException e) {
             _log.error("Unexpected IOException", e);
-            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + "\n");
+            return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
         }
     }
 
@@ -483,158 +498,170 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
         }
 
         if (opcode.equals("SEND")) {
-            if (props == null) {
-                _log.debug("No parameters specified in STREAM SEND message");
+            return execStreamSend(props);
+        } else if (opcode.equals("CONNECT")) {
+            return execStreamConnect(props);
+        } else if (opcode.equals("CLOSE")) {
+            return execStreamClose(props);
+        } else {
+            _log.debug("Unrecognized RAW message opcode: \""
+                       + opcode + "\"");
+            return false;
+        }
+    }
+            
+    private boolean execStreamSend(Properties props) {
+        if (props == null) {
+            _log.debug("No parameters specified in STREAM SEND message");
+            return false;
+        }
+
+        int id;
+        {
+            String strid = props.getProperty("ID");
+            if (strid == null) {
+                _log.debug("ID not specified in STREAM SEND message");
                 return false;
             }
-            
-            int id;
-            {
-                String strid = props.getProperty("ID");
-                if (strid == null) {
-                    _log.debug("ID not specified in STREAM SEND message");
-                    return false;
-                }
-                try {
-                    id = Integer.parseInt(strid);
-                } catch (NumberFormatException e) {
-                    _log.debug("Invalid STREAM SEND ID specified: " + strid);
-                    return false;
-                }
+            try {
+                id = Integer.parseInt(strid);
+            } catch (NumberFormatException e) {
+                _log.debug("Invalid STREAM SEND ID specified: " + strid);
+                return false;
             }
+        }
 
-            int size;
-            {
-                String strsize = props.getProperty("SIZE");
-                if (strsize == null) {
-                    _log.debug("Size not specified in STREAM SEND message");
-                    return false;
-                }
-                try {
-                    size = Integer.parseInt(strsize);
-                } catch (NumberFormatException e) {
-                    _log.debug("Invalid STREAM SEND size specified: "+strsize);
-                    return false;
-                }
-                if (!checkSize(size)) {
-                    _log.debug("Specified size (" + size
-                               + ") is out of protocol limits");
-                    return false;
-                }
+        int size;
+        {
+            String strsize = props.getProperty("SIZE");
+            if (strsize == null) {
+                _log.debug("Size not specified in STREAM SEND message");
+                return false;
             }
-
             try {
-                DataInputStream in = new DataInputStream(getClientSocketInputStream());
-                byte[] data = new byte[size];
+                size = Integer.parseInt(strsize);
+            } catch (NumberFormatException e) {
+                _log.debug("Invalid STREAM SEND size specified: "+strsize);
+                return false;
+            }
+            if (!checkSize(size)) {
+                _log.debug("Specified size (" + size
+                           + ") is out of protocol limits");
+                return false;
+            }
+        }
 
-                in.readFully(data);
+        try {
+            DataInputStream in = new DataInputStream(getClientSocketInputStream());
+            byte[] data = new byte[size];
 
-                if (!streamSession.sendBytes(id, data)) {
-                    _log.error("STREAM SEND failed");
-                    return false;
-                }
+            in.readFully(data);
 
-                return true;
-            } catch (EOFException e) {
-                _log.debug("Too few bytes with RAW SEND message (expected: "
-                           + size);
+            if (!streamSession.sendBytes(id, data)) {
+                _log.error("STREAM SEND failed");
                 return false;
-            } catch (IOException e) {
-                _log.debug("Caught IOException while parsing RAW SEND message",
-                           e);
+            }
+
+            return true;
+        } catch (EOFException e) {
+            _log.debug("Too few bytes with RAW SEND message (expected: "
+                       + size);
+            return false;
+        } catch (IOException e) {
+            _log.debug("Caught IOException while parsing RAW SEND message",
+                       e);
+            return false;
+        }
+    }
+
+    private boolean execStreamConnect(Properties props) {
+        if (props == null) {
+            _log.debug("No parameters specified in STREAM CONNECT message");
+            return false;
+        }
+
+        int id;
+        {
+            String strid = props.getProperty("ID");
+            if (strid == null) {
+                _log.debug("ID not specified in STREAM SEND message");
                 return false;
             }
-        } else if (opcode.equals("CONNECT")) {
-            if (props == null) {
-                _log.debug("No parameters specified in STREAM CONNECT message");
+            try {
+                id = Integer.parseInt(strid);
+            } catch (NumberFormatException e) {
+                _log.debug("Invalid STREAM CONNECT ID specified: " +strid);
                 return false;
             }
-            
-            int id;
-            {
-                String strid = props.getProperty("ID");
-                if (strid == null) {
-                    _log.debug("ID not specified in STREAM SEND message");
-                    return false;
-                }
-                try {
-                    id = Integer.parseInt(strid);
-                } catch (NumberFormatException e) {
-                    _log.debug("Invalid STREAM CONNECT ID specified: " +strid);
-                    return false;
-                }
-                if (id < 1) {
-                    _log.debug("Invalid STREAM CONNECT ID specified: " +strid);
-                    return false;
-                }
-                props.remove("ID");
+            if (id < 1) {
+                _log.debug("Invalid STREAM CONNECT ID specified: " +strid);
+                return false;
             }
+            props.remove("ID");
+        }
 
-            String dest = props.getProperty("DESTINATION");
-            if (dest == null) {
-                _log.debug("Destination not specified in RAW SEND message");
+        String dest = props.getProperty("DESTINATION");
+        if (dest == null) {
+            _log.debug("Destination not specified in RAW SEND message");
+            return false;
+        }
+        props.remove("DESTINATION");
+
+        try {
+            if (!streamSession.connect(id, dest, props)) {
+                _log.debug("STREAM connection failed");
                 return false;
             }
-            props.remove("DESTINATION");
+            return writeString("STREAM STATUS RESULT=OK ID=" + id + "\n");
+        } catch (DataFormatException e) {
+            _log.debug("Invalid destination in STREAM CONNECT message");
+            return writeString("STREAM STATUS RESULT=INVALID_KEY ID="
+                               + id + "\n");
+        } catch (SAMInvalidDirectionException e) {
+            _log.debug("STREAM CONNECT failed: " + e.getMessage());
+            return writeString("STREAM STATUS RESULT=INVALID_DIRECTION ID="
+                               + id + "\n");
+        } catch (ConnectException e) {
+            _log.debug("STREAM CONNECT failed: " + e.getMessage());
+            return writeString("STREAM STATUS RESULT=CONNECTION_REFUSED ID="
+                               + id + "\n");
+        } catch (NoRouteToHostException e) {
+            _log.debug("STREAM CONNECT failed: " + e.getMessage());
+            return writeString("STREAM STATUS RESULT=CANT_REACH_PEER ID="
+                               + id + "\n");
+        } catch (InterruptedIOException e) {
+            _log.debug("STREAM CONNECT failed: " + e.getMessage());
+            return writeString("STREAM STATUS RESULT=TIMEOUT ID="
+                               + id + "\n");
+        } catch (I2PException e) {
+            _log.debug("STREAM CONNECT failed: " + e.getMessage());
+            return writeString("STREAM STATUS RESULT=I2P_ERROR ID="
+                               + id + "\n");
+        }
+    }
+    
+    private boolean execStreamClose(Properties props) {
+        if (props == null) {
+            _log.debug("No parameters specified in STREAM CLOSE message");
+            return false;
+        }
 
-            try {
-                if (!streamSession.connect(id, dest, props)) {
-                    _log.debug("STREAM connection failed");
-                    return false;
-                }
-                return writeString("STREAM STATUS RESULT=OK ID=" + id + "\n");
-            } catch (DataFormatException e) {
-                _log.debug("Invalid destination in STREAM CONNECT message");
-                return writeString("STREAM STATUS RESULT=INVALID_KEY ID="
-                                   + id + "\n");
-            } catch (SAMInvalidDirectionException e) {
-                _log.debug("STREAM CONNECT failed: " + e.getMessage());
-                return writeString("STREAM STATUS RESULT=INVALID_DIRECTION ID="
-                                   + id + "\n");
-            } catch (ConnectException e) {
-                _log.debug("STREAM CONNECT failed: " + e.getMessage());
-                return writeString("STREAM STATUS RESULT=CONNECTION_REFUSED ID="
-                                   + id + "\n");
-            } catch (NoRouteToHostException e) {
-                _log.debug("STREAM CONNECT failed: " + e.getMessage());
-                return writeString("STREAM STATUS RESULT=CANT_REACH_PEER ID="
-                                   + id + "\n");
-            } catch (InterruptedIOException e) {
-                _log.debug("STREAM CONNECT failed: " + e.getMessage());
-                return writeString("STREAM STATUS RESULT=TIMEOUT ID="
-                                   + id + "\n");
-            } catch (I2PException e) {
-                _log.debug("STREAM CONNECT failed: " + e.getMessage());
-                return writeString("STREAM STATUS RESULT=I2P_ERROR ID="
-                                   + id + "\n");
-            }
-        } else if (opcode.equals("CLOSE")) {
-            if (props == null) {
-                _log.debug("No parameters specified in STREAM CLOSE message");
+        int id;
+        {
+            String strid = props.getProperty("ID");
+            if (strid == null) {
+                _log.debug("ID not specified in STREAM CLOSE message");
                 return false;
             }
-            
-            int id;
-            {
-                String strid = props.getProperty("ID");
-                if (strid == null) {
-                    _log.debug("ID not specified in STREAM CLOSE message");
-                    return false;
-                }
-                try {
-                    id = Integer.parseInt(strid);
-                } catch (NumberFormatException e) {
-                    _log.debug("Invalid STREAM CLOSE ID specified: " +strid);
-                    return false;
-                }
+            try {
+                id = Integer.parseInt(strid);
+            } catch (NumberFormatException e) {
+                _log.debug("Invalid STREAM CLOSE ID specified: " +strid);
+                return false;
             }
-
-            return streamSession.closeConnection(id);
-        } else {
-            _log.debug("Unrecognized RAW message opcode: \""
-                       + opcode + "\"");
-            return false;
         }
+
+        return streamSession.closeConnection(id);
     }
 
     /* Check whether a size is inside the limits allowed by this protocol */