forked from I2P_Developers/i2p.i2p
* NTCP:
Move SSU address notification handling from CSFI to NTCPTransport
This commit is contained in:
@ -194,249 +194,26 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
||||
//if (_context.router().isHidden())
|
||||
// return Collections.EMPTY_SET;
|
||||
List<RouterAddress> addresses = new ArrayList(_manager.getAddresses());
|
||||
|
||||
Transport ntcp = _manager.getTransport(NTCPTransport.STYLE);
|
||||
boolean hasNTCP = ntcp != null && ntcp.hasCurrentAddress();
|
||||
|
||||
boolean newCreated = false;
|
||||
if (!hasNTCP) {
|
||||
RouterAddress addr = createNTCPAddress(_context);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("NTCP address: " + addr);
|
||||
if (addr != null) {
|
||||
addresses.add(addr);
|
||||
newCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Creating addresses: " + addresses + " isNew? " + newCreated, new Exception("creator"));
|
||||
_log.info("Creating addresses: " + addresses, new Exception("creator"));
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
|
||||
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
|
||||
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
|
||||
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip";
|
||||
|
||||
/**
|
||||
* This only creates an address if the hostname AND port are set in router.config,
|
||||
* which should be rare.
|
||||
* Otherwise, notifyReplaceAddress() below takes care of it.
|
||||
* Note this is called both from above and from NTCPTransport.startListening()
|
||||
*
|
||||
* This should really be moved to ntcp/NTCPTransport.java, why is it here?
|
||||
*/
|
||||
public static RouterAddress createNTCPAddress(RouterContext ctx) {
|
||||
if (!TransportManager.isNTCPEnabled(ctx)) return null;
|
||||
String name = ctx.router().getConfigSetting(PROP_I2NP_NTCP_HOSTNAME);
|
||||
String port = ctx.router().getConfigSetting(PROP_I2NP_NTCP_PORT);
|
||||
/*
|
||||
boolean isNew = false;
|
||||
if (name == null) {
|
||||
name = "localhost";
|
||||
isNew = true;
|
||||
}
|
||||
if (port == null) {
|
||||
port = String.valueOf(ctx.random().nextInt(10240)+1024);
|
||||
isNew = true;
|
||||
}
|
||||
*/
|
||||
if ( (name == null) || (port == null) || (name.trim().length() <= 0) || ("null".equals(name)) )
|
||||
return null;
|
||||
try {
|
||||
int p = Integer.parseInt(port);
|
||||
if ( (p <= 0) || (p > 64*1024) )
|
||||
return null;
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
Properties props = new Properties();
|
||||
props.setProperty(NTCPAddress.PROP_HOST, name);
|
||||
props.setProperty(NTCPAddress.PROP_PORT, port);
|
||||
RouterAddress addr = new RouterAddress();
|
||||
addr.setCost(NTCPAddress.DEFAULT_COST);
|
||||
//addr.setExpiration(null);
|
||||
addr.setOptions(props);
|
||||
addr.setTransportStyle(NTCPTransport.STYLE);
|
||||
//if (isNew) {
|
||||
// why save the same thing?
|
||||
Map<String, String> changes = new HashMap();
|
||||
changes.put(PROP_I2NP_NTCP_HOSTNAME, name);
|
||||
changes.put(PROP_I2NP_NTCP_PORT, port);
|
||||
ctx.router().saveConfig(changes, null);
|
||||
//}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP changed addresses, tell NTCP and restart
|
||||
* This should really be moved to ntcp/NTCPTransport.java, why is it here?
|
||||
*
|
||||
* All the work moved to NTCPTransport.externalAddressReceived()
|
||||
*/
|
||||
@Override
|
||||
public synchronized void notifyReplaceAddress(RouterAddress udpAddr) {
|
||||
if (udpAddr == null)
|
||||
return;
|
||||
NTCPTransport t = (NTCPTransport) _manager.getTransport(NTCPTransport.STYLE);
|
||||
if (t == null)
|
||||
return;
|
||||
|
||||
//////// FIXME just take first IPv4 address for now
|
||||
List<RouterAddress> oldAddrs = t.getCurrentAddresses();
|
||||
RouterAddress oldAddr = null;
|
||||
for (RouterAddress ra : oldAddrs) {
|
||||
byte[] ipx = ra.getIP();
|
||||
if (ipx != null && ipx.length == 4) {
|
||||
oldAddr = ra;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Changing NTCP Address? was " + oldAddr);
|
||||
|
||||
RouterAddress newAddr = new RouterAddress();
|
||||
newAddr.setTransportStyle(NTCPTransport.STYLE);
|
||||
Properties newProps = new Properties();
|
||||
if (oldAddr == null) {
|
||||
newAddr.setCost(NTCPAddress.DEFAULT_COST);
|
||||
} else {
|
||||
newAddr.setCost(oldAddr.getCost());
|
||||
newProps.putAll(oldAddr.getOptionsMap());
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
// Auto Port Setting
|
||||
// old behavior (<= 0.7.3): auto-port defaults to false, and true trumps explicit setting
|
||||
// new behavior (>= 0.7.4): auto-port defaults to true, but explicit setting trumps auto
|
||||
// TODO rewrite this to operate on ints instead of strings
|
||||
String oport = newProps.getProperty(NTCPAddress.PROP_PORT);
|
||||
String nport = null;
|
||||
String cport = _context.getProperty(PROP_I2NP_NTCP_PORT);
|
||||
if (cport != null && cport.length() > 0) {
|
||||
nport = cport;
|
||||
} else if (_context.getBooleanPropertyDefaultTrue(PROP_I2NP_NTCP_AUTO_PORT)) {
|
||||
// 0.9.6 change
|
||||
// This wasn't quite right, as udpAddr is the EXTERNAL port and we really
|
||||
// want NTCP to bind to the INTERNAL port the first time,
|
||||
// because if they are different, the NAT is changing them, and
|
||||
// it probably isn't mapping UDP and TCP the same.
|
||||
public void notifyReplaceAddress(RouterAddress udpAddr) {
|
||||
byte[] ip = udpAddr != null ? udpAddr.getIP() : null;
|
||||
int port = udpAddr != null ? udpAddr.getPort() : 0;
|
||||
if (port < 0) {
|
||||
Transport udp = _manager.getTransport(UDPTransport.STYLE);
|
||||
if (udp != null) {
|
||||
int udpIntPort = udp.getRequestedPort();
|
||||
if (udpIntPort > 0)
|
||||
// should always be true
|
||||
nport = Integer.toString(udpIntPort);
|
||||
}
|
||||
if (nport == null)
|
||||
// fallback
|
||||
nport = udpAddr.getOption(UDPAddress.PROP_PORT);
|
||||
if (udp != null)
|
||||
port = udp.getRequestedPort();
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + oport + " config: " + cport + " new: " + nport);
|
||||
if (nport == null || nport.length() <= 0)
|
||||
return;
|
||||
// 0.9.6 change
|
||||
// Don't have NTCP "chase" SSU's external port,
|
||||
// as it may change, possibly frequently.
|
||||
//if (oport == null || ! oport.equals(nport)) {
|
||||
if (oport == null) {
|
||||
newProps.setProperty(NTCPAddress.PROP_PORT, nport);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Auto IP Setting
|
||||
// old behavior (<= 0.7.3): auto-ip defaults to false, and trumps configured hostname,
|
||||
// and ignores reachability status - leading to
|
||||
// "firewalled with inbound TCP enabled" warnings.
|
||||
// new behavior (>= 0.7.4): auto-ip defaults to true, and explicit setting trumps auto,
|
||||
// and only takes effect if reachability is OK.
|
||||
// And new "always" setting ignores reachability status, like
|
||||
// "true" was in 0.7.3
|
||||
String ohost = newProps.getProperty(NTCPAddress.PROP_HOST);
|
||||
String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true").toLowerCase(Locale.US);
|
||||
String name = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
|
||||
// hostname config trumps auto config
|
||||
if (name != null && name.length() > 0)
|
||||
enabled = "false";
|
||||
Transport udp = _manager.getTransport(UDPTransport.STYLE);
|
||||
short status = STATUS_UNKNOWN;
|
||||
if (udp != null)
|
||||
status = udp.getReachabilityStatus();
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " auto: " + enabled + " status: " + status);
|
||||
if (enabled.equals("always") ||
|
||||
(Boolean.parseBoolean(enabled) && status == STATUS_OK)) {
|
||||
String nhost = udpAddr.getOption(UDPAddress.PROP_HOST);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: " + nhost);
|
||||
if (nhost == null || nhost.length() <= 0)
|
||||
return;
|
||||
if (ohost == null || ! ohost.equalsIgnoreCase(nhost)) {
|
||||
newProps.setProperty(NTCPAddress.PROP_HOST, nhost);
|
||||
changed = true;
|
||||
}
|
||||
} else if (enabled.equals("false") &&
|
||||
name != null && name.length() > 0 &&
|
||||
!name.equals(ohost) &&
|
||||
nport != null) {
|
||||
// Host name is configured, and we have a port (either auto or configured)
|
||||
// but we probably only get here if the port is auto,
|
||||
// otherwise createNTCPAddress() would have done it already
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: " + name);
|
||||
newProps.setProperty(NTCPAddress.PROP_HOST, name);
|
||||
changed = true;
|
||||
} else if (ohost == null || ohost.length() <= 0) {
|
||||
return;
|
||||
} else if (Boolean.parseBoolean(enabled) && status != STATUS_OK) {
|
||||
// UDP transitioned to not-OK, turn off NTCP address
|
||||
// This will commonly happen at startup if we were initially OK
|
||||
// because UPnP was successful, but a subsequent SSU Peer Test determines
|
||||
// we are still firewalled (SW firewall, bad UPnP indication, etc.)
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: null");
|
||||
newAddr = null;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
if (oldAddr != null) {
|
||||
int oldCost = oldAddr.getCost();
|
||||
int newCost = NTCPAddress.DEFAULT_COST;
|
||||
if (TransportImpl.ADJUST_COST && !t.haveCapacity())
|
||||
newCost++;
|
||||
if (newCost != oldCost) {
|
||||
oldAddr.setCost(newCost);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Changing NTCP cost from " + oldCost + " to " + newCost);
|
||||
} else {
|
||||
_log.info("No change to NTCP Address");
|
||||
}
|
||||
} else {
|
||||
_log.info("No change to NTCP Address");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// stopListening stops the pumper, readers, and writers, so required even if
|
||||
// oldAddr == null since startListening starts them all again
|
||||
//
|
||||
// really need to fix this so that we can change or create an inbound address
|
||||
// without tearing down everything
|
||||
// Especially on disabling the address, we shouldn't tear everything down.
|
||||
//
|
||||
_log.warn("Halting NTCP to change address");
|
||||
t.stopListening();
|
||||
if (newAddr != null)
|
||||
newAddr.setOptions(newProps);
|
||||
// Wait for NTCP Pumper to stop so we don't end up with two...
|
||||
while (t.isAlive()) {
|
||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
t.restartListening(newAddr);
|
||||
_log.warn("Changed NTCP Address and started up, address is now " + newAddr);
|
||||
return;
|
||||
_manager.externalAddressReceived(Transport.AddressSource.SOURCE_SSU, ip, port);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -63,8 +63,7 @@ public interface Transport {
|
||||
SOURCE_INTERFACE("local"),
|
||||
/** unused */
|
||||
SOURCE_CONFIG("config"),
|
||||
/** unused */
|
||||
SOURCE_SSU_PEER("ssu");
|
||||
SOURCE_SSU("ssu");
|
||||
|
||||
private final String cfgstr;
|
||||
|
||||
|
@ -552,7 +552,7 @@ public abstract class TransportImpl implements Transport {
|
||||
* This implementation does nothing. Transports should override if they want notification.
|
||||
*
|
||||
* @param source defined in Transport.java
|
||||
* @param ip typ. IPv4 or IPv6 non-local
|
||||
* @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) {}
|
||||
|
@ -30,7 +30,7 @@ import net.i2p.data.i2np.I2NPMessage;
|
||||
import net.i2p.router.CommSystemFacade;
|
||||
import net.i2p.router.OutNetMessage;
|
||||
import net.i2p.router.RouterContext;
|
||||
import static net.i2p.router.transport.Transport.AddressSource.SOURCE_INTERFACE;
|
||||
import static net.i2p.router.transport.Transport.AddressSource.*;
|
||||
import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
|
||||
import net.i2p.router.transport.ntcp.NTCPTransport;
|
||||
import net.i2p.router.transport.udp.UDPTransport;
|
||||
@ -120,14 +120,16 @@ public class TransportManager implements TransportEventListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* callback from UPnP
|
||||
* callback from UPnP or SSU
|
||||
* Only tell SSU, it will tell NTCP
|
||||
*
|
||||
*/
|
||||
public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port) {
|
||||
Transport t = getTransport(UDPTransport.STYLE);
|
||||
if (t != null)
|
||||
t.externalAddressReceived(source, ip, port);
|
||||
for (Transport t : _transports.values()) {
|
||||
// don't loop
|
||||
if (!(source == SOURCE_SSU && t.getStyle().equals(UDPTransport.STYLE)))
|
||||
t.externalAddressReceived(source, ip, port);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,7 +387,7 @@ public class TransportManager implements TransportEventListener {
|
||||
int port = t.getRequestedPort();
|
||||
// Use UDP port for NTCP too - see comment in NTCPTransport.getRequestedPort() for why this is here
|
||||
if (t.getStyle().equals(NTCPTransport.STYLE) && port <= 0 &&
|
||||
_context.getBooleanProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)) {
|
||||
_context.getBooleanProperty(NTCPTransport.PROP_I2NP_NTCP_AUTO_PORT)) {
|
||||
Transport udp = getTransport(UDPTransport.STYLE);
|
||||
if (udp != null)
|
||||
port = t.getRequestedPort();
|
||||
|
@ -30,12 +30,15 @@ import net.i2p.router.OutNetMessage;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.transport.CommSystemFacadeImpl;
|
||||
import net.i2p.router.transport.Transport;
|
||||
import static net.i2p.router.transport.Transport.AddressSource.*;
|
||||
import net.i2p.router.transport.TransportBid;
|
||||
import net.i2p.router.transport.TransportImpl;
|
||||
import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
|
||||
import net.i2p.router.transport.udp.UDPTransport;
|
||||
import net.i2p.util.Addresses;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.Translate;
|
||||
|
||||
/**
|
||||
@ -62,6 +65,11 @@ public class NTCPTransport extends TransportImpl {
|
||||
*/
|
||||
private final Set<NTCPConnection> _establishing;
|
||||
|
||||
public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
|
||||
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
|
||||
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
|
||||
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip";
|
||||
|
||||
/** this is rarely if ever used, default is to bind to wildcard address */
|
||||
public static final String PROP_BIND_INTERFACE = "i2np.ntcp.bindInterface";
|
||||
|
||||
@ -471,11 +479,11 @@ public class NTCPTransport extends TransportImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called by CSFI.
|
||||
* Only called by externalAddressReceived().
|
||||
* Caller should stop the transport first, then
|
||||
* verify stopped with isAlive()
|
||||
*/
|
||||
public synchronized void restartListening(RouterAddress addr) {
|
||||
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())
|
||||
@ -528,9 +536,9 @@ 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(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_IP, "true")
|
||||
boolean isFixed = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true")
|
||||
.toLowerCase(Locale.US).equals("false");
|
||||
String fixedHost = _context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_HOSTNAME);
|
||||
String fixedHost = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
|
||||
if (isFixed && fixedHost != null) {
|
||||
try {
|
||||
String testAddr = InetAddress.getByName(fixedHost).getHostAddress();
|
||||
@ -638,12 +646,8 @@ public class NTCPTransport extends TransportImpl {
|
||||
|
||||
/** caller must synch on this */
|
||||
private void configureLocalAddress() {
|
||||
RouterContext ctx = getContext();
|
||||
if (ctx == null) {
|
||||
System.err.println("NIO transport has no context?");
|
||||
} else {
|
||||
// this generally returns null -- see javadoc
|
||||
RouterAddress ra = CommSystemFacadeImpl.createNTCPAddress(ctx);
|
||||
RouterAddress ra = createNTCPAddress();
|
||||
if (ra != null) {
|
||||
NTCPAddress addr = new NTCPAddress(ra);
|
||||
if (addr.getPort() <= 0) {
|
||||
@ -660,9 +664,200 @@ public class NTCPTransport extends TransportImpl {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("NTCP address is outbound only");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This only creates an address if the hostname AND port are set in router.config,
|
||||
* which should be rare.
|
||||
* Otherwise, notifyReplaceAddress() below takes care of it.
|
||||
* Note this is called both from above and from NTCPTransport.startListening()
|
||||
*
|
||||
* @since IPv6 moved from CSFI
|
||||
*/
|
||||
private RouterAddress createNTCPAddress() {
|
||||
String name = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
|
||||
if ( (name == null) || (name.trim().length() <= 0) || ("null".equals(name)) )
|
||||
return null;
|
||||
int p = _context.getProperty(PROP_I2NP_NTCP_PORT, -1);
|
||||
if (p <= 0 || p >= 64*1024)
|
||||
return null;
|
||||
OrderedProperties props = new OrderedProperties();
|
||||
props.setProperty(NTCPAddress.PROP_HOST, name);
|
||||
props.setProperty(NTCPAddress.PROP_PORT, Integer.toString(p));
|
||||
RouterAddress addr = new RouterAddress(STYLE, props, NTCPAddress.DEFAULT_COST);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP changed addresses, tell NTCP and restart
|
||||
*
|
||||
* @since IPv6 moved from CSFI.notifyReplaceAddress()
|
||||
*/
|
||||
@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);
|
||||
// ignore UPnP for now, get everything from SSU
|
||||
if (source != SOURCE_SSU)
|
||||
return;
|
||||
externalAddressReceived(ip, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP changed addresses, tell NTCP and restart
|
||||
* Port may be set to indicate requested port even if ip is null;
|
||||
* see CSFI.notifyReplaceAddress()
|
||||
*
|
||||
* @since IPv6 moved from CSFI.notifyReplaceAddress()
|
||||
*/
|
||||
private synchronized void externalAddressReceived(byte[] ip, int port) {
|
||||
// FIXME just take first IPv4 address for now
|
||||
// FIXME if SSU set to hostname, NTCP will be set to IP
|
||||
RouterAddress oldAddr = getCurrentAddress(false);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Changing NTCP Address? was " + oldAddr);
|
||||
|
||||
OrderedProperties newProps = new OrderedProperties();
|
||||
int cost;
|
||||
if (oldAddr == null) {
|
||||
cost = NTCPAddress.DEFAULT_COST;
|
||||
} else {
|
||||
cost = oldAddr.getCost();
|
||||
newProps.putAll(oldAddr.getOptionsMap());
|
||||
}
|
||||
RouterAddress newAddr = new RouterAddress(STYLE, newProps, cost);
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
// Auto Port Setting
|
||||
// old behavior (<= 0.7.3): auto-port defaults to false, and true trumps explicit setting
|
||||
// new behavior (>= 0.7.4): auto-port defaults to true, but explicit setting trumps auto
|
||||
// TODO rewrite this to operate on ints instead of strings
|
||||
String oport = newProps.getProperty(NTCPAddress.PROP_PORT);
|
||||
String nport = null;
|
||||
String cport = _context.getProperty(PROP_I2NP_NTCP_PORT);
|
||||
if (cport != null && cport.length() > 0) {
|
||||
nport = cport;
|
||||
} else if (_context.getBooleanPropertyDefaultTrue(PROP_I2NP_NTCP_AUTO_PORT)) {
|
||||
// 0.9.6 change
|
||||
// This wasn't quite right, as udpAddr is the EXTERNAL port and we really
|
||||
// want NTCP to bind to the INTERNAL port the first time,
|
||||
// because if they are different, the NAT is changing them, and
|
||||
// it probably isn't mapping UDP and TCP the same.
|
||||
if (port > 0)
|
||||
// should always be true
|
||||
nport = Integer.toString(port);
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + oport + " config: " + cport + " new: " + nport);
|
||||
if (nport == null || nport.length() <= 0)
|
||||
return;
|
||||
// 0.9.6 change
|
||||
// Don't have NTCP "chase" SSU's external port,
|
||||
// as it may change, possibly frequently.
|
||||
//if (oport == null || ! oport.equals(nport)) {
|
||||
if (oport == null) {
|
||||
newProps.setProperty(NTCPAddress.PROP_PORT, nport);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Auto IP Setting
|
||||
// old behavior (<= 0.7.3): auto-ip defaults to false, and trumps configured hostname,
|
||||
// and ignores reachability status - leading to
|
||||
// "firewalled with inbound TCP enabled" warnings.
|
||||
// new behavior (>= 0.7.4): auto-ip defaults to true, and explicit setting trumps auto,
|
||||
// and only takes effect if reachability is OK.
|
||||
// And new "always" setting ignores reachability status, like
|
||||
// "true" was in 0.7.3
|
||||
String ohost = newProps.getProperty(NTCPAddress.PROP_HOST);
|
||||
String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true").toLowerCase(Locale.US);
|
||||
String name = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
|
||||
// hostname config trumps auto config
|
||||
if (name != null && name.length() > 0)
|
||||
enabled = "false";
|
||||
|
||||
// assume SSU is happy if the address is non-null
|
||||
// TODO is this sufficient?
|
||||
boolean ssuOK = ip != null;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " auto: " + enabled + " ssuOK? " + ssuOK);
|
||||
if (enabled.equals("always") ||
|
||||
(Boolean.parseBoolean(enabled) && ssuOK)) {
|
||||
// ip non-null
|
||||
String nhost = Addresses.toString(ip);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: " + nhost);
|
||||
if (nhost == null || nhost.length() <= 0)
|
||||
return;
|
||||
if (ohost == null || ! ohost.equalsIgnoreCase(nhost)) {
|
||||
newProps.setProperty(NTCPAddress.PROP_HOST, nhost);
|
||||
changed = true;
|
||||
}
|
||||
} else if (enabled.equals("false") &&
|
||||
name != null && name.length() > 0 &&
|
||||
!name.equals(ohost) &&
|
||||
nport != null) {
|
||||
// Host name is configured, and we have a port (either auto or configured)
|
||||
// but we probably only get here if the port is auto,
|
||||
// otherwise createNTCPAddress() would have done it already
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: " + name);
|
||||
newProps.setProperty(NTCPAddress.PROP_HOST, name);
|
||||
changed = true;
|
||||
} else if (ohost == null || ohost.length() <= 0) {
|
||||
return;
|
||||
} else if (Boolean.parseBoolean(enabled) && !ssuOK) {
|
||||
// UDP transitioned to not-OK, turn off NTCP address
|
||||
// This will commonly happen at startup if we were initially OK
|
||||
// because UPnP was successful, but a subsequent SSU Peer Test determines
|
||||
// we are still firewalled (SW firewall, bad UPnP indication, etc.)
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("old: " + ohost + " config: " + name + " new: null");
|
||||
newAddr = null;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
if (oldAddr != null) {
|
||||
int oldCost = oldAddr.getCost();
|
||||
int newCost = NTCPAddress.DEFAULT_COST;
|
||||
if (TransportImpl.ADJUST_COST && !haveCapacity())
|
||||
newCost++;
|
||||
if (newCost != oldCost) {
|
||||
oldAddr.setCost(newCost);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Changing NTCP cost from " + oldCost + " to " + newCost);
|
||||
} else {
|
||||
_log.info("No change to NTCP Address");
|
||||
}
|
||||
} else {
|
||||
_log.info("No change to NTCP Address");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// stopListening stops the pumper, readers, and writers, so required even if
|
||||
// oldAddr == null since startListening starts them all again
|
||||
//
|
||||
// really need to fix this so that we can change or create an inbound address
|
||||
// without tearing down everything
|
||||
// Especially on disabling the address, we shouldn't tear everything down.
|
||||
//
|
||||
_log.warn("Halting NTCP to change address");
|
||||
stopListening();
|
||||
if (newAddr != null)
|
||||
newAddr.setOptions(newProps);
|
||||
// Wait for NTCP Pumper to stop so we don't end up with two...
|
||||
while (isAlive()) {
|
||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
restartListening(newAddr);
|
||||
_log.warn("Changed NTCP Address and started up, address is now " + newAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If we didn't used to be forwarded, and we have an address,
|
||||
* and we are configured to use UPnP, update our RouterAddress
|
||||
@ -698,7 +893,7 @@ public class NTCPTransport extends TransportImpl {
|
||||
// from here, so we do it in TransportManager.
|
||||
// if (Boolean.valueOf(_context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)).booleanValue())
|
||||
// return foo;
|
||||
return _context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_PORT, -1);
|
||||
return _context.getProperty(PROP_I2NP_NTCP_PORT, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +155,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
public static final String PROP_SOURCES = "i2np.udp.addressSources";
|
||||
public static final String DEFAULT_SOURCES = SOURCE_INTERFACE.toConfigString() + ',' +
|
||||
SOURCE_UPNP.toConfigString() + ',' +
|
||||
SOURCE_SSU_PEER.toConfigString();
|
||||
SOURCE_SSU.toConfigString();
|
||||
/** remember IP changes */
|
||||
public static final String PROP_IP= "i2np.lastIP";
|
||||
public static final String PROP_IP_CHANGE = "i2np.lastIPChange";
|
||||
@ -563,13 +563,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
* Not for info received from peers - see externalAddressReceived(Hash, ip, port)
|
||||
*
|
||||
* @param source as defined in Transport.SOURCE_xxx
|
||||
* @param ip publicly routable IPv4 or IPv6
|
||||
* @param ip publicly routable IPv4 or IPv6, null ok
|
||||
* @param port 0 if unknown
|
||||
*/
|
||||
@Override
|
||||
public void externalAddressReceived(Transport.AddressSource source, byte[] ip, int port) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Received address: " + Addresses.toString(ip, port) + " from: " + source);
|
||||
if (ip == null)
|
||||
return;
|
||||
if (source == SOURCE_INTERFACE && ip.length == 16) {
|
||||
// must be set before isValid() call
|
||||
_haveIPv6Address = true;
|
||||
|
Reference in New Issue
Block a user