Search in sources :

Example 26 with RouterInfo

use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.

the class CreateRouterInfoJob method createRouterInfo.

/**
 *  Writes 6 files: router.info (standard RI format),
 *  router.keys.dat, and 4 individual key files under keyBackup/
 *
 *  router.keys.dat file format: This is the
 *  same "eepPriv.dat" format used by the client code,
 *  as documented in PrivateKeyFile.
 *
 *  Old router.keys file format: Note that this is NOT the
 *  same "eepPriv.dat" format used by the client code.
 *<pre>
 *   - Private key (256 bytes)
 *   - Signing Private key (20 bytes)
 *   - Public key (256 bytes)
 *   - Signing Public key (128 bytes)
 *  Total 660 bytes
 *</pre>
 *
 *  Caller must hold Router.routerInfoFileLock.
 */
RouterInfo createRouterInfo() {
    SigType type = getSigTypeConfig(getContext());
    RouterInfo info = new RouterInfo();
    OutputStream fos1 = null;
    try {
        info.setAddresses(getContext().commSystem().createAddresses());
        // not necessary, in constructor
        // info.setPeers(new HashSet());
        info.setPublished(getCurrentPublishDate(getContext()));
        Object[] keypair = getContext().keyGenerator().generatePKIKeypair();
        PublicKey pubkey = (PublicKey) keypair[0];
        PrivateKey privkey = (PrivateKey) keypair[1];
        SimpleDataStructure[] signingKeypair = getContext().keyGenerator().generateSigningKeys(type);
        SigningPublicKey signingPubKey = (SigningPublicKey) signingKeypair[0];
        SigningPrivateKey signingPrivKey = (SigningPrivateKey) signingKeypair[1];
        RouterIdentity ident = new RouterIdentity();
        Certificate cert = createCertificate(getContext(), signingPubKey);
        ident.setCertificate(cert);
        ident.setPublicKey(pubkey);
        ident.setSigningPublicKey(signingPubKey);
        byte[] padding;
        int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
        if (padLen > 0) {
            padding = new byte[padLen];
            getContext().random().nextBytes(padding);
            ident.setPadding(padding);
        } else {
            padding = null;
        }
        info.setIdentity(ident);
        Properties stats = getContext().statPublisher().publishStatistics(ident.getHash());
        info.setOptions(stats);
        info.sign(signingPrivKey);
        if (!info.isValid())
            throw new DataFormatException("RouterInfo we just built is invalid: " + info);
        // remove router.keys
        (new File(getContext().getRouterDir(), KEYS_FILENAME)).delete();
        // write router.info
        File ifile = new File(getContext().getRouterDir(), INFO_FILENAME);
        fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
        info.writeBytes(fos1);
        // write router.keys.dat
        File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
        PrivateKeyFile pkf = new PrivateKeyFile(kfile, pubkey, signingPubKey, cert, privkey, signingPrivKey, padding);
        pkf.write();
        // set or overwrite old random keys
        Map<String, String> map = new HashMap<String, String>(2);
        byte[] rk = new byte[32];
        getContext().random().nextBytes(rk);
        map.put(Router.PROP_IB_RANDOM_KEY, Base64.encode(rk));
        getContext().random().nextBytes(rk);
        map.put(Router.PROP_OB_RANDOM_KEY, Base64.encode(rk));
        getContext().router().saveConfig(map, null);
        getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
        if (_log.shouldLog(Log.INFO))
            _log.info("Router info created and stored at " + ifile.getAbsolutePath() + " with private keys stored at " + kfile.getAbsolutePath() + " [" + info + "]");
        getContext().router().eventLog().addEvent(EventLog.REKEYED, ident.calculateHash().toBase64());
    } catch (GeneralSecurityException gse) {
        _log.log(Log.CRIT, "Error building the new router information", gse);
    } catch (DataFormatException dfe) {
        _log.log(Log.CRIT, "Error building the new router information", dfe);
    } catch (IOException ioe) {
        _log.log(Log.CRIT, "Error writing out the new router information", ioe);
    } finally {
        if (fos1 != null)
            try {
                fos1.close();
            } catch (IOException ioe) {
            }
    }
    return info;
}
Also used : PrivateKey(net.i2p.data.PrivateKey) SigningPrivateKey(net.i2p.data.SigningPrivateKey) HashMap(java.util.HashMap) RouterInfo(net.i2p.data.router.RouterInfo) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) OutputStream(java.io.OutputStream) Properties(java.util.Properties) SimpleDataStructure(net.i2p.data.SimpleDataStructure) BufferedOutputStream(java.io.BufferedOutputStream) SigningPublicKey(net.i2p.data.SigningPublicKey) SigningPublicKey(net.i2p.data.SigningPublicKey) PublicKey(net.i2p.data.PublicKey) RouterIdentity(net.i2p.data.router.RouterIdentity) GeneralSecurityException(java.security.GeneralSecurityException) PrivateKeyFile(net.i2p.data.PrivateKeyFile) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) PrivateKeyFile(net.i2p.data.PrivateKeyFile) File(java.io.File) Certificate(net.i2p.data.Certificate) KeyCertificate(net.i2p.data.KeyCertificate)

