* CSFI compile fix

* Start transports in a standard order to make testing easier
* When transports learn of interface addresses before being started, save them
  and use them at startup
* Pick SSU random port before startListening() and have the TransportManager
  pass it to NTCP before starting
* Only restart NTCP after changing addresses when necessary;
  prevent thrashing at startup (ticket #459)
* Only call rebuildRouterInfo() once at startup
* More checking of min/max SSU port config
* Invalid SSU bind config no longer fatal
* Allow "true" for ipv6 config
* log tweaks
* javadocs
This commit is contained in:
zzz
2013-05-11 19:22:20 +00:00
parent 5e953b0857
commit 5e51c6abef
9 changed files with 326 additions and 76 deletions

View File

@ -26,9 +26,6 @@ import net.i2p.data.RouterInfo;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.OutNetMessage;
import net.i2p.router.RouterContext;
import net.i2p.router.transport.ntcp.NTCPAddress;
import net.i2p.router.transport.ntcp.NTCPTransport;
import net.i2p.router.transport.udp.UDPAddress;
import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.util.Addresses;
import net.i2p.util.Log;
@ -203,6 +200,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
* UDP changed addresses, tell NTCP and restart
*
* All the work moved to NTCPTransport.externalAddressReceived()
*
* @param udpAddr may be null; or udpAddr's host/IP may be null
*/
@Override
public void notifyReplaceAddress(RouterAddress udpAddr) {

View File

@ -76,10 +76,45 @@ public interface Transport {
}
}
/**
* 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 before startListening() to set an initial address,
* or after the transport is running.
*
* @param source defined in Transport.java
* @param ip typ. IPv4 or IPv6 non-local; may be null to indicate IPv4 failure or port info only
* @param port 0 for unknown or unchanged
*/
public void externalAddressReceived(AddressSource source, byte[] ip, int port);
/**
* Notify a transport of the results of trying to forward a port.
*
* @param port the internal port
* @param externalPort the external port, which for now should always be the same as
* the internal port if the forwarding was successful.
*/
public void forwardPortStatus(int port, int externalPort, boolean success, String reason);
/**
* What INTERNAL port would the transport like to have forwarded by UPnP.
* This can't be passed via getCurrentAddress(), as we have to open the port
* before we can publish the address, and that's the external port anyway.
*
* @return port or -1 for none or 0 for any
*/
public int getRequestedPort();
/** Who to notify on message availability */
public void setListener(TransportEventListener listener);
public String getStyle();
public int countPeers();
@ -94,6 +129,11 @@ public interface Transport {
public short getReachabilityStatus();
public void recheckReachability();
public boolean isBacklogged(Hash dest);
/**
* Was the peer UNreachable (outbound only) the last time we tried it?
* This is NOT reset if the peer contacts us and it is never expired.
*/
public boolean wasUnreachable(Hash dest);
public boolean isUnreachable(Hash peer);

View File

@ -10,6 +10,9 @@ package net.i2p.router.transport;
import java.io.IOException;
import java.io.Writer;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@ -57,6 +60,7 @@ public abstract class TransportImpl implements Transport {
/** map from routerIdentHash to timestamp (Long) that the peer was last unreachable */
private final Map<Hash, Long> _unreachableEntries;
private final Set<Hash> _wasUnreachableEntries;
private final Set<InetAddress> _localAddresses;
/** global router ident -> IP */
private static final Map<Hash, byte[]> _IPMap;
@ -95,6 +99,7 @@ public abstract class TransportImpl implements Transport {
_sendPool = null;
_unreachableEntries = new HashMap(16);
_wasUnreachableEntries = new ConcurrentHashSet(16);
_localAddresses = new ConcurrentHashSet(4);
_context.simpleScheduler().addPeriodicEvent(new CleanupUnreachable(), 2 * UNREACHABLE_PERIOD, UNREACHABLE_PERIOD / 2);
}
@ -537,6 +542,26 @@ public abstract class TransportImpl implements Transport {
_listener.transportAddressChanged();
}
/**
* Save a local address we were notified about before we started.
*
* @since IPv6
*/
protected void saveLocalAddress(InetAddress address) {
_localAddresses.add(address);
}
/**
* Return and then clear all saved local addresses.
*
* @since IPv6
*/
protected Collection<InetAddress> getSavedLocalAddresses() {
List<InetAddress> rv = new ArrayList(_localAddresses);
_localAddresses.clear();
return rv;
}
/**
* Notify a transport of an external address change.
* This may be from a local interface, UPnP, a config change, etc.
@ -569,9 +594,9 @@ public abstract class TransportImpl implements Transport {
public void forwardPortStatus(int port, int externalPort, boolean success, String reason) {}
/**
* What port would the transport like to have forwarded by UPnP.
* What INTERNAL port would the transport like to have forwarded by UPnP.
* This can't be passed via getCurrentAddress(), as we have to open the port
* before we can publish the address.
* before we can publish the address, and that's the external port anyway.
*
* @return port or -1 for none or 0 for any
*/
@ -590,6 +615,7 @@ public abstract class TransportImpl implements Transport {
public boolean isEstablished(Hash dest) { return false; }
private static final long UNREACHABLE_PERIOD = 5*60*1000;
public boolean isUnreachable(Hash peer) {
long now = _context.clock().now();
synchronized (_unreachableEntries) {
@ -603,6 +629,7 @@ public abstract class TransportImpl implements Transport {
}
}
}
/** called when we can't reach a peer */
/** This isn't very useful since it is cleared when they contact us */
public void markUnreachable(Hash peer) {
@ -612,6 +639,7 @@ public abstract class TransportImpl implements Transport {
}
markWasUnreachable(peer, true);
}
/** called when we establish a peer connection (outbound or inbound) */
public void markReachable(Hash peer, boolean isInbound) {
// if *some* transport can reach them, then we shouldn't banlist 'em

View File

@ -87,13 +87,24 @@ public class TransportManager implements TransportEventListener {
private void configTransports() {
boolean enableUDP = _context.getBooleanPropertyDefaultTrue(PROP_ENABLE_UDP);
Transport udp = null;
if (enableUDP) {
UDPTransport udp = new UDPTransport(_context, _dhThread);
udp = new UDPTransport(_context, _dhThread);
addTransport(udp);
initializeAddress(udp);
}
if (isNTCPEnabled(_context))
addTransport(new NTCPTransport(_context, _dhThread));
if (isNTCPEnabled(_context)) {
Transport ntcp = new NTCPTransport(_context, _dhThread);
addTransport(ntcp);
initializeAddress(ntcp);
if (udp != null) {
// pass along the port SSU is probably going to use
// so that NTCP may bind early
int port = udp.getRequestedPort();
if (port > 0)
ntcp.externalAddressReceived(SOURCE_CONFIG, null, port);
}
}
if (_transports.isEmpty())
_log.log(Log.CRIT, "No transports are enabled");
}
@ -120,8 +131,8 @@ public class TransportManager implements TransportEventListener {
}
/**
* callback from UPnP or SSU
* Only tell SSU, it will tell NTCP
* Initialize from interfaces, and callback from UPnP or SSU.
* Tell all transports... but don't loop
*
*/
public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port) {
@ -154,7 +165,17 @@ public class TransportManager implements TransportEventListener {
_upnpManager.start();
configTransports();
_log.debug("Starting up the transport manager");
for (Transport t : _transports.values()) {
// Let's do this in a predictable order to make testing easier
// Start NTCP first so it can get notified from SSU
List<Transport> tps = new ArrayList();
Transport tp = getTransport(NTCPTransport.STYLE);
if (tp != null)
tps.add(tp);
tp = getTransport(UDPTransport.STYLE);
if (tp != null)
tps.add(tp);
//for (Transport t : _transports.values()) {
for (Transport t : tps) {
t.startListening();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Transport " + t.getStyle() + " started");

View File

@ -57,6 +57,8 @@ public abstract class TransportUtil {
for (IPv6Config cfg : IPv6Config.values()) {
BY_NAME.put(cfg.toConfigString(), cfg);
}
// alias
BY_NAME.put("true", IPv6Config.IPV6_ENABLED);
}
public static IPv6Config getIPv6Config(RouterContext ctx, String transportStyle) {

View File

@ -8,9 +8,11 @@ import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
@ -58,6 +60,10 @@ public class NTCPTransport extends TransportImpl {
private final EventPumper _pumper;
private final Reader _reader;
private net.i2p.router.transport.ntcp.Writer _writer;
private int _ssuPort;
/** synch on this */
private final Set<InetSocketAddress> _endpoints;
/**
* list of NTCPConnection of connections not yet established that we
* want to remove on establishment or close on timeout
@ -155,6 +161,7 @@ public class NTCPTransport extends TransportImpl {
_context.statManager().createRateStat("ntcp.wantsQueuedWrite", "", "ntcp", RATES);
//_context.statManager().createRateStat("ntcp.write", "", "ntcp", RATES);
_context.statManager().createRateStat("ntcp.writeError", "", "ntcp", RATES);
_endpoints = new HashSet(4);
_establishing = new ConcurrentHashSet(16);
_conLock = new Object();
_conByIdent = new ConcurrentHashMap(64);
@ -474,27 +481,47 @@ public class NTCPTransport extends TransportImpl {
startIt();
RouterAddress addr = configureLocalAddress();
int port;
if (addr != null)
bindAddress(addr);
// probably not set
port = addr.getPort();
else
// received by externalAddressReceived() from TransportManager
port = _ssuPort;
RouterAddress myAddress = bindAddress(port);
if (myAddress != null) {
replaceAddress(myAddress);
} else if (port > 0) {
for (InetAddress ia : getSavedLocalAddresses()) {
OrderedProperties props = new OrderedProperties();
props.setProperty(RouterAddress.PROP_HOST, ia.getHostAddress());
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
myAddress = new RouterAddress(STYLE, props, DEFAULT_COST);
replaceAddress(myAddress);
}
}
// TransportManager.startListening() calls router.rebuildRouterInfo()
}
/**
* Only called by externalAddressReceived().
* Caller should stop the transport first, then
* verify stopped with isAlive()
*
* Doesn't actually restart unless addr is non-null and
* the port is different from the current listen port.
*
* If we had interface addresses before, we lost them.
*
* @param addr may be null
*/
private synchronized void restartListening(RouterAddress addr) {
// try once again to prevent two pumpers which is fatal
// we could just return null since the return value is ignored
if (_pumper.isAlive())
return;
if (_log.shouldLog(Log.WARN)) _log.warn("Restarting ntcp transport listening");
startIt();
if (addr != null)
bindAddress(addr);
if (addr != null) {
RouterAddress myAddress = bindAddress(addr.getPort());
if (myAddress != null)
replaceAddress(myAddress);
else
replaceAddress(addr);
// UDPTransport.rebuildExternalAddress() calls router.rebuildRouterInfo()
}
}
/**
@ -526,12 +553,18 @@ public class NTCPTransport extends TransportImpl {
}
/**
* Only does something if myPort > 0 and myPort != current bound port
* (or there's no current port, or the configured interface or hostname changed).
* If we are changing the bound port, this restarts everything, which takes a long time.
*
* call from synchronized method
* @param myAddress new address, may be null
* @return new address or null
*
* @param myPort does nothing if <= 0
* @return new address ONLY if bound to specific address, otherwise null
*/
private RouterAddress bindAddress(RouterAddress myAddress) {
if (myAddress != null) {
private RouterAddress bindAddress(int port) {
RouterAddress myAddress = null;
if (port > 0) {
InetAddress bindToAddr = null;
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
@ -539,16 +572,7 @@ public class NTCPTransport extends TransportImpl {
// If we are configured with a fixed IP address,
// AND it's one of our local interfaces,
// bind only to that.
boolean isFixed = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true")
.toLowerCase(Locale.US).equals("false");
String fixedHost = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
if (isFixed && fixedHost != null) {
try {
String testAddr = InetAddress.getByName(fixedHost).getHostAddress();
if (Addresses.getAddresses().contains(testAddr))
bindTo = testAddr;
} catch (UnknownHostException uhe) {}
}
bindTo = getFixedHost();
}
if (bindTo != null) {
@ -564,43 +588,104 @@ public class NTCPTransport extends TransportImpl {
}
try {
ServerSocketChannel chan = ServerSocketChannel.open();
chan.configureBlocking(false);
int port = myAddress.getPort();
if (port > 0 && port < 1024)
_log.logAlways(Log.WARN, "Specified NTCP port is " + port + ", ports lower than 1024 not recommended");
InetSocketAddress addr = null;
InetSocketAddress addr;
if(bindToAddr==null) {
addr = new InetSocketAddress(port);
} else {
addr = new InetSocketAddress(bindToAddr, port);
if (_log.shouldLog(Log.WARN))
_log.warn("Binding only to " + bindToAddr);
OrderedProperties props = new OrderedProperties();
props.setProperty(RouterAddress.PROP_HOST, bindTo);
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
myAddress = new RouterAddress(STYLE, props, DEFAULT_COST);
}
if (!_endpoints.isEmpty()) {
// If we are already bound to the new address, OR
// if the host is specified and we are bound to the wildcard on the same port,
// do nothing. Changing config from wildcard to a specified host will
// require a restart.
if (_endpoints.contains(addr) ||
(bindToAddr != null && _endpoints.contains(new InetSocketAddress(port)))) {
if (_log.shouldLog(Log.WARN))
_log.warn("Already listening on " + addr);
return null;
}
// FIXME support multiple binds
// FIXME just close and unregister
stopWaitAndRestart();
}
if (port < 1024)
_log.logAlways(Log.WARN, "Specified NTCP port is " + port + ", ports lower than 1024 not recommended");
ServerSocketChannel chan = ServerSocketChannel.open();
chan.configureBlocking(false);
chan.socket().bind(addr);
_endpoints.add(addr);
if (_log.shouldLog(Log.INFO))
_log.info("Listening on " + addr);
_pumper.register(chan);
} catch (IOException ioe) {
_log.error("Error listening", ioe);
myAddress = null;
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Outbound NTCP connections only - no listener configured");
}
if (myAddress != null) {
replaceAddress(myAddress);
return myAddress;
} else {
return null;
}
return myAddress;
}
/**
* @return configured host or null. Must be one of our local interfaces.
* @since IPv6 moved from bindAddress()
*/
private String getFixedHost() {
boolean isFixed = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true")
.toLowerCase(Locale.US).equals("false");
String fixedHost = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
if (isFixed && fixedHost != null) {
try {
String testAddr = InetAddress.getByName(fixedHost).getHostAddress();
// FIXME range of IPv6 addresses
if (Addresses.getAddresses().contains(testAddr))
return testAddr;
} catch (UnknownHostException uhe) {}
}
return null;
}
/**
* Caller must sync
* @since IPv6 moved from externalAddressReceived()
*/
private void stopWaitAndRestart() {
if (_log.shouldLog(Log.WARN))
_log.warn("Halting NTCP to change address");
stopListening();
// Wait for NTCP Pumper to stop so we don't end up with two...
while (isAlive()) {
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
}
if (_log.shouldLog(Log.WARN))
_log.warn("Restarting NTCP transport listening");
startIt();
}
/**
* Hook for NTCPConnection
*/
Reader getReader() { return _reader; }
/**
* Hook for NTCPConnection
*/
net.i2p.router.transport.ntcp.Writer getWriter() { return _writer; }
public String getStyle() { return STYLE; }
/**
* Hook for NTCPConnection
*/
EventPumper getPumper() { return _pumper; }
/**
@ -677,6 +762,7 @@ public class NTCPTransport extends TransportImpl {
* @since IPv6 moved from CSFI
*/
private RouterAddress createNTCPAddress() {
// Fixme doesn't check PROP_BIND_INTERFACE
String name = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
if ( (name == null) || (name.trim().length() <= 0) || ("null".equals(name)) )
return null;
@ -691,7 +777,7 @@ public class NTCPTransport extends TransportImpl {
}
/**
* UDP changed addresses, tell NTCP and restart
* UDP changed addresses, tell NTCP and (possibly) restart
*
* @since IPv6 moved from CSFI.notifyReplaceAddress()
*/
@ -699,6 +785,23 @@ public class NTCPTransport extends TransportImpl {
public void externalAddressReceived(AddressSource source, byte[] ip, int port) {
if (_log.shouldLog(Log.WARN))
_log.warn("Received address: " + Addresses.toString(ip, port) + " from: " + source);
if (ip != null && !isPubliclyRoutable(ip)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid address: " + Addresses.toString(ip, port) + " from: " + source);
return;
}
if (!isAlive()) {
if (source == SOURCE_INTERFACE) {
try {
InetAddress ia = InetAddress.getByAddress(ip);
saveLocalAddress(ia);
} catch (UnknownHostException uhe) {}
} else if (source == SOURCE_CONFIG) {
// save for startListening()
_ssuPort = port;
}
return;
}
// ignore UPnP for now, get everything from SSU
if (source != SOURCE_SSU)
return;
@ -706,10 +809,10 @@ public class NTCPTransport extends TransportImpl {
}
/**
* UDP changed addresses, tell NTCP and restart
* Port may be set to indicate requested port even if ip is null;
* see CSFI.notifyReplaceAddress()
* UDP changed addresses, tell NTCP and restart.
* Port may be set to indicate requested port even if ip is null.
*
* @param ip previously validated
* @since IPv6 moved from CSFI.notifyReplaceAddress()
*/
private synchronized void externalAddressReceived(byte[] ip, int port) {
@ -845,16 +948,16 @@ public class NTCPTransport extends TransportImpl {
// without tearing down everything
// Especially on disabling the address, we shouldn't tear everything down.
//
if (_log.shouldLog(Log.WARN))
_log.warn("Halting NTCP to change address");
stopListening();
//if (_log.shouldLog(Log.WARN))
// _log.warn("Halting NTCP to change address");
//stopListening();
// Wait for NTCP Pumper to stop so we don't end up with two...
while (isAlive()) {
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
}
//while (isAlive()) {
// try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
//}
restartListening(newAddr);
if (_log.shouldLog(Log.WARN))
_log.warn("Changed NTCP Address and started up, address is now " + newAddr);
_log.warn("Updating NTCP Address with " + newAddr);
return;
}
@ -929,17 +1032,17 @@ public class NTCPTransport extends TransportImpl {
_writer.stopWriting();
_reader.stopReading();
_finisher.stop();
Map cons = null;
List<NTCPConnection> cons;
synchronized (_conLock) {
cons = new HashMap(_conByIdent);
cons = new ArrayList(_conByIdent.values());
_conByIdent.clear();
}
for (Iterator iter = cons.values().iterator(); iter.hasNext(); ) {
NTCPConnection con = (NTCPConnection)iter.next();
for (NTCPConnection con : cons) {
con.close();
}
NTCPConnection.releaseResources();
replaceAddress(null);
_endpoints.clear();
}
public static final String STYLE = "NTCP";

View File

@ -66,6 +66,7 @@ class InboundMessageFragments /*implements UDPTransport.PartialACKSource */{
_ackSender.shutdown();
_messageReceiver.shutdown();
}
public boolean isAlive() { return _alive; }
/**

View File

@ -108,9 +108,7 @@ class UDPEndpoint {
if (port <= 0) {
// try random ports rather than just do new DatagramSocket()
// so we stay out of the way of other I2P stuff
int minPort = _context.getProperty(PROP_MIN_PORT, MIN_RANDOM_PORT);
int maxPort = _context.getProperty(PROP_MAX_PORT, MAX_RANDOM_PORT);
port = minPort + _context.random().nextInt(maxPort - minPort);
port = selectRandomPort(_context);
}
try {
if (_bindAddress == null)
@ -136,6 +134,17 @@ class UDPEndpoint {
return socket;
}
/**
* Pick a random port between the configured boundaries
* @since IPv6
*/
public static int selectRandomPort(RouterContext ctx) {
int minPort = Math.min(65535, Math.max(1, ctx.getProperty(PROP_MIN_PORT, MIN_RANDOM_PORT)));
int maxPort = Math.min(65535, Math.max(minPort, ctx.getProperty(PROP_MAX_PORT, MAX_RANDOM_PORT)));
return minPort + ctx.random().nextInt(1 + maxPort - minPort);
}
/** call after startup() to get actual port or -1 on startup failure */
public int getListenPort() { return _listenPort; }
public UDPSender getSender() { return _sender; }

View File

@ -243,6 +243,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_introducersSelectedOn = -1;
_lastInboundReceivedOn = -1;
_mtu = PeerState.LARGE_MTU;
setupPort();
_needsRebuild = true;
_context.statManager().createRateStat("udp.alreadyConnected", "What is the lifetime of a reestablished session", "udp", RATES);
@ -264,7 +265,26 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_context.simpleScheduler().addPeriodicEvent(new PingIntroducers(), MIN_EXPIRE_TIMEOUT * 3 / 4);
}
public synchronized void startup() {
/**
* Pick a port if not previously configured, so that TransportManager may
* call getRequestedPort() before we've started to get a best-guess of what our
* port is going to be, and pass that to NTCP
*
* @since IPv6
*/
private void setupPort() {
int port = getRequestedPort();
if (port < 0) {
port = UDPEndpoint.selectRandomPort(_context);
Map<String, String> changes = new HashMap();
changes.put(PROP_INTERNAL_PORT, Integer.toString(port));
changes.put(PROP_EXTERNAL_PORT, Integer.toString(port));
_context.router().saveConfig(changes, null);
_log.logAlways(Log.INFO, "UDP selected random port " + port);
}
}
private synchronized void startup() {
_fragments.shutdown();
if (_pusher != null)
_pusher.shutdown();
@ -285,11 +305,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_introManager.reset();
UDPPacket.clearCache();
if (_log.shouldLog(Log.WARN)) _log.warn("Starting SSU transport listening");
_introKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]);
System.arraycopy(_context.routerHash().getData(), 0, _introKey.getData(), 0, SessionKey.KEYSIZE_BYTES);
rebuildExternalAddress();
// bind host
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
@ -312,9 +331,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
try {
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
_log.log(Log.CRIT, "Invalid SSU bind interface specified [" + bindTo + "]", uhe);
setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
return;
_log.error("Invalid SSU bind interface specified [" + bindTo + "]", uhe);
//setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
//return;
// fall thru...
}
}
@ -412,6 +432,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_expireEvent.setIsAlive(true);
_testEvent.setIsAlive(true); // this queues it for 3-6 minutes in the future...
_testEvent.reschedule(10*1000); // lets requeue it for Real Soon
// set up external addresses
// REA param is false;
// TransportManager.startListening() calls router.rebuildRouterInfo()
if (newPort > 0 && bindToAddr == null) {
for (InetAddress ia : getSavedLocalAddresses()) {
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
}
}
rebuildExternalAddress(false);
}
public synchronized void shutdown() {
@ -442,6 +472,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
UDPPacket.clearCache();
UDPAddress.clearCache();
}
/** @since IPv6 */
private boolean isAlive() {
return _inboundFragments.isAlive();
}
/**
* Introduction key that people should use to contact us
@ -581,8 +616,20 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
String sources = _context.getProperty(PROP_SOURCES, DEFAULT_SOURCES);
if (!sources.contains(source.toConfigString()))
return;
if (!isValid(ip))
if (!isValid(ip)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid address: " + Addresses.toString(ip, port) + " from: " + source);
return;
}
if (!isAlive()) {
if (source == SOURCE_INTERFACE) {
try {
InetAddress ia = InetAddress.getByAddress(ip);
saveLocalAddress(ia);
} catch (UnknownHostException uhe) {}
}
return;
}
if (source == SOURCE_INTERFACE) {
// temp prevent multiples
if (ip.length == 4) {