From c5432a209858ac9b9642a46e51a057f7ff330bf5 Mon Sep 17 00:00:00 2001 From: str4d <str4d@mail.i2p> Date: Sun, 22 May 2016 01:18:16 +0000 Subject: [PATCH] Dynamically load domain socket code --- .../net/i2p/client/DomainSocketFactory.java | 45 ------------------- .../net/i2p/client/impl/I2PSessionImpl.java | 29 +++++++++--- .../net/i2p/router/client/ClientManager.java | 30 +++++++++++-- .../client/DomainClientListenerRunner.java | 31 ------------- 4 files changed, 49 insertions(+), 86 deletions(-) delete mode 100644 core/java/src/net/i2p/client/DomainSocketFactory.java delete mode 100644 router/java/src/net/i2p/router/client/DomainClientListenerRunner.java diff --git a/core/java/src/net/i2p/client/DomainSocketFactory.java b/core/java/src/net/i2p/client/DomainSocketFactory.java deleted file mode 100644 index e32deebdd7..0000000000 --- a/core/java/src/net/i2p/client/DomainSocketFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -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). - * <p/> - * This is a stub that does nothing. - * This class is replaced in the Android build. - * - * @author str4d - * @since 0.9.14 - */ -public class DomainSocketFactory { - public static final 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/impl/I2PSessionImpl.java b/core/java/src/net/i2p/client/impl/I2PSessionImpl.java index 78e18c0e8a..84bed6adf5 100644 --- a/core/java/src/net/i2p/client/impl/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/impl/I2PSessionImpl.java @@ -14,6 +14,9 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.Socket; import java.net.UnknownHostException; import java.security.GeneralSecurityException; @@ -29,7 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger; import net.i2p.CoreVersion; import net.i2p.I2PAppContext; -import net.i2p.client.DomainSocketFactory; import net.i2p.client.I2PClient; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; @@ -597,9 +599,24 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2 _reader = new QueuedI2CPMessageReader(_queue, this); } else { if (SystemVersion.isAndroid() && - Boolean.parseBoolean(_options.getProperty(PROP_DOMAIN_SOCKET))) { - final DomainSocketFactory fact = new DomainSocketFactory(_context); - _socket = fact.createSocket(DomainSocketFactory.I2CP_SOCKET_ADDRESS); + _options.getProperty(PROP_DOMAIN_SOCKET) != null) { + try { + Class<?> clazz = Class.forName("net.i2p.client.DomainSocketFactory"); + Constructor<?> ctor = clazz.getDeclaredConstructor(I2PAppContext.class); + Object fact = ctor.newInstance(_context); + Method createSocket = clazz.getDeclaredMethod("createSocket", String.class); + _socket = (Socket) createSocket.invoke(fact, _options.getProperty(PROP_DOMAIN_SOCKET)); + } catch (ClassNotFoundException e) { + throw new I2PSessionException("Cannot load DomainSocketFactory", e); + } catch (NoSuchMethodException e) { + throw new I2PSessionException("Cannot load DomainSocketFactory", e); + } catch (InstantiationException e) { + throw new I2PSessionException("Cannot load DomainSocketFactory", e); + } catch (IllegalAccessException e) { + throw new I2PSessionException("Cannot load DomainSocketFactory", e); + } catch (InvocationTargetException e) { + throw new I2PSessionException("Cannot load DomainSocketFactory", e); + } } else if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) { try { I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp"); @@ -684,8 +701,8 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2 if (_context.isRouterContext()) msg = "Failed to build tunnels"; else if (SystemVersion.isAndroid() && - Boolean.parseBoolean(_options.getProperty(PROP_DOMAIN_SOCKET))) - msg = "Failed to bind to the router and build tunnels"; + _options.getProperty(PROP_DOMAIN_SOCKET) != null) + msg = "Failed to bind to the router on " + _options.getProperty(PROP_DOMAIN_SOCKET) + " and build tunnels"; else msg = "Cannot connect to the router on " + _hostname + ':' + _portNum + " and build tunnels"; throw new I2PSessionException(getPrefix() + msg, ioe); diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index 9c16aeb474..fbea7a7f21 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -10,6 +10,8 @@ package net.i2p.router.client; import java.io.IOException; import java.io.Writer; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -123,10 +125,30 @@ class ClientManager { protected void startListeners() { ClientListenerRunner listener; if (SystemVersion.isAndroid()) { - listener = new DomainClientListenerRunner(_ctx, this); - Thread t = new I2PThread(listener, "DomainClientListener", true); - t.start(); - _listeners.add(listener); + try { + Class<? extends ClientListenerRunner> clazz = Class.forName( + "net.i2p.router.client.DomainClientListenerRunner" + ).asSubclass(ClientListenerRunner.class); + Constructor<? extends ClientListenerRunner> ctor = + clazz.getDeclaredConstructor(RouterContext.class, + ClientManager.class); + listener = ctor.newInstance(_ctx, this); + Thread t = new I2PThread(listener, "DomainClientListener", true); + t.start(); + _listeners.add(listener); + } catch (ClassNotFoundException e) { + _log.warn("Could not find DomainClientListenerRunner class", e); + } catch (ClassCastException e) { + _log.error("Error creating DomainClientListenerRunner", e); + } catch (NoSuchMethodException e) { + _log.error("Error creating DomainClientListenerRunner", e); + } catch (InstantiationException e) { + _log.error("Error creating DomainClientListenerRunner", e); + } catch (IllegalAccessException e) { + _log.error("Error creating DomainClientListenerRunner", e); + } catch (InvocationTargetException e) { + _log.error("Error creating DomainClientListenerRunner", e); + } } if (!_ctx.getBooleanProperty(PROP_DISABLE_EXTERNAL)) { // there's no option to start both an SSL and non-SSL listener diff --git a/router/java/src/net/i2p/router/client/DomainClientListenerRunner.java b/router/java/src/net/i2p/router/client/DomainClientListenerRunner.java deleted file mode 100644 index 0f28a494f4..0000000000 --- a/router/java/src/net/i2p/router/client/DomainClientListenerRunner.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.i2p.router.client; - -import java.io.IOException; -import java.net.ServerSocket; - -import net.i2p.client.DomainSocketFactory; -import net.i2p.router.RouterContext; - -/** - * Unix domain socket version of ClientListenerRunner. - * <p/> - * This is a stub that does nothing. - * This class is replaced in the Android build. - * - * @author str4d - * @since 0.9.14 - */ -public class DomainClientListenerRunner extends ClientListenerRunner { - public DomainClientListenerRunner(RouterContext context, ClientManager manager) { - super(context, manager, -1); - } - - /** - * @throws IOException - */ - @Override - protected ServerSocket getServerSocket() throws IOException { - final DomainSocketFactory fact = new DomainSocketFactory(_context); - return fact.createServerSocket(DomainSocketFactory.I2CP_SOCKET_ADDRESS); - } -} -- GitLab