Example 27 with RouterInfo

use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.

the class LoadRouterInfoJob method loadRouterInfo.

/**
 *  Loads router.info and either router.keys.dat or router.keys.
 *
 *  See CreateRouterInfoJob for file formats
 */
private void loadRouterInfo() {
    RouterInfo info = null;
    File rif = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
    boolean infoExists = rif.exists();
    File rkf = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME);
    boolean keysExist = rkf.exists();
    File rkf2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
    boolean keys2Exist = rkf2.exists();
    InputStream fis1 = null;
    try {
        // so pretend the RI isn't there if there is no keyfile
        if (infoExists && (keys2Exist || keysExist)) {
            fis1 = new BufferedInputStream(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");
            // don't reuse if family name changed
            if (DataHelper.eq(info.getOption(FamilyKeyCrypto.OPT_NAME), getContext().getProperty(FamilyKeyCrypto.PROP_FAMILY_NAME))) {
                _us = info;
            } else {
                _log.logAlways(Log.WARN, "NetDb family name changed");
            }
        }
        if (keys2Exist || keysExist) {
            KeyData kd = readKeyData(rkf, rkf2);
            PublicKey pubkey = kd.routerIdentity.getPublicKey();
            SigningPublicKey signingPubKey = kd.routerIdentity.getSigningPublicKey();
            PrivateKey privkey = kd.privateKey;
            SigningPrivateKey signingPrivKey = kd.signingPrivateKey;
            SigType stype = signingPubKey.getType();
            // check if the sigtype config changed
            SigType cstype = CreateRouterInfoJob.getSigTypeConfig(getContext());
            boolean sigTypeChanged = stype != cstype;
            if (sigTypeChanged && getContext().getProperty(CreateRouterInfoJob.PROP_ROUTER_SIGTYPE) == null) {
                // TODO reduce to ~3 (i.e. increase probability) in future release
                if (getContext().random().nextInt(4) > 0) {
                    sigTypeChanged = false;
                    if (_log.shouldWarn())
                        _log.warn("Deferring RI rekey from " + stype + " to " + cstype);
                }
            }
            if (sigTypeChanged || shouldRebuild(privkey)) {
                if (_us != null) {
                    Hash h = _us.getIdentity().getHash();
                    _log.logAlways(Log.WARN, "Deleting old router identity " + h.toBase64());
                    // the netdb hasn't started yet, but we want to delete the RI
                    File f = PersistentDataStore.getRouterInfoFile(getContext(), h);
                    f.delete();
                    // the banlist can be called at any time
                    getContext().banlist().banlistRouterForever(h, "Our previous identity");
                    _us = null;
                }
                if (sigTypeChanged)
                    _log.logAlways(Log.WARN, "Rebuilding RouterInfo with new signature type " + cstype);
                // windows... close before deleting
                if (fis1 != null) {
                    try {
                        fis1.close();
                    } catch (IOException ioe) {
                    }
                    fis1 = null;
                }
                rif.delete();
                rkf.delete();
                rkf2.delete();
                return;
            }
            getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
        }
    } catch (IOException ioe) {
        _log.log(Log.CRIT, "Error reading the router info from " + rif.getAbsolutePath() + " and the keys from " + rkf.getAbsolutePath(), ioe);
        _us = null;
        // windows... close before deleting
        if (fis1 != null) {
            try {
                fis1.close();
            } catch (IOException ioe2) {
            }
            fis1 = null;
        }
        rif.delete();
        rkf.delete();
        rkf2.delete();
    } catch (DataFormatException dfe) {
        _log.log(Log.CRIT, "Corrupt router info or keys at " + rif.getAbsolutePath() + " / " + rkf.getAbsolutePath(), dfe);
        _us = null;
        // windows... close before deleting
        if (fis1 != null) {
            try {
                fis1.close();
            } catch (IOException ioe) {
            }
            fis1 = null;
        }
        rif.delete();
        rkf.delete();
        rkf2.delete();
    } finally {
        if (fis1 != null)
            try {
                fis1.close();
            } catch (IOException ioe) {
            }
    }
}
Also used : SigningPublicKey(net.i2p.data.SigningPublicKey) PrivateKey(net.i2p.data.PrivateKey) SigningPrivateKey(net.i2p.data.SigningPrivateKey) RouterInfo(net.i2p.data.router.RouterInfo) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) SigningPublicKey(net.i2p.data.SigningPublicKey) PublicKey(net.i2p.data.PublicKey) IOException(java.io.IOException) Hash(net.i2p.data.Hash) FileInputStream(java.io.FileInputStream) SigType(net.i2p.crypto.SigType) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException) BufferedInputStream(java.io.BufferedInputStream) File(java.io.File) RouterPrivateKeyFile(net.i2p.data.router.RouterPrivateKeyFile)

