Search in sources :

Example 1 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class TunnelRenderer method renderPool.

private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException {
    List<TunnelInfo> tunnels = null;
    if (in == null)
        tunnels = new ArrayList<TunnelInfo>();
    else
        tunnels = in.listTunnels();
    if (outPool != null)
        tunnels.addAll(outPool.listTunnels());
    long processedIn = (in != null ? in.getLifetimeProcessed() : 0);
    long processedOut = (outPool != null ? outPool.getLifetimeProcessed() : 0);
    int live = 0;
    int maxLength = 1;
    for (int i = 0; i < tunnels.size(); i++) {
        TunnelInfo info = tunnels.get(i);
        int length = info.getLength();
        if (length > maxLength)
            maxLength = length;
    }
    out.write("<table class=\"tunneldisplay tunnels_client\"><tr><th title=\"" + _t("Inbound or outbound?") + ("\">") + _t("In/Out") + "</th><th>" + _t("Expiry") + "</th><th>" + _t("Usage") + "</th><th>" + _t("Gateway") + "</th>");
    if (maxLength > 3) {
        out.write("<th align=\"center\" colspan=\"" + (maxLength - 2));
        out.write("\">" + _t("Participants") + "</th>");
    } else if (maxLength == 3) {
        out.write("<th>" + _t("Participant") + "</th>");
    }
    if (maxLength > 1) {
        out.write("<th>" + _t("Endpoint") + "</th>");
    }
    out.write("</tr>\n");
    for (int i = 0; i < tunnels.size(); i++) {
        TunnelInfo info = tunnels.get(i);
        long timeLeft = info.getExpiration() - _context.clock().now();
        if (timeLeft <= 0)
            // don't display tunnels in their grace period
            continue;
        live++;
        boolean isInbound = info.isInbound();
        if (isInbound)
            out.write("<tr><td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"" + _t("Inbound") + "\"></td>");
        else
            out.write("<tr><td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"" + _t("Outbound") + "\"></td>");
        out.write("<td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>\n");
        int count = info.getProcessedMessagesCount() * 1024 / 1000;
        out.write("<td class=\"cells\" align=\"center\">" + count + " KB</td>\n");
        int length = info.getLength();
        for (int j = 0; j < length; j++) {
            Hash peer = info.getPeer(j);
            TunnelId id = (isInbound ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
            if (_context.routerHash().equals(peer)) {
                if (length < maxLength && length == 1 && isInbound) {
                    // pad before inbound zero hop
                    for (int k = 1; k < maxLength; k++) {
                        out.write("<td class=\"cells\" align=\"center\">&nbsp;</td>");
                    }
                }
                // Add empty content placeholders to force alignment.
                out.write(" <td class=\"cells\" align=\"center\"><span class=\"tunnel_peer tunnel_local\" title=\"" + _t("Locally hosted tunnel") + "\">" + _t("Local") + "</span>&nbsp;<span class=\"tunnel_id\" title=\"" + _t("Tunnel identity") + "\">" + (id == null ? "" : "" + id) + "</span><b class=\"tunnel_cap\" title=\"" + _t("Bandwidth tier") + "\"></b></td>");
            } else {
                String cap = getCapacity(peer);
                out.write(" <td class=\"cells\" align=\"center\"><span class=\"tunnel_peer\">" + netDbLink(peer) + "</span>&nbsp;<span class=\"nowrap\"><span class=\"tunnel_id\" title=\"" + _t("Tunnel identity") + "\">" + (id == null ? "" : " " + id) + "</span><b class=\"tunnel_cap\" title=\"" + _t("Bandwidth tier") + "\">" + cap + "</b></span></td>");
            }
            if (length < maxLength && ((length == 1 && !isInbound) || j == length - 2)) {
                // pad out outbound zero hop; non-zero-hop pads in middle
                for (int k = length; k < maxLength; k++) {
                    out.write("<td class=\"cells\" align=\"center\">&nbsp;</td>");
                }
            }
        }
        out.write("</tr>\n");
        if (info.isInbound())
            processedIn += count;
        else
            processedOut += count;
    }
    out.write("</table>\n");
    if (in != null) {
        // PooledTunnelCreatorConfig
        List<?> pending = in.listPending();
        if (!pending.isEmpty()) {
            out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("inbound") + "</b></center></div>\n");
            live += pending.size();
        }
    }
    if (outPool != null) {
        // PooledTunnelCreatorConfig
        List<?> pending = outPool.listPending();
        if (!pending.isEmpty()) {
            out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("outbound") + "</b></center></div>\n");
            live += pending.size();
        }
    }
    if (live <= 0)
        out.write("<div class=\"statusnotes\"><center><b>" + _t("No tunnels; waiting for the grace period to end.") + "</b></center></div>\n");
    out.write("<div class=\"statusnotes\"><center><b>" + _t("Lifetime bandwidth usage") + ":&nbsp;&nbsp;" + DataHelper.formatSize2Decimal(processedIn * 1024) + "B " + _t("in") + ", " + DataHelper.formatSize2Decimal(processedOut * 1024) + "B " + _t("out") + "</b></center></div>");
}
Also used : ArrayList(java.util.ArrayList) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 2 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class RequestLeaseSetMessage method doReadMessage.

