use of i2p.bote.network.PacketBatch in project i2p.i2p-bote by i2p.
the class KademliaDHT method findDeleteAuthorizationKey.
@Override
public UniqueId findDeleteAuthorizationKey(Hash dhtKey, Hash verificationHash) throws InterruptedException {
final Collection<Destination> closeNodes = getClosestNodes(dhtKey);
log.info("Querying " + closeNodes.size() + " peers with DeletionQueries for Kademlia key " + dhtKey);
DhtStorageHandler storageHandler = storageHandlers.get(EncryptedEmailPacket.class);
if (storageHandler instanceof DeletionAwareDhtFolder) {
DeletionAwareDhtFolder<?> folder = (DeletionAwareDhtFolder<?>) storageHandler;
UniqueId delAuthorization = folder.getDeleteAuthorization(dhtKey);
if (delAuthorization != null)
return delAuthorization;
} else
log.error("StorageHandler for EncryptedEmailPackets is not a DeletionAwareDhtFolder!");
// Send the DeletionQueries
PacketBatch batch = new PacketBatch();
for (Destination node : closeNodes) if (// local has already been taken care of
!localDestination.equals(node))
batch.putPacket(new DeletionQuery(dhtKey), node);
sendQueue.send(batch);
batch.awaitSendCompletion();
// wait for replies
batch.awaitFirstReply(RESPONSE_TIMEOUT, TimeUnit.SECONDS);
log.info(batch.getResponses().size() + " response packets received for deletion query for hash " + dhtKey);
sendQueue.remove(batch);
Map<Destination, DataPacket> responses = batch.getResponses();
for (DataPacket response : responses.values()) if (response instanceof DeletionInfoPacket) {
DeletionInfoPacket delInfo = (DeletionInfoPacket) response;
DeletionRecord delRecord = delInfo.getEntry(dhtKey);
if (delRecord != null) {
boolean valid = Util.isDeleteAuthorizationValid(verificationHash, delRecord.delAuthorization);
if (valid)
return delRecord.delAuthorization;
}
}
return null;
}
use of i2p.bote.network.PacketBatch in project i2p.i2p-bote by i2p.
the class KademliaDHT method store.
@Override
public void store(DhtStorablePacket packet) throws DhtException, InterruptedException {
Hash key = packet.getDhtKey();
log.info("Looking up nodes to store a " + packet.getClass().getSimpleName() + " with key " + key);
List<Destination> closeNodes = getClosestNodes(key);
if (closeNodes.isEmpty())
throw new DhtException("Cannot store packet because no storage nodes found.");
// store on local node if appropriate
if (!closeNodes.contains(localDestination))
if (closeNodes.size() < KademliaConstants.K || isCloser(localDestination, closeNodes.get(0), key))
closeNodes.add(localDestination);
log.info("Storing a " + packet.getClass().getSimpleName() + " with key " + key + " on " + closeNodes.size() + " nodes");
PacketBatch batch = new PacketBatch();
for (Destination node : closeNodes) if (localDestination.equals(node))
storeLocally(packet, null);
else {
// use a separate packet id for each request
StoreRequest storeRequest = new StoreRequest(packet);
batch.putPacket(storeRequest, node);
}
sendQueue.send(batch);
batch.awaitSendCompletion();
// TODO awaitAllResponses, repeat if necessary
sendQueue.remove(batch);
}
use of i2p.bote.network.PacketBatch in project i2p.i2p-bote by i2p.
the class RelayPeerManager method run.
@Override
public void run() {
while (!Thread.interrupted()) {
try {
// ask all peers for their peer lists
Set<RelayPeer> peersToQuery = new HashSet<RelayPeer>(peers);
PacketBatch batch = new PacketBatch();
for (RelayPeer peer : peersToQuery) // don't reuse request packets because PacketBatch will not add the same one more than once
batch.putPacket(new PeerListRequest(), peer);
sendQueue.send(batch);
batch.awaitSendCompletion();
batch.awaitAllResponses(2, TimeUnit.MINUTES);
// build a Set of destinations
Set<Destination> responders = batch.getResponses().keySet();
// update reachability data
log.debug("Relay peer stats:");
for (RelayPeer peer : peersToQuery) {
// use peersToQuery (not peers) so new peers that have been added in the meantime are not wrongly considered unresponsive
boolean didRespond = responders.contains(peer);
peer.addReachabilitySample(didRespond);
if (log.shouldLog(Log.DEBUG)) {
StringBuilder logMessage = new StringBuilder(" ");
logMessage.append(Util.toBase32(peer));
logMessage.append(" ");
for (boolean responded : peer.getAllSamples()) logMessage.append(responded ? '*' : '.');
log.debug(logMessage.toString());
}
}
// make a Set with the new peers
Set<Destination> receivedPeers = new HashSet<Destination>();
BanList banList = BanList.getInstance();
for (DataPacket response : batch.getResponses().values()) {
if (!(response instanceof PeerList))
continue;
PeerList peerList = (PeerList) response;
for (Destination peer : peerList.getPeers()) if (!banList.isBanned(peer))
receivedPeers.add(peer);
}
log.debug("Received a total of " + receivedPeers.size() + " relay peers in " + batch.getResponses().size() + " packets.");
// replace low-reachability peers with new peers (a PeerList is supposed to contain only high-reachability peers)
synchronized (peers) {
// add all received peers, then remove low-reachability ones (all of which are existing peers)
for (Destination newPeer : receivedPeers) if (!localDestination.equals(newPeer))
peers.add(new RelayPeer(newPeer));
for (Iterator<RelayPeer> iterator = peers.iterator(); iterator.hasNext(); ) {
if (peers.size() <= MAX_PEERS)
break;
RelayPeer peer = iterator.next();
if (// don't remove the peer before it has had a chance to respond to a request
!peer.getAllSamples().isEmpty() && peer.getReachability() < MIN_REACHABILITY)
iterator.remove();
}
}
log.debug("Number of relay peers is now " + peers.size());
// if no good peers available, ask more often
if (getGoodPeers().isEmpty())
TimeUnit.MINUTES.sleep(UPDATE_INTERVAL_SHORT);
else
TimeUnit.MINUTES.sleep(UPDATE_INTERVAL_LONG);
} catch (InterruptedException e) {
break;
} catch (RuntimeException e) {
// catch unexpected exceptions to keep the thread running
log.error("Exception caught in RelayPeerManager loop", e);
}
}
writePeers(peerFile);
log.debug("RelayPeerManager thread exiting.");
}
use of i2p.bote.network.PacketBatch in project i2p.i2p-bote by i2p.
the class KademliaDHT method find.
private DhtResults find(Hash key, Class<? extends DhtStorablePacket> dataType, boolean exhaustive) throws InterruptedException {
final Collection<Destination> closeNodes = getClosestNodes(key);
log.info("Querying localhost + " + closeNodes.size() + " peers for data type " + dataType.getSimpleName() + ", Kademlia key " + key);
DhtStorablePacket localResult = findLocally(key, dataType);
// if a local packet exists and one result is requested, return the local packet
if (!exhaustive && localResult != null) {
log.debug("Locally stored packet found for hash " + key + " and data type " + dataType.getSimpleName());
DhtResults results = new DhtResults();
results.put(localDestination, localResult);
return results;
}
// Send the retrieve requests
PacketBatch batch = new PacketBatch();
for (Destination node : closeNodes) if (// local has already been taken care of
!localDestination.equals(node))
batch.putPacket(new RetrieveRequest(key, dataType), node);
sendQueue.send(batch);
batch.awaitSendCompletion();
// wait for replies
if (exhaustive)
batch.awaitAllResponses(RESPONSE_TIMEOUT, TimeUnit.SECONDS);
else
batch.awaitFirstReply(RESPONSE_TIMEOUT, TimeUnit.SECONDS);
log.info(batch.getResponses().size() + " response packets received for hash " + key + " and data type " + dataType.getSimpleName());
sendQueue.remove(batch);
return getDhtResults(batch, localResult);
}
Aggregations