Example 28 with RouterInfo

use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.

the class InboundMessageDistributor method distribute.

public void distribute(I2NPMessage msg, Hash target, TunnelId tunnel) {
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("IBMD for " + _client + " to " + target + " / " + tunnel + " : " + msg);
    // allow messages on client tunnels even after client disconnection, as it may
    // include e.g. test messages, etc.  DataMessages will be dropped anyway
    /*
        if ( (_client != null) && (!_context.clientManager().isLocal(_client)) ) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Not distributing a message, as it came down a client's tunnel (" 
                          + _client.toBase64() + ") after the client disconnected: " + msg);
            return;
        }
        */
    int type = msg.getType();
    // if the message came down a client tunnel:
    if (_client != null) {
        switch(type) {
            case DatabaseSearchReplyMessage.MESSAGE_TYPE:
                /**
                 **
                 *                     DatabaseSearchReplyMessage orig = (DatabaseSearchReplyMessage) msg;
                 *                     if (orig.getNumReplies() > 0) {
                 *                         if (_log.shouldLog(Log.INFO))
                 *                             _log.info("Removing replies from a DSRM down a tunnel for " + _client + ": " + msg);
                 *                         DatabaseSearchReplyMessage newMsg = new DatabaseSearchReplyMessage(_context);
                 *                         newMsg.setFromHash(orig.getFromHash());
                 *                         newMsg.setSearchKey(orig.getSearchKey());
                 *                         msg = newMsg;
                 *                     }
                 ***
                 */
                break;
            case DatabaseStoreMessage.MESSAGE_TYPE:
                DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
                if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
                    // Todo: if peer was ff and RI is not ff, queue for exploration in netdb (but that isn't part of the facade now)
                    if (_log.shouldLog(Log.WARN))
                        _log.warn("Dropping DSM down a tunnel for " + _client + ": " + msg);
                    // Handle safely by just updating the caps table, after doing basic validation
                    Hash key = dsm.getKey();
                    if (_context.routerHash().equals(key))
                        return;
                    RouterInfo ri = (RouterInfo) dsm.getEntry();
                    if (!key.equals(ri.getIdentity().getHash()))
                        return;
                    if (!ri.isValid())
                        return;
                    RouterInfo oldri = _context.netDb().lookupRouterInfoLocally(key);
                    // only update if RI is newer and non-ff
                    if (oldri != null && oldri.getPublished() < ri.getPublished() && !FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
                        if (_log.shouldLog(Log.WARN))
                            _log.warn("Updating caps for RI " + key + " from \"" + oldri.getCapabilities() + "\" to \"" + ri.getCapabilities() + '"');
                        _context.peerManager().setCapabilities(key, ri.getCapabilities());
                    }
                    return;
                } else if (dsm.getReplyToken() != 0) {
                    _context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, type);
                    _log.error("Dropping LS DSM w/ reply token down a tunnel for " + _client + ": " + msg);
                    return;
                } else {
                    // allow DSM of our own key (used by FloodfillVerifyStoreJob)
                    // or other keys (used by IterativeSearchJob)
                    // as long as there's no reply token (we will never set a reply token but an attacker might)
                    ((LeaseSet) dsm.getEntry()).setReceivedAsReply();
                }
                break;
            case DeliveryStatusMessage.MESSAGE_TYPE:
            case GarlicMessage.MESSAGE_TYPE:
            case TunnelBuildReplyMessage.MESSAGE_TYPE:
            case VariableTunnelBuildReplyMessage.MESSAGE_TYPE:
                // these are safe, handled below
                break;
            default:
                // drop it, since we should only get the above message types down
                // client tunnels
                _context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, type);
                _log.error("Dropped dangerous message down a tunnel for " + _client + ": " + msg, new Exception("cause"));
                return;
        }
    // switch
    } else {
        // expl. tunnel
        switch(type) {
            case DatabaseStoreMessage.MESSAGE_TYPE:
                DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
                if (dsm.getReplyToken() != 0) {
                    _context.statManager().addRateData("tunnel.dropDangerousExplTunnelMessage", 1, type);
                    _log.error("Dropping DSM w/ reply token down a expl. tunnel: " + msg);
                    return;
                }
                if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_LEASESET)
                    ((LeaseSet) dsm.getEntry()).setReceivedAsReply();
                break;
            case DatabaseSearchReplyMessage.MESSAGE_TYPE:
            case DeliveryStatusMessage.MESSAGE_TYPE:
            case GarlicMessage.MESSAGE_TYPE:
            case TunnelBuildReplyMessage.MESSAGE_TYPE:
            case VariableTunnelBuildReplyMessage.MESSAGE_TYPE:
                // these are safe, handled below
                break;
            default:
                _context.statManager().addRateData("tunnel.dropDangerousExplTunnelMessage", 1, type);
                _log.error("Dropped dangerous message down expl tunnel: " + msg, new Exception("cause"));
                return;
        }
    // switch
    }
    if ((target == null) || ((tunnel == null) && (_context.routerHash().equals(target)))) {
        // make sure we don't honor any remote requests directly (garlic instructions, etc)
        if (type == GarlicMessage.MESSAGE_TYPE) {
            // in case we're looking for replies to a garlic message (cough load tests cough)
            _context.inNetMessagePool().handleReplies(msg);
            // if (_log.shouldLog(Log.DEBUG))
            // _log.debug("received garlic message in the tunnel, parse it out");
            _receiver.receive((GarlicMessage) msg);
        } else {
            if (_log.shouldLog(Log.INFO))
                _log.info("distributing inbound tunnel message into our inNetMessagePool: " + msg);
            _context.inNetMessagePool().add(msg, null, null);
        }
    /**
     **** latency measuring attack?
     *        } else if (_context.routerHash().equals(target)) {
     *            // the want to send it to a tunnel, except we are also that tunnel's gateway
     *            // dispatch it directly
     *            if (_log.shouldLog(Log.INFO))
     *                _log.info("distributing inbound tunnel message back out, except we are the gateway");
     *            TunnelGatewayMessage gw = new TunnelGatewayMessage(_context);
     *            gw.setMessage(msg);
     *            gw.setTunnelId(tunnel);
     *            gw.setMessageExpiration(_context.clock().now()+10*1000);
     *            gw.setUniqueId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
     *            _context.tunnelDispatcher().dispatch(gw);
     *****
     */
    } else {
        // ok, they want us to send it remotely, but that'd bust our anonymity,
        // so we send it out a tunnel first
        // TODO use the OCMOSJ cache to pick OB tunnel we are already using?
        TunnelInfo out = _context.tunnelManager().selectOutboundTunnel(_client, target);
        if (out == null) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("no outbound tunnel to send the client message for " + _client + ": " + msg);
            return;
        }
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("distributing IB tunnel msg type " + type + " back out " + out + " targetting " + target);
        TunnelId outId = out.getSendTunnelId(0);
        if (outId == null) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("strange? outbound tunnel has no outboundId? " + out + " failing to distribute " + msg);
            return;
        }
        long exp = _context.clock().now() + 20 * 1000;
        if (msg.getMessageExpiration() < exp)
            msg.setMessageExpiration(exp);
        _context.tunnelDispatcher().dispatchOutbound(msg, outId, tunnel, target);
    }
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) DatabaseStoreMessage(net.i2p.data.i2np.DatabaseStoreMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 29 with RouterInfo

use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.

the class PeerTestManager method receiveFromAliceAsBob.

/**
 * The PeerTest message came from the peer referenced in the message (or there wasn't
 * any info in the message), plus we are not acting as Charlie (so we've got to be Bob).
 *
 * testInfo IP/port ignored
 * @param state null if new
 */
private void receiveFromAliceAsBob(RemoteHostId from, UDPPacketReader.PeerTestReader testInfo, long nonce, PeerTestState state) {
    // we are Bob, so pick a (potentially) Charlie and send Charlie Alice's info
    PeerState charlie;
    RouterInfo charlieInfo = null;
    int sz = from.getIP().length;
    boolean isIPv6 = sz == 16;
    if (state == null) {
        // pick a new charlie
        // if (from.getIP().length != 4) {
        // if (_log.shouldLog(Log.WARN))
        // _log.warn("PeerTest over IPv6 from Alice as Bob? " + from);
        // return;
        // }
        charlie = _transport.pickTestPeer(CHARLIE, isIPv6, from);
    } else {
        charlie = _transport.getPeerState(new RemoteHostId(state.getCharlieIP().getAddress(), state.getCharliePort()));
    }
    if (charlie == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Unable to pick a charlie (no peer), IPv6? " + isIPv6);
        return;
    }
    charlieInfo = _context.netDb().lookupRouterInfoLocally(charlie.getRemotePeer());
    if (charlieInfo == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Unable to pick a charlie (no RI), IPv6? " + isIPv6);
        return;
    }
    // TODO should only do most of this if isNew
    InetAddress aliceIP = null;
    SessionKey aliceIntroKey = null;
    try {
        aliceIP = InetAddress.getByAddress(from.getIP());
        aliceIntroKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]);
        testInfo.readIntroKey(aliceIntroKey.getData(), 0);
        RouterAddress raddr = _transport.getTargetAddress(charlieInfo);
        if (raddr == null) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Unable to pick a charlie (no addr), IPv6? " + isIPv6);
            return;
        }
        UDPAddress addr = new UDPAddress(raddr);
        byte[] ikey = addr.getIntroKey();
        if (ikey == null) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Unable to pick a charlie (no ikey), IPv6? " + isIPv6);
            return;
        }
        SessionKey charlieIntroKey = new SessionKey(ikey);
        // UDPPacket packet = _packetBuilder.buildPeerTestToAlice(aliceIP, from.getPort(), aliceIntroKey, charlieIntroKey, nonce);
        // _transport.send(packet);
        long now = _context.clock().now();
        boolean isNew = false;
        if (state == null) {
            isNew = true;
            state = new PeerTestState(BOB, isIPv6, nonce, now);
        } else {
            if (state.getReceiveAliceTime() > now - (RESEND_TIMEOUT / 2)) {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("Too soon, not retransmitting: " + state);
                return;
            }
        }
        state.setAliceIP(aliceIP);
        state.setAlicePort(from.getPort());
        state.setAliceIntroKey(aliceIntroKey);
        state.setCharlieIP(charlie.getRemoteIPAddress());
        state.setCharliePort(charlie.getRemotePort());
        state.setCharlieIntroKey(charlieIntroKey);
        state.setLastSendTime(now);
        state.setReceiveAliceTime(now);
        if (state.incrementPacketsRelayed() > MAX_RELAYED_PER_TEST_BOB) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Too many, not retransmitting: " + state);
            return;
        }
        if (isNew) {
            _activeTests.put(Long.valueOf(nonce), state);
            _context.simpleTimer2().addEvent(new RemoveTest(nonce), MAX_CHARLIE_LIFETIME);
        }
        UDPPacket packet = _packetBuilder.buildPeerTestToCharlie(aliceIP, from.getPort(), aliceIntroKey, nonce, charlie.getRemoteIPAddress(), charlie.getRemotePort(), charlie.getCurrentCipherKey(), charlie.getCurrentMACKey());
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Receive from Alice: " + state);
        _transport.send(packet);
    } catch (UnknownHostException uhe) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Unable to build the aliceIP from " + from, uhe);
        _context.statManager().addRateData("udp.testBadIP", 1);
    }
}
Also used : UnknownHostException(java.net.UnknownHostException) RouterInfo(net.i2p.data.router.RouterInfo) RouterAddress(net.i2p.data.router.RouterAddress) SessionKey(net.i2p.data.SessionKey) InetAddress(java.net.InetAddress)

