/** * Initialize the message history according to the router's configuration. Call this whenever the * router identity changes. */ public synchronized void initialize(boolean forceReinitialize) { if (!forceReinitialize) return; if (_context.router().getRouterInfo() == null) { _reinitializeJob.getTiming().setStartAfter(_context.clock().now() + 15 * 1000); _context.jobQueue().addJob(_reinitializeJob); } else { _localIdent = getName(_context.routerHash()); // _unwrittenEntries = new ArrayList(64); updateSettings(); // clear the history file on startup if (_firstPass) { File f = new File(_historyFile); if (!f.isAbsolute()) f = new File(_context.getLogDir(), _historyFile); f.delete(); _writeJob.getTiming().setStartAfter(_context.clock().now() + WRITE_DELAY); _context.jobQueue().addJob(_writeJob); _firstPass = false; } if (_doLog) addEntry(getPrefix() + "** Router initialized (started up or changed identities)"); // _submitMessageHistoryJob.getTiming().setStartAfter(_context.clock().now() + 2*60*1000); // _context.jobQueue().addJob(_submitMessageHistoryJob); } }
/** * If the tunnel is short enough, and everybody in the tunnel, and the OBEP or IBGW for the paired * tunnel, all support the new variable-sized tunnel build message, then use that, otherwise the * old 8-entry version. * * @return null on error */ private static TunnelBuildMessage createTunnelBuildMessage( RouterContext ctx, TunnelPool pool, PooledTunnelCreatorConfig cfg, TunnelInfo pairedTunnel, BuildExecutor exec) { Log log = ctx.logManager().getLog(BuildRequestor.class); long replyTunnel = 0; Hash replyRouter = null; boolean useVariable = SEND_VARIABLE && cfg.getLength() <= MEDIUM_RECORDS; if (cfg.isInbound()) { // replyTunnel = 0; // as above replyRouter = ctx.routerHash(); if (useVariable) { // check the reply OBEP and all the tunnel peers except ourselves if (!supportsVariable(ctx, pairedTunnel.getPeer(pairedTunnel.getLength() - 1))) { useVariable = false; } else { for (int i = 0; i < cfg.getLength() - 1; i++) { if (!supportsVariable(ctx, cfg.getPeer(i))) { useVariable = false; break; } } } } } else { replyTunnel = pairedTunnel.getReceiveTunnelId(0).getTunnelId(); replyRouter = pairedTunnel.getPeer(0); if (useVariable) { // check the reply IBGW and all the tunnel peers except ourselves if (!supportsVariable(ctx, replyRouter)) { useVariable = false; } else { for (int i = 1; i < cfg.getLength() - 1; i++) { if (!supportsVariable(ctx, cfg.getPeer(i))) { useVariable = false; break; } } } } } // populate and encrypt the message TunnelBuildMessage msg; List<Integer> order; if (useVariable) { if (cfg.getLength() <= SHORT_RECORDS) { msg = new VariableTunnelBuildMessage(ctx, SHORT_RECORDS); order = new ArrayList<Integer>(SHORT_ORDER); } else { msg = new VariableTunnelBuildMessage(ctx, MEDIUM_RECORDS); order = new ArrayList<Integer>(MEDIUM_ORDER); } } else { msg = new TunnelBuildMessage(ctx); order = new ArrayList<Integer>(ORDER); } // This is in BuildExecutor.buildTunnel() now // long replyMessageId = ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE); // cfg.setReplyMessageId(replyMessageId); Collections.shuffle(order, ctx.random()); // randomized placement within the message cfg.setReplyOrder(order); if (log.shouldLog(Log.DEBUG)) log.debug("Build order: " + order + " for " + cfg); for (int i = 0; i < msg.getRecordCount(); i++) { int hop = order.get(i).intValue(); PublicKey key = null; if (BuildMessageGenerator.isBlank(cfg, hop)) { // erm, blank } else { Hash peer = cfg.getPeer(hop); RouterInfo peerInfo = ctx.netDb().lookupRouterInfoLocally(peer); if (peerInfo == null) { if (log.shouldLog(Log.WARN)) log.warn( "Peer selected for hop " + i + "/" + hop + " was not found locally: " + peer + " for " + cfg); return null; } else { key = peerInfo.getIdentity().getPublicKey(); } } if (log.shouldLog(Log.DEBUG)) log.debug(cfg.getReplyMessageId() + ": record " + i + "/" + hop + " has key " + key); BuildMessageGenerator.createRecord(i, hop, msg, cfg, replyRouter, replyTunnel, ctx, key); } BuildMessageGenerator.layeredEncrypt(ctx, msg, cfg, order); return msg; }