2005-09-12 jrandom

* More aggressively publish updated routerInfo.
    * Expose the flag to force SSU introductions on the router console
    * Don't give people the option to disable SNTP time sync, at least not
      through the router console, because there is no reason to disable it.
      No, not even if your OS is "ntp synced", because chances are, its not.
This commit is contained in:
jrandom
2005-09-13 00:11:56 +00:00
committed by zzz
parent 31bdb8909a
commit b5784d6025
12 changed files with 120 additions and 90 deletions

View File

@ -16,6 +16,7 @@ import java.util.Iterator;
import java.util.Set;
import net.i2p.time.Timestamper;
import net.i2p.router.transport.udp.UDPTransport;
/**
* Handler to deal with form submissions from the main config form and act
@ -29,6 +30,7 @@ public class ConfigNetHandler extends FormHandler {
private boolean _saveRequested;
private boolean _recheckReachabilityRequested;
private boolean _timeSyncEnabled;
private boolean _requireIntroductions;
private String _tcpPort;
private String _udpPort;
private String _inboundRate;
@ -57,6 +59,7 @@ public class ConfigNetHandler extends FormHandler {
public void setSave(String moo) { _saveRequested = true; }
public void setEnabletimesync(String moo) { _timeSyncEnabled = true; }
public void setRecheckReachability(String moo) { _recheckReachabilityRequested = true; }
public void setRequireIntroductions(String moo) { _requireIntroductions = true; }
public void setHostname(String hostname) {
_hostname = (hostname != null ? hostname.trim() : null);
@ -253,7 +256,14 @@ public class ConfigNetHandler extends FormHandler {
}
}
if (_timeSyncEnabled) {
if (_requireIntroductions) {
_context.router().setConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS, "true");
addFormNotice("Requiring SSU introduers");
} else {
_context.router().removeConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS);
}
if (true || _timeSyncEnabled) {
// Time sync enable, means NOT disabled
_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
} else {

View File

@ -2,6 +2,9 @@ package net.i2p.router.web;
import net.i2p.time.Timestamper;
import net.i2p.router.RouterContext;
import net.i2p.router.CommSystemFacade;
import net.i2p.data.RouterAddress;
import net.i2p.router.transport.udp.UDPAddress;
public class ConfigNetHelper {
private RouterContext _context;
@ -43,19 +46,12 @@ public class ConfigNetHelper {
return "" + port;
}
public String getUdpPort() {
int port = 8887;
String val = _context.getProperty(PROP_I2NP_UDP_PORT);
if (val == null)
val = _context.getProperty(PROP_I2NP_INTERNAL_UDP_PORT);
if (val != null) {
try {
port = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
// ignore, use default from above
}
}
return "" + port;
public String getUdpAddress() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
UDPAddress ua = new UDPAddress(addr);
return ua.toString();
}
public String getEnableTimeSyncChecked() {
@ -66,6 +62,21 @@ public class ConfigNetHelper {
return " checked ";
}
public String getRequireIntroductionsChecked() {
short status = _context.commSystem().getReachabilityStatus();
switch (status) {
case CommSystemFacade.STATUS_OK:
return "";
case CommSystemFacade.STATUS_DIFFERENT:
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
return "checked=\"true\"";
case CommSystemFacade.STATUS_UNKNOWN:
return "";
default:
return "checked=\"true\"";
}
}
public static final String PROP_INBOUND_KBPS = "i2np.bandwidth.inboundKBytesPerSecond";
public static final String PROP_OUTBOUND_KBPS = "i2np.bandwidth.outboundKBytesPerSecond";
public static final String PROP_INBOUND_BURST = "i2np.bandwidth.inboundBurstKBytes";

View File

@ -28,14 +28,12 @@
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigNetHandler.nonce")%>" />
<input type="hidden" name="action" value="blah" />
UDP port: <i><jsp:getProperty name="nethelper" property="udpPort" /></i><br />
<!-- <input name="udpPort" type="text" size="5" value="<jsp:getProperty name="nethelper" property="udpPort" />" /><br /> -->
<b>You must poke a hole in your firewall or NAT (if applicable) to receive new inbound UDP packets on
this port from arbitrary peers (this requirement will be removed in i2p 0.6.1, but is necessary now)</b><br />
TCP port: <input name="tcpPort" type="text" size="5" value="<jsp:getProperty name="nethelper" property="tcpPort" />" /> <br />
<b>You must poke a hole in your firewall or NAT (if applicable) so that you can receive inbound TCP
connections on it (this requirement will be removed in i2p 0.6.1, but is necessary now)</b>
<br />
<b>External UDP address:</b> <i><jsp:getProperty name="nethelper" property="udpAddress" /></i><br />
<b>Require SSU introductions through NAT hole punching? </b>
<input type="checkbox" name="requireIntroductions" value="true" <jsp:getProperty name="nethelper" property="requireIntroductionsChecked" /> /><br />
<p>If you can't poke a hole in your NAT or firewall to allow unsolicited UDP packets to reach the
router, as detected with the <i>Status: ERR-Reject</i>, then you will need SSU introductions.
Users behind symmetric NATs, such as OpenBSD's pf, are not currently supported.</p>
<input type="submit" name="recheckReachability" value="Check network reachability..." />
<hr />
@ -53,35 +51,8 @@ this port from arbitrary peers (this requirement will be removed in i2p 0.6.1, b
<jsp:getProperty name="nethelper" property="sharePercentageBox" /><br />
Sharing a higher percentage will improve your anonymity and help the network
<hr />
Enable internal time synchronization? <input type="checkbox" <jsp:getProperty name="nethelper" property="enableTimeSyncChecked" /> name="enabletimesync" /><br />
<i>If disabled, your machine <b>must</b> be NTP synchronized - your clock must always
be within a few seconds of "correct". You will need to be able to send outbound UDP
packets on port 123 to one of the pool.ntp.org machines (or some other SNTP server).</i>
<hr />
<input type="submit" name="save" value="Save changes" /> <input type="reset" value="Cancel" /><br />
<i>Changing the TCP or UDP port will force a 'soft restart' - dropping your connections and clients as
if the router was stopped and restarted. <b>Please be patient</b> - it may take
a few seconds to complete.</i>
</form>
<hr />
<b>Advanced network config:</b>
<p>
One advanced network option has to do with reseeding - you should never need to
reseed your router as long as you can find at least one other peer on the network. However,
when you do need to reseed, a link will show up on the left hand side which will
fetch all of the routerInfo-* files from http://dev.i2p.net/i2pdb/. That URL is just an
apache folder pointing at the netDb/ directory of a router - anyone can run one, and you can
configure your router to seed off an alternate URL by adding the java environmental property
"i2p.reseedURL=someURL" (e.g. java -Di2p.reseedURL=http://dev.i2p.net/i2pdb/ ...). You can
also do it manually by getting routerInfo-*.dat files from someone (a friend, someone on IRC,
whatever) and saving them to your netDb/ directory.</p>
<p>
With the SSU transport, the internal UDP port may be different from the external
UDP port (in case of a firewall/NAT) - the UDP port field above specifies the
external one and assumes they are the same, but if you want to set the internal
port to something else, you can add "i2np.udp.internalPort=1234" to the
<a href="configadvanced.jsp">advanced</a> config and restart the router.
</p>
</div>
</body>

View File

@ -1,4 +1,11 @@
$Id: history.txt,v 1.243 2005/09/09 23:30:37 jrandom Exp $
$Id: history.txt,v 1.244 2005/09/10 22:22:52 jrandom Exp $
2005-09-12 jrandom
* More aggressively publish updated routerInfo.
* Expose the flag to force SSU introductions on the router console
* Don't give people the option to disable SNTP time sync, at least not
through the router console, because there is no reason to disable it.
No, not even if your OS is "ntp synced", because chances are, its not.
2005-09-10 jrandom
* Test the router's reachability earlier and more aggressively

View File

@ -132,7 +132,9 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
curIndex += 4;
if (_replyToken > 0) {
_replyTunnel = new TunnelId(DataHelper.fromLong(data, curIndex, 4));
long tunnel = DataHelper.fromLong(data, curIndex, 4);
if (tunnel > 0)
_replyTunnel = new TunnelId(tunnel);
curIndex += 4;
byte gw[] = new byte[Hash.HASH_LENGTH];
@ -202,7 +204,10 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
curIndex += 4;
if (_replyToken > 0) {
byte id[] = DataHelper.toLong(4, _replyTunnel.getTunnelId());
long replyTunnel = 0;
if (_replyTunnel != null)
replyTunnel = _replyTunnel.getTunnelId();
byte id[] = DataHelper.toLong(4, replyTunnel);
System.arraycopy(id, 0, out, curIndex, 4);
curIndex += 4;
System.arraycopy(_replyGateway.getData(), 0, out, curIndex, Hash.HASH_LENGTH);

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.230 $ $Date: 2005/09/09 23:30:36 $";
public final static String ID = "$Revision: 1.231 $ $Date: 2005/09/10 22:22:52 $";
public final static String VERSION = "0.6.0.5";
public final static long BUILD = 5;
public final static long BUILD = 6;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -230,47 +230,26 @@ public class StatisticsManager implements Service {
return buf.toString();
}
private String renderThroughput(double bytes, long ms) {
if (bytes <= 0)
return "0;0;0;0;";
else
return num(bytes/(ms/1000)) + ";0;0;0;";
}
private void includeThroughput(Properties stats) {
double sendBytes5m = 0;
double sendBytes60m = 0;
double recvBytes5m = 0;
double recvBytes60m = 0;
RateStat sendRate = _context.statManager().getRate("transport.sendMessageSize");
RateStat sendRate = _context.statManager().getRate("bw.sendRate");
if (sendRate != null) {
Rate r = sendRate.getRate(5*60*1000);
if (r != null)
sendBytes5m = r.getLastTotalValue();
stats.setProperty("stat_bandwidthSendBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
r = sendRate.getRate(60*60*1000);
if (r != null)
sendBytes60m = r.getLastTotalValue();
stats.setProperty("stat_bandwidthSendBps.60m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
}
RateStat recvRate = _context.statManager().getRate("transport.receiveMessageSize");
RateStat recvRate = _context.statManager().getRate("bw.recvRate");
if (recvRate != null) {
Rate r = recvRate.getRate(5*60*1000);
if (r != null)
recvBytes5m = r.getLastTotalValue();
stats.setProperty("stat_bandwidthReceiveBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
r = recvRate.getRate(60*60*1000);
if (r != null)
recvBytes60m = r.getLastTotalValue();
stats.setProperty("stat_bandwidthReceiveBps.60m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
}
String throughputRate = renderThroughput(sendBytes5m, 5*60*1000);
stats.setProperty("stat_bandwidthSendBps.5m", throughputRate);
//throughputRate = renderThroughput(sendBytes60m, 60*60*1000);
//stats.setProperty("stat_bandwidthSendBps.60m", throughputRate);
throughputRate = renderThroughput(recvBytes5m, 5*60*1000);
stats.setProperty("stat_bandwidthReceiveBps.5m", throughputRate);
//throughputRate = renderThroughput(recvBytes60m, 60*60*1000);
//stats.setProperty("stat_bandwidthReceiveBps.60m", throughputRate);
}

View File

@ -24,6 +24,16 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
_context.inNetMessagePool().registerHandlerJobBuilder(DatabaseStoreMessage.MESSAGE_TYPE, new FloodfillDatabaseStoreMessageHandler(_context, this));
}
private static final long PUBLISH_TIMEOUT = 30*1000;
/**
* @throws IllegalArgumentException if the local router info is invalid
*/
public void publish(RouterInfo localRouterInfo) throws IllegalArgumentException {
super.publish(localRouterInfo);
sendStore(localRouterInfo.getIdentity().calculateHash(), localRouterInfo, null, null, PUBLISH_TIMEOUT, null);
}
public void sendStore(Hash key, DataStructure ds, Job onSuccess, Job onFailure, long sendTimeout, Set toIgnore) {
// if we are a part of the floodfill netDb, don't send out our own leaseSets as part
// of the flooding - instead, send them to a random floodfill peer so *they* can flood 'em out.

View File

@ -34,6 +34,7 @@ class FloodfillPeerSelector extends PeerSelector {
peersToIgnore = new HashSet(1);
peersToIgnore.add(_context.router().getRouterInfo().getIdentity().getHash());
FloodfillSelectionCollector matches = new FloodfillSelectionCollector(key, peersToIgnore, maxNumRouters);
if (kbuckets == null) return new ArrayList();
kbuckets.getAll(matches);
List rv = matches.get(maxNumRouters);
if (_log.shouldLog(Log.DEBUG))
@ -44,6 +45,7 @@ class FloodfillPeerSelector extends PeerSelector {
}
public List selectFloodfillParticipants(KBucketSet kbuckets) {
if (kbuckets == null) return new ArrayList();
FloodfillSelectionCollector matches = new FloodfillSelectionCollector(null, null, 0);
kbuckets.getAll(matches);
return matches.getFloodfillParticipants();

View File

@ -8,9 +8,7 @@ package net.i2p.router.networkdb.kademlia;
*
*/
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.*;
import net.i2p.data.DataStructure;
import net.i2p.data.Hash;
@ -21,6 +19,7 @@ import net.i2p.data.i2np.DatabaseStoreMessage;
import net.i2p.data.i2np.I2NPMessage;
import net.i2p.router.Job;
import net.i2p.router.JobImpl;
import net.i2p.router.OutNetMessage;
import net.i2p.router.ReplyJob;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelInfo;
@ -198,7 +197,9 @@ class StoreJob extends JobImpl {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug(getJobId() + ": Current routing key for " + key + ": " + rkey);
return _peerSelector.selectNearestExplicit(rkey, numClosest, alreadyChecked, _facade.getKBuckets());
KBucketSet ks = _facade.getKBuckets();
if (ks == null) return new ArrayList();
return _peerSelector.selectNearestExplicit(rkey, numClosest, alreadyChecked, ks);
}
/**
@ -231,13 +232,43 @@ class StoreJob extends JobImpl {
}
private void sendStore(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
if (msg.getValueType() == DatabaseStoreMessage.KEY_TYPE_LEASESET)
if (msg.getValueType() == DatabaseStoreMessage.KEY_TYPE_LEASESET) {
getContext().statManager().addRateData("netDb.storeLeaseSetSent", 1, 0);
else
sendStoreThroughGarlic(msg, peer, expiration);
} else {
getContext().statManager().addRateData("netDb.storeRouterInfoSent", 1, 0);
sendStoreThroughGarlic(msg, peer, expiration);
sendDirect(msg, peer, expiration);
}
}
private void sendDirect(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
long token = getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);
msg.setReplyToken(token);
msg.setReplyGateway(getContext().routerHash());
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": send(dbStore) w/ token expected " + token);
_state.addPending(peer.getIdentity().getHash());
SendSuccessJob onReply = new SendSuccessJob(getContext(), peer);
FailedJob onFail = new FailedJob(getContext(), peer, getContext().clock().now());
StoreMessageSelector selector = new StoreMessageSelector(getContext(), getJobId(), peer, token, expiration);
if (_log.shouldLog(Log.DEBUG))
_log.debug("sending store directly to " + peer.getIdentity().getHash());
OutNetMessage m = new OutNetMessage(getContext());
m.setExpiration(expiration);
m.setMessage(msg);
m.setOnFailedReplyJob(onFail);
m.setOnFailedSendJob(onFail);
m.setOnReplyJob(onReply);
m.setPriority(STORE_PRIORITY);
m.setReplySelector(selector);
m.setTarget(peer);
getContext().commSystem().processMessage(m);
}
private void sendStoreThroughGarlic(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
long token = getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);

View File

@ -26,6 +26,7 @@ public class IntroductionManager {
_builder = new PacketBuilder(ctx);
_outbound = Collections.synchronizedMap(new HashMap(128));
_inbound = new ArrayList(128);
ctx.statManager().createRateStat("udp.receiveRelayIntro", "How often we get a relayed request for us to talk to someone?", "udp", new long[] { 60*1000, 5*60*1000, 10*60*1000 });
}
public void reset() {
@ -81,6 +82,7 @@ public class IntroductionManager {
}
public void receiveRelayIntro(RemoteHostId bob, UDPPacketReader reader) {
_context.statManager().addRateData("udp.receiveRelayIntro", 1, 0);
_transport.send(_builder.buildHolePunch(reader));
}

View File

@ -97,7 +97,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String PROP_FIXED_PORT = "i2np.udp.fixedPort";
private static final String DEFAULT_FIXED_PORT = "true";
/** do we require introducers, regardless of our status? */
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
/** how many relays offered to us will we use at a time? */
public static final int PUBLIC_RELAY_COUNT = 3;
@ -808,7 +811,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_context.router().rebuildRouterInfo();
}
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
public boolean introducersRequired() {
String forceIntroducers = _context.getProperty(PROP_FORCE_INTRODUCERS);
if ( (forceIntroducers != null) && (Boolean.valueOf(forceIntroducers).booleanValue()) )