use of i2p.bote.packet.dht.IndexPacket in project i2p.i2p-bote by i2p.
the class OutboxProcessor method sendToOne.
/**
* Sends an {@link Email} to one recipient.
* @param senderIdentity The sender's Email Identity, or <code>null</code> for anonymous emails
* @param recipient
* @param email
* @throws MessagingException
* @throws DhtException
* @throws GeneralSecurityException
* @throws PasswordException
* @throws InterruptedException
*/
private void sendToOne(EmailIdentity senderIdentity, String recipient, Email email) throws MessagingException, DhtException, GeneralSecurityException, PasswordException, InterruptedException {
// only used for logging
String logSuffix = null;
try {
logSuffix = "Recipient = '" + recipient + "' Message ID = '" + email.getMessageID() + "'";
log.info("Sending email: " + logSuffix);
EmailDestination recipientDest = new EmailDestination(recipient);
EmailIdentity.IdentityConfig identityConfig;
if (email.isAnonymous())
identityConfig = configuration;
else
identityConfig = senderIdentity.getWrappedConfig(configuration);
int hops = identityConfig.getNumStoreHops();
long minDelay = identityConfig.getRelayMinDelay() * 60 * 1000;
long maxDelay = identityConfig.getRelayMaxDelay() * 60 * 1000;
int relayRedundancy = identityConfig.getRelayRedundancy();
int maxPacketSize = getMaxEmailPacketSize(hops);
Collection<UnencryptedEmailPacket> emailPackets = email.createEmailPackets(senderIdentity, identities, recipient, maxPacketSize);
IndexPacket indexPacket = new IndexPacket(recipientDest);
EmailMetadata metadata = email.getMetadata();
for (UnencryptedEmailPacket unencryptedPacket : emailPackets) {
EncryptedEmailPacket emailPacket = new EncryptedEmailPacket(unencryptedPacket, recipientDest);
send(emailPacket, hops, minDelay, maxDelay, relayRedundancy);
indexPacket.put(emailPacket);
metadata.addPacketInfo(recipientDest, emailPacket.getDhtKey(), emailPacket.getDeleteVerificationHash());
}
send(indexPacket, hops, minDelay, maxDelay, relayRedundancy);
outbox.saveMetadata(email);
} catch (GeneralSecurityException e) {
log.error("Invalid recipient address. " + logSuffix, e);
outbox.setStatus(email, new EmailStatus(Status.INVALID_RECIPIENT, recipient));
throw e;
} catch (MessagingException e) {
log.error("Can't create email packets. " + logSuffix, e);
outbox.setStatus(email, new EmailStatus(Status.ERROR_CREATING_PACKETS, e.getLocalizedMessage()));
throw e;
} catch (DhtException e) {
log.error("Can't store email packet on the DHT. " + logSuffix, e);
outbox.setStatus(email, new EmailStatus(Status.ERROR_SENDING, e.getLocalizedMessage()));
throw e;
} catch (IOException e) {
log.error("Can't save metadata. " + logSuffix, e);
outbox.setStatus(email, new EmailStatus(Status.ERROR_SAVING_METADATA, e.getLocalizedMessage()));
}
}
use of i2p.bote.packet.dht.IndexPacket 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.IndexPacket in project i2p.i2p-bote by i2p.
the class IndexPacketFolderTest method testCheckExpiration.
@Test
public void testCheckExpiration() throws GeneralSecurityException, InterruptedException, PasswordException {
long cutoffTime = System.currentTimeMillis() - ExpirationListener.EXPIRATION_TIME_MILLISECONDS;
// store a packet that expired 3 seconds ago
IndexPacket indexPacket = new IndexPacket(destination1);
indexPacket.put(emailPacket1);
long expirationTime1 = cutoffTime - 3 * 1000;
setStoreTime(indexPacket, emailPacket1.getDhtKey(), expirationTime1);
assertEquals(1, indexPacket.getNumEntries());
folder.store(indexPacket);
assertEquals(1, folder.getElements().size());
assertEquals(1, folder.getElements().get(0).getNumEntries());
// round to seconds
assertEquals(expirationTime1 / 1000L, folder.getElements().get(0).iterator().next().storeTime / 1000L);
// store a packet that expires in 3 seconds
indexPacket.put(emailPacket2);
long expirationTime2 = cutoffTime + 3 * 1000;
setStoreTime(indexPacket, emailPacket2.getDhtKey(), expirationTime2);
assertEquals(2, indexPacket.getNumEntries());
folder.store(indexPacket);
assertEquals(1, folder.getElements().size());
// delete expired packets and check that one of the two packets got deleted
folder.deleteExpired();
assertEquals(1, folder.iterator().next().getNumEntries());
// 4 seconds later, the remaining packet should have expired
TimeUnit.SECONDS.sleep(4);
folder.deleteExpired();
assertEquals(0, folder.iterator().next().getNumEntries());
}
use of i2p.bote.packet.dht.IndexPacket in project i2p.i2p-bote by i2p.
the class IndexPacketFolder method deleteExpired.
/**
* Does not add a Deletion Record, just deletes the file.
*/
@Override
public synchronized void deleteExpired() {
long currentTime = System.currentTimeMillis();
for (IndexPacket indexPacket : this) {
// true if at least one entry was removed
boolean removed = false;
synchronized (indexPacket) {
Iterator<IndexPacketEntry> iterator = indexPacket.iterator();
while (iterator.hasNext()) {
IndexPacketEntry entry = iterator.next();
if (currentTime > entry.storeTime + EXPIRATION_TIME_MILLISECONDS) {
log.debug("Deleting expired index packet entry: file=<" + getFilename(indexPacket.getDhtKey()) + ">, emailPktKey=" + entry.emailPacketKey.toBase64());
iterator.remove();
removed = true;
}
}
if (removed)
// don't merge, but overwrite the file with the entry/entries removed
super.store(indexPacket);
}
}
}
use of i2p.bote.packet.dht.IndexPacket in project i2p.i2p-bote by i2p.
the class IndexPacketFolder method individualPackets.
/**
* Overridden to put each index packet entry in its own index packet
*/
@Override
public Iterator<IndexPacket> individualPackets() {
final Iterator<IndexPacket> bigPackets = super.individualPackets();
return new Iterator<IndexPacket>() {
IndexPacket currentPacket;
Iterator<IndexPacketEntry> currentPacketIterator;
@Override
public boolean hasNext() {
if (currentPacketIterator != null && currentPacketIterator.hasNext())
return true;
while (bigPackets.hasNext()) {
currentPacket = bigPackets.next();
currentPacketIterator = currentPacket.iterator();
if (currentPacketIterator.hasNext())
return true;
}
return false;
}
@Override
public IndexPacket next() {
if (currentPacketIterator == null || !currentPacketIterator.hasNext()) {
currentPacket = bigPackets.next();
currentPacketIterator = currentPacket.iterator();
}
IndexPacketEntry entry = currentPacketIterator.next();
IndexPacket indexPacket = new IndexPacket(currentPacket.getDhtKey());
indexPacket.put(entry);
return indexPacket;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported!");
}
};
}
Aggregations