Search in sources :

Example 21 with LeaseSet

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

the class TransientDataStore method put.

/**
 *  @param data must be validated before here
 *  @return success
 */
public boolean put(Hash key, DatabaseEntry data) {
    if (data == null)
        return false;
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Storing key " + key);
    DatabaseEntry old = _data.putIfAbsent(key, data);
    boolean rv = false;
    if (data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
        // Don't do this here so we don't reset it at router startup;
        // the StoreMessageJob calls this
        // _context.profileManager().heardAbout(key);
        RouterInfo ri = (RouterInfo) data;
        if (old != null) {
            RouterInfo ori = (RouterInfo) old;
            if (ri.getPublished() < ori.getPublished()) {
                if (_log.shouldLog(Log.INFO))
                    _log.info("Almost clobbered an old router! " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + ']');
            } else if (ri.getPublished() == ori.getPublished()) {
                if (_log.shouldLog(Log.INFO))
                    _log.info("Duplicate " + key);
            } else {
                if (_log.shouldLog(Log.INFO))
                    _log.info("Updated the old router for " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + ']');
                _data.put(key, data);
                rv = true;
            }
        } else {
            if (_log.shouldLog(Log.INFO))
                _log.info("New router for " + key + ": published on " + new Date(ri.getPublished()));
            rv = true;
        }
    } else if (data.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
        LeaseSet ls = (LeaseSet) data;
        if (old != null) {
            LeaseSet ols = (LeaseSet) old;
            if (ls.getEarliestLeaseDate() < ols.getEarliestLeaseDate()) {
                if (_log.shouldLog(Log.INFO))
                    _log.info("Almost clobbered an old leaseSet! " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
            } else if (ls.getEarliestLeaseDate() == ols.getEarliestLeaseDate()) {
                if (_log.shouldLog(Log.INFO))
                    _log.info("Duplicate " + key);
            } else {
                if (_log.shouldLog(Log.INFO)) {
                    _log.info("Updated old leaseSet " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
                }
                _data.put(key, data);
                rv = true;
            }
        } else {
            if (_log.shouldLog(Log.INFO)) {
                _log.info("New leaseset for " + key + ": expires " + new Date(ls.getEarliestLeaseDate()));
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
            }
            rv = true;
        }
    }
    return rv;
}
Also used : LeaseSet(net.i2p.data.LeaseSet) RouterInfo(net.i2p.data.router.RouterInfo) DatabaseEntry(net.i2p.data.DatabaseEntry) Date(java.util.Date)

Example 22 with LeaseSet

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

the class LocalClientMessageEventListener method startCreateSessionJob.

/**
 *  Immediately send a fake leaseset
 */
@Override
protected void startCreateSessionJob(SessionConfig config) {
    long exp = _context.clock().now() + 10 * 60 * 1000;
    LeaseSet ls = new LeaseSet();
    Lease lease = new Lease();
    lease.setGateway(Hash.FAKE_HASH);
    TunnelId id = new TunnelId(1);
    lease.setTunnelId(id);
    Date date = new Date(exp);
    lease.setEndDate(date);
    ls.addLease(lease);
    _runner.requestLeaseSet(config.getDestination().calculateHash(), ls, exp, null, null);
}
Also used : LeaseSet(net.i2p.data.LeaseSet) Lease(net.i2p.data.Lease) TunnelId(net.i2p.data.TunnelId) Date(java.util.Date)

Example 23 with LeaseSet

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

the class RequestVariableLeaseSetMessageHandler method handleMessage.

@Override
public void handleMessage(I2CPMessage message, I2PSessionImpl session) {
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Handle message " + message);
    RequestVariableLeaseSetMessage msg = (RequestVariableLeaseSetMessage) message;
    LeaseSet leaseSet = new LeaseSet();
    for (int i = 0; i < msg.getEndpoints(); i++) {
        leaseSet.addLease(msg.getEndpoint(i));
    }
    signLeaseSet(leaseSet, session);
}
Also used : LeaseSet(net.i2p.data.LeaseSet) RequestVariableLeaseSetMessage(net.i2p.data.i2cp.RequestVariableLeaseSetMessage)

Example 24 with LeaseSet

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

the class RequestLeaseSetJob method runJob.

public void runJob() {
    if (_runner.isDead())
        return;
    LeaseSet requested = _requestState.getRequested();
    long endTime = requested.getEarliestLeaseDate();
    // Add a small number of ms (0 to MAX_FUDGE) that increases as we approach the expire time.
    // Since the earliest date functions as a version number,
    // this will force the floodfill to flood each new version;
    // otherwise it won't if the earliest time hasn't changed.
    long fudge = MAX_FUDGE - ((endTime - getContext().clock().now()) / (10 * 60 * 1000 / MAX_FUDGE));
    // if (_log.shouldLog(Log.DEBUG))
    // _log.debug("Adding fudge " + fudge);
    endTime += fudge;
    SessionId id = _runner.getSessionId(requested.getDestination().calculateHash());
    if (id == null) {
        _runner.failLeaseRequest(_requestState);
        return;
    }
    I2CPMessage msg;
    if (getContext().getProperty(PROP_VARIABLE, DFLT_VARIABLE) && (_runner instanceof QueuedClientConnectionRunner || RequestVariableLeaseSetMessage.isSupported(_runner.getClientVersion()))) {
        // new style - leases will have individual expirations
        RequestVariableLeaseSetMessage rmsg = new RequestVariableLeaseSetMessage();
        rmsg.setSessionId(id);
        for (int i = 0; i < requested.getLeaseCount(); i++) {
            Lease lease = requested.getLease(i);
            if (lease.getEndDate().getTime() < endTime) {
                // don't modify old object, we don't know where it came from
                Lease nl = new Lease();
                nl.setGateway(lease.getGateway());
                nl.setTunnelId(lease.getTunnelId());
                nl.setEndDate(new Date(endTime));
                lease = nl;
            // if (_log.shouldLog(Log.INFO))
            // _log.info("Adjusted end date to " + endTime + " for " + lease);
            }
            rmsg.addEndpoint(lease);
        }
        msg = rmsg;
    } else {
        // old style - all leases will have same expiration
        RequestLeaseSetMessage rmsg = new RequestLeaseSetMessage();
        Date end = new Date(endTime);
        rmsg.setEndDate(end);
        rmsg.setSessionId(id);
        for (int i = 0; i < requested.getLeaseCount(); i++) {
            Lease lease = requested.getLease(i);
            rmsg.addEndpoint(lease.getGateway(), lease.getTunnelId());
        }
        msg = rmsg;
    }
    try {
        // _runner.setLeaseRequest(state);
        _runner.doSend(msg);
        getContext().jobQueue().addJob(new CheckLeaseRequestStatus());
    } catch (I2CPMessageException ime) {
        getContext().statManager().addRateData("client.requestLeaseSetDropped", 1);
        _log.error("Error sending I2CP message requesting the lease set", ime);
        _requestState.setIsSuccessful(false);
        if (_requestState.getOnFailed() != null)
            RequestLeaseSetJob.this.getContext().jobQueue().addJob(_requestState.getOnFailed());
        _runner.failLeaseRequest(_requestState);
    // Don't disconnect, the tunnel will retry
    // _runner.disconnectClient("I2CP error requesting leaseSet");
    }
}
Also used : LeaseSet(net.i2p.data.LeaseSet) I2CPMessageException(net.i2p.data.i2cp.I2CPMessageException) Lease(net.i2p.data.Lease) I2CPMessage(net.i2p.data.i2cp.I2CPMessage) RequestVariableLeaseSetMessage(net.i2p.data.i2cp.RequestVariableLeaseSetMessage) SessionId(net.i2p.data.i2cp.SessionId) Date(java.util.Date) RequestLeaseSetMessage(net.i2p.data.i2cp.RequestLeaseSetMessage)

Example 25 with LeaseSet

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

the class OutboundClientMessageOneShotJob method send.

/**
 * Send the message to the specified tunnel by creating a new garlic message containing
 * the (already created) payload clove as well as a new delivery status message.  This garlic
 * message is sent out one of our tunnels, destined for the lease (tunnel+router) specified, and the delivery
 * status message is targetting one of our free inbound tunnels as well.  We use a new
 * reply selector to keep an eye out for that delivery status message's token
 */
private void send() {
    synchronized (this) {
        if (_finished != Result.NONE) {
            if (_log.shouldLog(Log.WARN))
                _log.warn(OutboundClientMessageOneShotJob.this.getJobId() + ": SEND-AFTER-" + _finished);
            return;
        }
    }
    long now = getContext().clock().now();
    if (now >= _overallExpiration) {
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED);
        return;
    }
    _outTunnel = selectOutboundTunnel(_to);
    if (_outTunnel == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn(getJobId() + ": Could not find any outbound tunnels to send the payload through... this might take a while");
        getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start);
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_TUNNELS);
        return;
    }
    // boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5;
    // what's the point of 5% random? possible improvements or replacements:
    // DONE (getNextLease() is called before this): wantACK if we changed their inbound lease (getNextLease() sets _wantACK)
    // DONE (selectOutboundTunnel() moved above here): wantACK if we changed our outbound tunnel (selectOutboundTunnel() sets _wantACK)
    // DONE (added new cache): wantACK if we haven't in last 1m (requires a new static cache probably)
    Long lastReplyRequestSent = _cache.lastReplyRequestCache.get(_hashPair);
    boolean shouldRequestReply = lastReplyRequestSent == null || lastReplyRequestSent.longValue() < now - REPLY_REQUEST_INTERVAL;
    int sendFlags = _clientMessage.getFlags();
    // Per-message flag > 0 overrides per-session option
    int tagsRequired = SendMessageOptions.getTagThreshold(sendFlags);
    boolean wantACK = _wantACK || shouldRequestReply || GarlicMessageBuilder.needsTags(getContext(), _leaseSet.getEncryptionKey(), _from.calculateHash(), tagsRequired);
    LeaseSet replyLeaseSet;
    // Per-message flag == false overrides session option which is default true
    String allow = _clientMessage.getSenderConfig().getOptions().getProperty(BUNDLE_REPLY_LEASESET);
    boolean allowLeaseBundle = SendMessageOptions.getSendLeaseSet(sendFlags) && (allow == null || Boolean.parseBoolean(allow));
    if (allowLeaseBundle) {
        // If we want an ack, bundle a leaseSet...
        // replyLeaseSet = getReplyLeaseSet(wantACK);
        // Only when necessary. We don't need to force.
        // ACKs find their own way back, they don't need a leaseset.
        replyLeaseSet = getReplyLeaseSet(false);
        // ... and vice versa  (so we know he got it)
        if (replyLeaseSet != null)
            wantACK = true;
    } else {
        replyLeaseSet = null;
    }
    long token;
    if (wantACK) {
        _cache.lastReplyRequestCache.put(_hashPair, Long.valueOf(now));
        token = getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);
        _inTunnel = selectInboundTunnel();
    } else {
        token = -1;
    }
    PayloadGarlicConfig clove = buildClove();
    if (clove == null) {
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION);
        return;
    }
    // if (_log.shouldLog(Log.DEBUG))
    // _log.debug(getJobId() + ": Clove built to " + _toString);
    PublicKey key = _leaseSet.getEncryptionKey();
    SessionKey sessKey = new SessionKey();
    Set<SessionTag> tags = new HashSet<SessionTag>();
    // Per-message flag > 0 overrides per-session option
    int tagsToSend = SendMessageOptions.getTagsToSend(sendFlags);
    GarlicMessage msg = OutboundClientMessageJobHelper.createGarlicMessage(getContext(), token, _overallExpiration, key, clove, _from.calculateHash(), _to, _inTunnel, tagsToSend, tagsRequired, sessKey, tags, wantACK, replyLeaseSet);
    if (msg == null) {
        // we dont receive the reply? hmm...)
        if (_log.shouldLog(Log.WARN))
            _log.warn(getJobId() + ": Unable to create the garlic message (no tunnels left or too lagged) to " + _toString);
        getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start);
        dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_TUNNELS);
        return;
    }
    // if (_log.shouldLog(Log.DEBUG))
    // _log.debug(getJobId() + ": send() - token expected " + token + " to " + _toString);
    SendSuccessJob onReply = null;
    SendTimeoutJob onFail = null;
    ReplySelector selector = null;
    if (wantACK) {
        TagSetHandle tsh = null;
        if (!tags.isEmpty()) {
            SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
            if (skm != null)
                tsh = skm.tagsDelivered(_leaseSet.getEncryptionKey(), sessKey, tags);
        }
        onReply = new SendSuccessJob(getContext(), sessKey, tsh);
        onFail = new SendTimeoutJob(getContext(), sessKey, tsh);
        long expiration = Math.max(_overallExpiration, _start + REPLY_TIMEOUT_MS_MIN);
        selector = new ReplySelector(token, expiration);
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug(getJobId() + ": Sending msg out " + _outTunnel.getSendTunnelId(0) + " to " + _toString + " at " + _lease.getTunnelId() + " on " + _lease.getGateway());
    DispatchJob dispatchJob = new DispatchJob(getContext(), msg, selector, onReply, onFail);
    // if (false) // dispatch may take 100+ms, so toss it in its own job
    // getContext().jobQueue().addJob(dispatchJob);
    // else
    dispatchJob.runJob();
    getContext().statManager().addRateData("client.dispatchPrepareTime", now - _start);
    if (!wantACK)
        getContext().statManager().addRateData("client.dispatchNoACK", 1);
}
Also used : PublicKey(net.i2p.data.PublicKey) SessionKeyManager(net.i2p.crypto.SessionKeyManager) TagSetHandle(net.i2p.crypto.TagSetHandle) LeaseSet(net.i2p.data.LeaseSet) SessionKey(net.i2p.data.SessionKey) GarlicMessage(net.i2p.data.i2np.GarlicMessage) SessionTag(net.i2p.data.SessionTag) HashSet(java.util.HashSet)

Aggregations

LeaseSet (net.i2p.data.LeaseSet)29 Date (java.util.Date)7 Hash (net.i2p.data.Hash)7 Lease (net.i2p.data.Lease)6 RouterInfo (net.i2p.data.router.RouterInfo)6 Destination (net.i2p.data.Destination)5 DatabaseEntry (net.i2p.data.DatabaseEntry)4 DataFormatException (net.i2p.data.DataFormatException)3 TunnelId (net.i2p.data.TunnelId)3 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 I2CPMessageException (net.i2p.data.i2cp.I2CPMessageException)2 RequestLeaseSetMessage (net.i2p.data.i2cp.RequestLeaseSetMessage)2 RequestVariableLeaseSetMessage (net.i2p.data.i2cp.RequestVariableLeaseSetMessage)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 EOFException (java.io.EOFException)1 BigInteger (java.math.BigInteger)1 DecimalFormat (java.text.DecimalFormat)1 Collection (java.util.Collection)1