forked from I2P_Developers/i2p.i2p
Transports: Add 4/6 transport caps
WIP, disabled by default for now, to be enabled before relese Add caps to NTCP2 when in hidden mode or firewalled Add SSU address and caps when in hidden mode Add 4 cap to introducer address Other cases todo; ref: http://zzz.i2p/topics/3050 When hidden, store last IP address in config, calling replaceCurrentExternalAddress(), and IP change event logging; wasn't done before
This commit is contained in:
@@ -70,6 +70,17 @@ public abstract class TransportImpl implements Transport {
|
||||
private static final long UNREACHABLE_PERIOD = 5*60*1000;
|
||||
private static final long WAS_UNREACHABLE_PERIOD = 30*60*1000;
|
||||
|
||||
/** @since 0.9.50 */
|
||||
protected static final String PROP_TRANSPORT_CAPS = "i2np.transportCaps";
|
||||
/** @since 0.9.50 */
|
||||
protected static final boolean ENABLE_TRANSPORT_CAPS = false;
|
||||
/** @since 0.9.50 */
|
||||
public static final String CAP_IPV4 = "4";
|
||||
/** @since 0.9.50 */
|
||||
public static final String CAP_IPV6 = "6";
|
||||
/** @since 0.9.50 */
|
||||
public static final String CAP_IPV4_IPV6 = CAP_IPV4 + CAP_IPV6;
|
||||
|
||||
/** @since 0.9.44 */
|
||||
protected static final String PROP_IPV6_FIREWALLED = "i2np.lastIPv6Firewalled";
|
||||
|
||||
|
||||
@@ -1247,8 +1247,19 @@ public class NTCPTransport extends TransportImpl {
|
||||
if (!_enableNTCP2)
|
||||
return;
|
||||
// only set i if we are not firewalled
|
||||
if (props.containsKey("host"))
|
||||
if (props.containsKey("host")) {
|
||||
props.setProperty("i", _b64Ntcp2StaticIV);
|
||||
} else if (_context.getProperty(PROP_TRANSPORT_CAPS, ENABLE_TRANSPORT_CAPS)) {
|
||||
String caps;
|
||||
TransportUtil.IPv6Config config = getIPv6Config();
|
||||
if (config == IPV6_ONLY)
|
||||
caps = CAP_IPV6;
|
||||
else if (config != IPV6_DISABLED && _haveIPv6Address)
|
||||
caps = CAP_IPV4_IPV6;
|
||||
else
|
||||
caps = CAP_IPV4;
|
||||
props.setProperty("caps", caps);
|
||||
}
|
||||
props.setProperty("s", _b64Ntcp2StaticPubkey);
|
||||
props.setProperty("v", NTCP2_VERSION);
|
||||
}
|
||||
|
||||
@@ -187,6 +187,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
|
||||
private static final String CAP_TESTING = Character.toString(UDPAddress.CAPACITY_TESTING);
|
||||
private static final String CAP_TESTING_INTRO = CAP_TESTING + UDPAddress.CAPACITY_INTRODUCER;
|
||||
private static final String CAP_TESTING_4 = CAP_TESTING + CAP_IPV4;
|
||||
|
||||
/** how many relays offered to us will we use at a time? */
|
||||
public static final int PUBLIC_RELAY_COUNT = 3;
|
||||
@@ -204,6 +205,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
private static final int MAX_CONSECUTIVE_FAILED = 5;
|
||||
|
||||
public static final int DEFAULT_COST = 5;
|
||||
private static final int SSU_OUTBOUND_COST = 14;
|
||||
static final long[] RATES = { 10*60*1000 };
|
||||
/** minimum active peers to maintain IP detection, etc. */
|
||||
private static final int MIN_PEERS = 5;
|
||||
@@ -610,12 +612,21 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
// REA param is false;
|
||||
// TransportManager.startListening() calls router.rebuildRouterInfo()
|
||||
if (newPort > 0 && bindToAddrs.isEmpty()) {
|
||||
// Update some config variables and event logs,
|
||||
// because changeAddress() below won't do that for hidden mode
|
||||
// because rebuildExternalAddress() always returns null.
|
||||
boolean save = _context.router().isHidden();
|
||||
Map<String, String> changes = save ? new HashMap<String, String>(4) : null;
|
||||
boolean hasv6 = false;
|
||||
for (InetAddress ia : getSavedLocalAddresses()) {
|
||||
// Discovered or configured addresses are presumed good at the start.
|
||||
// when externalAddressReceived() was called with SOURCE_INTERFACE,
|
||||
// isAlive() was false, so setReachabilityStatus() was not called
|
||||
if (ia.getAddress().length == 16) {
|
||||
byte[] addr = ia.getAddress();
|
||||
String prop = addr.length == 4 ? PROP_IP : PROP_IPV6;
|
||||
String oldIP = save ? _context.getProperty(prop) : null;
|
||||
String newIP = Addresses.toString(addr);
|
||||
if (addr.length == 16) {
|
||||
// only call REA for one v6 address
|
||||
if (hasv6)
|
||||
continue;
|
||||
@@ -625,14 +636,23 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
} else {
|
||||
_lastInboundIPv6 = _context.clock().now();
|
||||
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK, true);
|
||||
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
|
||||
rebuildExternalAddress(newIP, newPort, false);
|
||||
}
|
||||
} else {
|
||||
if (!isIPv4Firewalled())
|
||||
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
|
||||
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
|
||||
rebuildExternalAddress(newIP, newPort, false);
|
||||
}
|
||||
if (save && !newIP.equals(oldIP)) {
|
||||
changes.put(prop, newIP);
|
||||
if (addr.length == 4)
|
||||
changes.put(PROP_IP_CHANGE, Long.toString(_context.clock().now()));
|
||||
if (oldIP != null)
|
||||
_context.router().eventLog().addEvent(EventLog.CHANGE_IP, newIP);
|
||||
}
|
||||
}
|
||||
if (save && !changes.isEmpty())
|
||||
_context.router().saveConfig(changes, null);
|
||||
} else if (newPort > 0 && !bindToAddrs.isEmpty()) {
|
||||
for (InetAddress ia : bindToAddrs) {
|
||||
if (ia.getAddress().length == 16) {
|
||||
@@ -725,6 +745,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
*/
|
||||
SessionKey getIntroKey() { return _introKey; }
|
||||
|
||||
/**
|
||||
* Published or requested port
|
||||
*/
|
||||
int getExternalPort(boolean ipv6) {
|
||||
RouterAddress addr = getCurrentAddress(ipv6);
|
||||
if (addr != null) {
|
||||
@@ -736,7 +759,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
|
||||
/**
|
||||
* IPv4 only
|
||||
* Published IP, IPv4 only
|
||||
* @return IP or null
|
||||
* @since 0.9.2
|
||||
*/
|
||||
@@ -942,6 +965,24 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
gotIPv6Addr = true;
|
||||
}
|
||||
}
|
||||
if ((source == SOURCE_INTERFACE || source == SOURCE_UPNP) &&
|
||||
_context.router().isHidden()) {
|
||||
// Update some config variables and event logs,
|
||||
// because changeAddress() below won't do that for hidden mode
|
||||
// because rebuildExternalAddress() always returns null.
|
||||
String prop = ip.length == 4 ? PROP_IP : PROP_IPV6;
|
||||
String oldIP = _context.getProperty(prop);
|
||||
String newIP = Addresses.toString(ip);
|
||||
if (!newIP.equals(oldIP)) {
|
||||
Map<String, String> changes = new HashMap<String, String>(2);
|
||||
changes.put(prop, newIP);
|
||||
if (ip.length == 4)
|
||||
changes.put(PROP_IP_CHANGE, Long.toString(_context.clock().now()));
|
||||
_context.router().saveConfig(changes, null);
|
||||
if (oldIP != null)
|
||||
_context.router().eventLog().addEvent(EventLog.CHANGE_IP, newIP);
|
||||
}
|
||||
}
|
||||
boolean changed = changeAddress(ip, port);
|
||||
// Assume if we have an interface with a public IP that we aren't firewalled.
|
||||
// If this is wrong, the peer test will figure it out and change the status.
|
||||
@@ -2351,13 +2392,49 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
private RouterAddress locked_rebuildExternalAddress(String host, int port, boolean allowRebuildRouterInfo) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("REA4 " + host + ' ' + port, new Exception());
|
||||
if (_context.router().isHidden())
|
||||
return null;
|
||||
|
||||
boolean isIPv6 = host != null && host.contains(":");
|
||||
OrderedProperties options = new OrderedProperties();
|
||||
if (_context.router().isHidden()) {
|
||||
// save the external address, since we didn't publish it
|
||||
if (port > 0 && host != null) {
|
||||
RouterAddress old = getCurrentExternalAddress(isIPv6);
|
||||
if (old == null || !host.equals(old.getHost()) || port != old.getPort()) {
|
||||
options.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
|
||||
options.setProperty(UDPAddress.PROP_HOST, host);
|
||||
RouterAddress local = new RouterAddress(STYLE, options, SSU_OUTBOUND_COST);
|
||||
replaceCurrentExternalAddress(local, isIPv6);
|
||||
options = new OrderedProperties();
|
||||
}
|
||||
}
|
||||
if (!_context.getProperty(PROP_TRANSPORT_CAPS, ENABLE_TRANSPORT_CAPS))
|
||||
return null;
|
||||
// As of 0.9.50, make an address with only 4/6 caps
|
||||
String caps;
|
||||
TransportUtil.IPv6Config config = getIPv6Config();
|
||||
if (config == IPV6_ONLY)
|
||||
caps = CAP_IPV6;
|
||||
else if (config != IPV6_DISABLED && hasIPv6Address())
|
||||
caps = CAP_IPV4_IPV6;
|
||||
else
|
||||
caps = CAP_IPV4;
|
||||
options.setProperty(UDPAddress.PROP_CAPACITY, caps);
|
||||
RouterAddress current = getCurrentAddress(false);
|
||||
RouterAddress addr = new RouterAddress(STYLE, options, SSU_OUTBOUND_COST);
|
||||
if (!addr.deepEquals(current)) {
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Address rebuilt: " + addr, new Exception());
|
||||
replaceAddress(addr);
|
||||
if (allowRebuildRouterInfo)
|
||||
rebuildRouterInfo();
|
||||
} else {
|
||||
addr = null;
|
||||
}
|
||||
_needsRebuild = false;
|
||||
return addr;
|
||||
}
|
||||
|
||||
boolean directIncluded;
|
||||
// DNS name assumed IPv4
|
||||
boolean isIPv6 = host != null && host.contains(":");
|
||||
boolean introducersRequired = (!isIPv6) && introducersRequired();
|
||||
if (!introducersRequired && allowDirectUDP() && port > 0 && host != null) {
|
||||
options.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
|
||||
@@ -2388,10 +2465,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
|
||||
// if we have explicit external addresses, they had better be reachable
|
||||
if (introducersRequired)
|
||||
options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING);
|
||||
else
|
||||
options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING_INTRO);
|
||||
String caps;
|
||||
if (introducersRequired) {
|
||||
if (_context.getProperty(PROP_TRANSPORT_CAPS, ENABLE_TRANSPORT_CAPS))
|
||||
caps = CAP_TESTING_4;
|
||||
else
|
||||
caps = CAP_TESTING;
|
||||
} else {
|
||||
caps = CAP_TESTING_INTRO;
|
||||
}
|
||||
options.setProperty(UDPAddress.PROP_CAPACITY, caps);
|
||||
|
||||
// MTU since 0.9.2
|
||||
int mtu;
|
||||
|
||||
Reference in New Issue
Block a user