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;