merge of '0d58ec9e2b160029e92a584b0c707ffdf4f25c7e'

and 'd4e270a4df0c8134d7bac1585e30ef8ddef37f85'
This commit is contained in:
zzz
2009-11-04 16:06:46 +00:00
25 changed files with 320 additions and 171 deletions

View File

@ -33,7 +33,8 @@ public class ConfigRestartBean {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD));
//ctx.router().shutdown(Router.EXIT_HARD); // never returns
ctx.router().shutdownGracefully(Router.EXIT_HARD); // give the UI time to respond
} else if ("cancelShutdown".equals(action) || _("Cancel shutdown", ctx).equals(action)) {
} else if ("cancelShutdown".equals(action) || _("Cancel shutdown", ctx).equals(action) ||
_("Cancel restart", ctx).equals(action)) {
ctx.router().cancelGracefulShutdown();
} else if ("restartImmediate".equals(action) || _("Restart immediately", ctx).equals(action)) {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART));

View File

@ -37,6 +37,7 @@ public class ConfigUIHelper extends HelperBase {
}
private static final String langs[] = {"de", "en", "fr", "nl", "se", "zh"};
private static final String flags[] = {"de", "us", "fr", "nl", "se", "cn"};
private static final String xlangs[] = {_x("German"), _x("English"), _x("French"),
_x("Dutch"), _x("Swedish"), _x("Chinese")};
@ -49,7 +50,9 @@ public class ConfigUIHelper extends HelperBase {
buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
if (langs[i].equals(current))
buf.append("checked=\"true\" ");
buf.append("value=\"").append(langs[i]).append("\">").append(_(xlangs[i])).append("<br>\n");
buf.append("value=\"").append(langs[i]).append("\">")
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(flags[i]).append("\"> ")
.append(_(xlangs[i])).append("<br>\n");
}
return buf.toString();
}

View File

