allow the user to override the I2CP options (exposed on the command line, ala

SAMBridge [[listenHost ]listenPort[ name=val]*]
where listenHost defaults to localhost, listenPort defaults to 7656, and name=val
can be the I2CP options to override (e.g. i2cp.tcp.host=localhost i2cp.tcp.port=4001)
This commit is contained in:
jrandom
2004-04-20 07:26:34 +00:00
committed by zzz
parent bed7d09764
commit 203d0e870a
4 changed files with 144 additions and 65 deletions

View File

@ -12,6 +12,7 @@ import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.Properties;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -25,62 +26,114 @@ public class SAMBridge implements Runnable {
private final static Log _log = new Log(SAMBridge.class); private final static Log _log = new Log(SAMBridge.class);
private ServerSocket serverSocket; private ServerSocket serverSocket;
private Properties i2cpProps;
private boolean acceptConnections = true; private boolean acceptConnections = true;
private final static int SAM_LISTENPORT = 7656; private final static int SAM_LISTENPORT = 7656;
/** private SAMBridge() {}
* Build a new SAM bridge listening on 127.0.0.1.
*
* @param listenPort The port to listen on
*/
public SAMBridge(int listenPort) {
this((String)null, listenPort);
}
/** /**
* Build a new SAM bridge. * Build a new SAM bridge.
* *
* @param listenHost The network interface to listen on * @param listenHost hostname to listen for SAM connections on ("0.0.0.0" for all)
* @param listenPort The port to listen on * @param listenPort port number to listen for SAM connections on
* @param i2cpProps set of I2CP properties for finding and communicating with the router
*/ */
public SAMBridge(String listenHost, int listenPort) { public SAMBridge(String listenHost, int listenPort, Properties i2cpProps) {
try { try {
if (listenHost != null) { if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) {
serverSocket = new ServerSocket(listenPort, 0, serverSocket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost));
InetAddress.getByName(listenHost)); if (_log.shouldLog(Log.DEBUG))
_log.debug("SAM bridge listening on " _log.debug("SAM bridge listening on "
+ listenHost + ":" + listenPort); + listenHost + ":" + listenPort);
} else { } else {
serverSocket = new ServerSocket(listenPort); serverSocket = new ServerSocket(listenPort);
if (_log.shouldLog(Log.DEBUG))
_log.debug("SAM bridge listening on 0.0.0.0:" + listenPort); _log.debug("SAM bridge listening on 0.0.0.0:" + listenPort);
} }
} catch (Exception e) { } catch (Exception e) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error starting SAM bridge on " _log.error("Error starting SAM bridge on "
+ (listenHost == null ? "0.0.0.0" : listenHost) + (listenHost == null ? "0.0.0.0" : listenHost)
+ ":" + listenPort, e); + ":" + listenPort, e);
} }
this.i2cpProps = i2cpProps;
} }
/**
* Usage:
* <pre>SAMBridge [[listenHost ]listenPort[ name=val]*]</pre>
*
* name=val options are passed to the I2CP code to build a session,
* allowing the bridge to specify an alternate I2CP host and port, tunnel
* depth, etc.
*/
public static void main(String args[]) { public static void main(String args[]) {
SAMBridge bridge = new SAMBridge(SAM_LISTENPORT); int port = SAM_LISTENPORT;
String host = "0.0.0.0";
Properties opts = null;
if (args.length > 0) {
int portIndex = 0;
try {
port = Integer.parseInt(args[portIndex]);
} catch (NumberFormatException nfe) {
host = args[0];
portIndex++;
try {
port = Integer.parseInt(args[portIndex]);
} catch (NumberFormatException nfe1) {
usage();
return;
}
}
opts = parseOptions(args, portIndex+1);
}
SAMBridge bridge = new SAMBridge(host, port, opts);
I2PThread t = new I2PThread(bridge, "SAMListener"); I2PThread t = new I2PThread(bridge, "SAMListener");
t.start(); t.start();
} }
private static Properties parseOptions(String args[], int startArgs) {
Properties props = new Properties();
// skip over first few options
for (int i = startArgs; i < args.length; i++) {
int eq = args[i].indexOf('=');
if (eq <= 0) continue;
if (eq >= args[i].length()-1) continue;
String key = args[i].substring(0, eq);
String val = args[i].substring(eq+1);
key = key.trim();
val = val.trim();
if ( (key.length() > 0) && (val.length() > 0) )
props.setProperty(key, val);
}
return props;
}
private static void usage() {
System.err.println("Usage: SAMBridge [listenHost listenPortNum[ name=val]*]");
System.err.println(" listenHost: interface to listen on (0.0.0.0 for all interfaces)");
System.err.println(" listenPort: port to listen for SAM connections on (default 7656)");
System.err.println(" name=val: options to pass when connecting via I2CP, such as ");
System.err.println(" i2cp.host=localhost and i2cp.port=7654");
}
public void run() { public void run() {
try { try {
while (acceptConnections) { while (acceptConnections) {
Socket s = serverSocket.accept(); Socket s = serverSocket.accept();
if (_log.shouldLog(Log.DEBUG))
_log.debug("New connection from " _log.debug("New connection from "
+ s.getInetAddress().toString() + ":" + s.getInetAddress().toString() + ":"
+ s.getPort()); + s.getPort());
try { try {
SAMHandler handler = SAMHandlerFactory.createSAMHandler(s); SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps);
if (handler == null) { if (handler == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("SAM handler has not been instantiated"); _log.debug("SAM handler has not been instantiated");
try { try {
s.close(); s.close();
@ -89,14 +142,17 @@ public class SAMBridge implements Runnable {
} }
handler.startHandling(); handler.startHandling();
} catch (SAMException e) { } catch (SAMException e) {
_log.error("SAM error: " + e.getMessage()); if (_log.shouldLog(Log.ERROR))
_log.error("SAM error: " + e.getMessage(), e);
s.close(); s.close();
} }
} }
} catch (Exception e) { } catch (Exception e) {
if (_log.shouldLog(Log.ERROR))
_log.error("Unexpected error while listening for connections", e); _log.error("Unexpected error while listening for connections", e);
} finally { } finally {
try { try {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Shutting down, closing server socket"); _log.debug("Shutting down, closing server socket");
serverSocket.close(); serverSocket.close();
} catch (IOException e) {} } catch (IOException e) {}

View File

@ -13,6 +13,8 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.util.Properties;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -36,6 +38,9 @@ public abstract class SAMHandler implements Runnable {
protected int verMajor = 0; protected int verMajor = 0;
protected int verMinor = 0; protected int verMinor = 0;
/** I2CP options configuring the I2CP connection (port, host, numHops, etc) */
protected Properties i2cpProps = null;
private Object stopLock = new Object(); private Object stopLock = new Object();
private boolean stopHandler = false; private boolean stopHandler = false;
@ -45,14 +50,16 @@ public abstract class SAMHandler implements Runnable {
* @param s Socket attached to a SAM client * @param s Socket attached to a SAM client
* @param verMajor SAM major version to manage * @param verMajor SAM major version to manage
* @param verMinor SAM minor version to manage * @param verMinor SAM minor version to manage
* @param i2cpProps properties to configure the I2CP connection (host, port, etc)
*/ */
protected SAMHandler(Socket s, protected SAMHandler(Socket s,
int verMajor, int verMinor) throws IOException { int verMajor, int verMinor, Properties i2cpProps) throws IOException {
socket = s; socket = s;
socketOS = socket.getOutputStream(); socketOS = socket.getOutputStream();
this.verMajor = verMajor; this.verMajor = verMajor;
this.verMinor = verMinor; this.verMinor = verMinor;
this.i2cpProps = i2cpProps;
} }
/** /**

View File

@ -31,10 +31,11 @@ public class SAMHandlerFactory {
* required by the client. * required by the client.
* *
* @param s Socket attached to SAM client * @param s Socket attached to SAM client
* @param i2cpProps config options for our i2cp connection
* *
* @return A SAM protocol handler * @return A SAM protocol handler
*/ */
public static SAMHandler createSAMHandler(Socket s) throws SAMException { public static SAMHandler createSAMHandler(Socket s, Properties i2cpProps) throws SAMException {
BufferedReader br; BufferedReader br;
String line; String line;
StringTokenizer tok; StringTokenizer tok;
@ -127,7 +128,7 @@ public class SAMHandlerFactory {
try { try {
switch (verMajor) { switch (verMajor) {
case 1: case 1:
handler = new SAMv1Handler(s, verMajor, verMinor); handler = new SAMv1Handler(s, verMajor, verMinor, i2cpProps);
break; break;
default: default:
_log.error("BUG! Trying to initialize the wrong SAM version!"); _log.error("BUG! Trying to initialize the wrong SAM version!");

View File

@ -55,7 +55,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
* @param verMinor SAM minor version to manage * @param verMinor SAM minor version to manage
*/ */
public SAMv1Handler(Socket s, int verMajor, int verMinor) throws SAMException, IOException { public SAMv1Handler(Socket s, int verMajor, int verMinor) throws SAMException, IOException {
super(s, verMajor, verMinor); this(s, verMajor, verMinor, new Properties());
}
/**
* Create a new SAM version 1 handler. This constructor expects
* that the SAM HELLO message has been still answered (and
* stripped) from the socket input stream.
*
* @param s Socket attached to a SAM client
* @param verMajor SAM major version to manage (should be 1)
* @param verMinor SAM minor version to manage
* @param i2cpProps properties to configure the I2CP connection (host, port, etc)
*/
public SAMv1Handler(Socket s, int verMajor, int verMinor, Properties i2cpProps) throws SAMException, IOException {
super(s, verMajor, verMinor, i2cpProps);
_log.debug("SAM version 1 handler instantiated"); _log.debug("SAM version 1 handler instantiated");
if ((this.verMajor != 1) || (this.verMinor != 0)) { if ((this.verMajor != 1) || (this.verMinor != 0)) {
@ -113,6 +126,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
+ "\"; opcode: \"" + opcode + "\")"); + "\"; opcode: \"" + opcode + "\")");
} }
props = SAMUtils.parseParams(tok); props = SAMUtils.parseParams(tok);
if (i2cpProps != null)
props.putAll(i2cpProps); // make sure we've got the i2cp settings
if (domain.equals("STREAM")) { if (domain.equals("STREAM")) {
canContinue = execStreamMessage(opcode, props); canContinue = execStreamMessage(opcode, props);