Transport: Ticket #1458 continued...

Implement methods to remove only a single IPv4 or IPv6 address,
so that IPv6 addresses will remain when SSU detects that IPv4 is firewalled
Summary bar status fixes
Fix getIsPortFixed() for more enum cases
log tweaks, cleanups
This commit is contained in:
zzz
2015-04-30 20:33:46 +00:00
parent 4588f1ec75
commit 1868d2b50f
8 changed files with 269 additions and 52 deletions

View File

@ -160,7 +160,6 @@ public class SummaryHelper extends HelperBase {
case IPV4_OK_IPV6_UNKNOWN: case IPV4_OK_IPV6_UNKNOWN:
case IPV4_OK_IPV6_FIREWALLED: case IPV4_OK_IPV6_FIREWALLED:
case IPV4_UNKNOWN_IPV6_OK: case IPV4_UNKNOWN_IPV6_OK:
case IPV4_FIREWALLED_IPV6_OK:
case IPV4_DISABLED_IPV6_OK: case IPV4_DISABLED_IPV6_OK:
case IPV4_SNAT_IPV6_OK: case IPV4_SNAT_IPV6_OK:
RouterAddress ra = routerInfo.getTargetAddress("NTCP"); RouterAddress ra = routerInfo.getTargetAddress("NTCP");
@ -179,10 +178,12 @@ public class SummaryHelper extends HelperBase {
return _("ERR-SymmetricNAT"); return _("ERR-SymmetricNAT");
case REJECT_UNSOLICITED: case REJECT_UNSOLICITED:
case IPV4_FIREWALLED_IPV6_UNKNOWN:
case IPV4_DISABLED_IPV6_FIREWALLED: case IPV4_DISABLED_IPV6_FIREWALLED:
if (routerInfo.getTargetAddress("NTCP") != null) if (routerInfo.getTargetAddress("NTCP") != null)
return _("WARN-Firewalled with Inbound TCP Enabled"); return _("WARN-Firewalled with Inbound TCP Enabled");
// fall through...
case IPV4_FIREWALLED_IPV6_OK:
case IPV4_FIREWALLED_IPV6_UNKNOWN:
if (((FloodfillNetworkDatabaseFacade)_context.netDb()).floodfillEnabled()) if (((FloodfillNetworkDatabaseFacade)_context.netDb()).floodfillEnabled())
return _("WARN-Firewalled and Floodfill"); return _("WARN-Firewalled and Floodfill");
//if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0) //if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)

View File

@ -113,7 +113,19 @@ public abstract class CommSystemFacade implements Service {
/** /**
* Tell other transports our address changed * Tell other transports our address changed
*/ */
public void notifyReplaceAddress(RouterAddress UDPAddr) {} public void notifyReplaceAddress(RouterAddress address) {}
/**
* Tell other transports our address changed
* @since 0.9.20
*/
public void notifyRemoveAddress(RouterAddress address) {}
/**
* Tell other transports our address changed
* @since 0.9.20
*/
public void notifyRemoveAddress(boolean ipv6) {}
/** /**
* Pluggable transport * Pluggable transport

View File

@ -238,7 +238,34 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
if (udp != null) if (udp != null)
port = udp.getRequestedPort(); port = udp.getRequestedPort();
} }
_manager.externalAddressReceived(Transport.AddressSource.SOURCE_SSU, ip, port); if (ip != null || port > 0)
_manager.externalAddressReceived(Transport.AddressSource.SOURCE_SSU, ip, port);
else
notifyRemoveAddress(false);
}
/**
* Tell other transports our address changed
*
* @param address non-null; but address's host/IP may be null
* @since 0.9.20
*/
@Override
public void notifyRemoveAddress(RouterAddress address) {
// just keep this simple for now, multiple v4 or v6 addresses not yet supported
notifyRemoveAddress(address != null &&
address.getIP() != null &&
address.getIP().length == 16);
}
/**
* Tell other transports our address changed
*
* @since 0.9.20
*/
@Override
public void notifyRemoveAddress(boolean ipv6) {
_manager.externalAddressRemoved(Transport.AddressSource.SOURCE_SSU, ipv6);
} }
/** /**

View File

@ -98,6 +98,24 @@ public interface Transport {
*/ */
public void externalAddressReceived(AddressSource source, byte[] ip, int port); public void externalAddressReceived(AddressSource source, byte[] ip, int port);
/**
* Notify a transport of an external address change.
* This may be from a local interface, UPnP, a config change, etc.
* This should not be called if the ip didn't change
* (from that source's point of view), or is a local address.
* May be called multiple times for IPv4 or IPv6.
* The transport should also do its own checking on whether to accept
* notifications from this source.
*
* This can be called after the transport is running.
*
* TODO externalAddressRemoved(source, ip, port)
*
* @param source defined in Transport.java
* @since 0.9.20
*/
public void externalAddressRemoved(AddressSource source, boolean ipv6);
/** /**
* Notify a transport of the results of trying to forward a port. * Notify a transport of the results of trying to forward a port.
* *

View File

@ -554,6 +554,7 @@ public abstract class TransportImpl implements Transport {
* with the same IP length (4 or 16) with the given one. * with the same IP length (4 or 16) with the given one.
* TODO: Allow multiple addresses of the same length. * TODO: Allow multiple addresses of the same length.
* Calls listener.transportAddressChanged() * Calls listener.transportAddressChanged()
* To remove all IPv4 or IPv6 addresses, use removeAddress(boolean).
* *
* @param address null to remove all * @param address null to remove all
*/ */
@ -566,6 +567,7 @@ public abstract class TransportImpl implements Transport {
boolean isIPv6 = TransportUtil.isIPv6(address); boolean isIPv6 = TransportUtil.isIPv6(address);
for (RouterAddress ra : _currentAddresses) { for (RouterAddress ra : _currentAddresses) {
if (isIPv6 == TransportUtil.isIPv6(ra)) if (isIPv6 == TransportUtil.isIPv6(ra))
// COWAL
_currentAddresses.remove(ra); _currentAddresses.remove(ra);
} }
_currentAddresses.add(address); _currentAddresses.add(address);
@ -576,6 +578,61 @@ public abstract class TransportImpl implements Transport {
_listener.transportAddressChanged(); _listener.transportAddressChanged();
} }
/**
* Remove only this address.
* Calls listener.transportAddressChanged().
* To remove all IPv4 or IPv6 addresses, use removeAddress(boolean).
* To remove all IPv4 and IPv6 addresses, use replaceAddress(null).
*
* @param ipv6 true to remove all IPv6 addresses, false to remove all IPv4 addresses
* @since 0.9.20
*/
protected void removeAddress(RouterAddress address) {
if (_log.shouldWarn())
_log.warn("Removing address " + address, new Exception());
boolean changed = _currentAddresses.remove(address);
changed = true;
if (changed) {
if (_log.shouldWarn())
_log.warn(getStyle() + " now has " + _currentAddresses.size() + " addresses");
if (_listener != null)
_listener.transportAddressChanged();
} else {
if (_log.shouldWarn())
_log.warn(getStyle() + " no addresses removed");
}
}
/**
* Remove all existing addresses with the specified IP length (4 or 16).
* Calls listener.transportAddressChanged().
* To remove all IPv4 and IPv6 addresses, use replaceAddress(null).
*
* @param ipv6 true to remove all IPv6 addresses, false to remove all IPv4 addresses
* @since 0.9.20
*/
protected void removeAddress(boolean ipv6) {
if (_log.shouldWarn())
_log.warn("Removing addresses, ipv6? " + ipv6, new Exception());
boolean changed = false;
for (RouterAddress ra : _currentAddresses) {
if (ipv6 == TransportUtil.isIPv6(ra)) {
// COWAL
if (_currentAddresses.remove(ra))
changed = true;
}
}
if (changed) {
if (_log.shouldWarn())
_log.warn(getStyle() + " now has " + _currentAddresses.size() + " addresses");
if (_listener != null)
_listener.transportAddressChanged();
} else {
if (_log.shouldWarn())
_log.warn(getStyle() + " no addresses removed");
}
}
/** /**
* Save a local address we were notified about before we started. * Save a local address we were notified about before we started.
* *
@ -699,6 +756,26 @@ public abstract class TransportImpl implements Transport {
*/ */
public void externalAddressReceived(AddressSource source, byte[] ip, int port) {} public void externalAddressReceived(AddressSource source, byte[] ip, int port) {}
/**
* Notify a transport of an external address change.
* This may be from a local interface, UPnP, a config change, etc.
* This should not be called if the ip didn't change
* (from that source's point of view), or is a local address.
* May be called multiple times for IPv4 or IPv6.
* The transport should also do its own checking on whether to accept
* notifications from this source.
*
* This can be called after the transport is running.
*
* TODO externalAddressRemoved(source, ip, port)
*
* This implementation does nothing. Transports should override if they want notification.
*
* @param source defined in Transport.java
* @since 0.9.20
*/
public void externalAddressRemoved(AddressSource source, boolean ipv6) {}
/** /**
* Notify a transport of the results of trying to forward a port. * Notify a transport of the results of trying to forward a port.
* *

View File

@ -193,7 +193,8 @@ public class TransportManager implements TransportEventListener {
/** /**
* Initialize from interfaces, and callback from UPnP or SSU. * Initialize from interfaces, and callback from UPnP or SSU.
* Tell all transports... but don't loop * See CSFI.notifyReplaceAddress().
* Tell all transports... but don't loop.
* *
*/ */
public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port) { public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port) {
@ -204,6 +205,21 @@ public class TransportManager implements TransportEventListener {
} }
} }
/**
* Remove all ipv4 or ipv6 addresses.
* See CSFI.notifyRemoveAddress().
* Tell all transports... but don't loop.
*
* @since 0.9.20
*/
public void externalAddressRemoved(Transport.AddressSource source, boolean ipv6) {
for (Transport t : _transports.values()) {
// don't loop
if (!(source == SOURCE_SSU && t.getStyle().equals(UDPTransport.STYLE)))
t.externalAddressRemoved(source, ipv6);
}
}
/** /**
* callback from UPnP * callback from UPnP
* *

View File

@ -602,7 +602,7 @@ public class NTCPTransport extends TransportImpl {
// try once again to prevent two pumpers which is fatal // try once again to prevent two pumpers which is fatal
if (_pumper.isAlive()) if (_pumper.isAlive())
return; return;
if (_log.shouldLog(Log.WARN)) _log.warn("Starting ntcp transport listening"); if (_log.shouldLog(Log.WARN)) _log.warn("Starting NTCP transport listening");
startIt(); startIt();
RouterAddress addr = configureLocalAddress(); RouterAddress addr = configureLocalAddress();
@ -636,16 +636,19 @@ public class NTCPTransport extends TransportImpl {
/** /**
* Only called by externalAddressReceived(). * Only called by externalAddressReceived().
* Calls replaceAddress() or removeAddress().
* To remove all addresses, call replaceAddress(null) directly.
* *
* Doesn't actually restart unless addr is non-null and * Doesn't actually restart unless addr is non-null and
* the port is different from the current listen port. * the port is different from the current listen port.
* If addr is null, removes IPv4 addresses only. * If addr is null, removes the addresses specified (v4 or v6)
* *
* If we had interface addresses before, we lost them. * If we had interface addresses before, we lost them.
* *
* @param addr may be null to indicate remove the IPv4 address only * @param addr may be null to indicate remove the address
* @param ipv6 ignored if addr is non-null
*/ */
private synchronized void restartListening(RouterAddress addr) { private synchronized void restartListening(RouterAddress addr, boolean ipv6) {
if (addr != null) { if (addr != null) {
RouterAddress myAddress = bindAddress(addr.getPort()); RouterAddress myAddress = bindAddress(addr.getPort());
if (myAddress != null) if (myAddress != null)
@ -654,16 +657,11 @@ public class NTCPTransport extends TransportImpl {
replaceAddress(addr); replaceAddress(addr);
// UDPTransport.rebuildExternalAddress() calls router.rebuildRouterInfo() // UDPTransport.rebuildExternalAddress() calls router.rebuildRouterInfo()
} else { } else {
// can't do this, want to remove IPv4 only removeAddress(ipv6);
//replaceAddress(null); if (ipv6)
for (RouterAddress ra : _currentAddresses) { _lastInboundIPv6 = 0;
byte[] ip = ra.getIP(); else
if (ip != null && ip.length == 4) { _lastInboundIPv4 = 0;
// COWAL
_currentAddresses.remove(ra);
}
}
_lastInboundIPv4 = 0;
} }
} }
@ -952,7 +950,7 @@ public class NTCPTransport extends TransportImpl {
@Override @Override
public void externalAddressReceived(AddressSource source, byte[] ip, int port) { public void externalAddressReceived(AddressSource source, byte[] ip, int port) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Received address: " + Addresses.toString(ip, port) + " from: " + source); _log.warn("Received address: " + Addresses.toString(ip, port) + " from: " + source, new Exception());
if ((source == SOURCE_INTERFACE || source == SOURCE_SSU) if ((source == SOURCE_INTERFACE || source == SOURCE_SSU)
&& ip != null && ip.length == 16) { && ip != null && ip.length == 16) {
// must be set before isValid() call // must be set before isValid() call
@ -978,8 +976,35 @@ public class NTCPTransport extends TransportImpl {
// ignore UPnP for now, get everything from SSU // ignore UPnP for now, get everything from SSU
if (source != SOURCE_SSU) if (source != SOURCE_SSU)
return; return;
externalAddressReceived(ip, port); boolean isIPv6 = ip != null && ip.length == 16;
externalAddressReceived(ip, isIPv6, port);
} }
/**
* Notify a transport of an external address change.
* This may be from a local interface, UPnP, a config change, etc.
* This should not be called if the ip didn't change
* (from that source's point of view), or is a local address.
* May be called multiple times for IPv4 or IPv6.
* The transport should also do its own checking on whether to accept
* notifications from this source.
*
* This can be called after the transport is running.
*
* TODO externalAddressRemoved(source, ip, port)
*
* @param source defined in Transport.java
* @since 0.9.20
*/
@Override
public void externalAddressRemoved(AddressSource source, boolean ipv6) {
if (_log.shouldWarn())
_log.warn("Removing address, ipv6? " + ipv6 + " from: " + source, new Exception());
// ignore UPnP for now, get everything from SSU
if (source != SOURCE_SSU)
return;
externalAddressReceived(null, ipv6, 0);
}
/** /**
* UDP changed addresses, tell NTCP and restart. * UDP changed addresses, tell NTCP and restart.
@ -988,10 +1013,9 @@ public class NTCPTransport extends TransportImpl {
* @param ip previously validated; may be null to indicate IPv4 failure or port info only * @param ip previously validated; may be null to indicate IPv4 failure or port info only
* @since IPv6 moved from CSFI.notifyReplaceAddress() * @since IPv6 moved from CSFI.notifyReplaceAddress()
*/ */
private synchronized void externalAddressReceived(byte[] ip, int port) { private synchronized void externalAddressReceived(byte[] ip, boolean isIPv6, int port) {
// FIXME just take first address for now // FIXME just take first address for now
// FIXME if SSU set to hostname, NTCP will be set to IP // FIXME if SSU set to hostname, NTCP will be set to IP
boolean isIPv6 = ip != null && ip.length == 16;
RouterAddress oldAddr = getCurrentAddress(isIPv6); RouterAddress oldAddr = getCurrentAddress(isIPv6);
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Changing NTCP Address? was " + oldAddr); _log.info("Changing NTCP Address? was " + oldAddr);
@ -1136,13 +1160,11 @@ public class NTCPTransport extends TransportImpl {
//while (isAlive()) { //while (isAlive()) {
// try { Thread.sleep(5*1000); } catch (InterruptedException ie) {} // try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
//} //}
restartListening(newAddr); restartListening(newAddr, isIPv6);
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Updating NTCP Address with " + newAddr); _log.warn("Updating NTCP Address (ipv6? " + isIPv6 + ") with " + newAddr);
return; return;
} }
/** /**
* If we didn't used to be forwarded, and we have an address, * If we didn't used to be forwarded, and we have an address,

View File

@ -92,6 +92,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* TODO periodically update via CSFI.NetMonitor? * TODO periodically update via CSFI.NetMonitor?
*/ */
private boolean _haveIPv6Address; private boolean _haveIPv6Address;
private long _lastInboundIPv6;
/** do we need to rebuild our external router address asap? */ /** do we need to rebuild our external router address asap? */
private boolean _needsRebuild; private boolean _needsRebuild;
@ -464,6 +465,20 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
// TransportManager.startListening() calls router.rebuildRouterInfo() // TransportManager.startListening() calls router.rebuildRouterInfo()
if (newPort > 0 && bindToAddrs.isEmpty()) { if (newPort > 0 && bindToAddrs.isEmpty()) {
for (InetAddress ia : getSavedLocalAddresses()) { 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
// TODO should we set both to unknown and wait for an inbound v6 conn,
// since there's no v6 testing?
if (ia.getAddress().length == 16) {
// FIXME we need to check and time out after an hour of no inbound ipv6,
// change to firewalled maybe? but we don't have any test to restore
// a v6 address after it's removed.
_lastInboundIPv6 = _context.clock().now();
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK);
} else {
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
}
rebuildExternalAddress(ia.getHostAddress(), newPort, false); rebuildExternalAddress(ia.getHostAddress(), newPort, false);
} }
} }
@ -497,6 +512,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_introManager.reset(); _introManager.reset();
UDPPacket.clearCache(); UDPPacket.clearCache();
UDPAddress.clearCache(); UDPAddress.clearCache();
_lastInboundIPv6 = 0;
} }
/** /**
@ -664,6 +680,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
void inboundConnectionReceived(boolean isIPv6) { void inboundConnectionReceived(boolean isIPv6) {
if (isIPv6) { if (isIPv6) {
_lastInboundIPv6 = _context.clock().now();
if (_currentOurV6Address != null) if (_currentOurV6Address != null)
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK); setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK);
} else { } else {
@ -775,8 +792,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* @param ourPort >= 1024 * @param ourPort >= 1024
*/ */
void externalAddressReceived(Hash from, byte ourIP[], int ourPort) { void externalAddressReceived(Hash from, byte ourIP[], int ourPort) {
if (ourIP.length != 4)
return;
boolean isValid = isValid(ourIP) && boolean isValid = isValid(ourIP) &&
TransportUtil.isValidPort(ourPort); TransportUtil.isValidPort(ourPort);
boolean explicitSpecified = explicitAddressSpecified(); boolean explicitSpecified = explicitAddressSpecified();
@ -785,6 +800,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.info("External address received: " + Addresses.toString(ourIP, ourPort) + " from " _log.info("External address received: " + Addresses.toString(ourIP, ourPort) + " from "
+ from + ", isValid? " + isValid + ", explicitSpecified? " + explicitSpecified + from + ", isValid? " + isValid + ", explicitSpecified? " + explicitSpecified
+ ", receivedInboundRecent? " + inboundRecent + " status " + _reachabilityStatus); + ", receivedInboundRecent? " + inboundRecent + " status " + _reachabilityStatus);
if (ourIP.length != 4) {
return;
}
if (explicitSpecified) if (explicitSpecified)
return; return;
@ -993,7 +1011,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (prop != null) if (prop != null)
return Boolean.parseBoolean(prop); return Boolean.parseBoolean(prop);
Status status = getReachabilityStatus(); Status status = getReachabilityStatus();
return status != Status.REJECT_UNSOLICITED; return status != Status.REJECT_UNSOLICITED &&
status != Status.IPV4_FIREWALLED_IPV6_OK &&
status != Status.IPV4_FIREWALLED_IPV6_UNKNOWN;
} }
/** /**
@ -1035,6 +1055,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* @since 0.9.3 * @since 0.9.3
*/ */
void changePeerPort(PeerState peer, int newPort) { void changePeerPort(PeerState peer, int newPort) {
// this happens a lot
int oldPort; int oldPort;
synchronized (_addDropLock) { synchronized (_addDropLock) {
oldPort = peer.getRemotePort(); oldPort = peer.getRemotePort();
@ -1044,8 +1065,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_peersByRemoteHost.put(peer.getRemoteHostId(), peer); _peersByRemoteHost.put(peer.getRemoteHostId(), peer);
} }
} }
if (_log.shouldLog(Log.WARN) && oldPort != newPort) if (_log.shouldInfo() && oldPort != newPort)
_log.warn("Changed port from " + oldPort + " to " + newPort + " for " + peer); _log.info("Changed port from " + oldPort + " to " + newPort + " for " + peer);
} }
/** /**
@ -1131,8 +1152,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (remotePeer != null) { if (remotePeer != null) {
oldPeer = _peersByIdent.put(remotePeer, peer); oldPeer = _peersByIdent.put(remotePeer, peer);
if ( (oldPeer != null) && (oldPeer != peer) ) { if ( (oldPeer != null) && (oldPeer != peer) ) {
if (_log.shouldLog(Log.WARN)) // this happens a lot
_log.warn("Peer already connected (PBID): old=" + oldPeer + " new=" + peer); if (_log.shouldInfo())
_log.info("Peer already connected (PBID): old=" + oldPeer + " new=" + peer);
// transfer over the old state/inbound message fragments/etc // transfer over the old state/inbound message fragments/etc
peer.loadFrom(oldPeer); peer.loadFrom(oldPeer);
oldEstablishedOn = oldPeer.getKeyEstablishedTime(); oldEstablishedOn = oldPeer.getKeyEstablishedTime();
@ -1147,8 +1169,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
RemoteHostId oldID = oldPeer.getRemoteHostId(); RemoteHostId oldID = oldPeer.getRemoteHostId();
if (!remoteId.equals(oldID)) { if (!remoteId.equals(oldID)) {
// leak fix, remove old address // leak fix, remove old address
if (_log.shouldLog(Log.WARN)) if (_log.shouldInfo())
_log.warn(remotePeer + " changed address FROM " + oldID + " TO " + remoteId); _log.info(remotePeer + " changed address FROM " + oldID + " TO " + remoteId);
PeerState oldPeer2 = _peersByRemoteHost.remove(oldID); PeerState oldPeer2 = _peersByRemoteHost.remove(oldID);
// different ones in the two maps? shouldn't happen // different ones in the two maps? shouldn't happen
if (oldPeer2 != oldPeer && oldPeer2 != null) { if (oldPeer2 != oldPeer && oldPeer2 != null) {
@ -1532,8 +1554,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
// max of 1000 pps // max of 1000 pps
int toSleep = Math.max(8, (1000 / burstps)); int toSleep = Math.max(8, (1000 / burstps));
int count = 0; int count = 0;
if (_log.shouldLog(Log.WARN)) if (_log.shouldInfo())
_log.warn("Sending destroy to : " + howMany + " peers"); _log.info("Sending destroy to : " + howMany + " peers");
for (PeerState peer : _peersByIdent.values()) { for (PeerState peer : _peersByIdent.values()) {
sendDestroy(peer); sendDestroy(peer);
// 1000 per second * 48 bytes = 400 KBps // 1000 per second * 48 bytes = 400 KBps
@ -1858,6 +1880,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** /**
* Update our IPv4 or IPv6 address and optionally tell the router to rebuild and republish the router info. * Update our IPv4 or IPv6 address and optionally tell the router to rebuild and republish the router info.
* FIXME no way to remove an IPv6 address
* *
* @param host new validated IPv4 or IPv6 or DNS hostname or null * @param host new validated IPv4 or IPv6 or DNS hostname or null
* @param port new validated port or 0/-1 * @param port new validated port or 0/-1
@ -1972,7 +1995,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (wantsRebuild) { if (wantsRebuild) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Address rebuilt: " + addr); _log.info("Address rebuilt: " + addr, new Exception());
replaceAddress(addr); replaceAddress(addr);
if (allowRebuildRouterInfo) if (allowRebuildRouterInfo)
_context.router().rebuildRouterInfo(); _context.router().rebuildRouterInfo();
@ -1999,9 +2022,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (hasCurrentAddress()) { if (hasCurrentAddress()) {
// We must remove current address, otherwise the user will see // We must remove current address, otherwise the user will see
// "firewalled with inbound NTCP enabled" warning in console. // "firewalled with inbound NTCP enabled" warning in console.
// Unfortunately this will remove any IPv6 also, // Remove the IPv4 address only
// but we don't have a method to remove just the IPv4 address. FIXME removeAddress(false);
replaceAddress(null);
if (allowRebuildRouterInfo) if (allowRebuildRouterInfo)
_context.router().rebuildRouterInfo(); _context.router().rebuildRouterInfo();
} }
@ -2049,6 +2071,30 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_context.commSystem().notifyReplaceAddress(address); _context.commSystem().notifyReplaceAddress(address);
} }
/**
* Remove then tell NTCP that we changed.
*
* @since 0.9.20
*/
@Override
protected void removeAddress(RouterAddress address) {
super.removeAddress(address);
_context.commSystem().notifyRemoveAddress(address);
}
/**
* Remove then tell NTCP that we changed.
*
* @since 0.9.20
*/
@Override
protected void removeAddress(boolean ipv6) {
super.removeAddress(ipv6);
if (ipv6)
_lastInboundIPv6 = 0;
_context.commSystem().notifyRemoveAddress(ipv6);
}
/** /**
* Calls replaceAddress(address), then shuts down the router if * Calls replaceAddress(address), then shuts down the router if
* dynamic keys is enabled, which it never is, so all this is unused. * dynamic keys is enabled, which it never is, so all this is unused.
@ -2858,16 +2904,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
*/ */
public Status getReachabilityStatus() { public Status getReachabilityStatus() {
String override = _context.getProperty(PROP_REACHABILITY_STATUS_OVERRIDE); String override = _context.getProperty(PROP_REACHABILITY_STATUS_OVERRIDE);
if (override == null) if (override != null) {
return _reachabilityStatus; if ("ok".equals(override))
return Status.OK;
if ("ok".equals(override)) else if ("err-reject".equals(override))
return Status.OK; return Status.REJECT_UNSOLICITED;
else if ("err-reject".equals(override)) else if ("err-different".equals(override))
return Status.REJECT_UNSOLICITED; return Status.DIFFERENT;
else if ("err-different".equals(override)) }
return Status.DIFFERENT;
return _reachabilityStatus; return _reachabilityStatus;
} }