- UPnP defaults to on - I didn't do all this for nothing

- Set Status to OK for local public addresses or UPnP port open
- Allow UDP address changes after we transition to firewalled
- Have NTCP start reporting reachability status, this will
  get OK on the console more often and mask UDP problems,
  which might be good or bad...
- Fix UDP port configuration
- Reword and rearrange configuration options again
- Rearrange configuration help
- More right-alignment on config
- Prevent Concurrent modification exception in UPnP
- UPnP HTML output tweaks - remove "plugin" references
- Move UDP message failed log from WARN to INFO
- Short-circuit message history call in UDP
This commit is contained in:
zzz
2009-05-02 18:23:41 +00:00
parent 0e4c846942
commit d41afc0c43
7 changed files with 103 additions and 48 deletions

View File

@@ -61,7 +61,7 @@ public class MessageHistory {
}
void setDoLog(boolean log) { _doLog = log; }
boolean getDoLog() { return _doLog; }
public boolean getDoLog() { return _doLog; }
void setPauseFlushes(boolean doPause) { _doPause = doPause; }
String getFilename() { return _historyFile; }

View File

@@ -44,6 +44,7 @@ public class TransportManager implements TransportEventListener {
private final static String PROP_ENABLE_NTCP = "i2np.ntcp.enable";
private final static String DEFAULT_ENABLE_NTCP = "true";
private final static String DEFAULT_ENABLE_UDP = "true";
/** default true */
public final static String PROP_ENABLE_UPNP = "i2np.upnp.enable";
public TransportManager(RouterContext context) {
@@ -56,7 +57,7 @@ public class TransportManager implements TransportEventListener {
_context.statManager().createRateStat("transport.bidFailNoTransports", "Could not attempt to bid on message, as none of the transports could attempt it", "Transport", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("transport.bidFailAllTransports", "Could not attempt to bid on message, as all of the transports had failed", "Transport", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_transports = new ArrayList();
if (Boolean.valueOf(_context.getProperty(PROP_ENABLE_UPNP)).booleanValue())
if (Boolean.valueOf(_context.getProperty(PROP_ENABLE_UPNP, "true")).booleanValue())
_upnpManager = new UPnPManager(context, this);
}
@@ -227,15 +228,15 @@ public class TransportManager implements TransportEventListener {
return skews;
}
/** @return the best status of any transport */
public short getReachabilityStatus() {
if (_transports.size() <= 0) return CommSystemFacade.STATUS_UNKNOWN;
short status[] = new short[_transports.size()];
for (int i = 0; i < _transports.size(); i++) {
status[i] = ((Transport)_transports.get(i)).getReachabilityStatus();
short rv = CommSystemFacade.STATUS_UNKNOWN;
for (Transport t : _transports) {
short s = t.getReachabilityStatus();
if (s < rv)
rv = s;
}
// the values for the statuses are increasing for their 'badness'
Arrays.sort(status);
return status[0];
return rv;
}
public void recheckReachability() {

View File

@@ -232,7 +232,7 @@ public class UPnP extends ControlPoint implements DeviceChangeListener {
public void unregisterPortMappings() {
Set ports;
synchronized(lock) {
ports = portsForwarded;
ports = new HashSet(portsForwarded);
}
this.unregisterPorts(ports);
}
@@ -406,10 +406,10 @@ public class UPnP extends ControlPoint implements DeviceChangeListener {
sb.append("<a name=\"upnp\"><b>UPnP Status:</b><br />");
if(isDisabled) {
sb.append("The plugin has been disabled; Do you have more than one UPnP Internet Gateway Device on your LAN ?");
sb.append("UPnP has been disabled; Do you have more than one UPnP Internet Gateway Device on your LAN ?");
return sb.toString();
} else if(!isNATPresent()) {
sb.append("The plugin hasn't found any UPnP aware, compatible device on your LAN.");
sb.append("UPnP has not found any UPnP-aware, compatible device on your LAN.");
return sb.toString();
}

View File

@@ -20,6 +20,7 @@ import net.i2p.data.Hash;
import net.i2p.data.RouterAddress;
import net.i2p.data.RouterIdentity;
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.CommSystemFacadeImpl;
@@ -37,7 +38,7 @@ public class NTCPTransport extends TransportImpl {
private SharedBid _slowBid;
private SharedBid _transientFail;
private final Object _conLock;
private Map _conByIdent;
private Map<Hash, NTCPConnection> _conByIdent;
private NTCPAddress _myAddress;
private EventPumper _pumper;
private Reader _reader;
@@ -566,6 +567,27 @@ public class NTCPTransport extends TransportImpl {
return _context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_PORT, -1);
}
/**
* Maybe we should trust UPnP here and report OK if it opened the port, but
* for now we don't. Just go through and if we have one inbound connection,
* we must be good. As we drop idle connections pretty quickly, this will
* be fairly accurate.
*
* We have to be careful here because much of the router console code assumes
* that the reachability status is really just the UDP status.
*/
public short getReachabilityStatus() {
if (isAlive() && _myAddress != null) {
synchronized (_conLock) {
for (NTCPConnection con : _conByIdent.values()) {
if (con.isInbound())
return CommSystemFacade.STATUS_OK;
}
}
}
return CommSystemFacade.STATUS_UNKNOWN;
}
/**
* This doesn't (completely) block, caller should check isAlive()
* before calling startListening() or restartListening()

View File

@@ -346,7 +346,28 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
String sources = _context.getProperty(PROP_SOURCES, DEFAULT_SOURCES);
if (!sources.contains(source))
return;
changeAddress(ip, port);
boolean changed = changeAddress(ip, port);
// Assume if we have an interface with a public IP that we aren't firewalled.
// If this is wrong, the peer test will figure it out and change the status.
if (changed && source.equals(Transport.SOURCE_INTERFACE))
setReachabilityStatus(CommSystemFacade.STATUS_OK);
}
/**
* Callback from UPnP.
* If we we have an IP address and UPnP claims success, believe it.
* If this is wrong, the peer test will figure it out and change the status.
* Don't do anything if UPnP claims failure.
*/
public void forwardPortStatus(int port, boolean success, String reason) {
if (_log.shouldLog(Log.WARN)) {
if (success)
_log.warn("UPnP has opened the SSU port: " + port);
else
_log.warn("UPnP has failed to open the SSU port: " + port + " reason: " + reason);
}
if (success && _externalListenHost != null)
setReachabilityStatus(CommSystemFacade.STATUS_OK);
}
/**
@@ -397,7 +418,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/**
* @param ourPort >= 1024 or 0 for no change
*/
private void changeAddress(byte ourIP[], int ourPort) {
private boolean changeAddress(byte ourIP[], int ourPort) {
boolean fixedPort = getIsPortFixed();
boolean updated = false;
boolean fireTest = false;
@@ -405,7 +426,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
synchronized (this) {
if ( (_externalListenHost == null) ||
(!eq(_externalListenHost.getAddress(), _externalListenPort, ourIP, ourPort)) ) {
if ( (_reachabilityStatus == CommSystemFacade.STATUS_UNKNOWN) ||
if ( (_reachabilityStatus != CommSystemFacade.STATUS_OK) ||
(_externalListenHost == null) || (_externalListenPort <= 0) ||
(_context.clock().now() - _reachabilityStatusLastUpdated > 2*TEST_FREQUENCY) ) {
// they told us something different and our tests are either old or failing
@@ -452,6 +473,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_testEvent.forceRun();
SimpleTimer.getInstance().addEvent(_testEvent, 5*1000);
}
return updated;
}
private static final boolean eq(byte laddr[], int lport, byte raddr[], int rport) {
@@ -1199,8 +1221,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
// + " lastSentFully: " + sendDelay
// + " expired? " + msg.isExpired());
consecutive = msg.getPeer().incrementConsecutiveFailedSends();
if (_log.shouldLog(Log.WARN))
_log.warn("Consecutive failure #" + consecutive
if (_log.shouldLog(Log.INFO))
_log.info("Consecutive failure #" + consecutive
+ " on " + msg.toString()
+ " to " + msg.getPeer());
if ( (_context.clock().now() - msg.getPeer().getLastSendFullyTime() <= 60*1000) || (consecutive < MAX_CONSECUTIVE_FAILED) ) {
@@ -1220,6 +1242,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
private void noteSend(OutboundMessageState msg, boolean successful) {
// bail before we do all the work
if (!_context.messageHistory().getDoLog())
return;
int pushCount = msg.getPushCount();
int sends = msg.getMaxSends();
boolean expired = msg.isExpired();
@@ -1256,10 +1281,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public void failed(OutNetMessage msg, String reason) {
if (msg == null) return;
if (_log.shouldLog(Log.WARN))
_log.warn("Sending message failed: " + msg, new Exception("failed from"));
if (_log.shouldLog(Log.INFO))
_log.info("Sending message failed: " + msg, new Exception("failed from"));
_context.messageHistory().sendMessage(msg.getMessageType(), msg.getMessageId(), msg.getExpiration(),
if (!_context.messageHistory().getDoLog())
_context.messageHistory().sendMessage(msg.getMessageType(), msg.getMessageId(), msg.getExpiration(),
msg.getTarget().getIdentity().calculateHash(), false, reason);
super.afterSend(msg, false);
}