forked from I2P_Developers/i2p.i2p
Stubs for I2CP connections over Unix domain sockets
This commit is contained in:
45
core/java/src/net/i2p/client/DomainSocketFactory.java
Normal file
45
core/java/src/net/i2p/client/DomainSocketFactory.java
Normal file
@@ -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).
|
||||
* <p/>
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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(); }
|
||||
}
|
||||
|
||||
@@ -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<ClientListenerRunner> _listeners;
|
||||
// Destination --> ClientConnectionRunner
|
||||
// Locked for adds/removes but not lookups
|
||||
private final Map<Destination, ClientConnectionRunner> _runners;
|
||||
@@ -87,6 +90,7 @@ class ClientManager {
|
||||
// "How large are messages received by the client?",
|
||||
// "ClientMessages",
|
||||
// new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
|
||||
_listeners = new ArrayList<ClientListenerRunner>();
|
||||
_runners = new ConcurrentHashMap<Destination, ClientConnectionRunner>();
|
||||
_runnersByHash = new ConcurrentHashMap<Hash, ClientConnectionRunner>();
|
||||
_pendingRunners = new HashSet<ClientConnectionRunner>();
|
||||
@@ -105,14 +109,22 @@ class ClientManager {
|
||||
|
||||
/** Todo: Start a 3rd listener for IPV6? */
|
||||
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);
|
||||
}
|
||||
if (!_ctx.getBooleanProperty(PROP_DISABLE_EXTERNAL)) {
|
||||
// there's no option to start both an SSL and non-SSL listener
|
||||
if (_ctx.getBooleanProperty(PROP_ENABLE_SSL))
|
||||
_listener = new SSLClientListenerRunner(_ctx, this, _port);
|
||||
listener = new SSLClientListenerRunner(_ctx, this, _port);
|
||||
else
|
||||
_listener = new ClientListenerRunner(_ctx, this, _port);
|
||||
Thread t = new I2PThread(_listener, "ClientListener:" + _port, true);
|
||||
listener = new ClientListenerRunner(_ctx, this, _port);
|
||||
Thread t = new I2PThread(listener, "ClientListener:" + _port, true);
|
||||
t.start();
|
||||
_listeners.add(listener);
|
||||
}
|
||||
_isStarted = true;
|
||||
}
|
||||
@@ -132,8 +144,9 @@ class ClientManager {
|
||||
public synchronized void shutdown(String msg) {
|
||||
_isStarted = false;
|
||||
_log.info("Shutting down the ClientManager");
|
||||
if (_listener != null)
|
||||
_listener.stopListening();
|
||||
for (ClientListenerRunner listener : _listeners)
|
||||
listener.stopListening();
|
||||
_listeners.clear();
|
||||
Set<ClientConnectionRunner> runners = new HashSet<ClientConnectionRunner>();
|
||||
synchronized (_runners) {
|
||||
for (ClientConnectionRunner runner : _runners.values()) {
|
||||
@@ -169,8 +182,13 @@ class ClientManager {
|
||||
return hisQueue;
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return _isStarted && (_listener == null || _listener.isListening());
|
||||
public synchronized boolean isAlive() {
|
||||
boolean listening = true;
|
||||
if (!_listeners.isEmpty()) {
|
||||
for (ClientListenerRunner listener : _listeners)
|
||||
listening = listening && listener.isListening();
|
||||
}
|
||||
return _isStarted && (_listeners.isEmpty() || listening);
|
||||
}
|
||||
|
||||
public void registerConnection(ClientConnectionRunner runner) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
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.
|
||||
* This is a stub that does nothing.
|
||||
* This class is replaced in the Android build.
|
||||
*
|
||||
* @since 0.9.15
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@ class SSLClientListenerRunner extends ClientListenerRunner {
|
||||
* Create (if necessary) and load the key store, then run.
|
||||
*/
|
||||
@Override
|
||||
public void runServer() {
|
||||
protected void runServer() {
|
||||
File keyStore = new File(_context.getConfigDir(), "keystore/i2cp.ks");
|
||||
if (verifyKeyStore(keyStore) && initializeFactory(keyStore)) {
|
||||
super.runServer();
|
||||
|
||||
Reference in New Issue
Block a user