/** * Send to a subset of all floodfill peers. We do this to implement Kademlia within the * floodfills, i.e. we flood to those closest to the key. */ public void flood(DatabaseEntry ds) { Hash key = ds.getHash(); Hash rkey = _context.routingKeyGenerator().getRoutingKey(key); FloodfillPeerSelector sel = (FloodfillPeerSelector) getPeerSelector(); List<Hash> peers = sel.selectFloodfillParticipants(rkey, MAX_TO_FLOOD, getKBuckets()); int flooded = 0; for (int i = 0; i < peers.size(); i++) { Hash peer = peers.get(i); RouterInfo target = lookupRouterInfoLocally(peer); if ((target == null) || (_context.banlist().isBanlisted(peer))) continue; // Don't flood a RI back to itself // Not necessary, a ff will do its own flooding (reply token == 0) // if (peer.equals(target.getIdentity().getHash())) // continue; if (peer.equals(_context.routerHash())) continue; DatabaseStoreMessage msg = new DatabaseStoreMessage(_context); msg.setEntry(ds); OutNetMessage m = new OutNetMessage( _context, msg, _context.clock().now() + FLOOD_TIMEOUT, FLOOD_PRIORITY, target); // note send failure but don't give credit on success // might need to change this Job floodFail = new FloodFailedJob(_context, peer); m.setOnFailedSendJob(floodFail); _context.commSystem().processMessage(m); flooded++; if (_log.shouldLog(Log.INFO)) _log.info("Flooding the entry for " + key.toBase64() + " to " + peer.toBase64()); } if (_log.shouldLog(Log.INFO)) _log.info("Flooded the data to " + flooded + " of " + peers.size() + " peers"); }
/** * Resend the leaseSet to the peer who had previously failed to provide us with the data when we * asked them. */ private boolean resend(RouterInfo toPeer, LeaseSet ls) { Hash to = toPeer.getIdentity().getHash(); DatabaseStoreMessage msg = new DatabaseStoreMessage(getContext()); msg.setEntry(ls); msg.setMessageExpiration(getContext().clock().now() + RESEND_TIMEOUT); TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to); if (outTunnel != null) { TunnelId targetTunnelId = null; // not needed Job onSend = null; // not wanted if (_log.shouldLog(Log.DEBUG)) _log.debug("resending leaseSet out to " + to + " through " + outTunnel + ": " + msg); getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), null, to); return true; } else { if (_log.shouldLog(Log.WARN)) _log.warn("unable to resend a leaseSet - no outbound exploratory tunnels!"); return false; } }