use of i2p.bote.packet.dht.DeleteRequest 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.packet.dht.DeleteRequest 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.packet.dht.DeleteRequest in project i2p.i2p-bote by i2p.
the class IndexPacketFolderTest method testProcessDeleteRequest.
@Test
public void testProcessDeleteRequest() throws GeneralSecurityException, MalformedPacketException, PasswordException {
IndexPacketFolder folder = new IndexPacketFolder(folderDir);
// create another packet with the same destination as emailPacket1
EncryptedEmailPacket emailPacket3 = new EncryptedEmailPacket(unencryptedPacket2, destination1);
IndexPacket indexPacket = new IndexPacket(destination1);
indexPacket.put(emailPacket1);
indexPacket.put(emailPacket3);
folder.store(indexPacket);
assertEquals("Folder should have exactly one element!", 1, folder.getElements().size());
// add two entries and delete them via delete requests
Hash dest1Hash = destination1.getHash();
IndexPacketDeleteRequest delRequest = new IndexPacketDeleteRequest(dest1Hash);
Hash dhtKey1 = emailPacket1.getDhtKey();
Hash dhtKey3 = emailPacket3.getDhtKey();
delRequest.put(dhtKey1, unencryptedPacket1.getDeleteAuthorization());
delRequest.put(dhtKey3, unencryptedPacket2.getDeleteAuthorization());
folder.process(delRequest);
DhtStorablePacket storedPacket = folder.retrieve(dest1Hash);
assertTrue(storedPacket instanceof IndexPacket);
assertEquals("The index packet should have no entries!", 0, ((IndexPacket) storedPacket).getNumEntries());
// verify that there is one deletion file containing two entries
File[] files = folder.getStorageDirectory().listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith("DEL_");
}
});
assertEquals(1, files.length);
DataPacket dataPacket = DataPacket.createPacket(files[0]);
assertTrue(dataPacket instanceof DeletionInfoPacket);
DeletionInfoPacket delInfoPacket = (DeletionInfoPacket) dataPacket;
Iterator<DeletionRecord> delPacketIterator = delInfoPacket.iterator();
assertTrue("DeletionInfoPacket has no elements!", delPacketIterator.hasNext());
delPacketIterator.next();
assertTrue("DeletionInfoPacket has less than one element!", delPacketIterator.hasNext());
delPacketIterator.next();
assertFalse("DeletionInfoPacket has more than two elements!", delPacketIterator.hasNext());
// verify that the two deletion records match the DHT keys and auth keys of the deleted packets
DeleteRequest newDelRequest = folder.storeAndCreateDeleteRequest(indexPacket);
assertTrue(newDelRequest instanceof IndexPacketDeleteRequest);
IndexPacketDeleteRequest newIndexPacketDelRequest = (IndexPacketDeleteRequest) newDelRequest;
assertEquals(newIndexPacketDelRequest.getDeleteAuthorization(dhtKey1), unencryptedPacket1.getDeleteAuthorization());
assertEquals(newIndexPacketDelRequest.getDeleteAuthorization(dhtKey3), unencryptedPacket2.getDeleteAuthorization());
}
use of i2p.bote.packet.dht.DeleteRequest in project i2p.i2p-bote by i2p.
the class EmailPacketFolder method storeAndCreateDeleteRequest.
@Override
public DeleteRequest storeAndCreateDeleteRequest(DhtStorablePacket packetToStore) {
if (!(packetToStore instanceof EncryptedEmailPacket))
throw new IllegalArgumentException("Invalid packet type: " + packetToStore.getClass().getSimpleName() + "; this folder only stores packets of type " + EncryptedEmailPacket.class.getSimpleName() + ".");
DeleteRequest delRequest = null;
// read the deletion info file for the email packet's DHT key
Hash dhtKey = packetToStore.getDhtKey();
String delFileName = getDeletionFileName(dhtKey);
DeletionInfoPacket delInfo = createDelInfoPacket(delFileName);
if (delInfo != null) {
DeletionRecord delRecord = delInfo.getEntry(dhtKey);
if (delRecord != null)
delRequest = new EmailPacketDeleteRequest(delRecord.dhtKey, delRecord.delAuthorization);
} else
// if the DHT key has not been recorded as deleted, store the email packet
store(packetToStore);
return delRequest;
}
use of i2p.bote.packet.dht.DeleteRequest 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