public long receiveEncrypted(byte encrypted[]) { TunnelDataMessage msg = new TunnelDataMessage(_context); msg.setData(encrypted); msg.setTunnelId(_config.getConfig(0).getSendTunnel()); if (_log.shouldLog(Log.DEBUG)) _log.debug("received encrypted, sending out " + _config + ": " + msg); RouterInfo ri = _nextHopCache; if (ri == null) ri = _context.netDb().lookupRouterInfoLocally(_config.getPeer(1)); if (ri != null) { _nextHopCache = ri; send(msg, ri); return msg.getUniqueId(); } else { // It should be rare to forget the router info for a peer in our own tunnel. if (_log.shouldLog(Log.WARN)) _log.warn("lookup of " + _config.getPeer(1) + " required for " + msg); _context .netDb() .lookupRouterInfo( _config.getPeer(1), new SendJob(_context, msg), new FailedJob(_context), MAX_LOOKUP_TIME); return -1; } }
public OutboundReceiver(RouterContext ctx, TunnelCreatorConfig cfg) { _context = ctx; _log = ctx.logManager().getLog(OutboundReceiver.class); _config = cfg; _nextHopCache = _context.netDb().lookupRouterInfoLocally(_config.getPeer(1)); // all createRateStat() in TunnelDispatcher }
/** * The next hop * * @return non-null * @since 0.9.3 */ public Hash getSendTo() { return _config.getPeer(1); }
private void runTest() { I2PAppContext ctx = I2PAppContext.getGlobalContext(); Log log = ctx.logManager().getLog(getClass()); List order = pickOrder(ctx); TunnelCreatorConfig cfg = createConfig(ctx); _replyRouter = new Hash(); byte h[] = new byte[Hash.HASH_LENGTH]; Arrays.fill(h, (byte) 0xFF); _replyRouter.setData(h); _replyTunnel = 42; // populate and encrypt the message BuildMessageGenerator gen = new BuildMessageGenerator(); TunnelBuildMessage msg = new TunnelBuildMessage(ctx); for (int i = 0; i < BuildMessageGenerator.ORDER.length; i++) { int hop = ((Integer) order.get(i)).intValue(); PublicKey key = null; if (hop < _pubKeys.length) key = _pubKeys[hop]; gen.createRecord(i, hop, msg, cfg, _replyRouter, _replyTunnel, ctx, key); } gen.layeredEncrypt(ctx, msg, cfg, order); log.debug( "\n================================================================" + "\nMessage fully encrypted" + "\n================================================================"); // now msg is fully encrypted, so lets go through the hops, decrypting and replying // as necessary BuildMessageProcessor proc = new BuildMessageProcessor(ctx); for (int i = 0; i < cfg.getLength(); i++) { // this not only decrypts the current hop's record, but encrypts the other records // with the reply key BuildRequestRecord req = proc.decrypt(ctx, msg, _peers[i], _privKeys[i]); if (req == null) { // no records matched the _peers[i], or the decryption failed throw new RuntimeException("foo @ " + i); } long ourId = req.readReceiveTunnelId(); byte replyIV[] = req.readReplyIV(); long nextId = req.readNextTunnelId(); Hash nextPeer = req.readNextIdentity(); boolean isInGW = req.readIsInboundGateway(); boolean isOutEnd = req.readIsOutboundEndpoint(); long time = req.readRequestTime(); long now = (ctx.clock().now() / (60l * 60l * 1000l)) * (60 * 60 * 1000); int ourSlot = -1; BuildResponseRecord resp = new BuildResponseRecord(); byte reply[] = resp.create(ctx, 0, req.readReplyKey(), req.readReplyIV(), -1); for (int j = 0; j < TunnelBuildMessage.RECORD_COUNT; j++) { if (msg.getRecord(j) == null) { ourSlot = j; msg.setRecord(j, new ByteArray(reply)); break; } } log.debug( "Read slot " + ourSlot + " containing hop " + i + " @ " + _peers[i].toBase64() + " receives on " + ourId + " w/ replyIV " + Base64.encode(replyIV) + " sending to " + nextId + " on " + nextPeer.toBase64() + " inGW? " + isInGW + " outEnd? " + isOutEnd + " time difference " + (now - time)); } log.debug( "\n================================================================" + "\nAll hops traversed and replies gathered" + "\n================================================================"); // now all of the replies are populated, toss 'em into a reply message and handle it TunnelBuildReplyMessage reply = new TunnelBuildReplyMessage(ctx); for (int i = 0; i < TunnelBuildMessage.RECORD_COUNT; i++) reply.setRecord(i, msg.getRecord(i)); BuildReplyHandler handler = new BuildReplyHandler(); int statuses[] = handler.decrypt(ctx, reply, cfg, order); if (statuses == null) throw new RuntimeException("bar"); boolean allAgree = true; for (int i = 0; i < cfg.getLength(); i++) { Hash peer = cfg.getPeer(i); int record = ((Integer) order.get(i)).intValue(); if (statuses[record] != 0) allAgree = false; // else // penalize peer according to the rejection cause } log.debug( "\n================================================================" + "\nAll peers agree? " + allAgree + "\n================================================================"); }