diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java
index a7b25020749fc07b70f18d12e20d24793f6ad792..28ea37e12be0615d265f7c7953d697bcc2af20c8 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java
@@ -119,6 +119,8 @@ public abstract class SAMHandler implements Runnable {
      * @return True is the string was successfully written, false otherwise
      */
     protected final boolean writeString(String str) {
+        if (_log.shouldLog(Log.DEBUG))
+            _log.debug("Sending the client: [" + str + "]");
         try {
             writeBytes(str.getBytes("ISO-8859-1"));
         } catch (IOException e) {
diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
index 5dd826e4774296036ef2522d7a9700257ae923c0..cac35d60ac233d5032f7f7420c2a9ca1742f43d6 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
@@ -17,6 +17,7 @@ import java.net.Socket;
 import java.util.Properties;
 import java.util.StringTokenizer;
 
+import net.i2p.data.DataHelper;
 import net.i2p.util.Log;
 
 /**
@@ -36,14 +37,11 @@ public class SAMHandlerFactory {
      * @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;
         String line;
         StringTokenizer tok;
 
         try {
-            br = new BufferedReader(new InputStreamReader(s.getInputStream(),
-                                                          "ISO-8859-1"));
-            line = br.readLine();
+            line = DataHelper.readLine(s.getInputStream());
             if (line == null) {
                 _log.debug("Connection closed by client");
                 return null;
diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
index 6ae5691686fdda8a4e67b8f58775aa0a375cbf31..e5f0d10600c42315bf5f3e53f31587a48f75e032 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
@@ -201,12 +201,17 @@ public class SAMStreamSession {
      *
      * @return True if the data was sent, false otherwise
      */
-    public boolean sendBytes(int id, InputStream in, int size) { 
-        Destination d = new Destination();
+    public boolean sendBytes(int id, InputStream in, int size) throws IOException { 
         SAMStreamSessionSocketHandler handler = getSocketHandler(id);
         
         if (handler == null) {
             _log.error("Trying to send bytes through inexistent handler " +id);
+            // even though it failed, we need to read those bytes! 
+            for (int i = 0; i < size; i++) {
+                int c = in.read();
+                if (c == -1)
+                    break;
+            }
             return false;
         }
 
@@ -420,6 +425,8 @@ public class SAMStreamSession {
             } catch (I2PException e) {
                 _log.debug("Caught I2PException", e);
             }
+            
+            close();
 
             _log.debug("Shutting down SAM STREAM session server");
         }
@@ -463,27 +470,25 @@ public class SAMStreamSession {
          *
          * @return True if data has been sent without errors, false otherwise
          */
-        public boolean sendBytes(InputStream in, int size) { // byte[] data) {
+        public boolean sendBytes(InputStream in, int size) throws IOException {
             if (_log.shouldLog(Log.DEBUG)) {
                 _log.debug("Handler " + id + ": sending " + size
                            + " bytes");
             }
             ByteCache cache = ByteCache.getInstance(1024, 4);
             ByteArray ba = cache.acquire();
+            int remaining = size;
             try {
-                int remaining = size;
                 byte buf[] = ba.getData(); 
                 while (remaining > 0) {
                     int read = in.read(buf, 0, remaining > buf.length ? buf.length : remaining);
                     if (read == -1)
                         throw new IOException("Insufficient data from the SAM client (" + remaining + "/" + size + ")");
-                    i2pSocketOS.write(buf, 0, read);
+                    else if (read > 0)
+                        i2pSocketOS.write(buf, 0, read);
+                    
                     remaining -= read;
                 }
-                //i2pSocketOS.flush();
-            } catch (IOException e) {
-                _log.error("Error sending data through I2P socket", e);
-                return false;
             } finally {
                 cache.release(ba);
             }
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
index eb3807cbf40589cbd61ee28d507fe11e04e4c5d0..f25733e18e1d4100a8f269757da8cf3866fef84c 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java
@@ -26,6 +26,7 @@ import net.i2p.I2PException;
 import net.i2p.client.I2PSessionException;
 import net.i2p.data.Base64;
 import net.i2p.data.DataFormatException;
+import net.i2p.data.DataHelper;
 import net.i2p.data.Destination;
 import net.i2p.util.Log;
 
@@ -80,9 +81,10 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
     }
 
     public void handle() {
-        String msg, domain, opcode;
+        String msg = null;
+        String domain = null;
+        String opcode = null;
         boolean canContinue = false;
-        ByteArrayOutputStream buf = new ByteArrayOutputStream(IN_BUFSIZE);
         StringTokenizer tok;
         Properties props;
 
@@ -99,22 +101,15 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
                     break;
                 }
 
-                while ((b = in.read()) != -1) {
-                    if (b == '\n') {
-                        break;
-                    }
-                    buf.write(b);
-                }
-                if (b == -1) {
+                msg = DataHelper.readLine(in);
+                if (msg == null) {
                     _log.debug("Connection closed by client");
                     break;
                 }
 
-                msg = buf.toString("ISO-8859-1").trim();
                 if (_log.shouldLog(Log.DEBUG)) {
                     _log.debug("New message received: [" + msg + "]");
                 }
-                buf.reset();
 
                 tok = new StringTokenizer(msg, " ");
                 if (tok.countTokens() < 2) {
@@ -154,14 +149,11 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
                     break;
                 }
             }
-        } catch (UnsupportedEncodingException e) {
-            _log.error("Caught UnsupportedEncodingException ("
-                       + e.getMessage() + ")", e);
         } catch (IOException e) {
             _log.debug("Caught IOException ("
-                       + e.getMessage() + ")", e);
+                       + e.getMessage() + ") for message [" + msg + "]", e);
         } catch (Exception e) {
-            _log.error("Unexpected exception", e);
+            _log.error("Unexpected exception for message [" + msg + "]", e);
         } finally {
             _log.debug("Stopping handler");
             try {
@@ -555,7 +547,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
 
         try {
             if (!streamSession.sendBytes(id, getClientSocketInputStream(), size)) { // data)) {
-                _log.error("STREAM SEND failed");
+                _log.error("STREAM SEND [" + size + "] failed");
                 boolean rv = writeString("STREAM CLOSED RESULT=CANT_REACH_PEER ID=" + id + " MESSAGE=\"Send of " + size + " bytes failed\"\n");
                 streamSession.closeConnection(id);
                 return rv;
@@ -563,11 +555,11 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
 
             return true;
         } catch (EOFException e) {
-            _log.debug("Too few bytes with RAW SEND message (expected: "
+            _log.debug("Too few bytes with STREAM SEND message (expected: "
                        + size);
             return false;
         } catch (IOException e) {
-            _log.debug("Caught IOException while parsing RAW SEND message",
+            _log.debug("Caught IOException while parsing STREAM SEND message",
                        e);
             return false;
         }
diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java
index d226004aa54a5629c62f1e3b8945554fd0521653..da3be47f26db7e1ce67d0becd6c81dde7de6b0f8 100644
--- a/core/java/src/net/i2p/data/DataHelper.java
+++ b/core/java/src/net/i2p/data/DataHelper.java
@@ -670,6 +670,26 @@ public class DataHelper {
         }
         return cur;
     }
+    
+    /**
+     * Read a newline delimited line from the stream, returning the line (without
+     * the newline), or null if EOF reached before the newline was found
+     */
+    public static String readLine(InputStream in) throws IOException {
+        StringBuffer buf = new StringBuffer(128);
+
+        int c = -1;
+        while ( (c = in.read()) != -1) {
+            if (c == '\n')
+                break;
+            buf.append((char)c);
+        }
+        if (c == -1) 
+            return null;
+        else
+            return buf.toString();
+    }
+    
 
     public static List sortStructures(Collection dataStructures) {
         if (dataStructures == null) return new ArrayList();
diff --git a/history.txt b/history.txt
index 005249d66c299d953836f98a0b0daa74ebd33716..5c3b24ad422ccb7fe719d64460dc7d6ee860439a 100644
--- a/history.txt
+++ b/history.txt
@@ -1,4 +1,9 @@
-$Id: history.txt,v 1.95 2004/12/05 05:22:58 jrandom Exp $
+$Id: history.txt,v 1.96 2004/12/05 10:32:34 jrandom Exp $
+
+2004-12-05  jrandom
+    * Default the I2CP listener to localhost only, unless overridden by 
+      i2cp.tcp.bindAllInterfaces=true (thanks dm!)
+    * More SAM fixes for things recently broken (whee)
 
 2004-12-05  jrandom
     * Fix the recently broken SAM bridge (duh)
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 23926157c13097e7da5c715f578bd99cd563c6fa..e54faf13ba255d526febe409efba6d482fb48756 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
  *
  */
 public class RouterVersion {
-    public final static String ID = "$Revision: 1.100 $ $Date: 2004/12/05 05:22:58 $";
+    public final static String ID = "$Revision: 1.101 $ $Date: 2004/12/05 10:32:33 $";
     public final static String VERSION = "0.4.2.2";
-    public final static long BUILD = 4;
+    public final static long BUILD = 5;
     public static void main(String args[]) {
         System.out.println("I2P Router version: " + VERSION);
         System.out.println("Router ID: " + RouterVersion.ID);
diff --git a/router/java/src/net/i2p/router/client/ClientListenerRunner.java b/router/java/src/net/i2p/router/client/ClientListenerRunner.java
index 52937d3b709102e9ffec24a70f7bac9d44fa23b5..e23136d1276ca5d014e9cda3b5e40bb3bb4dd98e 100644
--- a/router/java/src/net/i2p/router/client/ClientListenerRunner.java
+++ b/router/java/src/net/i2p/router/client/ClientListenerRunner.java
@@ -9,6 +9,7 @@ package net.i2p.router.client;
  */
 
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 
@@ -28,15 +29,21 @@ public class ClientListenerRunner implements Runnable {
     private ClientManager _manager;
     private ServerSocket _socket;
     private int _port;
+    private boolean _bindAllInterfaces;
     private boolean _running;
     private long _nextFailDelay = 1000;
     
+    public static final String BIND_ALL_INTERFACES = "i2cp.tcp.bindAllInterfaces";
+
     public ClientListenerRunner(RouterContext context, ClientManager manager, int port) {
         _context = context;
         _log = _context.logManager().getLog(ClientListenerRunner.class);
         _manager = manager;
         _port = port;
         _running = false;
+        
+        String val = context.getProperty(BIND_ALL_INTERFACES, "False");
+        _bindAllInterfaces = Boolean.valueOf(val).booleanValue();
     }
     
     public void setPort(int port) { _port = port; }
@@ -55,7 +62,11 @@ public class ClientListenerRunner implements Runnable {
         while (_running) {
             try {
                 _log.info("Starting up listening for connections on port " + _port);
-                _socket = new ServerSocket(_port);
+                if (_bindAllInterfaces)
+                    _socket = new ServerSocket(_port);
+                else
+                    _socket = new ServerSocket(_port, 5, InetAddress.getLocalHost());
+                
                 curDelay = 0;
                 while (_running) {
                     try {
@@ -82,7 +93,7 @@ public class ClientListenerRunner implements Runnable {
                 if (_context.router().isAlive()) 
                     _log.error("Error listening on port " + _port, ioe);
             }
-
+            
             if (_socket != null) {
                 try { _socket.close(); } catch (IOException ioe) {}
                 _socket = null;