@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
    try {
        _sessionId = new SessionId();
        _sessionId.readBytes(in);
        int numTunnels = (int) DataHelper.readLong(in, 1);
        _endpoints.clear();
        for (int i = 0; i < numTunnels; i++) {
            // Hash router = new Hash();
            // router.readBytes(in);
            Hash router = Hash.create(in);
            TunnelId tunnel = new TunnelId();
            tunnel.readBytes(in);
            _endpoints.add(new TunnelEndpoint(router, tunnel));
        }
        _end = DataHelper.readDate(in);
    } catch (DataFormatException dfe) {
        throw new I2CPMessageException("Unable to load the message data", dfe);
    }
}
Also used : DataFormatException(net.i2p.data.DataFormatException) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 3 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class DatabaseStoreMessage method readMessage.

public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
    if (type != MESSAGE_TYPE)
        throw new I2NPMessageException("Message type is incorrect for this message");
    int curIndex = offset;
    _key = Hash.create(data, curIndex);
    // Fast-fail here to save resources.
    if (_key.equals(Hash.FAKE_HASH)) {
        // createRateStat in KNDF
        _context.statManager().addRateData("netDb.DSMAllZeros", 1);
        throw new I2NPMessageException("DSM all zeros");
    }
    curIndex += Hash.HASH_LENGTH;
    // as of 0.9.18, ignore other 7 bits of the type byte, in preparation for future options
    int dbType = data[curIndex] & 0x01;
    curIndex++;
    _replyToken = DataHelper.fromLong(data, curIndex, 4);
    curIndex += 4;
    if (_replyToken > 0) {
        long tunnel = DataHelper.fromLong(data, curIndex, 4);
        if (tunnel > 0)
            _replyTunnel = new TunnelId(tunnel);
        curIndex += 4;
        _replyGateway = Hash.create(data, curIndex);
        curIndex += Hash.HASH_LENGTH;
    } else {
        _replyTunnel = null;
        _replyGateway = null;
    }
    if (dbType == DatabaseEntry.KEY_TYPE_LEASESET) {
        _dbEntry = new LeaseSet();
        try {
            _dbEntry.readBytes(new ByteArrayInputStream(data, curIndex, data.length - curIndex));
        } catch (DataFormatException dfe) {
            throw new I2NPMessageException("Error reading the leaseSet", dfe);
        } catch (IOException ioe) {
            throw new I2NPMessageException("Error reading the leaseSet", ioe);
        }
    } else {
        // dbType == DatabaseEntry.KEY_TYPE_ROUTERINFO
        _dbEntry = new RouterInfo();
        int compressedSize = (int) DataHelper.fromLong(data, curIndex, 2);
        curIndex += 2;
        if (compressedSize <= 0 || curIndex + compressedSize > data.length || curIndex + compressedSize > dataSize + offset)
            throw new I2NPMessageException("Compressed RI length: " + compressedSize + " but remaining bytes: " + Math.min(data.length - curIndex, dataSize + offset - curIndex));
        try {
            // TODO we could delay decompression, just copy to a new byte array and store in _byteCache
            // May not be necessary since the IBGW now uses UnknownI2NPMessage.
            // DSMs at the OBEP are generally garlic wrapped, so the OBEP won't see it.
            // If we do delay it, getEntry() will have to check if _dbEntry is null and _byteCache
            // is non-null, and then decompress.
            byte[] decompressed = DataHelper.decompress(data, curIndex, compressedSize);
            _dbEntry.readBytes(new ByteArrayInputStream(decompressed));
        } catch (DataFormatException dfe) {
            throw new I2NPMessageException("Error reading the routerInfo", dfe);
        } catch (IOException ioe) {
            throw new I2NPMessageException("Corrupt compressed routerInfo size = " + compressedSize, ioe);
        }
    }