Example 30 with RouterInfo

use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.

the class TunnelParticipant method dispatch.

public void dispatch(TunnelDataMessage msg, Hash recvFrom) {
    boolean ok = false;
    if (_processor != null)
        ok = _processor.process(msg.getData(), 0, msg.getData().length, recvFrom);
    else if (_inboundEndpointProcessor != null)
        ok = _inboundEndpointProcessor.retrievePreprocessedData(msg.getData(), 0, msg.getData().length, recvFrom);
    if (!ok) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Failed to dispatch " + msg + ": processor=" + _processor + " inboundEndpoint=" + _inboundEndpointProcessor);
        if (_config != null)
            _config.incrementProcessedMessages();
        _context.statManager().addRateData("tunnel.corruptMessage", 1, 1);
        return;
    }
    if ((_config != null) && (_config.getSendTo() != null)) {
        _config.incrementProcessedMessages();
        RouterInfo ri = _nextHopCache;
        if (ri == null)
            ri = _context.netDb().lookupRouterInfoLocally(_config.getSendTo());
        if (ri != null) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Send off to nextHop directly (" + _config.getSendTo() + " for " + msg);
            send(_config, msg, ri);
        // see comments below
        // if (_config != null)
        // incrementThroughput(_config.getReceiveFrom());
        } else {
            // It should be rare to forget the router info for the next peer
            if (_log.shouldLog(Log.WARN))
                _log.warn("Lookup the nextHop (" + _config.getSendTo() + " for " + msg);
            _context.netDb().lookupRouterInfo(_config.getSendTo(), new SendJob(_context, msg), new TimeoutJob(_context, msg), MAX_LOOKUP_TIME);
        }
    } else {
        _inboundEndpointProcessor.getConfig().incrementProcessedMessages();
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Receive fragment: on " + _config + ": " + msg);
        _handler.receiveTunnelMessage(msg.getData(), 0, msg.getData().length);
    }
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo)

Aggregations

RouterInfo (net.i2p.data.router.RouterInfo)95 Hash (net.i2p.data.Hash)45 ArrayList (java.util.ArrayList)18 RouterAddress (net.i2p.data.router.RouterAddress)17 DataFormatException (net.i2p.data.DataFormatException)11 IOException (java.io.IOException)10 RouterIdentity (net.i2p.data.router.RouterIdentity)10 DatabaseEntry (net.i2p.data.DatabaseEntry)9 OutNetMessage (net.i2p.router.OutNetMessage)9 File (java.io.File)8 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)8 Properties (java.util.Properties)7 LeaseSet (net.i2p.data.LeaseSet)6 BigInteger (java.math.BigInteger)5 Date (java.util.Date)5 SigType (net.i2p.crypto.SigType)5 TunnelId (net.i2p.data.TunnelId)5 TunnelInfo (net.i2p.router.TunnelInfo)5 FileOutputStream (java.io.FileOutputStream)4 HashMap (java.util.HashMap)4