* Router:

- Add a lock for reading/writing the router.info file
      - Check our RouterInfo validity after reading and before saving,
        to catch fatal errors sooner
This commit is contained in:
zzz
2011-06-04 12:05:48 +00:00
parent 4e16ef35a2
commit 5974160805
6 changed files with 70 additions and 28 deletions

View File

@@ -1,3 +1,15 @@
2011-06-04 zzz
* NBigI: Recognize Android
* KeyGenerator: Restore old return type to not break ABI (thx kytv)
* Router:
- Add a lock for reading/writing the router.info file
- Check our RouterInfo validity after reading and before saving,
to catch fatal errors sooner
2011-06-03 zzz
* Android: More build updates, start working on JNI for GMP
* Build: Fix dependency issue cause by misspelled file name
2011-06-02 zzz
* Android: Build fixes
* Crypto:

View File

@@ -63,6 +63,7 @@ public class Router {
/** full path */
private String _configFilename;
private RouterInfo _routerInfo;
public final Object routerInfoFileLock = new Object();
private long _started;
private boolean _higherVersionSeen;
//private SessionKeyPersistenceHelper _sessionKeyPersistenceHelper;
@@ -312,6 +313,9 @@ public class Router {
public RouterInfo getRouterInfo() { return _routerInfo; }
/**
* Caller must ensure info is valid - no validation done here
*/
public void setRouterInfo(RouterInfo info) {
_routerInfo = info;
if (_log.shouldLog(Log.INFO))
@@ -452,6 +456,8 @@ public class Router {
}
ri.sign(key);
setRouterInfo(ri);
if (!ri.isValid())
throw new DataFormatException("Our RouterInfo has a bad signature");
Republish r = new Republish();
if (blockingRebuild)
r.timeReached();
@@ -1582,13 +1588,14 @@ private static class ShutdownHook extends Thread {
/** update the router.info file whenever its, er, updated */
private static class PersistRouterInfoJob extends JobImpl {
private Log _log;
public PersistRouterInfoJob(RouterContext ctx) {
super(ctx);
}
public String getName() { return "Persist Updated Router Information"; }
public void runJob() {
_log = getContext().logManager().getLog(PersistRouterInfoJob.class);
Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Persisting updated router info");
@@ -1598,6 +1605,7 @@ private static class PersistRouterInfoJob extends JobImpl {
RouterInfo info = getContext().router().getRouterInfo();
FileOutputStream fos = null;
synchronized (getContext().router().routerInfoFileLock) {
try {
fos = new SecureFileOutputStream(infoFile);
info.writeBytes(fos);
@@ -1610,5 +1618,6 @@ private static class PersistRouterInfoJob extends JobImpl {
}
}
}
}
}

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 16;
public final static long BUILD = 17;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -31,7 +31,7 @@ import net.i2p.util.SecureFileOutputStream;
public class CreateRouterInfoJob extends JobImpl {
private static Log _log = new Log(CreateRouterInfoJob.class);
private Job _next;
private final Job _next;
public CreateRouterInfoJob(RouterContext ctx, Job next) {
super(ctx);
@@ -43,10 +43,15 @@ public class CreateRouterInfoJob extends JobImpl {
public void runJob() {
_log.debug("Creating the new router info");
// create a new router info and store it where LoadRouterInfoJob looks
synchronized (getContext().router().routerInfoFileLock) {
createRouterInfo();
}
getContext().jobQueue().addJob(_next);
}
/**
* Caller must hold Router.routerInfoFileLock
*/
RouterInfo createRouterInfo() {
RouterInfo info = new RouterInfo();
FileOutputStream fos1 = null;
@@ -79,6 +84,9 @@ public class CreateRouterInfoJob extends JobImpl {
info.sign(signingPrivKey);
if (!info.isValid())
throw new DataFormatException("RouterInfo we just built is invalid: " + info);
String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
File ifile = new File(getContext().getRouterDir(), infoFilename);
fos1 = new SecureFileOutputStream(ifile);

View File

@@ -24,7 +24,7 @@ import net.i2p.router.RouterContext;
import net.i2p.util.Log;
public class LoadRouterInfoJob extends JobImpl {
private Log _log;
private final Log _log;
private boolean _keysExist;
private boolean _infoExists;
private RouterInfo _us;
@@ -37,7 +37,9 @@ public class LoadRouterInfoJob extends JobImpl {
public String getName() { return "Load Router Info"; }
public void runJob() {
synchronized (getContext().router().routerInfoFileLock) {
loadRouterInfo();
}
if (_us == null) {
RebuildRouterInfoJob r = new RebuildRouterInfoJob(getContext());
r.rebuildRouterInfo(false);
@@ -78,6 +80,10 @@ public class LoadRouterInfoJob extends JobImpl {
fis1 = new FileInputStream(rif);
info = new RouterInfo();
info.readBytes(fis1);
// Catch this here before it all gets worse
if (!info.isValid())
throw new DataFormatException("Our RouterInfo has a bad signature");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Reading in routerInfo from " + rif.getAbsolutePath() + " and it has " + info.getAddresses().size() + " addresses");
_us = info;
}

View File

@@ -45,7 +45,7 @@ import net.i2p.util.SecureFileOutputStream;
*
*/
public class RebuildRouterInfoJob extends JobImpl {
private Log _log;
private final Log _log;
private final static long REBUILD_DELAY = 45*1000; // every 30 seconds
@@ -134,7 +134,13 @@ public class RebuildRouterInfoJob extends JobImpl {
return;
}
if (!info.isValid()) {
_log.log(Log.CRIT, "RouterInfo we just built is invalid: " + info, new Exception());
return;
}
FileOutputStream fos = null;
synchronized (getContext().router().routerInfoFileLock) {
try {
fos = new SecureFileOutputStream(infoFile);
info.writeBytes(fos);
@@ -145,6 +151,7 @@ public class RebuildRouterInfoJob extends JobImpl {
} finally {
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
}
}
} else {
_log.warn("Private key file " + keyFile.getAbsolutePath() + " deleted! Rebuilding a brand new router identity!");