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:
@ -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,81 +26,136 @@ 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);
|
||||||
_log.debug("SAM bridge listening on 0.0.0.0:" + listenPort);
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
}
|
_log.debug("SAM bridge listening on 0.0.0.0:" + listenPort);
|
||||||
} catch (Exception e) {
|
}
|
||||||
_log.error("Error starting SAM bridge on "
|
} catch (Exception e) {
|
||||||
+ (listenHost == null ? "0.0.0.0" : listenHost)
|
if (_log.shouldLog(Log.ERROR))
|
||||||
+ ":" + listenPort, e);
|
_log.error("Error starting SAM bridge on "
|
||||||
}
|
+ (listenHost == null ? "0.0.0.0" : listenHost)
|
||||||
|
+ ":" + 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;
|
||||||
I2PThread t = new I2PThread(bridge, "SAMListener");
|
String host = "0.0.0.0";
|
||||||
t.start();
|
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");
|
||||||
|
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();
|
||||||
_log.debug("New connection from "
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
+ s.getInetAddress().toString() + ":"
|
_log.debug("New connection from "
|
||||||
+ s.getPort());
|
+ s.getInetAddress().toString() + ":"
|
||||||
|
+ s.getPort());
|
||||||
try {
|
|
||||||
SAMHandler handler = SAMHandlerFactory.createSAMHandler(s);
|
try {
|
||||||
if (handler == null) {
|
SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps);
|
||||||
_log.debug("SAM handler has not been instantiated");
|
if (handler == null) {
|
||||||
try {
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
s.close();
|
_log.debug("SAM handler has not been instantiated");
|
||||||
} catch (IOException e) {}
|
try {
|
||||||
continue;
|
s.close();
|
||||||
}
|
} catch (IOException e) {}
|
||||||
handler.startHandling();
|
continue;
|
||||||
} catch (SAMException e) {
|
}
|
||||||
_log.error("SAM error: " + e.getMessage());
|
handler.startHandling();
|
||||||
s.close();
|
} catch (SAMException e) {
|
||||||
}
|
if (_log.shouldLog(Log.ERROR))
|
||||||
}
|
_log.error("SAM error: " + e.getMessage(), e);
|
||||||
} catch (Exception e) {
|
s.close();
|
||||||
_log.error("Unexpected error while listening for connections", e);
|
}
|
||||||
} finally {
|
}
|
||||||
try {
|
} catch (Exception e) {
|
||||||
_log.debug("Shutting down, closing server socket");
|
if (_log.shouldLog(Log.ERROR))
|
||||||
serverSocket.close();
|
_log.error("Unexpected error while listening for connections", e);
|
||||||
} catch (IOException e) {}
|
} finally {
|
||||||
}
|
try {
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Shutting down, closing server socket");
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -35,6 +37,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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!");
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user