// if (!key.equals(_dbEntry.getHash()))
// throw new I2NPMessageException("Hash mismatch in DSM");
}
Also used : LeaseSet(net.i2p.data.LeaseSet) DataFormatException(net.i2p.data.DataFormatException) ByteArrayInputStream(java.io.ByteArrayInputStream) RouterInfo(net.i2p.data.router.RouterInfo) IOException(java.io.IOException) TunnelId(net.i2p.data.TunnelId)

Example 4 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class DeliveryInstructionsTest method createDataStructure.

public DataStructure createDataStructure() throws DataFormatException {
    DeliveryInstructions instructions = new DeliveryInstructions();
    // instructions.setDelayRequested(true);
    // instructions.setDelaySeconds(42);
    instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
    // encryption key read/write disabled
    // instructions.setEncrypted(true);
    // SessionKey key = new SessionKey();
    // byte keyData[] = new byte[SessionKey.KEYSIZE_BYTES];
    // for (int i = 0; i < keyData.length; i++)
    // keyData[i] = (byte)i;
    // key.setData(keyData);
    // instructions.setEncryptionKey(key);
    Hash hash = new Hash();
    byte[] hashData = new byte[32];
    for (int i = 0; i < hashData.length; i++) hashData[i] = (byte) (i % 32);
    hash.setData(hashData);
    instructions.setRouter(hash);
    TunnelId id = new TunnelId();
    id.setTunnelId(666);
    instructions.setTunnelId(id);
    return instructions;
}
Also used : Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 5 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class BuildHandler method handleReq.

/**
 * If we are dropping lots of requests before even trying to handle them,
 * I suppose you could call us "overloaded"
 */
/**
 ** unused, see handleReq() below
 *    private final static int MAX_PROACTIVE_DROPS = 240;
 *
 *    private int countProactiveDrops() {
 *        int dropped = 0;
 *        dropped += countEvents("tunnel.dropLoadProactive", 60*1000);
 *        dropped += countEvents("tunnel.dropLoad", 60*1000);
 *        dropped += countEvents("tunnel.dropLoadBacklog", 60*1000);
 *        dropped += countEvents("tunnel.dropLoadDelay", 60*1000);
 *        return dropped;
 *    }
 *
 *    private int countEvents(String stat, long period) {
 *        RateStat rs = _context.statManager().getRate(stat);
 *        if (rs != null) {
 *            Rate r = rs.getRate(period);
 *            if (r != null)
 *                return (int)r.getCurrentEventCount();
 *        }
 *        return 0;
 *    }
 ***
 */
/**
 *  Actually process the request and send the reply.
 *
 *  Todo: Replies are not subject to RED for bandwidth reasons,
 *  and the bandwidth is not credited to any tunnel.
 *  If we did credit the reply to the tunnel, it would
 *  prevent the classification of the tunnel as 'inactive' on tunnels.jsp.
 */
