use of i2p.bote.network.DhtStorageHandler in project i2p.i2p-bote by i2p.
the class KademliaDHT method storeLocally.
/**
* Stores a DHT packet locally. The folder the packet is stored in depends on the packet type.
* @param packetToStore
* @param sender The peer that sent the store request; can be <code>null</code> for the local node
*/
private void storeLocally(DhtStorablePacket packetToStore, Destination sender) {
if (packetToStore != null) {
DhtStorageHandler storageHandler = storageHandlers.get(packetToStore.getClass());
if (storageHandler != null) {
// If another peer is trying to store a packet that we know has been deleted, let them know and don't store the packet.
if (storageHandler instanceof DeletionAwareDhtFolder<?> && sender != null) {
DeletionAwareDhtFolder<?> folder = (DeletionAwareDhtFolder<?>) storageHandler;
DeleteRequest delRequest = folder.storeAndCreateDeleteRequest(packetToStore);
if (delRequest != null)
sendQueue.send(delRequest, sender);
} else
storageHandler.store(packetToStore);
replicateThread.packetStored(storageHandler, packetToStore);
} else
log.warn("No storage handler found for type " + packetToStore.getClass().getSimpleName() + ".");
}
}
use of i2p.bote.network.DhtStorageHandler 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.DhtStorageHandler in project i2p.i2p-bote by i2p.
the class ReplicateThread method replicate.
private void replicate() throws InterruptedException {
log.debug("Replicating DHT data...");
replicationRunning = true;
// refresh peers close to the local destination
ClosestNodesLookupTask lookupTask = new ClosestNodesLookupTask(localDestination.calculateHash(), sendQueue, i2pReceiver, bucketManager);
List<Destination> closestNodes = lookupTask.call();
closestNodes.remove(localDestination);
int numReplicated = 0;
int numSkipped = 0;
// If a peer responds with a delete request, replicate the delete request instead.
for (DhtStorageHandler dhtStore : dhtStores) for (Iterator<? extends DhtStorablePacket> packetIterator = dhtStore.individualPackets(); packetIterator.hasNext(); ) {
DhtStorablePacket packet = packetIterator.next();
Hash dhtKey = packet.getDhtKey();
if (!keysToSkip.contains(dhtKey)) {
StoreRequest request = new StoreRequest(packet);
List<Destination> closestPeers = bucketManager.getClosestPeers(dhtKey, KademliaConstants.K);
for (Destination peer : closestPeers) {
// Send the store request and give the peer time to respond with a delete request
sendQueue.send(request, peer).await(SEND_TIMEOUT_MINUTES, TimeUnit.MINUTES);
TimeUnit.SECONDS.sleep(WAIT_TIME_SECONDS);
// If we received a delete request for the DHT item, notify the other close peers
DeleteRequest delRequest = receivedDeleteRequests.get(dhtKey);
if (delRequest != null) {
// KademliaDHT handles the delete request for local data, but we forward the
// request to the other nodes close to the DHT key.
// Note that the delete request contains only one entry, see packetReceived()
sendDeleteRequest(delRequest, closestPeers, peer);
break;
}
}
numReplicated++;
} else
numSkipped++;
}
keysToSkip.clear();
replicationRunning = false;
receivedDeleteRequests.clear();
log.debug("Replication finished. Replicated " + numReplicated + " packets, skipped: " + numSkipped);
}
use of i2p.bote.network.DhtStorageHandler in project i2p.i2p-bote by i2p.
the class KademliaDHT method packetReceived.
// PacketListener implementation
@Override
public void packetReceived(CommunicationPacket packet, Destination sender, long receiveTime) {
if (packet instanceof FindClosePeersPacket)
sendPeerList((FindClosePeersPacket) packet, sender);
else if (packet instanceof StoreRequest) {
DhtStorablePacket packetToStore = ((StoreRequest) packet).getPacketToStore();
storeLocally(packetToStore, sender);
} else if (packet instanceof RetrieveRequest) {
RetrieveRequest retrieveRequest = (RetrieveRequest) packet;
DhtStorageHandler storageHandler = storageHandlers.get(retrieveRequest.getDataType());
if (storageHandler != null) {
DhtStorablePacket storedPacket = storageHandler.retrieve(retrieveRequest.getKey());
// if requested packet found, send it to the requester
Collection<ResponsePacket> response = ResponsePacket.create(storedPacket, StatusCode.OK, retrieveRequest.getPacketId());
if (storedPacket != null)
log.debug("Packet found for retrieve request: [" + retrieveRequest + "], replying to sender: [" + Util.toBase32(sender) + "]");
else
log.debug("No matching packet found for retrieve request: [" + retrieveRequest + "]");
sendQueue.send(response, sender);
} else
log.warn("No storage handler found for type " + packet.getClass().getSimpleName() + ".");
} else if (packet instanceof DeleteRequest) {
DeleteRequest delRequest = (DeleteRequest) packet;
DhtStorageHandler storageHandler = storageHandlers.get(delRequest.getDataType());
if (storageHandler instanceof DeletionAwareDhtFolder<?>)
((DeletionAwareDhtFolder<?>) storageHandler).process(delRequest);
} else if (packet instanceof DeletionQuery) {
DhtStorageHandler storageHandler = storageHandlers.get(EncryptedEmailPacket.class);
if (storageHandler instanceof DeletionAwareDhtFolder) {
Hash dhtKey = ((DeletionQuery) packet).getDhtKey();
UniqueId delAuthorization = ((DeletionAwareDhtFolder<?>) storageHandler).getDeleteAuthorization(dhtKey);
// If we know the Delete Authorization for the DHT key, send it to the peer
if (delAuthorization != null) {
DeletionInfoPacket delInfo = new DeletionInfoPacket();
delInfo.put(dhtKey, delAuthorization);
Collection<ResponsePacket> response = ResponsePacket.create(delInfo, StatusCode.OK, packet.getPacketId());
sendQueue.send(response, sender);
}
}
}
// bucketManager is not registered as a PacketListener, so notify it here
bucketManager.packetReceived(packet, sender, receiveTime);
}
Aggregations