Changeset 0a73303


Ignore:
Timestamp:
May 10, 2019 5:02:30 PM (11 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
c1adcfc
Parents:
d8980d1
Message:

NetDB: Store Meta LS2 to floodfills (proposal #123)

Location:
router/java/src/net/i2p/router
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/ClientManagerFacade.java

    rd8980d1 r0a73303  
    1414import java.util.Set;
    1515
     16import net.i2p.client.I2PSessionException;
    1617import net.i2p.crypto.SessionKeyManager;
    1718import net.i2p.data.Destination;
     
    105106    /** @since 0.8.8 */
    106107    public abstract void shutdown(String msg);
     108
     109    /**
     110     *  Declare that we're going to publish a meta LS for this destination.
     111     *  Must be called before publishing the leaseset.
     112     *
     113     *  @throws I2PSessionException on duplicate dest
     114     *  @since 0.9.41
     115     */
     116    public void registerMetaDest(Destination dest) throws I2PSessionException {}
     117
     118    /**
     119     *  Declare that we're no longer going to publish a meta LS for this destination.
     120     *
     121     *  @since 0.9.41
     122     */
     123    public void unregisterMetaDest(Destination dest) {}
    107124}
  • router/java/src/net/i2p/router/client/ClientManager.java

    rd8980d1 r0a73303  
    4444import net.i2p.router.JobImpl;
    4545import net.i2p.router.RouterContext;
     46import net.i2p.util.ConcurrentHashSet;
    4647import net.i2p.util.I2PThread;
    4748import net.i2p.util.Log;
     
    6869    private final Set<ClientConnectionRunner> _pendingRunners;
    6970    private final Set<SessionId> _runnerSessionIds;
     71    private final Set<Destination> _metaDests;
     72    private final Set<Hash> _metaHashes;
    7073    protected final RouterContext _ctx;
    7174    protected final int _port;
     
    101104        //                                      "ClientMessages",
    102105        //                                      new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
    103         _listeners = new ArrayList<ClientListenerRunner>();
    104         _runners = new ConcurrentHashMap<Destination, ClientConnectionRunner>();
    105         _runnersByHash = new ConcurrentHashMap<Hash, ClientConnectionRunner>();
    106         _pendingRunners = new HashSet<ClientConnectionRunner>();
    107         _runnerSessionIds = new HashSet<SessionId>();
     106        _listeners = new ArrayList<ClientListenerRunner>(4);
     107        _runners = new ConcurrentHashMap<Destination, ClientConnectionRunner>(4);
     108        _runnersByHash = new ConcurrentHashMap<Hash, ClientConnectionRunner>(4);
     109        _pendingRunners = new HashSet<ClientConnectionRunner>(4);
     110        _runnerSessionIds = new HashSet<SessionId>(4);
     111        _metaDests = new ConcurrentHashSet<Destination>(4);
     112        _metaHashes = new ConcurrentHashSet<Hash>(4);
    108113        _port = port;
    109114        _clientTimestamper = new ClientTimestamper();
     
    369374
    370375    /**
     376     *  Declare that we're going to publish a meta LS for this destination.
     377     *  Must be called before publishing the leaseset.
     378     *
     379     *  @throws I2PSessionException on duplicate dest
     380     *  @since 0.9.41
     381     */
     382    public void registerMetaDest(Destination dest) throws I2PSessionException {
     383        synchronized (_runners) {
     384            if (_runners.containsKey(dest) || _metaDests.contains(dest)) {
     385                String msg = "Client attempted to register duplicate destination " + dest.toBase32();
     386                _log.error(msg);
     387                throw new I2PSessionException(msg);
     388            }
     389            _metaDests.add(dest);
     390            _metaHashes.add(dest.calculateHash());
     391        }
     392    }
     393
     394    /**
     395     *  Declare that we're no longer going to publish a meta LS for this destination.
     396     *
     397     *  @since 0.9.41
     398     */
     399    public void unregisterMetaDest(Destination dest) {
     400        synchronized (_runners) {
     401            _metaDests.remove(dest);
     402            _metaHashes.remove(dest.calculateHash());
     403        }
     404    }
     405
     406    /**
    371407     *  Generate a new random, unused sessionId. Caller must synch on _runners.
    372408     *  @return null on failure
     
    516552   
    517553    /**
    518      *  Unsynchronized
     554     *  Unsynchronized.
     555     *  DOES contain meta destinations.
    519556     */
    520557    public boolean isLocal(Destination dest) {
    521         return _runners.containsKey(dest);
    522     }
    523 
    524     /**
    525      *  Unsynchronized
     558        return _runners.containsKey(dest) || _metaDests.contains(dest);
     559    }
     560
     561    /**
     562     *  Unsynchronized.
     563     *  DOES contain meta destinations.
    526564     */
    527565    public boolean isLocal(Hash destHash) {
    528566        if (destHash == null) return false;
    529         return _runnersByHash.containsKey(destHash);
     567        return _runnersByHash.containsKey(destHash) || _metaHashes.contains(destHash);
    530568    }
    531569   
     
    543581
    544582    /**
    545      *  Unsynchronized
     583     *  Unsynchronized.
     584     *  Does NOT contain meta destinations.
    546585     */
    547586    public Set<Destination> listClients() {
  • router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java

    rd8980d1 r0a73303  
    267267        throw new I2PSessionException("No manager yet");
    268268    }
     269
     270    /**
     271     *  Declare that we're going to publish a meta LS for this destination.
     272     *  Must be called before publishing the leaseset.
     273     *
     274     *  @throws I2PSessionException on duplicate dest
     275     *  @since 0.9.41
     276     */
     277    @Override
     278    public void registerMetaDest(Destination dest) throws I2PSessionException {
     279        if (_manager != null)
     280            _manager.registerMetaDest(dest);
     281    }
     282
     283    /**
     284     *  Declare that we're no longer going to publish a meta LS for this destination.
     285     *
     286     *  @since 0.9.41
     287     */
     288    @Override
     289    public void unregisterMetaDest(Destination dest) {
     290        if (_manager != null)
     291            _manager.unregisterMetaDest(dest);
     292    }
    269293}
  • router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java

    rd8980d1 r0a73303  
    347347            // if it is an encrypted leaseset...
    348348            if (getContext().keyRing().get(msg.getKey()) != null)
    349                 sendStoreThroughGarlic(msg, peer, expiration);
     349                sendStoreThroughExploratory(msg, peer, expiration);
     350            else if (msg.getEntry().getType() == DatabaseEntry.KEY_TYPE_META_LS2)
     351                sendWrappedStoreThroughExploratory(msg, peer, expiration);
    350352            else
    351353                sendStoreThroughClient(msg, peer, expiration);
     
    356358                sendDirect(msg, peer, expiration);
    357359            else
    358                 sendStoreThroughGarlic(msg, peer, expiration);
     360                sendStoreThroughExploratory(msg, peer, expiration);
    359361        }
    360362    }
     
    388390   
    389391    /**
    390      * This is misnamed, it means sending it out through an exploratory tunnel,
     392     * Send it out through an exploratory tunnel,
    391393     * with the reply to come back through an exploratory tunnel.
    392394     * There is no garlic encryption added.
    393395     *
    394      */
    395     private void sendStoreThroughGarlic(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
     396     * @since 0.9.41 renamed from sendStoreThroughGarlic()
     397     */
     398    private void sendStoreThroughExploratory(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
    396399        long token = 1 + getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);
    397400       
     
    516519   
    517520    /**
     521     * Send a leaseset store message out an exploratory tunnel,
     522     * with the reply to come back through a exploratory tunnel.
     523     * Stores are garlic encrypted to hide the identity from the OBEP.
     524     *
     525     * Only for Meta LS2, for now.
     526     *
     527     * @param msg must contain a leaseset
     528     * @since 0.9.41
     529     */
     530    private void sendWrappedStoreThroughExploratory(DatabaseStoreMessage msg, RouterInfo peer, long expiration) {
     531        long token = 1 + getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE);
     532        Hash to = peer.getIdentity().getHash();
     533        TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundExploratoryTunnel(to);
     534        if (replyTunnel == null) {
     535            if (_log.shouldLog(Log.WARN))
     536                _log.warn("No inbound expl. tunnels for reply - delaying...");
     537            // continueSending() above did an addPending() so remove it here.
     538            // This means we will skip the peer next time, can't be helped for now
     539            // without modding StoreState
     540            _state.replyTimeout(to);
     541            Job waiter = new WaitJob(getContext());
     542            waiter.getTiming().setStartAfter(getContext().clock().now() + 3*1000);
     543            getContext().jobQueue().addJob(waiter);
     544            return;
     545        }
     546        TunnelId replyTunnelId = replyTunnel.getReceiveTunnelId(0);
     547        msg.setReplyToken(token);
     548        msg.setReplyTunnel(replyTunnelId);
     549        msg.setReplyGateway(replyTunnel.getPeer(0));
     550
     551        if (_log.shouldLog(Log.DEBUG))
     552            _log.debug(getJobId() + ": send(dbStore) w/ token expected " + token);
     553
     554        TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to);
     555        if (outTunnel != null) {
     556            I2NPMessage sent;
     557            // garlic encrypt using router SKM
     558            MessageWrapper.WrappedMessage wm = MessageWrapper.wrap(getContext(), msg, null, peer);
     559            if (wm == null) {
     560                if (_log.shouldLog(Log.WARN))
     561                    _log.warn("Fail garlic encrypting");
     562                fail();
     563                return;
     564            }
     565            sent = wm.getMessage();
     566            _state.addPending(to, wm);
     567
     568            SendSuccessJob onReply = new SendSuccessJob(getContext(), peer, outTunnel, sent.getMessageSize());
     569            FailedJob onFail = new FailedJob(getContext(), peer, getContext().clock().now());
     570            StoreMessageSelector selector = new StoreMessageSelector(getContext(), getJobId(), peer, token, expiration);
     571   
     572            if (_log.shouldLog(Log.DEBUG)) {
     573                _log.debug(getJobId() + ": sending encrypted store to " + peer.getIdentity().getHash() + " through " + outTunnel + ": " + sent);
     574            }
     575            getContext().messageRegistry().registerPending(selector, onReply, onFail);
     576            getContext().tunnelDispatcher().dispatchOutbound(sent, outTunnel.getSendTunnelId(0), null, to);
     577        } else {
     578            if (_log.shouldLog(Log.WARN))
     579                _log.warn("No outbound expl. tunnels to send a dbStore out - delaying...");
     580            // continueSending() above did an addPending() so remove it here.
     581            // This means we will skip the peer next time, can't be helped for now
     582            // without modding StoreState
     583            _state.replyTimeout(to);
     584            Job waiter = new WaitJob(getContext());
     585            waiter.getTiming().setStartAfter(getContext().clock().now() + 3*1000);
     586            getContext().jobQueue().addJob(waiter);
     587        }
     588    }
     589   
     590    /**
    518591     * Called to wait a little while
    519592     * @since 0.7.10
Note: See TracChangeset for help on using the changeset viewer.