private void handleReq(RouterInfo nextPeerInfo, BuildMessageState state, BuildRequestRecord req, Hash nextPeer) {
    long ourId = req.readReceiveTunnelId();
    long nextId = req.readNextTunnelId();
    boolean isInGW = req.readIsInboundGateway();
    boolean isOutEnd = req.readIsOutboundEndpoint();
    Hash from = state.fromHash;
    if (from == null && state.from != null)
        from = state.from.calculateHash();
    if (isInGW && isOutEnd) {
        _context.statManager().addRateData("tunnel.rejectHostile", 1);
        _log.error("Dropping build request, IBGW+OBEP: " + req);
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        return;
    }
    if (ourId <= 0 || ourId > TunnelId.MAX_ID_VALUE || nextId <= 0 || nextId > TunnelId.MAX_ID_VALUE) {
        _context.statManager().addRateData("tunnel.rejectHostile", 1);
        if (_log.shouldWarn())
            _log.warn("Dropping build request, bad tunnel ID: " + req);
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        return;
    }
    // Loop checks
    if ((!isOutEnd) && _context.routerHash().equals(nextPeer)) {
        _context.statManager().addRateData("tunnel.rejectHostile", 1);
        // old i2pd
        if (_log.shouldWarn())
            _log.warn("Dropping build request, we are the next hop: " + req);
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        return;
    }
    if (!isInGW) {
        // but if not, something is seriously wrong here.
        if (from == null || _context.routerHash().equals(from)) {
            _context.statManager().addRateData("tunnel.rejectHostile", 1);
            if (_log.shouldWarn())
                _log.warn("Dropping build request, we are the previous hop: " + req);
            return;
        }
    }
    if ((!isOutEnd) && (!isInGW)) {
        // A-B-C-A is not preventable
        if (nextPeer.equals(from)) {
            // i2pd does this
            _context.statManager().addRateData("tunnel.rejectHostile", 1);
            if (_log.shouldLog(Log.WARN))
                _log.warn("Dropping build request with the same previous and next hop: " + req);
            _context.commSystem().mayDisconnect(from);
            return;
        }
    }
    // time is in hours, rounded down.
    // tunnel-alt-creation.html specifies that this is enforced +/- 1 hour but it was not.
    // As of 0.9.16, allow + 5 minutes to - 65 minutes.
    long time = req.readRequestTime();
    long now = (_context.clock().now() / (60l * 60l * 1000l)) * (60 * 60 * 1000);
    long timeDiff = now - time;
    if (timeDiff > MAX_REQUEST_AGE) {
        _context.statManager().addRateData("tunnel.rejectTooOld", 1);
        if (_log.shouldLog(Log.WARN))
            _log.warn("Dropping build request too old... replay attack? " + DataHelper.formatDuration(timeDiff) + ": " + req);
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        return;
    }
    if (timeDiff < 0 - MAX_REQUEST_FUTURE) {
        _context.statManager().addRateData("tunnel.rejectFuture", 1);
        if (_log.shouldLog(Log.WARN))
            _log.warn("Dropping build request too far in future " + DataHelper.formatDuration(0 - timeDiff) + ": " + req);
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        return;
    }
    int response;
    if (_context.router().isHidden()) {
        _context.throttle().setTunnelStatus(_x("Rejecting tunnels: Hidden mode"));
        response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
    } else {
        response = _context.throttle().acceptTunnelRequest();
    }
    // This only checked OUR tunnels, so the log message was wrong.
    // Now checked by TunnelDispatcher.joinXXX()
    // and returned as success value, checked below.
    // if (_context.tunnelManager().getTunnelInfo(new TunnelId(ourId)) != null) {
    // if (_log.shouldLog(Log.ERROR))
    // _log.error("Already participating in a tunnel with the given Id (" + ourId + "), so gotta reject");
    // if (response == 0)
    // response = TunnelHistory.TUNNEL_REJECT_PROBABALISTIC_REJECT;
    // }
    // if ( (response == 0) && (_context.random().nextInt(50) <= 1) )
    // response = TunnelHistory.TUNNEL_REJECT_PROBABALISTIC_REJECT;
    long recvDelay = _context.clock().now() - state.recvTime;
    if (response == 0) {
        // unused
        // int proactiveDrops = countProactiveDrops();
        float pDrop = ((float) recvDelay) / (float) (BuildRequestor.REQUEST_TIMEOUT * 3);
        pDrop = (float) Math.pow(pDrop, 16);
        if (_context.random().nextFloat() < pDrop) {
            // || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) {
            _context.statManager().addRateData("tunnel.rejectOverloaded", recvDelay);
            _context.throttle().setTunnelStatus(_x("Rejecting tunnels: Request overload"));
            // if (true || (proactiveDrops < MAX_PROACTIVE_DROPS*2))
            response = TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD;
        // else
        // response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
        } else {
            _context.statManager().addRateData("tunnel.acceptLoad", recvDelay);
        }
    }
    /*
         * Being a IBGW or OBEP generally leads to more connections, so if we are
         * approaching our connection limit (i.e. !haveCapacity()),
         * reject this request.
         *
         * Don't do this for class N or O, under the assumption that they are already talking
         * to most of the routers, so there's no reason to reject. This may drive them
         * to their conn. limits, but it's hopefully a temporary solution to the
         * tunnel build congestion. As the net grows this will have to be revisited.
         */
    RouterInfo ri = _context.router().getRouterInfo();
    if (response == 0) {
        if (ri == null) {
            // ?? We should always have a RI
            response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
        } else {
            char bw = ri.getBandwidthTier().charAt(0);
            if (bw != 'O' && bw != 'N' && bw != 'P' && bw != 'X' && ((isInGW && !_context.commSystem().haveInboundCapacity(87)) || (isOutEnd && !_context.commSystem().haveOutboundCapacity(87)))) {
                _context.statManager().addRateData("tunnel.rejectConnLimits", 1);
                _context.throttle().setTunnelStatus(_x("Rejecting tunnels: Connection limit"));
                response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
            }
        }
    }
    // We may need another counter above for requests.
    if (response == 0 && !isInGW) {
        if (from != null && _throttler.shouldThrottle(from)) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Rejecting tunnel (hop throttle), previous hop: " + from + ": " + req);
            // no setTunnelStatus() indication
            _context.statManager().addRateData("tunnel.rejectHopThrottle", 1);
            response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
        }
    }
    if (response == 0 && (!isOutEnd) && _throttler.shouldThrottle(nextPeer)) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Rejecting tunnel (hop throttle), next hop: " + req);
        _context.statManager().addRateData("tunnel.rejectHopThrottle", 1);
        // no setTunnelStatus() indication
        response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
    }
    HopConfig cfg = null;
    if (response == 0) {
        cfg = new HopConfig();
        cfg.setCreation(_context.clock().now());
        cfg.setExpiration(_context.clock().now() + 10 * 60 * 1000);
        cfg.setIVKey(req.readIVKey());
        cfg.setLayerKey(req.readLayerKey());
        if (isInGW) {
        // default
        // cfg.setReceiveFrom(null);
        } else {
            if (from != null) {
                cfg.setReceiveFrom(from);
            } else {
                // b0rk
                return;
            }
        }
        cfg.setReceiveTunnelId(DataHelper.toLong(4, ourId));
        if (isOutEnd) {
        // default
        // cfg.setSendTo(null);
        // cfg.setSendTunnelId(null);
        } else {
            cfg.setSendTo(nextPeer);
            cfg.setSendTunnelId(DataHelper.toLong(4, nextId));
        }
        // now "actually" join
        boolean success;
        if (isOutEnd)
            success = _context.tunnelDispatcher().joinOutboundEndpoint(cfg);
        else if (isInGW)
            success = _context.tunnelDispatcher().joinInboundGateway(cfg);
        else
            success = _context.tunnelDispatcher().joinParticipant(cfg);
        if (success) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Joining: " + req);
        } else {
            // Dup Tunnel ID. This can definitely happen (birthday paradox).
            // Probability in 11 minutes (per hop type):
            // 0.1% for 2900 tunnels; 1% for 9300 tunnels
            response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
            _context.statManager().addRateData("tunnel.rejectDupID", 1);
            if (_log.shouldLog(Log.WARN))
                _log.warn("DUP ID failure: " + req);
        }
    }
    if (response != 0) {
        _context.statManager().addRateData("tunnel.reject." + response, 1);
        _context.messageHistory().tunnelRejected(from, new TunnelId(ourId), nextPeer, // (isOutEnd ? "outbound endpoint" : isInGW ? "inbound gw" : "participant"));
        Integer.toString(response));
        if (from != null)
            _context.commSystem().mayDisconnect(from);
        // 81% = between 75% control measures in Transports and 87% rejection above
        if ((!_context.routerHash().equals(nextPeer)) && (!_context.commSystem().haveOutboundCapacity(81)) && (!_context.commSystem().isEstablished(nextPeer))) {
            _context.statManager().addRateData("tunnel.dropConnLimits", 1);
            if (_log.shouldLog(Log.WARN))
                _log.warn("Not sending rejection due to conn limits: " + req);
            return;
        }
    } else if (isInGW && from != null) {
        // we're the start of the tunnel, no use staying connected
        _context.commSystem().mayDisconnect(from);
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Responding to " + state.msg.getUniqueId() + " after " + recvDelay + " with " + response + " from " + (from != null ? from : "tunnel") + ": " + req);
    EncryptedBuildRecord reply = BuildResponseRecord.create(_context, response, req.readReplyKey(), req.readReplyIV(), state.msg.getUniqueId());
    int records = state.msg.getRecordCount();
    int ourSlot = -1;
    for (int j = 0; j < records; j++) {
        if (state.msg.getRecord(j) == null) {
            ourSlot = j;
            state.msg.setRecord(j, reply);
            // + ": " + Base64.encode(reply));
            break;
        }
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Read slot " + ourSlot + " containing: " + req + " accepted? " + response + " recvDelay " + recvDelay + " replyMessage " + req.readReplyMessageId());
    // now actually send the response
    long expires = _context.clock().now() + NEXT_HOP_SEND_TIMEOUT;
    if (!isOutEnd) {
        state.msg.setUniqueId(req.readReplyMessageId());
        state.msg.setMessageExpiration(expires);
        OutNetMessage msg = new OutNetMessage(_context, state.msg, expires, PRIORITY, nextPeerInfo);
        if (response == 0)
            msg.setOnFailedSendJob(new TunnelBuildNextHopFailJob(_context, cfg));
        _context.outNetMessagePool().add(msg);
    } else {
        // We are the OBEP.
        // send it to the reply tunnel on the reply peer within a new TunnelBuildReplyMessage
        // (enough layers jrandom?)
        TunnelBuildReplyMessage replyMsg;
        if (records == TunnelBuildMessage.MAX_RECORD_COUNT)
            replyMsg = new TunnelBuildReplyMessage(_context);
        else
            replyMsg = new VariableTunnelBuildReplyMessage(_context, records);
        for (int i = 0; i < records; i++) replyMsg.setRecord(i, state.msg.getRecord(i));
        replyMsg.setUniqueId(req.readReplyMessageId());
        replyMsg.setMessageExpiration(expires);
        TunnelGatewayMessage m = new TunnelGatewayMessage(_context);
        m.setMessage(replyMsg);
        m.setMessageExpiration(expires);
        m.setTunnelId(new TunnelId(nextId));
        if (_context.routerHash().equals(nextPeer)) {
            // ok, we are the gateway, so inject it
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("We are the reply gateway for " + nextId + " when replying to replyMessage " + req);
            _context.tunnelDispatcher().dispatch(m);
        } else {
            // ok, the gateway is some other peer, shove 'er across
            OutNetMessage outMsg = new OutNetMessage(_context, m, expires, PRIORITY, nextPeerInfo);
            if (response == 0)
                outMsg.setOnFailedSendJob(new TunnelBuildNextHopFailJob(_context, cfg));
            _context.outNetMessagePool().add(outMsg);
        }
    }
}
Also used : EncryptedBuildRecord(net.i2p.data.i2np.EncryptedBuildRecord) TunnelGatewayMessage(net.i2p.data.i2np.TunnelGatewayMessage) RouterInfo(net.i2p.data.router.RouterInfo) HopConfig(net.i2p.router.tunnel.HopConfig) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId) VariableTunnelBuildReplyMessage(net.i2p.data.i2np.VariableTunnelBuildReplyMessage) TunnelBuildReplyMessage(net.i2p.data.i2np.TunnelBuildReplyMessage) VariableTunnelBuildReplyMessage(net.i2p.data.i2np.VariableTunnelBuildReplyMessage) OutNetMessage(net.i2p.router.OutNetMessage)

Aggregations

TunnelId (net.i2p.data.TunnelId)33 Hash (net.i2p.data.Hash)20 TunnelInfo (net.i2p.router.TunnelInfo)8 RouterInfo (net.i2p.data.router.RouterInfo)5 DataFormatException (net.i2p.data.DataFormatException)3 LeaseSet (net.i2p.data.LeaseSet)3 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)3 I2NPMessage (net.i2p.data.i2np.I2NPMessage)3 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 Lease (net.i2p.data.Lease)2 DataMessage (net.i2p.data.i2np.DataMessage)2 DeliveryStatusMessage (net.i2p.data.i2np.DeliveryStatusMessage)2 TunnelGatewayMessage (net.i2p.data.i2np.TunnelGatewayMessage)2 Job (net.i2p.router.Job)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 IOException (java.io.IOException)1 TreeSet (java.util.TreeSet)1 SessionKey (net.i2p.data.SessionKey)1