diff --git a/core/java/src/net/i2p/client/DomainSocketFactory.java b/core/java/src/net/i2p/client/DomainSocketFactory.java new file mode 100644 index 0000000000..280236e5e7 --- /dev/null +++ b/core/java/src/net/i2p/client/DomainSocketFactory.java @@ -0,0 +1,45 @@ +package net.i2p.client; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +import net.i2p.I2PAppContext; + +/** + * Bridge to Unix domain socket (or similar). + *
+ * This is a stub that does nothing. + * This class is replaced in the Android build. + * + * @author str4d + * @since 0.9.15 + */ +public class DomainSocketFactory { + public static String I2CP_SOCKET_ADDRESS = "net.i2p.client.i2cp"; + + /** + * @throws UnsupportedOperationException always + */ + public DomainSocketFactory(I2PAppContext context) { + throw new UnsupportedOperationException(); + } + + /** + * Override in Android. + * @throws IOException + * @throws UnsupportedOperationException always + */ + public Socket createSocket(String name) throws IOException { + throw new UnsupportedOperationException(); + } + + /** + * Override in Android. + * @throws IOException + * @throws UnsupportedOperationException always + */ + public ServerSocket createServerSocket(String name) throws IOException { + throw new UnsupportedOperationException(); + } +} diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index 20aa43550b..fd60b7404b 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -52,6 +52,7 @@ import net.i2p.util.LHMCache; import net.i2p.util.Log; import net.i2p.util.OrderedProperties; import net.i2p.util.SimpleTimer2; +import net.i2p.util.SystemVersion; import net.i2p.util.VersionComparator; /** @@ -157,6 +158,12 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa protected static final String PROP_USER = "i2cp.username"; protected static final String PROP_PW = "i2cp.password"; + /** + * Use Unix domain socket (or similar) to connect to a router + * @since 0.9.15 + */ + protected static final String PROP_DOMAIN_SOCKET = "i2cp.domainSocket"; + private static final long VERIFY_USAGE_TIME = 60*1000; private static final long MAX_SEND_WAIT = 10*1000; @@ -279,6 +286,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa if (_context.isRouterContext()) // just for logging return "[internal connection]"; + else if (SystemVersion.isAndroid() && + Boolean.parseBoolean(_options.getProperty(PROP_DOMAIN_SOCKET))) + // just for logging + return "[Domain socket connection]"; return _options.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1"); } @@ -287,7 +298,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa * @since 0.9.7 was in loadConfig() */ private int getPort() { - if (_context.isRouterContext()) + if (_context.isRouterContext() || + (SystemVersion.isAndroid() && + Boolean.parseBoolean(_options.getProperty(PROP_DOMAIN_SOCKET)))) // just for logging return 0; String portNum = _options.getProperty(I2PClient.PROP_TCP_PORT, LISTEN_PORT + ""); @@ -447,7 +460,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { // protect w/ closeSocket() synchronized(_stateLock) { - // If we are in the router JVM, connect using the interal queue + // If we are in the router JVM, connect using the internal queue if (_context.isRouterContext()) { // _socket and _writer remain null InternalClientManager mgr = _context.internalClientManager(); @@ -457,7 +470,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa _queue = mgr.connect(); _reader = new QueuedI2CPMessageReader(_queue, this); } else { - if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) { + if (SystemVersion.isAndroid() && + Boolean.parseBoolean(_options.getProperty(PROP_DOMAIN_SOCKET))) { + final DomainSocketFactory fact = new DomainSocketFactory(_context); + _socket = fact.createSocket(DomainSocketFactory.I2CP_SOCKET_ADDRESS); + } else if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) { try { I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp"); _socket = fact.createSocket(_hostname, _portNum); diff --git a/router/java/src/net/i2p/router/client/ClientListenerRunner.java b/router/java/src/net/i2p/router/client/ClientListenerRunner.java index 9b169ca757..44d7811b6b 100644 --- a/router/java/src/net/i2p/router/client/ClientListenerRunner.java +++ b/router/java/src/net/i2p/router/client/ClientListenerRunner.java @@ -64,7 +64,9 @@ class ClientListenerRunner implements Runnable { return new ServerSocket(_port, 0, InetAddress.getByName(listenInterface)); } } - + + public void run() { runServer(); } + /** * Start up the socket listener, listens for connections, and * fires those connections off via {@link #runConnection runConnection}. @@ -72,7 +74,7 @@ class ClientListenerRunner implements Runnable { * failure. * */ - public void runServer() { + protected void runServer() { _running = true; int curDelay = 1000; while (_running) { @@ -173,5 +175,4 @@ class ClientListenerRunner implements Runnable { _socket = null; } catch (IOException ioe) {} } - public void run() { runServer(); } } diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index 96e6ac20b6..c982671b75 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -10,8 +10,10 @@ package net.i2p.router.client; import java.io.IOException; import java.io.Writer; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; @@ -37,6 +39,7 @@ import net.i2p.router.JobImpl; import net.i2p.router.RouterContext; import net.i2p.util.I2PThread; import net.i2p.util.Log; +import net.i2p.util.SystemVersion; /** * Coordinate connections and various tasks @@ -45,7 +48,7 @@ import net.i2p.util.Log; */ class ClientManager { private final Log _log; - protected ClientListenerRunner _listener; + protected List