/** * Stores a packet in the DHT directly or via relay peers. * @param hops The number of hops, or zero to store it directly in the DHT * @throws DhtException * @throws InterruptedException */ private void send(DhtStorablePacket dhtPacket, int hops, long minDelay, long maxDelay, int relayRedundancy) throws DhtException, InterruptedException { if (hops > 0) { StoreRequest storeRequest = new StoreRequest(dhtPacket); for (int i=0; i<relayRedundancy; i++) { // TODO don't use the same relay peer twice if there are enough peers RelayRequest packet = RelayRequest.create(storeRequest, peerManager, hops, minDelay, maxDelay); relayPacketFolder.add(packet); } } else dht.store(dhtPacket); }
@Test public void toByteArrayAndBack() throws Exception { byte[] arrayA = storeRequest.toByteArray(); byte[] arrayB = new StoreRequest(arrayA).toByteArray(); assertArrayEquals("The two arrays differ!", arrayA, arrayB); }
@Override public byte[] toByteArray() { ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); DataOutputStream dataStream = new DataOutputStream(byteArrayStream); try { writeHeader(dataStream); String hashCashString = hashCash.toString(); dataStream.writeShort(hashCashString.length()); dataStream.write(hashCashString.getBytes()); byte[] dataToStore = packetToStore.toByteArray(); dataStream.writeShort(dataToStore.length); dataStream.write(dataToStore); } catch (IOException e) { log.error("Can't write to ByteArrayOutputStream.", e); } return byteArrayStream.toByteArray(); }
final DhtStorablePacket dhtPacket = ((StoreRequest)payload).getPacketToStore();
@Test public void testCreateAndUnwrap() throws I2PSessionException, DataFormatException, MalformedPacketException { byte[] storeRequestBytes = storeRequest.toByteArray(); CommunicationPacket commPacket = relayRequestMulti; for (int i=0; i<destKeys.length; i++) { assertTrue(commPacket instanceof CommunicationPacket); RelayRequest relayRequest = (RelayRequest)commPacket; commPacket = decryptDataPacket(relayRequest, relayRequest.getNextDestination()); } assertArrayEquals(storeRequestBytes, commPacket.toByteArray()); }
@Test public void testGetPacketToStore() throws Exception { byte[] arrayA = dhtPacket.toByteArray(); byte[] arrayB = storeRequest.getPacketToStore().toByteArray(); assertArrayEquals("The two arrays differ!", arrayA, arrayB); } }
@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 { StoreRequest storeRequest = new StoreRequest(packet); // use a separate packet id for each request batch.putPacket(storeRequest, node); } sendQueue.send(batch); batch.awaitSendCompletion(); // TODO awaitAllResponses, repeat if necessary sendQueue.remove(batch); }
sendPeerList((FindClosePeersPacket)packet, sender); else if (packet instanceof StoreRequest) { DhtStorablePacket packetToStore = ((StoreRequest)packet).getPacketToStore(); storeLocally(packetToStore, sender);
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) {
@Before public void setUp() throws Exception { File tempDir = new File(System.getProperty("java.io.tmpdir")); testDir = new File(tempDir, "RelayPacketFolderTest-" + System.currentTimeMillis()); folderDir = new File(testDir, "relay_pkt"); folder = new RelayPacketFolder(folderDir); // make an EncryptedEmailPacket String base64Destination = "X3oKYQJ~1EAz7B1ZYGSrOTIMCW5Rnn2Svoc38dx5D9~zvz8vqiWcH-pCqQDwLgPWl9RTBzHtTmZcGRPXIv54i0XWeUfX6rTPDQGuZsnBMM0xrkH2FNLNFaJa0NgW3uKXWpNj9AI1AXUXzK-2MYTYoaZHx5SBoCaKfAGMcFJvTON1~kopxBxdBF9Q7T4~PJ3I2LeU-ycmUlehe9N9bIu7adUGyPGVl8Ka-UxwQromoJ~vSWHHl8HkwcDkW--v9Aj~wvFqxqriFkB1EeBiThi3V4XtVY~GUP4IkRj9YZGTsSBf3eS4xwXgnYWlB7IvxAGBfHY9MCg3lbAa1Dg~1IH6rhtXxsXUtGcXsz9yMZTxXHd~rGo~JrXeM1y~Vcenpr6tJcum6pxevkKzzT0qDegGPH3Zhqz7sSeeIaJEcPBUAkX89csqyFWFIjTMm6yZp2rW-QYUnVNLNTjf7vndYUAEICogAkq~btqpIzrGEpm3Pr9F23br3SpbOmdxQxg51AMmAAAA"; Destination nextDestination = new Destination(base64Destination.substring(0, 516)); long delayMilliseconds = TimeUnit.MILLISECONDS.convert(111, TimeUnit.MINUTES); String content = "Warum, warum, warum\n" + "Ist die Banane krumm?\n" + "Weil niemand in den Urwald zog\n" + "Und die Banane grade bog.\n"; byte[] messageIdBytes = new byte[] {-69, -24, -109, 1, 69, -122, -69, 113, -68, -90, 55, -28, 105, 97, 125, 70, 51, 58, 14, 2, -13, -53, 90, -29, 36, 67, 36, -94, -108, -125, 11, 123}; UniqueId messageId = new UniqueId(messageIdBytes, 0); int fragmentIndex = 0; InputStream contentStream = new ByteArrayInputStream(content.getBytes()); UnencryptedEmailPacket unencryptedPacket = new UnencryptedEmailPacket(contentStream, messageId, fragmentIndex, I2PBotePacket.MAX_DATAGRAM_SIZE); unencryptedPacket.setNumFragments(1); String base64EmailDest = "rIbyUukqtsacD-MDJJ8KbIP9d3WQQo~t~zysc3bNcF1mSwz9PcGJnvWCNhnG2nzbdUAIDouESZjLRnBr7-mxNS"; EmailDestination recipient = new EmailDestination(base64EmailDest); emailPacket = new EncryptedEmailPacket(unencryptedPacket, recipient); // make a RelayRequest StoreRequest storeRequest = new StoreRequest(emailPacket); relayRequest = new RelayRequest(storeRequest, nextDestination, delayMilliseconds, 1000); }
@Before public void setUp() throws Exception { byte[] emailContent = new byte[] {2, 109, -80, -37, -106, 83, -33, -39, -94, -76, -112, -98, 99, 25, -61, 44, -92, -85, 1, 10, -128, -2, -27, -86, -126, -33, -11, 42, 56, 3, -97, -101, 111, 7, -96, 25, 121, 74, 89, -40, -33, 82, -50, -18, 49, 106, 13, -121, 53, -83, -2, 35, -7, 71, -71, 26, 90, 1}; UniqueId messageId = new UniqueId(new byte[] {-69, -24, -109, 1, 69, -122, -69, 113, -68, -90, 55, -28, 105, 97, 125, 70, 51, 58, 14, 2, -13, -53, 90, -29, 36, 67, 36, -94, -108, -125, 11, 123}, 0); String base64Identity = "piYT1uJ3O8~bBPZmTvehMbp3-Zksg5enhvIlp2X8txqL25l0WdQMWwyt30UAOVQqxGdnMPTqqjh~-zoa~rCQORo~J1gRxLwCX9LlHQqaIimJilrbN-rhKy4Xlft054wbgQjLSC-WICE4W64KDfitwRzdr7lV6lz~0KFiZ8erZ-~WPMG1CgWEku9lILQUdUHyFBguPcK9oPDq7oGBuFGy8w0CvAq7ex3nmbL7zQVA~VqILtOGeGK2fidCuuofj4AQsTcXmH9O0nxZGCIJBhf~4EWmazvxu8XVB8pabNQvRDbmFu6q85JTwmxC45lCjqNw30hp8q2zoqP-zchjWOrxFUhSumpBdD0xXJR~qmhejh4WnuRnnam9j3fcxH5i~T7xWgmvIbpZEI4kyc9VEbXbLI7k-bU2A6sdP-AGt5~TjGLcxpdsPnOLRXO-Dsi7E9-3Kc84s4TmdpEJdtHn1dxYyeeT-ysVOqXjv5w5Cuk0XJpUIJG8n7aXHpNb-QLxPD3yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWF3qnAX-p41Po~VNmOUzS-Yt~noD8-e~L3P5rZXBWf-XtB4hkloo6m1jwqphEdf1"; EmailIdentity identity = new EmailIdentity(base64Identity); EmailDestination destination = new EmailDestination(identity.getKey()); int fragmentIndex = 0; UnencryptedEmailPacket emailPacket = new UnencryptedEmailPacket(new ByteArrayInputStream(emailContent), messageId, fragmentIndex, I2PBotePacket.MAX_DATAGRAM_SIZE); emailPacket.setNumFragments(1); dhtPacket = new EncryptedEmailPacket(emailPacket, destination); storeRequest = new StoreRequest(dhtPacket); }
IndexPacket indexPacket = new IndexPacket(destination); storeRequest = new StoreRequest(indexPacket); long delayMilliseconds = TimeUnit.MILLISECONDS.convert(123, TimeUnit.MINUTES); relayRequestSingle = new RelayRequest(storeRequest, nextDestination, delayMilliseconds, 1000);