diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index 1581b7b4dfaa9fa3f0db943a2a17a5f272bde933..42dcd3352bfd5f62c92b83cd90c10c6bf0f8c08a 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -160,7 +160,6 @@ public class SummaryHelper extends HelperBase { case IPV4_OK_IPV6_UNKNOWN: case IPV4_OK_IPV6_FIREWALLED: case IPV4_UNKNOWN_IPV6_OK: - case IPV4_FIREWALLED_IPV6_OK: case IPV4_DISABLED_IPV6_OK: case IPV4_SNAT_IPV6_OK: RouterAddress ra = routerInfo.getTargetAddress("NTCP"); @@ -179,10 +178,12 @@ public class SummaryHelper extends HelperBase { return _("ERR-SymmetricNAT"); case REJECT_UNSOLICITED: - case IPV4_FIREWALLED_IPV6_UNKNOWN: case IPV4_DISABLED_IPV6_FIREWALLED: if (routerInfo.getTargetAddress("NTCP") != null) return _("WARN-Firewalled with Inbound TCP Enabled"); + // fall through... + case IPV4_FIREWALLED_IPV6_OK: + case IPV4_FIREWALLED_IPV6_UNKNOWN: if (((FloodfillNetworkDatabaseFacade)_context.netDb()).floodfillEnabled()) return _("WARN-Firewalled and Floodfill"); //if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0) diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index cdd4624f342f7bedffa9faa92fdea5770fd4e8a1..e9c050762fea74a5a99fc6bfc46f5c9419af2624 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -113,7 +113,19 @@ public abstract class CommSystemFacade implements Service { /** * 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 diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index d2e29f21c85f5508892fafa558ca0690de9d3077..a9b8020607ea8f634696fa03b9d2c902fa0d9d89 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -238,7 +238,34 @@ public class CommSystemFacadeImpl extends CommSystemFacade { if (udp != null) 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); } /** diff --git a/router/java/src/net/i2p/router/transport/Transport.java b/router/java/src/net/i2p/router/transport/Transport.java index 0789d7e75ffc5125a77066dc7c075c3c99eb4bd0..a9c03b2ee8b07e194751f370ae4b1ecf507d1de2 100644 --- a/router/java/src/net/i2p/router/transport/Transport.java +++ b/router/java/src/net/i2p/router/transport/Transport.java @@ -98,6 +98,24 @@ public interface Transport { */ 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. * diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index 6056089dd038c414dfc322db1891d758ac97269f..b5f0870aadefab5d75e4e1b0580780c33ff5b582 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -554,6 +554,7 @@ public abstract class TransportImpl implements Transport { * with the same IP length (4 or 16) with the given one. * TODO: Allow multiple addresses of the same length. * Calls listener.transportAddressChanged() + * To remove all IPv4 or IPv6 addresses, use removeAddress(boolean). * * @param address null to remove all */ @@ -566,6 +567,7 @@ public abstract class TransportImpl implements Transport { boolean isIPv6 = TransportUtil.isIPv6(address); for (RouterAddress ra : _currentAddresses) { if (isIPv6 == TransportUtil.isIPv6(ra)) + // COWAL _currentAddresses.remove(ra); } _currentAddresses.add(address); @@ -576,6 +578,61 @@ public abstract class TransportImpl implements Transport { _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. * @@ -699,6 +756,26 @@ public abstract class TransportImpl implements Transport { */ 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. * diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index 217b1acbebdd1744a510b1c3226d2e136bf85dd7..eb44660133b224e0deb14b07eb7f2e23143190a0 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -193,7 +193,8 @@ public class TransportManager implements TransportEventListener { /** * 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) { @@ -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 * diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java index 3b681afdb72c0639d8a4a759c6227d906920d9cb..ca6259e456578529bd88d01a526b3196530842e0 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java @@ -602,7 +602,7 @@ public class NTCPTransport extends TransportImpl { // try once again to prevent two pumpers which is fatal if (_pumper.isAlive()) return; - if (_log.shouldLog(Log.WARN)) _log.warn("Starting ntcp transport listening"); + if (_log.shouldLog(Log.WARN)) _log.warn("Starting NTCP transport listening"); startIt(); RouterAddress addr = configureLocalAddress(); @@ -636,16 +636,19 @@ public class NTCPTransport extends TransportImpl { /** * 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 * 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. * - * @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) { RouterAddress myAddress = bindAddress(addr.getPort()); if (myAddress != null) @@ -654,16 +657,11 @@ public class NTCPTransport extends TransportImpl { replaceAddress(addr); // UDPTransport.rebuildExternalAddress() calls router.rebuildRouterInfo() } else { - // can't do this, want to remove IPv4 only - //replaceAddress(null); - for (RouterAddress ra : _currentAddresses) { - byte[] ip = ra.getIP(); - if (ip != null && ip.length == 4) { - // COWAL - _currentAddresses.remove(ra); - } - } - _lastInboundIPv4 = 0; + removeAddress(ipv6); + if (ipv6) + _lastInboundIPv6 = 0; + else + _lastInboundIPv4 = 0; } } @@ -952,7 +950,7 @@ public class NTCPTransport extends TransportImpl { @Override public void externalAddressReceived(AddressSource source, byte[] ip, int port) { 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) && ip != null && ip.length == 16) { // must be set before isValid() call @@ -978,8 +976,35 @@ public class NTCPTransport extends TransportImpl { // ignore UPnP for now, get everything from SSU if (source != SOURCE_SSU) 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. @@ -988,10 +1013,9 @@ public class NTCPTransport extends TransportImpl { * @param ip previously validated; may be null to indicate IPv4 failure or port info only * @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 if SSU set to hostname, NTCP will be set to IP - boolean isIPv6 = ip != null && ip.length == 16; RouterAddress oldAddr = getCurrentAddress(isIPv6); if (_log.shouldLog(Log.INFO)) _log.info("Changing NTCP Address? was " + oldAddr); @@ -1136,13 +1160,11 @@ public class NTCPTransport extends TransportImpl { //while (isAlive()) { // try { Thread.sleep(5*1000); } catch (InterruptedException ie) {} //} - restartListening(newAddr); + restartListening(newAddr, isIPv6); if (_log.shouldLog(Log.WARN)) - _log.warn("Updating NTCP Address with " + newAddr); + _log.warn("Updating NTCP Address (ipv6? " + isIPv6 + ") with " + newAddr); return; } - - /** * If we didn't used to be forwarded, and we have an address, diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 9e7dbf618029543b930e558fd2faa2269a04355d..41d2cb813770b11b70d2717ff3ec6229d34c77cd 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -92,6 +92,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * TODO periodically update via CSFI.NetMonitor? */ private boolean _haveIPv6Address; + private long _lastInboundIPv6; /** do we need to rebuild our external router address asap? */ private boolean _needsRebuild; @@ -464,6 +465,20 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // TransportManager.startListening() calls router.rebuildRouterInfo() if (newPort > 0 && bindToAddrs.isEmpty()) { 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); } } @@ -497,6 +512,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _introManager.reset(); UDPPacket.clearCache(); UDPAddress.clearCache(); + _lastInboundIPv6 = 0; } /** @@ -664,6 +680,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority void inboundConnectionReceived(boolean isIPv6) { if (isIPv6) { + _lastInboundIPv6 = _context.clock().now(); if (_currentOurV6Address != null) setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK); } else { @@ -775,8 +792,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * @param ourPort >= 1024 */ void externalAddressReceived(Hash from, byte ourIP[], int ourPort) { - if (ourIP.length != 4) - return; boolean isValid = isValid(ourIP) && TransportUtil.isValidPort(ourPort); boolean explicitSpecified = explicitAddressSpecified(); @@ -785,6 +800,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _log.info("External address received: " + Addresses.toString(ourIP, ourPort) + " from " + from + ", isValid? " + isValid + ", explicitSpecified? " + explicitSpecified + ", receivedInboundRecent? " + inboundRecent + " status " + _reachabilityStatus); + if (ourIP.length != 4) { + return; + } if (explicitSpecified) return; @@ -993,7 +1011,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (prop != null) return Boolean.parseBoolean(prop); 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 */ void changePeerPort(PeerState peer, int newPort) { + // this happens a lot int oldPort; synchronized (_addDropLock) { oldPort = peer.getRemotePort(); @@ -1044,8 +1065,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _peersByRemoteHost.put(peer.getRemoteHostId(), peer); } } - if (_log.shouldLog(Log.WARN) && oldPort != newPort) - _log.warn("Changed port from " + oldPort + " to " + newPort + " for " + peer); + if (_log.shouldInfo() && oldPort != newPort) + _log.info("Changed port from " + oldPort + " to " + newPort + " for " + peer); } /** @@ -1131,8 +1152,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (remotePeer != null) { oldPeer = _peersByIdent.put(remotePeer, peer); if ( (oldPeer != null) && (oldPeer != peer) ) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Peer already connected (PBID): old=" + oldPeer + " new=" + peer); + // this happens a lot + if (_log.shouldInfo()) + _log.info("Peer already connected (PBID): old=" + oldPeer + " new=" + peer); // transfer over the old state/inbound message fragments/etc peer.loadFrom(oldPeer); oldEstablishedOn = oldPeer.getKeyEstablishedTime(); @@ -1147,8 +1169,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority RemoteHostId oldID = oldPeer.getRemoteHostId(); if (!remoteId.equals(oldID)) { // leak fix, remove old address - if (_log.shouldLog(Log.WARN)) - _log.warn(remotePeer + " changed address FROM " + oldID + " TO " + remoteId); + if (_log.shouldInfo()) + _log.info(remotePeer + " changed address FROM " + oldID + " TO " + remoteId); PeerState oldPeer2 = _peersByRemoteHost.remove(oldID); // different ones in the two maps? shouldn't happen if (oldPeer2 != oldPeer && oldPeer2 != null) { @@ -1532,8 +1554,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // max of 1000 pps int toSleep = Math.max(8, (1000 / burstps)); int count = 0; - if (_log.shouldLog(Log.WARN)) - _log.warn("Sending destroy to : " + howMany + " peers"); + if (_log.shouldInfo()) + _log.info("Sending destroy to : " + howMany + " peers"); for (PeerState peer : _peersByIdent.values()) { sendDestroy(peer); // 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. + * FIXME no way to remove an IPv6 address * * @param host new validated IPv4 or IPv6 or DNS hostname or null * @param port new validated port or 0/-1 @@ -1972,7 +1995,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (wantsRebuild) { if (_log.shouldLog(Log.INFO)) - _log.info("Address rebuilt: " + addr); + _log.info("Address rebuilt: " + addr, new Exception()); replaceAddress(addr); if (allowRebuildRouterInfo) _context.router().rebuildRouterInfo(); @@ -1999,9 +2022,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (hasCurrentAddress()) { // We must remove current address, otherwise the user will see // "firewalled with inbound NTCP enabled" warning in console. - // Unfortunately this will remove any IPv6 also, - // but we don't have a method to remove just the IPv4 address. FIXME - replaceAddress(null); + // Remove the IPv4 address only + removeAddress(false); if (allowRebuildRouterInfo) _context.router().rebuildRouterInfo(); } @@ -2049,6 +2071,30 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _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 * 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() { String override = _context.getProperty(PROP_REACHABILITY_STATUS_OVERRIDE); - if (override == null) - return _reachabilityStatus; - - if ("ok".equals(override)) - return Status.OK; - else if ("err-reject".equals(override)) - return Status.REJECT_UNSOLICITED; - else if ("err-different".equals(override)) - return Status.DIFFERENT; - + if (override != null) { + if ("ok".equals(override)) + return Status.OK; + else if ("err-reject".equals(override)) + return Status.REJECT_UNSOLICITED; + else if ("err-different".equals(override)) + return Status.DIFFERENT; + } return _reachabilityStatus; }