@ -84,8 +84,8 @@ public class NetDbRenderer {
public void renderLeaseSetHTML(Writer out) throws IOException {
StringBuilder buf = new StringBuilder(4*1024);
buf.append("<h2>" + _("Network Database Contents") + "</h2>\n");
buf.append("<a href=\"netdb.jsp\">" + _("View") + " RouterInfo</a>");
buf.append("<h3>LeaseSets</h3>\n");
buf.append("<a href=\"netdb.jsp\">" + _("View RouterInfo") + "</a>");
buf.append("<h3>").append(_("LeaseSets")).append("</h3>\n");
Set leases = new TreeSet(new LeaseSetComparator());
leases.addAll(_context.netDb().getLeases());
long now = _context.clock().now();
@ -132,7 +132,7 @@ public class NetDbRenderer {
}
public void renderStatusHTML(Writer out, boolean full) throws IOException {
out.write("<h2>" + _("Network Database Contents") + " (<a href=\"netdb.jsp?l=1\">" + _("View") + " LeaseSets</a>)</h2>\n");
out.write("<h2>" + _("Network Database Contents") + " (<a href=\"netdb.jsp?l=1\">" + _("View LeaseSets") + "</a>)</h2>\n");
if (!_context.netDb().isInitialized()) {
out.write(_("Not initialized"));
out.flush();
@ -244,7 +244,7 @@ public class NetDbRenderer {
}
for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) {
RouterAddress addr = (RouterAddress)iter.next();
buf.append(DataHelper.stripHTML(addr.getTransportStyle())).append(": ");
buf.append("<b>").append(DataHelper.stripHTML(addr.getTransportStyle())).append("</b>: ");
for (Iterator optIter = addr.getOptions().keySet().iterator(); optIter.hasNext(); ) {
String name = (String)optIter.next();
String val = addr.getOptions().getProperty(name);

View File

@ -105,6 +105,9 @@ class ProfileOrganizerRenderer {
buf.append("<tr><td align=\"center\" nowrap>");
buf.append(_context.commSystem().renderPeerHTML(peer));
// debug
//if(prof.getIsExpandedDB())
// buf.append(" ** ");
buf.append("</td><td align=\"center\">");
switch (tier) {
@ -145,18 +148,19 @@ class ProfileOrganizerRenderer {
buf.append("</td><td align=\"right\">").append(num(prof.getIntegrationValue()));
buf.append("</td><td align=\"center\">");
if (_context.shitlist().isShitlisted(peer)) buf.append(_("Banned"));
if (prof.getIsFailing()) buf.append(" ").append(_("Failing"));
if (_context.commSystem().wasUnreachable(peer)) buf.append(" ").append(_("Unreachable"));
if (prof.getIsFailing()) buf.append(' ').append(_("Failing"));
if (_context.commSystem().wasUnreachable(peer)) buf.append(' ').append(_("Unreachable"));
Rate failed = prof.getTunnelHistory().getFailedRate().getRate(30*60*1000);
long fails = failed.getCurrentEventCount() + failed.getLastEventCount();
if (fails > 0) {
Rate accepted = prof.getTunnelCreateResponseTime().getRate(30*60*1000);
long total = fails + accepted.getCurrentEventCount() + accepted.getLastEventCount();
if (total / fails <= 10) // hide if < 10%
buf.append(' ').append(fails).append('/').append(total).append(" ").append(_("Test Fails"));
buf.append(' ').append(fails).append('/').append(total).append(' ').append(_("Test Fails"));
}
buf.append("&nbsp;</td>");
buf.append("<td nowrap align=\"center\"><a target=\"_blank\" href=\"dumpprofile.jsp?peer=").append(peer.toBase64().substring(0,6)).append("\">profile</a>");
buf.append("<td nowrap align=\"center\"><a target=\"_blank\" href=\"dumpprofile.jsp?peer=")
.append(peer.toBase64().substring(0,6)).append("\">").append(_("profile")).append("</a>");
buf.append("&nbsp;<a href=\"configpeer.jsp?peer=").append(peer.toBase64()).append("\">+-</a></td>\n");
buf.append("</tr>");
// let's not build the whole page in memory (~500 bytes per peer)
@ -223,14 +227,20 @@ class ProfileOrganizerRenderer {
buf.append("<td align=\"right\">").append(dbh.getUnpromptedDbStoreOld()).append("</td>");
buf.append("<td align=\"right\">").append(davg(dbh, 60*60*1000l)).append("</td>");
buf.append("<td align=\"right\">").append(davg(dbh, 24*60*60*1000l)).append("</td>");
} else {
for (int i = 0; i < 6; i++)
buf.append("<td align=\"right\">").append(_(NA));
}
}
buf.append("</table>");
buf.append("<h3>").append(_("Thresholds:")).append("</h3>");
buf.append("<p><b>").append(_("Speed")).append(":</b> ").append(num(_organizer.getSpeedThreshold())).append(" (").append(fast).append(" fast peers)<br>");
buf.append("<b>").append(_("Capacity")).append(":</b> ").append(num(_organizer.getCapacityThreshold())).append(" (").append(reliable).append(" high capacity peers)<br>");
buf.append("<b>").append(_("Integration")).append(":</b> ").append(num(_organizer.getIntegrationThreshold())).append(" (").append(integrated).append(" well integrated peers)</p>");
buf.append("<p><b>").append(_("Speed")).append(":</b> ").append(num(_organizer.getSpeedThreshold()))
.append(" (").append(fast).append(' ').append(_("fast peers")).append(")<br>");
buf.append("<b>").append(_("Capacity")).append(":</b> ").append(num(_organizer.getCapacityThreshold()))
.append(" (").append(reliable).append(' ').append(_("high capacity peers")).append(")<br>");
buf.append("<b>").append(_("Integration")).append(":</b> ").append(num(_organizer.getIntegrationThreshold()))
.append(" (").append(integrated).append(' ').append(_(" well integrated peers")).append(")</p>");
buf.append("<h3>").append(_("Definitions")).append(":</h3><ul>");
buf.append("<li><b>").append(_("groups")).append("</b>: ").append(_("as determined by the profile organizer")).append("</li>");
buf.append("<li><b>").append(_("caps")).append("</b>: ").append(_("capabilities in the netDb, not used to determine profiles")).append("</li>");
@ -295,29 +305,29 @@ class ProfileOrganizerRenderer {
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");
private final static String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final static String na = "n/a";
private final static String NA = HelperBase._x("n/a");
private static String avg (PeerProfile prof, long rate) {
private String avg (PeerProfile prof, long rate) {
RateStat rs = prof.getDbResponseTime();
if (rs == null)
return na;
return _(NA);
Rate r = rs.getRate(rate);
if (r == null)
return na;
return _(NA);
long c = r.getCurrentEventCount() + r.getLastEventCount();
if (c == 0)
return na;
return _(NA);
double d = r.getCurrentTotalValue() + r.getLastTotalValue();
return Math.round(d/c) + "ms";
}
private static String davg (DBHistory dbh, long rate) {
private String davg (DBHistory dbh, long rate) {
RateStat rs = dbh.getFailedLookupRate();
if (rs == null)
return na;
return _(NA);
Rate r = rs.getRate(rate);
if (r == null)
return na;
return _(NA);
long c = r.getCurrentEventCount() + r.getLastEventCount();
return "" + c;
}

View File

@ -104,7 +104,7 @@
<input name ="udpHost1" type="text" size="16" value="<jsp:getProperty name="nethelper" property="udphostname" />" />
<% String[] ips = nethelper.getAddresses();
if (ips.length > 0) {
out.print(" " + intl._("or") + " <select name=\"udpHost2\"><option value=\"\" selected=\"true\">"+intl._("Select Interface")+"</option>\n");
out.print(intl._("or") + " <select name=\"udpHost2\"><option value=\"\" selected=\"true\">"+intl._("Select Interface")+"</option>\n");
for (int i = 0; i < ips.length; i++) {
out.print("<option value=\"");
out.print(ips[i]);
@ -156,7 +156,7 @@
<hr><div class="formaction">
<input type="submit" name="save" value="<%=intl._("Save changes")%>" /> <input type="reset" value="<%=intl._("Cancel")%>" />
</div><h3><a name="chelp"><%=intl._("Configuration Help")%>:</a></h3><div align="justify"><p>
<%=intl._("While I2P will work fine behind most firewalls, your speeds and network integration will generally improve if the I2P port (generally 8887) is forwarded for both UDP and TCP.")%>
<%=intl._("While I2P will work fine behind most firewalls, your speeds and network integration will generally improve if the I2P port is forwarded for both UDP and TCP.")%>
</p><p>
<%=intl._("If you can, please poke a hole in your firewall to allow unsolicited UDP and TCP packets to reach you.")%>
<%=intl._("If you can't, I2P supports UPnP (Universal Plug and Play) and UDP hole punching with \"SSU introductions\" to relay traffic.")%>
@ -187,7 +187,7 @@
<%=intl._("When in doubt, leave the settings at the defaults.")%>
</p>
<h3><a name="help"><%=intl._("Reachability Help")%>:</a></h3><p>
<%=intl._("While I2P will work fine behind most firewalls, your speeds and network integration will generally improve if the I2P port (generally 8887) is forwarded for both UDP and TCP.")%>
<%=intl._("While I2P will work fine behind most firewalls, your speeds and network integration will generally improve if the I2P port is forwarded for both UDP and TCP.")%>
<%=intl._("If you think you have opened up your firewall and I2P still thinks you are firewalled, remember that you may have multiple firewalls, for example both software packages and external hardware routers.")%>
<%=intl._("If there is an error, the <a href=\"logs.jsp\">logs</a> may also help diagnose the problem.")%>
<ul>
@ -196,7 +196,7 @@
<li class="tidylist"><b><%=intl._("Firewalled")%></b> -
<%=intl._("Your UDP port appears to be firewalled.")%>
<%=intl._("As the firewall detection methods are not 100% reliable, this may occasionally be displayed in error.")%>
<%=intl._("However, if it appears consistently, you should check whether both your external and internal firewalls are open on port 8887.")%>
<%=intl._("However, if it appears consistently, you should check whether both your external and internal firewalls are open for your port.")%>
<%=intl._("I2P will work fine when firewalled, there is no reason for concern. When firewalled, the router uses \"introducers\" to relay inbound connections.")%>
<%=intl._("However, you will get more participating traffic and help the network more if you can open your firewall(s).")%>
<%=intl._("If you think you have already done so, remember that you may have both a hardware and a software firewall, or be behind an additional, institutional firewall you cannot control.")%>
@ -230,7 +230,7 @@
<%=intl._("I2P does not work well behind this type of firewall. You will probably not be able to accept inbound connections, which will limit your participation in the network.")%>
<li class="tidylist"><b><%=intl._("ERR - UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart")%></b> -
<%=intl._("I2P was unable to bind to port 8887 or other configured port.")%>
<%=intl._("Check to see if another program is using port 8887. If so, stop that program or configure I2P to use a different port.")%>
<%=intl._("Check to see if another program is using the configured port. If so, stop that program or configure I2P to use a different port.")%>
<%=intl._("This may be a transient error, if the other program is no longer using the port.")%>
<%=intl._("However, a restart is always required after this error.")%>
<li class="tidylist"><b><%=intl._("ERR - UDP Disabled and Inbound TCP host/port not set")%></b> -

View File

@ -291,7 +291,8 @@
<!-- polecat: please put your modified toolbar.html in installer/resources/toolbar.html
and uncomment the following -->
<!-- <copy file="installer/resources/toolbar.html" todir="pkg-temp/docs/" /> -->
<copy file="initialNews.xml" tofile="pkg-temp/docs/news.xml" />
<!-- overwrite the news put in by the updater -->
<copy file="installer/resources/initialNews.xml" tofile="pkg-temp/docs/news.xml" overwrite="true" />
<copy file="installer/resources/startconsole.html" todir="pkg-temp/docs/" />
<copy file="installer/resources/start.ico" todir="pkg-temp/docs/" />
<copy file="installer/resources/console.ico" todir="pkg-temp/docs/" />
@ -351,7 +352,7 @@
<fileset dir="installer/resources/themes/console/images/" />
</copy>
<copy todir="pkg-temp/docs/" >
<fileset dir="." includes="readme*.html" />
<fileset dir="installer/resources/readme/" includes="readme*.html" />
</copy>
</target>
@ -398,7 +399,8 @@
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
<copy file="build/i2psnark.war" todir="pkg-temp/webapps/" />
<copy file="history.txt" todir="pkg-temp/" />
<copy file="news.xml" todir="pkg-temp/docs/" />
<!-- may be pointless now, people with split directories will never see this -->
<copy file="installer/resources/news.xml" todir="pkg-temp/docs/" />
</target>
<target name="prepupdateSmall" depends="buildSmall, prepupdateRouter, prepthemeupdates">
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
@ -574,9 +576,9 @@
<exec executable="ls">
<arg value="-l" />
<arg value="history.txt" />
<arg value="initialNews.xml" />
<arg value="installer/resources/initialNews.xml" />
<arg value="installer/install.xml" />
<arg value="news.xml" />
<arg value="installer/resources/news.xml" />
<arg value="core/java/src/net/i2p/CoreVersion.java" />
<arg value="router/java/src/net/i2p/router/RouterVersion.java" />
</exec>

View File

@ -11,10 +11,6 @@ While you are waiting, please <b>adjust your bandwidth settings</b> on the
<a href="config.jsp">configuration page</a>.
</li>
<li>
If you can, open up <b>port 8887</b> on your firewall, then <b>enable inbound TCP</b> on the
<a href="config.jsp">configuration page</a>.
</li>
<li>
Once you have a "shared clients" destination listed on the left,
please <b>check out</b> our
<a href="http://www.i2p2.i2p/faq.html">FAQ</a>.
@ -35,9 +31,6 @@ Passe bitte In der Wartezeit <b>deine Einstellungen zur Bandbreite</b> auf der
<a href="config.jsp">Einstellungsseite</a> an.
</li>
<li>
Bitte &ouml;ffne sobald m&ouml;glich den <b>Port 8887</b> in deiner Firewall, aktiviere danach den <b>eingehenden TCP Verkehr</b> auf der <a href="config.jsp">Einstellungsseite</a>.
</li>
<li>
Sobald auf der linken Seite eine "shared clients" Verbindung aufgelistet ist <b>besuche bitte</b> unsere <a href="http://www.i2p2.i2p/faq_de.html">FAQ</a>.
</li>
<li>

View File

@ -34,7 +34,7 @@ class RouterThrottleImpl implements RouterThrottle {
private static final int DEFAULT_MAX_TUNNELS = 2500;
private static final String PROP_DEFAULT_KBPS_THROTTLE = "router.defaultKBpsThrottle";
private static final String PROP_MAX_PROCESSINGTIME = "router.defaultProcessingTimeThrottle";
private static final int DEFAULT_MAX_PROCESSINGTIME = 1500;
private static final int DEFAULT_MAX_PROCESSINGTIME = 1250;
/** tunnel acceptance */
public static final int TUNNEL_ACCEPT = 0;
@ -137,7 +137,7 @@ class RouterThrottleImpl implements RouterThrottle {
_log.warn("Refusing tunnel request due to sendProcessingTime of " + avgSendProcessingTime
+ " ms over the last two minutes, which is too much.");
}
setTunnelStatus("Rejecting tunnels: congestion");
setTunnelStatus("Rejecting tunnels: High message delay");
return TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
}
}

View File

@ -659,7 +659,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException {
long now = _context.clock().now();
boolean upLongEnough = _context.router().getUptime() > 60*60*1000;
// Once we're over 150 routers, reduce the expiration time down from the default,
// Once we're over 120 routers, reduce the expiration time down from the default,
// as a crude way of limiting memory usage.
// i.e. at 300 routers the expiration time will be about half the default, etc.
// And if we're floodfill, we can keep the expiration really short, since
@ -673,7 +673,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
// _kb.size() includes leasesets but that's ok
adjustedExpiration = Math.min(ROUTER_INFO_EXPIRATION,
ROUTER_INFO_EXPIRATION_MIN +
((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * 150 / (_kb.size() + 1)));
((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * 120 / (_kb.size() + 1)));
if (!key.equals(routerInfo.getIdentity().getHash())) {
if (_log.shouldLog(Log.WARN))
@ -891,12 +891,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
public int getPeerTimeout(Hash peer) {
PeerProfile prof = _context.profileOrganizer().getProfile(peer);
double responseTime = MAX_PER_PEER_TIMEOUT;
if (prof != null)
if (prof != null && prof.getIsExpandedDB()) {
responseTime = prof.getDbResponseTime().getLifetimeAverageValue();
if (responseTime < MIN_PER_PEER_TIMEOUT)
responseTime = MIN_PER_PEER_TIMEOUT;
else if (responseTime > MAX_PER_PEER_TIMEOUT)
responseTime = MAX_PER_PEER_TIMEOUT;
if (responseTime < MIN_PER_PEER_TIMEOUT)
responseTime = MIN_PER_PEER_TIMEOUT;
else if (responseTime > MAX_PER_PEER_TIMEOUT)
responseTime = MAX_PER_PEER_TIMEOUT;
}
return 4 * (int)responseTime; // give it up to 4x the average response time
}

View File

@ -174,11 +174,13 @@ class StoreJob extends JobImpl {
_state.addSkipped(peer);
} else {
int peerTimeout = _facade.getPeerTimeout(peer);
PeerProfile prof = getContext().profileOrganizer().getProfile(peer);
if (prof != null) {
RateStat failing = prof.getDBHistory().getFailedLookupRate();
Rate failed = failing.getRate(60*60*1000);
}
//PeerProfile prof = getContext().profileOrganizer().getProfile(peer);
//if (prof != null && prof.getIsExpandedDB()) {
// RateStat failing = prof.getDBHistory().getFailedLookupRate();
// Rate failed = failing.getRate(60*60*1000);
//}
//long failedCount = failed.getCurrentEventCount()+failed.getLastEventCount();
//if (failedCount > 10) {
// _state.addSkipped(peer);

View File

@ -19,12 +19,15 @@ public class IntegrationCalculator extends Calculator {
@Override
public double calc(PeerProfile profile) {
// give more weight to recent counts
long val = profile.getDbIntroduction().getRate(24*60*60*1000l).getCurrentEventCount();
val += 2 * 4 * profile.getDbIntroduction().getRate(6*60*60*1000l).getLastEventCount();
val += 3 * 4 * profile.getDbIntroduction().getRate(6*60*60*1000l).getCurrentEventCount();
val += 4 * 24 * profile.getDbIntroduction().getRate(60*60*1000l).getCurrentEventCount();
val /= 10;
long val = 0;
if (profile.getIsExpandedDB()) {
// give more weight to recent counts
val = profile.getDbIntroduction().getRate(24*60*60*1000l).getCurrentEventCount();
val += 2 * 4 * profile.getDbIntroduction().getRate(6*60*60*1000l).getLastEventCount();
val += 3 * 4 * profile.getDbIntroduction().getRate(6*60*60*1000l).getCurrentEventCount();
val += 4 * 24 * profile.getDbIntroduction().getRate(60*60*1000l).getCurrentEventCount();
val /= 10;
}
val += profile.getIntegrationBonus();
return val;
}

View File

@ -36,8 +36,8 @@ public class PeerProfile {
private long _lastHeardFrom;
private double _tunnelTestResponseTimeAvg;
// periodic rates
private RateStat _sendSuccessSize = null;
private RateStat _receiveSize = null;
//private RateStat _sendSuccessSize = null;
//private RateStat _receiveSize = null;
private RateStat _dbResponseTime = null;
private RateStat _tunnelCreateResponseTime = null;
private RateStat _tunnelTestResponseTime = null;
@ -56,6 +56,7 @@ public class PeerProfile {
private DBHistory _dbHistory;
// does this peer profile contain expanded data, or just the basics?
private boolean _expanded;
private boolean _expandedDB;
private int _consecutiveShitlists;
public PeerProfile(RouterContext context, Hash peer) {
@ -72,6 +73,8 @@ public class PeerProfile {
_consecutiveShitlists = 0;
_tunnelTestResponseTimeAvg = 0.0d;
_peer = peer;
// this is always true, and there are several places in the router that will NPE
// if it is false, so all need to be fixed before we can have non-expanded profiles
if (expand)
expandProfile();
}
@ -87,6 +90,7 @@ public class PeerProfile {
*
*/
public boolean getIsExpanded() { return _expanded; }
public boolean getIsExpandedDB() { return _expandedDB; }
public int incrementShitlists() { return _consecutiveShitlists++; }
public void unshitlist() { _consecutiveShitlists = 0; }
@ -107,18 +111,25 @@ public class PeerProfile {
*
* Note: this appears to be the only use for these two RateStats.
*
* Update: Rewritten so we can get rid of the two RateStats.
* This also helps by not having it depend on coalesce boundaries.
*
* @param period must be one of the periods in the RateStat constructors below
* (5*60*1000 or 60*60*1000)
*/
public boolean getIsActive(long period) {
if ( (getSendSuccessSize().getRate(period).getCurrentEventCount() > 0) ||
(getSendSuccessSize().getRate(period).getLastEventCount() > 0) ||
(getReceiveSize().getRate(period).getCurrentEventCount() > 0) ||
(getReceiveSize().getRate(period).getLastEventCount() > 0) ||
_context.commSystem().isEstablished(_peer) )
return true;
else
return false;
//if ( (getSendSuccessSize().getRate(period).getCurrentEventCount() > 0) ||
// (getSendSuccessSize().getRate(period).getLastEventCount() > 0) ||
// (getReceiveSize().getRate(period).getCurrentEventCount() > 0) ||
// (getReceiveSize().getRate(period).getLastEventCount() > 0) ||
// _context.commSystem().isEstablished(_peer) )
// return true;
//else
// return false;
long before = _context.clock().now() - period;
return getLastHeardFrom() < before ||
getLastSendSuccessful() < before ||
_context.commSystem().isEstablished(_peer);
}
@ -142,25 +153,31 @@ public class PeerProfile {
public long getLastHeardFrom() { return _lastHeardFrom; }
public void setLastHeardFrom(long when) { _lastHeardFrom = when; }
/** history of tunnel activity with the peer */
/** history of tunnel activity with the peer
Warning - may return null if !getIsExpanded() */
public TunnelHistory getTunnelHistory() { return _tunnelHistory; }
public void setTunnelHistory(TunnelHistory history) { _tunnelHistory = history; }
/** history of db activity with the peer */
/** history of db activity with the peer
Warning - may return null if !getIsExpandedDB() */
public DBHistory getDBHistory() { return _dbHistory; }
public void setDBHistory(DBHistory hist) { _dbHistory = hist; }
/** how large successfully sent messages are, calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getSendSuccessSize() { return _sendSuccessSize; }
//public RateStat getSendSuccessSize() { return _sendSuccessSize; }
/** how large received messages are, calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getReceiveSize() { return _receiveSize; }
/** how long it takes to get a db response from the peer (in milliseconds), calculated over a 1 minute, 1 hour, and 1 day period */
//public RateStat getReceiveSize() { return _receiveSize; }
/** how long it takes to get a db response from the peer (in milliseconds), calculated over a 1 minute, 1 hour, and 1 day period
Warning - may return null if !getIsExpandedDB() */
public RateStat getDbResponseTime() { return _dbResponseTime; }
/** how long it takes to get a tunnel create response from the peer (in milliseconds), calculated over a 1 minute, 1 hour, and 1 day period */
/** how long it takes to get a tunnel create response from the peer (in milliseconds), calculated over a 1 minute, 1 hour, and 1 day period
Warning - may return null if !getIsExpanded() */
public RateStat getTunnelCreateResponseTime() { return _tunnelCreateResponseTime; }
/** how long it takes to successfully test a tunnel this peer participates in (in milliseconds), calculated over a 10 minute, 1 hour, and 1 day period */
/** how long it takes to successfully test a tunnel this peer participates in (in milliseconds), calculated over a 10 minute, 1 hour, and 1 day period
Warning - may return null if !getIsExpanded() */
public RateStat getTunnelTestResponseTime() { return _tunnelTestResponseTime; }
/** how many new peers we get from dbSearchReplyMessages or dbStore messages, calculated over a 1 hour, 1 day, and 1 week period */
/** how many new peers we get from dbSearchReplyMessages or dbStore messages, calculated over a 1 hour, 1 day, and 1 week period
Warning - may return null if !getIsExpandedDB() */
public RateStat getDbIntroduction() { return _dbIntroduction; }
/**
@ -327,10 +344,12 @@ public class PeerProfile {
* extensive stats on them, call this to discard excess data points. Specifically,
* this drops the rates, the tunnelHistory, and the dbHistory.
*
* UNUSED for now, will cause NPEs elsewhere
*/
/*****
public void shrinkProfile() {
_sendSuccessSize = null;
_receiveSize = null;
//_sendSuccessSize = null;
//_receiveSize = null;
_dbResponseTime = null;
_tunnelCreateResponseTime = null;
_tunnelTestResponseTime = null;
@ -339,7 +358,9 @@ public class PeerProfile {
_dbHistory = null;
_expanded = false;
_expandedDB = false;
}
******/
/**
* When the given peer is performing well enough that we want to keep detailed
@ -350,32 +371,43 @@ public class PeerProfile {
*/
public void expandProfile() {
String group = (null == _peer ? "profileUnknown" : _peer.toBase64().substring(0,6));
if (_sendSuccessSize == null)
_sendSuccessSize = new RateStat("sendSuccessSize", "How large successfully sent messages are", group, new long[] { 5*60*1000l, 60*60*1000l });
if (_receiveSize == null)
_receiveSize = new RateStat("receiveSize", "How large received messages are", group, new long[] { 5*60*1000l, 60*60*1000l } );
if (_dbResponseTime == null)
_dbResponseTime = new RateStat("dbResponseTime", "how long it takes to get a db response from the peer (in milliseconds)", group, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000 } );
//if (_sendSuccessSize == null)
// _sendSuccessSize = new RateStat("sendSuccessSize", "How large successfully sent messages are", group, new long[] { 5*60*1000l, 60*60*1000l });
//if (_receiveSize == null)
// _receiveSize = new RateStat("receiveSize", "How large received messages are", group, new long[] { 5*60*1000l, 60*60*1000l } );
if (_tunnelCreateResponseTime == null)
_tunnelCreateResponseTime = new RateStat("tunnelCreateResponseTime", "how long it takes to get a tunnel create response from the peer (in milliseconds)", group, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000 } );
if (_tunnelTestResponseTime == null)
_tunnelTestResponseTime = new RateStat("tunnelTestResponseTime", "how long it takes to successfully test a tunnel this peer participates in (in milliseconds)", group, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000 } );
if (_dbIntroduction == null)
_dbIntroduction = new RateStat("dbIntroduction", "how many new peers we get from dbSearchReplyMessages or dbStore messages", group, new long[] { 60*60*1000l, 6*60*60*1000l, 24*60*60*1000l });
if (_tunnelHistory == null)
_tunnelHistory = new TunnelHistory(_context, group);
//_sendSuccessSize.setStatLog(_context.statManager().getStatLog());
//_receiveSize.setStatLog(_context.statManager().getStatLog());
_tunnelCreateResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelTestResponseTime.setStatLog(_context.statManager().getStatLog());
_expanded = true;
}
/**
* For floodfills
*/
public synchronized void expandDBProfile() {
String group = (null == _peer ? "profileUnknown" : _peer.toBase64().substring(0,6));
if (_dbResponseTime == null)
_dbResponseTime = new RateStat("dbResponseTime", "how long it takes to get a db response from the peer (in milliseconds)", group, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000 } );
if (_dbIntroduction == null)
_dbIntroduction = new RateStat("dbIntroduction", "how many new peers we get from dbSearchReplyMessages or dbStore messages", group, new long[] { 60*60*1000l, 6*60*60*1000l, 24*60*60*1000l });
if (_dbHistory == null)
_dbHistory = new DBHistory(_context, group);
_sendSuccessSize.setStatLog(_context.statManager().getStatLog());
_receiveSize.setStatLog(_context.statManager().getStatLog());
_dbResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelCreateResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelTestResponseTime.setStatLog(_context.statManager().getStatLog());
_dbIntroduction.setStatLog(_context.statManager().getStatLog());
_expanded = true;
_expandedDB = true;
}
/** once a day, on average, cut the measured throughtput values in half */
/** let's try once an hour times 3/4 */
private static final int DROP_PERIOD_MINUTES = 60;
@ -419,14 +451,16 @@ public class PeerProfile {
/** update the stats and rates (this should be called once a minute) */
public void coalesceStats() {
if (!_expanded) return;
_dbIntroduction.coalesceStats();
_dbResponseTime.coalesceStats();
_receiveSize.coalesceStats();
_sendSuccessSize.coalesceStats();
//_receiveSize.coalesceStats();
//_sendSuccessSize.coalesceStats();
_tunnelCreateResponseTime.coalesceStats();
_tunnelTestResponseTime.coalesceStats();
_dbHistory.coalesceStats();
_tunnelHistory.coalesceStats();
if (_expandedDB) {
_dbIntroduction.coalesceStats();
_dbResponseTime.coalesceStats();
_dbHistory.coalesceStats();
}
coalesceThroughput();

View File

@ -39,7 +39,7 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastSendSuccessful(_context.clock().now());
data.getSendSuccessSize().addData(bytesSent, msToSend);
//data.getSendSuccessSize().addData(bytesSent, msToSend);
}
/**
@ -169,11 +169,14 @@ public class ProfileManagerImpl implements ProfileManager {
/**
* Note that the peer was able to return the valid data for a db lookup
*
* This will force creation of DB stats
*/
public void dbLookupSuccessful(Hash peer, long responseTimeMs) {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
if (!data.getIsExpandedDB())
data.expandDBProfile();
data.getDbResponseTime().addData(responseTimeMs, responseTimeMs);
DBHistory hist = data.getDBHistory();
hist.lookupSuccessful();
@ -183,10 +186,13 @@ public class ProfileManagerImpl implements ProfileManager {
* Note that the peer was unable to reply to a db lookup - either with data or with
* a lookupReply redirecting the user elsewhere
*
* This will force creation of DB stats
*/
public void dbLookupFailed(Hash peer) {
PeerProfile data = getProfile(peer);
if (data == null) return;
if (!data.getIsExpandedDB())
data.expandDBProfile();
DBHistory hist = data.getDBHistory();
hist.lookupFailed();
}
@ -203,6 +209,8 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
if (!data.getIsExpandedDB())
return;
data.getDbResponseTime().addData(responseTimeMs, responseTimeMs);
data.getDbIntroduction().addData(newPeers, responseTimeMs);
DBHistory hist = data.getDBHistory();
@ -217,6 +225,8 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
if (!data.getIsExpandedDB())
return;
DBHistory hist = data.getDBHistory();
hist.lookupReceived();
}
@ -229,6 +239,8 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
if (!data.getIsExpandedDB())
return;
DBHistory hist = data.getDBHistory();
hist.unpromptedStoreReceived(wasNewKey);
}
@ -242,8 +254,10 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
long now = _context.clock().now();
data.setLastSendSuccessful(now);
data.setLastHeardFrom(now);
if (!data.getIsExpandedDB())
return;
data.setLastSendSuccessful(now);
// we could do things like update some sort of "how many successful stores we've sent them"...
// naah.. dont really care now
}
@ -279,7 +293,7 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
data.getReceiveSize().addData(bytesRead, msToReceive);
//data.getReceiveSize().addData(bytesRead, msToReceive);
}
private PeerProfile getProfile(Hash peer) {

View File

@ -241,7 +241,7 @@ public class ProfileOrganizer {
*/
public boolean peerSendsBadReplies(Hash peer) {
PeerProfile profile = getProfile(peer);
if (profile != null) {
if (profile != null && profile.getIsExpandedDB()) {
RateStat invalidReplyRateStat = profile.getDBHistory().getInvalidReplyRate();
Rate invalidReplyRate = invalidReplyRateStat.getRate(30*60*1000l);
if ( (invalidReplyRate.getCurrentTotalValue() > MAX_BAD_REPLIES_PER_HOUR) ||

View File

@ -128,18 +128,20 @@ class ProfilePersistenceHelper {
out.write(buf.toString().getBytes());
profile.getTunnelHistory().store(out);
profile.getDBHistory().store(out);
if (profile.getIsExpanded()) {
// only write out expanded data if, uh, we've got it
profile.getDbIntroduction().store(out, "dbIntroduction");
profile.getDbResponseTime().store(out, "dbResponseTime");
profile.getReceiveSize().store(out, "receiveSize");
profile.getSendSuccessSize().store(out, "sendSuccessSize");
profile.getTunnelHistory().store(out);
//profile.getReceiveSize().store(out, "receiveSize");
//profile.getSendSuccessSize().store(out, "sendSuccessSize");
profile.getTunnelCreateResponseTime().store(out, "tunnelCreateResponseTime");
profile.getTunnelTestResponseTime().store(out, "tunnelTestResponseTime");
}
if (profile.getIsExpandedDB()) {
profile.getDBHistory().store(out);
profile.getDbIntroduction().store(out, "dbIntroduction");
profile.getDbResponseTime().store(out, "dbResponseTime");
}
}
public Set readProfiles() {
@ -211,12 +213,22 @@ class ProfilePersistenceHelper {
profile.setPeakTunnel1mThroughputKBps(getDouble(props, "tunnelPeakTunnel1mThroughput"));
profile.getTunnelHistory().load(props);
profile.getDBHistory().load(props);
profile.getDbIntroduction().load(props, "dbIntroduction", true);
profile.getDbResponseTime().load(props, "dbResponseTime", true);
profile.getReceiveSize().load(props, "receiveSize", true);
profile.getSendSuccessSize().load(props, "sendSuccessSize", true);
// In the interest of keeping the in-memory profiles small,
// don't load the DB info at all unless there is something interesting there
// (i.e. floodfills)
// It seems like we do one or two lookups as a part of handshaking?
// Not sure, to be researched.
if (getLong(props, "dbHistory.successfulLookups") > 1 ||
getLong(props, "dbHistory.failedlLokups") > 1) {
profile.expandDBProfile();
profile.getDBHistory().load(props);
profile.getDbIntroduction().load(props, "dbIntroduction", true);
profile.getDbResponseTime().load(props, "dbResponseTime", true);
}
//profile.getReceiveSize().load(props, "receiveSize", true);
//profile.getSendSuccessSize().load(props, "sendSuccessSize", true);
profile.getTunnelCreateResponseTime().load(props, "tunnelCreateResponseTime", true);
profile.getTunnelTestResponseTime().load(props, "tunnelTestResponseTime", true);

View File

@ -636,25 +636,20 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis
}
public void run() {
HashMap<ForwardPort, ForwardPortStatus> map = new HashMap(1);
for(ForwardPort port : portsToForwardNow) {
String proto = protoToString(port.protocol);
map.clear();
ForwardPortStatus fps;
if (proto.length() <= 1) {
HashMap<ForwardPort, ForwardPortStatus> map = new HashMap<ForwardPort, ForwardPortStatus>();
map.put(port, new ForwardPortStatus(ForwardPortStatus.DEFINITE_FAILURE, "Protocol not supported", port.portNumber));
forwardCallback.portForwardStatus(map);
continue;
}
if(tryAddMapping(proto, port.portNumber, port.name, port)) {
HashMap<ForwardPort, ForwardPortStatus> map = new HashMap<ForwardPort, ForwardPortStatus>();
map.put(port, new ForwardPortStatus(ForwardPortStatus.MAYBE_SUCCESS, "Port apparently forwarded by UPnP", port.portNumber));
forwardCallback.portForwardStatus(map);
continue;
fps = new ForwardPortStatus(ForwardPortStatus.DEFINITE_FAILURE, "Protocol not supported", port.portNumber);
} else if(tryAddMapping(proto, port.portNumber, port.name, port)) {
fps = new ForwardPortStatus(ForwardPortStatus.MAYBE_SUCCESS, "Port apparently forwarded by UPnP", port.portNumber);
} else {
HashMap<ForwardPort, ForwardPortStatus> map = new HashMap<ForwardPort, ForwardPortStatus>();
map.put(port, new ForwardPortStatus(ForwardPortStatus.PROBABLE_FAILURE, "UPnP port forwarding apparently failed", port.portNumber));
forwardCallback.portForwardStatus(map);
continue;
fps = new ForwardPortStatus(ForwardPortStatus.PROBABLE_FAILURE, "UPnP port forwarding apparently failed", port.portNumber);
}
map.put(port, fps);
forwardCallback.portForwardStatus(map);
}
}
}

View File

@ -22,7 +22,11 @@ public class UDPEndpoint {
private DatagramSocket _socket;
private InetAddress _bindAddress;
public UDPEndpoint(RouterContext ctx, UDPTransport transport, int listenPort, InetAddress bindAddress) throws SocketException {
/**
* @param listenPort -1 or the requested port, may not be honored
* @param bindAddress null ok
*/
public UDPEndpoint(RouterContext ctx, UDPTransport transport, int listenPort, InetAddress bindAddress) {
_context = ctx;
_log = ctx.logManager().getLog(UDPEndpoint.class);
_transport = transport;
@ -30,23 +34,20 @@ public class UDPEndpoint {
_listenPort = listenPort;
}
/** caller should call getListenPort() after this to get the actual bound port and determine success */
public void startup() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Starting up the UDP endpoint");
shutdown();
try {
if (_bindAddress == null)
_socket = new DatagramSocket(_listenPort);
else
_socket = new DatagramSocket(_listenPort, _bindAddress);
_sender = new UDPSender(_context, _socket, "UDPSender");
_receiver = new UDPReceiver(_context, _transport, _socket, "UDPReceiver");
_sender.startup();
_receiver.startup();
} catch (SocketException se) {
_transport.setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
_log.log(Log.CRIT, "Unable to bind on port " + _listenPort, se);
_socket = getSocket();
if (_socket == null) {
_log.log(Log.CRIT, "UDP Unable to open a port");
return;
}
_sender = new UDPSender(_context, _socket, "UDPSender");
_receiver = new UDPReceiver(_context, _transport, _socket, "UDPReceiver");
_sender.startup();
_receiver.startup();
}
public void shutdown() {
@ -60,6 +61,8 @@ public class UDPEndpoint {
}
public void setListenPort(int newPort) { _listenPort = newPort; }
/*******
public void updateListenPort(int newPort) {
if (newPort == _listenPort) return;
try {
@ -76,7 +79,54 @@ public class UDPEndpoint {
_log.error("Unable to bind on " + _listenPort);
}
}
********/
/** 8998 is monotone, and 32000 is the wrapper, so let's stay between those */
private static final int MIN_RANDOM_PORT = 9111;
private static final int MAX_RANDOM_PORT = 31777;
private static final int MAX_PORT_RETRIES = 20;
/**
* Open socket using requested port in _listenPort and bind host in _bindAddress.
* If _listenPort <= 0, or requested port is busy, repeatedly try a new random port.
* @return null on failure
* Sets _listenPort to actual port or -1 on failure
*/
private DatagramSocket getSocket() {
DatagramSocket socket = null;
int port = _listenPort;
for (int i = 0; i < MAX_PORT_RETRIES; i++) {
if (port <= 0) {
// try random ports rather than just do new DatagramSocket()
// so we stay out of the way of other I2P stuff
port = MIN_RANDOM_PORT + _context.random().nextInt(MAX_RANDOM_PORT - MIN_RANDOM_PORT);
}
try {
if (_bindAddress == null)
socket = new DatagramSocket(port);
else
socket = new DatagramSocket(port, _bindAddress);
break;
} catch (SocketException se) {
if (_log.shouldLog(Log.WARN))
_log.warn("Binding to port " + port + " failed: " + se);
}
port = -1;
}
if (socket == null) {
_log.log(Log.CRIT, "SSU Unable to bind to a port on " + _bindAddress);
} else if (port != _listenPort) {
if (_listenPort > 0)
_log.error("SSU Unable to bind to requested port " + _listenPort + ", using random port " + port);
else
_log.error("SSU selected random port " + port);
}
_listenPort = port;
return socket;
}
/** call after startup() to get actual port or -1 on startup failure */
public int getListenPort() { return _listenPort; }
public UDPSender getSender() { return _sender; }

View File

@ -100,6 +100,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String STYLE = "SSU";
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
/** now unused, we pick a random port */
public static final int DEFAULT_INTERNAL_PORT = 8887;
/** since fixed port defaults to true, this doesnt do anything at the moment.
* We should have an exception if it matches the existing low port. */
@ -137,6 +138,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
/** do we allow direct SSU connections, sans introducers? */
public static final String PROP_ALLOW_DIRECT = "i2np.udp.allowDirect";
/** this is rarely if ever used, default is to bind to wildcard address */
public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface";
/** how many relays offered to us will we use at a time? */
@ -226,40 +228,41 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
System.arraycopy(_context.routerHash().getData(), 0, _introKey.getData(), 0, SessionKey.KEYSIZE_BYTES);
rebuildExternalAddress();
int port = -1;
if (_externalListenPort <= 0) {
// no explicit external port, so lets try an internal one
port = _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT);
// attempt to use it as our external port - this will be overridden by
// externalAddressReceived(...)
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, port+"");
_context.router().saveConfig();
} else {
port = _externalListenPort;
if (_log.shouldLog(Log.INFO))
_log.info("Binding to the explicitly specified external port: " + port);
}
if (_endpoint == null) {
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
InetAddress bindToAddr = null;
if (bindTo != null) {
try {
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Invalid SSU bind interface specified [" + bindTo + "]", uhe);
bindToAddr = null;
}
}
// bind host
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
InetAddress bindToAddr = null;
if (bindTo != null) {
try {
_endpoint = new UDPEndpoint(_context, this, port, bindToAddr);
} catch (SocketException se) {
if (_log.shouldLog(Log.CRIT))
_log.log(Log.CRIT, "Unable to listen on the UDP port (" + port + ")", se);
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
_log.log(Log.CRIT, "Invalid SSU bind interface specified [" + bindTo + "]", uhe);
setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
return;
}
}
// Requested bind port
// This may be -1 or may not be honored if busy,
// we will check below after starting up the endpoint.
int port;
int oldIPort = _context.getProperty(PROP_INTERNAL_PORT, -1);
int oldEPort = _context.getProperty(PROP_EXTERNAL_PORT, -1);
if (_externalListenPort <= 0) {
// no explicit external port, so lets try an internal one
if (oldIPort > 0)
port = oldIPort;
else
port = oldEPort;
} else {
port = _externalListenPort;
}
if (_log.shouldLog(Log.INFO))
_log.info("Binding to the port: " + port);
if (_endpoint == null) {
_endpoint = new UDPEndpoint(_context, this, port, bindToAddr);
} else {
// todo, set bind address too
_endpoint.setListenPort(port);
}
@ -278,7 +281,24 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (_flooder == null)
_flooder = new UDPFlooder(_context, this);
// Startup the endpoint with the requested port, check the actual port, and
// take action if it failed or was different than requested or it needs to be saved
_endpoint.startup();
int newPort = _endpoint.getListenPort();
_externalListenPort = newPort;
if (newPort <= 0) {
_log.log(Log.CRIT, "Unable to open UDP port");
setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
return;
}
if (newPort != port || newPort != oldIPort || newPort != oldEPort) {
// attempt to use it as our external port - this will be overridden by
// externalAddressReceived(...)
_context.router().setConfigSetting(PROP_INTERNAL_PORT, newPort+"");
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, newPort+"");
_context.router().saveConfig();
}
_establisher.startup();
_handler.startup();
_fragments.startup();
@ -321,11 +341,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public int getLocalPort() { return _externalListenPort; }
public InetAddress getLocalAddress() { return _externalListenHost; }
public int getExternalPort() { return _externalListenPort; }
/**
* _externalListenPort should always be set (by startup()) before this is called,
* so the returned value should be > 0
*/
@Override
public int getRequestedPort() {
if (_externalListenPort > 0)
return _externalListenPort;
return _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT);
return _context.getProperty(PROP_INTERNAL_PORT, -1);
}
/**
@ -2003,6 +2028,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(" <td align=\"center\"><b>").append(resentTotal);
buf.append("</b></td> <td align=\"center\"><b>").append(dupRecvTotal).append("</b></td>\n");
buf.append(" </tr></table></div>\n");
/*****
long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
// NPE here early
double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue();
@ -2012,6 +2039,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
double bwResent = (nondupSent <= 0 ? 0d : ((((double)resentTotal)*averagePacketSize) / nondupSent));
buf.append("<h3>Percentage of bytes retransmitted (lifetime): ").append(formatPct(bwResent));
buf.append("</h3><i>(Includes retransmission required by packet loss)</i>\n");
*****/
out.write(buf.toString());
buf.setLength(0);
out.write(KEY);