package net.i2p.router.startup; /* * free (adj.): unencumbered; not under the control of others * Written by jrandom in 2003 and released into the public domain * with no warranty of any kind, either expressed or implied. * It probably won't make your computer catch on fire, or eat * your children, but it might. Use at your own risk. * */ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; import net.i2p.crypto.SigType; import net.i2p.data.Certificate; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; import net.i2p.data.PrivateKey; import net.i2p.data.PublicKey; import net.i2p.data.router.RouterIdentity; import net.i2p.data.router.RouterInfo; import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPublicKey; import net.i2p.router.JobImpl; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.startup.LoadRouterInfoJob.KeyData; import net.i2p.util.Log; import net.i2p.util.SecureFileOutputStream; /** * This used be called from StartAcceptingClientsJob but is now disabled. * It is still called once from LoadRouterInfoJob (but not run as a Job). * * The following comments appear to be incorrect... * it rebuilds if the router.info file does not exist. * There is no check for a router.info.rebuild file. * * If the file router.info.rebuild exists, rebuild the router info and republish. * This is useful for dhcp or other situations where the router addresses change - * simply create the router.info.rebuild file after modifying router.config and within * 45 seconds (the current check frequency), the router info will be rebuilt with new * addresses and stats, as well as a new version, then republished. Afterwards, the * router.info.rebuild file is deleted * */ class RebuildRouterInfoJob extends JobImpl { private final Log _log; private final static long REBUILD_DELAY = 45*1000; // every 30 seconds public RebuildRouterInfoJob(RouterContext context) { super(context); _log = context.logManager().getLog(RebuildRouterInfoJob.class); } public String getName() { return "Rebuild Router Info"; } public void runJob() { throw new UnsupportedOperationException(); /**** _log.debug("Testing to rebuild router info"); File info = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME); File keyFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME); if (!info.exists() || !keyFile.exists()) { _log.info("Router info file [" + info.getAbsolutePath() + "] or private key file [" + keyFile.getAbsolutePath() + "] deleted, rebuilding"); rebuildRouterInfo(); } else { _log.debug("Router info file [" + info.getAbsolutePath() + "] exists, not rebuilding"); } getTiming().setStartAfter(getContext().clock().now() + REBUILD_DELAY); getContext().jobQueue().addJob(this); ****/ } void rebuildRouterInfo() { rebuildRouterInfo(true); } /** * @param alreadyRunning unused */ void rebuildRouterInfo(boolean alreadyRunning) { _log.debug("Rebuilding the new router info"); RouterInfo info = null; File infoFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME); File keyFile = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME); File keyFile2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME); if (keyFile2.exists() || keyFile.exists()) { // ok, no need to rebuild a brand new identity, just update what we can RouterInfo oldinfo = getContext().router().getRouterInfo(); if (oldinfo == null) { try { KeyData kd = LoadRouterInfoJob.readKeyData(keyFile, keyFile2); info = new RouterInfo(); info.setIdentity(kd.routerIdentity); } catch (DataFormatException e) { _log.log(Log.CRIT, "Error reading in the key data from " + keyFile.getAbsolutePath(), e); keyFile.delete(); keyFile2.delete(); rebuildRouterInfo(alreadyRunning); return; } catch (IOException e) { _log.log(Log.CRIT, "Error reading in the key data from " + keyFile.getAbsolutePath(), e); keyFile.delete(); keyFile2.delete(); rebuildRouterInfo(alreadyRunning); return; } } else { // Make a new RI from the old identity, or else info.setAddresses() will throw an ISE info = new RouterInfo(oldinfo); } try { info.setAddresses(getContext().commSystem().createAddresses()); Properties stats = getContext().statPublisher().publishStatistics(info.getHash()); info.setOptions(stats); // info.setPeers(new HashSet()); // this would have the trusted peers info.setPublished(CreateRouterInfoJob.getCurrentPublishDate(getContext())); info.sign(getContext().keyManager().getSigningPrivateKey()); } catch (DataFormatException dfe) { _log.log(Log.CRIT, "Error rebuilding the new router info", dfe); 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); } catch (DataFormatException dfe) { _log.log(Log.CRIT, "Error rebuilding the router information", dfe); } catch (IOException ioe) { _log.log(Log.CRIT, "Error writing out the rebuilt router information", ioe); } 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!"); // this proc writes the keys and info to the file as well as builds the latest and greatest info CreateRouterInfoJob j = new CreateRouterInfoJob(getContext(), null); synchronized (getContext().router().routerInfoFileLock) { info = j.createRouterInfo(); } } //MessageHistory.initialize(); getContext().router().setRouterInfo(info); _log.info("Router info rebuilt and stored at " + infoFile + " [" + info + "]"); } }