forked from I2P_Developers/i2p.i2p
Transport: UPnP fixes for Android
This commit is contained in:
@@ -52,6 +52,7 @@ import net.i2p.router.startup.StartupJob;
|
|||||||
import net.i2p.router.startup.WorkingDir;
|
import net.i2p.router.startup.WorkingDir;
|
||||||
import net.i2p.router.tasks.*;
|
import net.i2p.router.tasks.*;
|
||||||
import net.i2p.router.transport.FIFOBandwidthLimiter;
|
import net.i2p.router.transport.FIFOBandwidthLimiter;
|
||||||
|
import net.i2p.router.transport.UPnPScannerCallback;
|
||||||
import net.i2p.router.transport.ntcp.NTCPTransport;
|
import net.i2p.router.transport.ntcp.NTCPTransport;
|
||||||
import net.i2p.router.transport.udp.UDPTransport;
|
import net.i2p.router.transport.udp.UDPTransport;
|
||||||
import net.i2p.router.util.EventLog;
|
import net.i2p.router.util.EventLog;
|
||||||
@@ -103,6 +104,7 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
private FamilyKeyCrypto _familyKeyCrypto;
|
private FamilyKeyCrypto _familyKeyCrypto;
|
||||||
private boolean _familyKeyCryptoFail;
|
private boolean _familyKeyCryptoFail;
|
||||||
public final Object _familyKeyLock = new Object();
|
public final Object _familyKeyLock = new Object();
|
||||||
|
private UPnPScannerCallback _upnpScannerCallback;
|
||||||
|
|
||||||
public final static String PROP_CONFIG_FILE = "router.configLocation";
|
public final static String PROP_CONFIG_FILE = "router.configLocation";
|
||||||
|
|
||||||
@@ -384,6 +386,8 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
} catch (NumberFormatException nfe) {}
|
} catch (NumberFormatException nfe) {}
|
||||||
}
|
}
|
||||||
_networkID = id;
|
_networkID = id;
|
||||||
|
// for testing
|
||||||
|
setUPnPScannerCallback(new LoggerCallback());
|
||||||
changeState(State.INITIALIZED);
|
changeState(State.INITIALIZED);
|
||||||
// ********* Start no threads before here ********* //
|
// ********* Start no threads before here ********* //
|
||||||
}
|
}
|
||||||
@@ -606,6 +610,32 @@ public class Router implements RouterClock.ClockShiftListener {
|
|||||||
*/
|
*/
|
||||||
public RouterContext getContext() { return _context; }
|
public RouterContext getContext() { return _context; }
|
||||||
|
|
||||||
|
private class LoggerCallback implements UPnPScannerCallback {
|
||||||
|
public void beforeScan() { _log.info("SSDP beforeScan()"); }
|
||||||
|
public void afterScan() { _log.info("SSDP afterScan()"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Android only.
|
||||||
|
* MUST be set before runRouter() is called.
|
||||||
|
*
|
||||||
|
* @param callback the callback or null to clear it
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public synchronized void setUPnPScannerCallback(UPnPScannerCallback callback) {
|
||||||
|
_upnpScannerCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Android only.
|
||||||
|
*
|
||||||
|
* @return the callback or null if none
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public synchronized UPnPScannerCallback getUPnPScannerCallback() {
|
||||||
|
return _upnpScannerCallback;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This must be called after instantiation.
|
* This must be called after instantiation.
|
||||||
* Starts the threads. Does not install updates.
|
* Starts the threads. Does not install updates.
|
||||||
|
|||||||
@@ -341,7 +341,10 @@ public class TransportManager implements TransportEventListener {
|
|||||||
// Maybe we need a config option to force on? Probably not.
|
// Maybe we need a config option to force on? Probably not.
|
||||||
// What firewall supports UPnP and is configured with a public address on the LAN side?
|
// What firewall supports UPnP and is configured with a public address on the LAN side?
|
||||||
// Unlikely.
|
// Unlikely.
|
||||||
if (_upnpManager != null && Addresses.getAnyAddress() == null)
|
// Always start on Android, as we may have a cellular IPv4 address but
|
||||||
|
// are routing all traffic through WiFi.
|
||||||
|
// Also, conditions may change rapidly.
|
||||||
|
if (_upnpManager != null && (SystemVersion.isAndroid() || Addresses.getAnyAddress() == null))
|
||||||
_upnpManager.start();
|
_upnpManager.start();
|
||||||
configTransports();
|
configTransports();
|
||||||
_log.debug("Starting up the transport manager");
|
_log.debug("Starting up the transport manager");
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ class UPnPManager {
|
|||||||
private final RouterContext _context;
|
private final RouterContext _context;
|
||||||
private final UPnP _upnp;
|
private final UPnP _upnp;
|
||||||
private final UPnPCallback _upnpCallback;
|
private final UPnPCallback _upnpCallback;
|
||||||
|
private final UPnPScannerCallback _scannerCallback;
|
||||||
|
private final DelayedCallback _delayedCallback;
|
||||||
private volatile boolean _isRunning;
|
private volatile boolean _isRunning;
|
||||||
private volatile boolean _shouldBeRunning;
|
private volatile boolean _shouldBeRunning;
|
||||||
private volatile long _lastRescan;
|
private volatile long _lastRescan;
|
||||||
@@ -73,6 +75,8 @@ class UPnPManager {
|
|||||||
Debug.initialize(context);
|
Debug.initialize(context);
|
||||||
_upnp = new UPnP(context);
|
_upnp = new UPnP(context);
|
||||||
_upnpCallback = new UPnPCallback();
|
_upnpCallback = new UPnPCallback();
|
||||||
|
_scannerCallback = _context.router().getUPnPScannerCallback();
|
||||||
|
_delayedCallback = (_scannerCallback != null) ? new DelayedCallback() : null;
|
||||||
_rescanner = new Rescanner();
|
_rescanner = new Rescanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +95,16 @@ class UPnPManager {
|
|||||||
// and will eventually hit 1024 and then negative
|
// and will eventually hit 1024 and then negative
|
||||||
_upnp.setHTTPPort(_context.getProperty(PROP_HTTP_PORT, DEFAULT_HTTP_PORT));
|
_upnp.setHTTPPort(_context.getProperty(PROP_HTTP_PORT, DEFAULT_HTTP_PORT));
|
||||||
_upnp.setSSDPPort(_context.getProperty(PROP_SSDP_PORT, DEFAULT_SSDP_PORT));
|
_upnp.setSSDPPort(_context.getProperty(PROP_SSDP_PORT, DEFAULT_SSDP_PORT));
|
||||||
|
if (_scannerCallback != null) {
|
||||||
|
_scannerCallback.beforeScan();
|
||||||
|
}
|
||||||
_isRunning = _upnp.runPlugin();
|
_isRunning = _upnp.runPlugin();
|
||||||
|
if (_scannerCallback != null) {
|
||||||
|
if (_isRunning)
|
||||||
|
_delayedCallback.reschedule();
|
||||||
|
else
|
||||||
|
_scannerCallback.afterScan();
|
||||||
|
}
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.info("UPnP runPlugin took " + (_context.clock().now() - b));
|
_log.info("UPnP runPlugin took " + (_context.clock().now() - b));
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
@@ -100,6 +113,9 @@ class UPnPManager {
|
|||||||
_log.error("UPnP error, please report", e);
|
_log.error("UPnP error, please report", e);
|
||||||
_errorLogged = true;
|
_errorLogged = true;
|
||||||
}
|
}
|
||||||
|
if (_scannerCallback != null) {
|
||||||
|
_scannerCallback.afterScan();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_isRunning) {
|
if (_isRunning) {
|
||||||
@@ -156,6 +172,8 @@ class UPnPManager {
|
|||||||
return false;
|
return false;
|
||||||
_lastRescan = now;
|
_lastRescan = now;
|
||||||
if (_isRunning) {
|
if (_isRunning) {
|
||||||
|
if (_scannerCallback != null)
|
||||||
|
_scannerCallback.beforeScan();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("UPnP Rescan");
|
_log.debug("UPnP Rescan");
|
||||||
// TODO default search MX (jitter) is 3 seconds... reduce?
|
// TODO default search MX (jitter) is 3 seconds... reduce?
|
||||||
@@ -163,6 +181,8 @@ class UPnPManager {
|
|||||||
// Adaptive Jitter Control for UPnP M-Search
|
// Adaptive Jitter Control for UPnP M-Search
|
||||||
// Kevin Mills and Christopher Dabrowski
|
// Kevin Mills and Christopher Dabrowski
|
||||||
_upnp.search();
|
_upnp.search();
|
||||||
|
if (_scannerCallback != null)
|
||||||
|
_delayedCallback.reschedule();
|
||||||
} else {
|
} else {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
@@ -189,6 +209,33 @@ class UPnPManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delayed Callback
|
||||||
|
*
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
private class DelayedCallback extends SimpleTimer2.TimedEvent {
|
||||||
|
|
||||||
|
/** caller must reschedule() */
|
||||||
|
public DelayedCallback() {
|
||||||
|
super(_context.simpleTimer2());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void timeReached() {
|
||||||
|
_scannerCallback.afterScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes out.
|
||||||
|
* We do it this way because we may have two scans running concurrently,
|
||||||
|
* we only want to call afterScan() once.
|
||||||
|
*/
|
||||||
|
void reschedule() {
|
||||||
|
// false == use latest time
|
||||||
|
reschedule((_upnp.getSearchMx() * 1000) + 500, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call when the ports might have changed
|
* Call when the ports might have changed
|
||||||
* The transports can call this pretty quickly at startup,
|
* The transports can call this pretty quickly at startup,
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package net.i2p.router.transport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Android MulticastLock.
|
||||||
|
*
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public interface UPnPScannerCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before a SSDP search begins.
|
||||||
|
* This may be called more than once before afterScan()
|
||||||
|
* if there are multiple searches in parallel.
|
||||||
|
*/
|
||||||
|
public void beforeScan();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after a SSDP search ends.
|
||||||
|
* This will only be called once after the last scan ends.
|
||||||
|
*/
|
||||||
|
public void afterScan();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user