2004-12-14 jrandom

* Periodically send a message along all I2NP connections with the router's
      current time, allowing the receiving peer to determine that the clock
      has skewed too much, and hence, disconnect.  For backwards compatability
      reasons, this is being kludged into a DeliveryStatusMessage (ewww).  The
      next time we have a backwards compatability break, we can put in a proper
      message setup for it.
This commit is contained in:
jrandom
2004-12-14 16:42:35 +00:00
committed by zzz
parent ad72e5cbdf
commit 8824815d6d
4 changed files with 66 additions and 3 deletions

View File

@ -1,4 +1,12 @@
$Id: history.txt,v 1.105 2004/12/13 08:45:52 jrandom Exp $
$Id: history.txt,v 1.106 2004/12/14 06:54:39 jrandom Exp $
2004-12-14 jrandom
* Periodically send a message along all I2NP connections with the router's
current time, allowing the receiving peer to determine that the clock
has skewed too much, and hence, disconnect. For backwards compatability
reasons, this is being kludged into a DeliveryStatusMessage (ewww). The
next time we have a backwards compatability break, we can put in a proper
message setup for it.
2004-12-14 jrandom
* Reenable the probabalistic drop on the TCP queues to deal with good old

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.110 $ $Date: 2004/12/13 08:45:52 $";
public final static String ID = "$Revision: 1.111 $ $Date: 2004/12/14 06:54:39 $";
public final static String VERSION = "0.4.2.3";
public final static long BUILD = 4;
public final static long BUILD = 5;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -2,9 +2,11 @@ package net.i2p.router.transport.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import net.i2p.data.DataFormatException;
import net.i2p.data.i2np.I2NPMessage;
import net.i2p.data.i2np.DeliveryStatusMessage;
import net.i2p.router.OutNetMessage;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
@ -21,6 +23,9 @@ class ConnectionRunner implements Runnable {
private TCPConnection _con;
private boolean _keepRunning;
private byte _writeBuffer[];
private long _lastTimeSend;
private static final long TIME_SEND_FREQUENCY = 60*1000;
public ConnectionRunner(RouterContext ctx, TCPConnection con) {
_context = ctx;
@ -32,6 +37,7 @@ class ConnectionRunner implements Runnable {
public void startRunning() {
_keepRunning = true;
_writeBuffer = new byte[38*1024]; // expansion factor
_lastTimeSend = -1;
String name = "TCP " + _context.routerHash().toBase64().substring(0,6)
+ " to "
@ -39,6 +45,7 @@ class ConnectionRunner implements Runnable {
I2PThread t = new I2PThread(this, name);
t.start();
}
public void stopRunning() {
_keepRunning = false;
}
@ -85,6 +92,12 @@ class ConnectionRunner implements Runnable {
msg.timestamp("ConnectionRunner.sendMessage data");
I2NPMessage timeMessage = null;
if (_lastTimeSend < _context.clock().now() - TIME_SEND_FREQUENCY) {
timeMessage = buildTimeMessage();
_lastTimeSend = _context.clock().now();
}
OutputStream out = _con.getOutputStream();
boolean ok = false;
long before = -1;
@ -93,6 +106,8 @@ class ConnectionRunner implements Runnable {
synchronized (out) {
before = _context.clock().now();
out.write(buf, 0, written);
if (timeMessage != null)
out.write(timeMessage.toByteArray());
out.flush();
after = _context.clock().now();
}
@ -110,4 +125,18 @@ class ConnectionRunner implements Runnable {
}
_con.sent(msg, ok, after - before);
}
/**
* Build up a new message to be sent with the current router's time
*
*/
private I2NPMessage buildTimeMessage() {
// holy crap this is a kludge - strapping ourselves into a
// deliveryStatusMessage
DeliveryStatusMessage tm = new DeliveryStatusMessage(_context);
tm.setArrival(new Date(_context.clock().now()));
tm.setMessageId(0);
tm.setUniqueId(0);
return tm;
}
}

View File

@ -1,9 +1,12 @@
package net.i2p.router.transport.tcp;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.RouterIdentity;
import net.i2p.data.i2np.I2NPMessageReader;
import net.i2p.data.i2np.I2NPMessage;
import net.i2p.data.i2np.DeliveryStatusMessage;
import net.i2p.router.Router;
import net.i2p.util.Log;
/**
@ -35,9 +38,32 @@ public class MessageHandler implements I2NPMessageReader.I2NPMessageEventListene
_log.debug("Just received message " + message.getUniqueId() + " from "
+ _identHash.toBase64().substring(0,6)
+ " readTime = " + msToRead + "ms type = " + message.getClass().getName());
if (message instanceof DeliveryStatusMessage) {
DeliveryStatusMessage msg = (DeliveryStatusMessage)message;
if ( (msg.getMessageId() == 0) && (msg.getUniqueId() == 0) ) {
timeMessageReceived(msg.getArrival().getTime());
// dont propogate the message, its just a fake
return;
}
}
_transport.messageReceived(message, _ident, _identHash, msToRead, size);
}
private void timeMessageReceived(long remoteTime) {
long delta = _con.getRouterContext().clock().now() - remoteTime;
if ( (delta > Router.CLOCK_FUDGE_FACTOR) || (delta < 0 - Router.CLOCK_FUDGE_FACTOR) ) {
_log.error("Peer " + _identHash.toBase64().substring(0,6) + " is too far skewed ("
+ DataHelper.formatDuration(delta) + ") after uptime of "
+ DataHelper.formatDuration(_con.getLifetime()) );
_con.closeConnection();
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Peer " + _identHash.toBase64().substring(0,6) + " is only skewed by ("
+ DataHelper.formatDuration(delta) + ") after uptime of "
+ DataHelper.formatDuration(_con.getLifetime()) );
}
}
public void readError(I2NPMessageReader reader, Exception error) {
_con.closeConnection();
}