Package freenet.node

Source Code of freenet.node.NewPacketFormatTest

/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.node;

import java.util.Arrays;
import java.util.List;

import freenet.crypt.BlockCipher;
import freenet.crypt.ciphers.Rijndael;
import freenet.io.comm.DMT;
import freenet.io.comm.Message;
import freenet.support.MutableBoolean;
import junit.framework.TestCase;

public class NewPacketFormatTest extends TestCase {
 
  @Override
  public void setUp() {
    // Because we don't call maybeSendPacket, the packet sent times are not updated,
    // so lets turn off the keepalives.
    NewPacketFormat.DO_KEEPALIVES = false;
  }
 
  public void testEmptyCreation() throws BlockedTooLongException {
    NewPacketFormat npf = new NewPacketFormat(null, 0, 0);
    PeerMessageQueue pmq = new PeerMessageQueue();
    SessionKey s = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    NPFPacket p = npf.createPacket(1400, pmq, s, false, true);
    if(p != null) fail("Created packet from nothing");
  }

  public void testAckOnlyCreation() throws BlockedTooLongException, InterruptedException {
    BasePeerNode pn = new NullBasePeerNode();
    NewPacketFormat npf = new NewPacketFormat(pn, 0, 0);
    PeerMessageQueue pmq = new PeerMessageQueue();
    SessionKey s = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    NPFPacket p = null;

    //Packet that should be acked
    p = new NPFPacket();
    p.addMessageFragment(new MessageFragment(true, false, true, 0, 8, 8, 0, new byte[] {(byte) 0x01,
                    (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD,
                    (byte) 0xEF }, null));
    assertEquals(1, npf.handleDecryptedPacket(p, s).size());

    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY*2);
    p = npf.createPacket(1400, pmq, s, false, true);
    assertEquals(1, p.getAcks().size());
  }

  public void testLostLastAck() throws BlockedTooLongException, InterruptedException {
    NullBasePeerNode senderNode = new NullBasePeerNode();
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode();
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    PeerMessageQueue receiverQueue = new PeerMessageQueue();
    SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    senderNode.currentKey = senderKey;
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[1024], null, false, null, (short) 0, false, false), 1024);

    NPFPacket fragment1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment1.getFragments().size());
    receiver.handleDecryptedPacket(fragment1, receiverKey);

    NPFPacket fragment2 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment2.getFragments().size());
    receiver.handleDecryptedPacket(fragment2, receiverKey);

    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY*2);
    NPFPacket ack1 = receiver.createPacket(512, receiverQueue, receiverKey, false, true);
    assertEquals(2, ack1.getAcks().size());
    assertEquals(0, (int)ack1.getAcks().first());
    assertEquals(1, (int)ack1.getAcks().last());
    sender.handleDecryptedPacket(ack1, senderKey);

    NPFPacket fragment3 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment3.getFragments().size());
    receiver.handleDecryptedPacket(fragment3, receiverKey);
    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY*2);
    receiver.createPacket(512, senderQueue, receiverKey, false, true); //Sent, but lost

    try {
      Thread.sleep(2000); //RTT is 250ms by default since there is no PeerNode to track it
    } catch (InterruptedException e) { fail(); }

    NPFPacket resend1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    if(resend1 == null) fail("No packet to resend");
    assertEquals(0, receiver.handleDecryptedPacket(resend1, receiverKey).size());

    //Make sure an ack is sent
    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY*2);
    NPFPacket ack2 = receiver.createPacket(512, receiverQueue, receiverKey, false, true);
    assertNotNull(ack2);
    assertEquals(1, ack2.getAcks().size());
    assertEquals(0, ack2.getFragments().size());
  }

  public void testOutOfOrderDelivery() throws BlockedTooLongException {
    NullBasePeerNode senderNode = new NullBasePeerNode();
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode();
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[1024], null, false, null, (short) 0, false, false), 1024);

    NPFPacket fragment1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment1.getFragments().size());

    NPFPacket fragment2 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment2.getFragments().size());

    NPFPacket fragment3 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment3.getFragments().size());

    receiver.handleDecryptedPacket(fragment1, receiverKey);
    receiver.handleDecryptedPacket(fragment3, receiverKey);
    assertEquals(1, receiver.handleDecryptedPacket(fragment2, receiverKey).size());
  }

  public void testReceiveUnknownMessageLength() throws BlockedTooLongException {
    NullBasePeerNode senderNode = new NullBasePeerNode();
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode();
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[1024], null, false, null, (short) 0, false, false), 1024);

    NPFPacket fragment1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment1.getFragments().size());
    NPFPacket fragment2 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment2.getFragments().size());
    NPFPacket fragment3 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, fragment3.getFragments().size());

    receiver.handleDecryptedPacket(fragment3, receiverKey);
    receiver.handleDecryptedPacket(fragment2, receiverKey);
    assertEquals(1, receiver.handleDecryptedPacket(fragment1, receiverKey).size());
  }

  public void testResendAlreadyCompleted() throws BlockedTooLongException, InterruptedException {
    NullBasePeerNode senderNode = new NullBasePeerNode();
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode();
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[128], null, false, null, (short) 0, false, false), 1024);

    Thread.sleep(PacketSender.MAX_COALESCING_DELAY*2);
    NPFPacket packet1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, receiver.handleDecryptedPacket(packet1, receiverKey).size());

    //Receiving the same packet twice should work
    assertEquals(0, receiver.handleDecryptedPacket(packet1, receiverKey).size());

    //Same message, new sequence number ie. resend
    assertEquals(0, receiver.handleDecryptedPacket(packet1, receiverKey).size());
  }
 
  // Test sending it when the peer wants it to be sent. This is as a real message, *not* as a lossy message.
  public void testLoadStatsSendWhenPeerWants() throws BlockedTooLongException, InterruptedException {
    final Message loadMessage = DMT.createFNPVoid();
    final MutableBoolean gotMessage = new MutableBoolean();
    final SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    NullBasePeerNode senderNode = new NullBasePeerNode() {
     
      boolean shouldSend = true;
     
      @Override
      public MessageItem makeLoadStats(boolean realtime, boolean highPriority, boolean noRemember) {
        return new MessageItem(loadMessage, null, null, (short)0);
      }

      @Override
      public synchronized boolean grabSendLoadStatsASAP(boolean realtime) {
        boolean ret = shouldSend;
        shouldSend = false;
        return ret;
      }

      @Override
      public synchronized void setSendLoadStatsASAP(boolean realtime) {
        shouldSend = true;
      }
     
      @Override
      public SessionKey getCurrentKeyTracker() {
        return senderKey;
      }

    };
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode() {
     
      @Override
      public void handleMessage(Message msg) {
        assert(msg.getSpec().equals(DMT.FNPVoid));
        synchronized(gotMessage) {
          gotMessage.value = true;
        }
      }
     
      @Override
      public void processDecryptedMessage(byte[] data, int offset, int length, int overhead) {
        Message m = Message.decodeMessageFromPacket(data, offset, length, this, overhead);
        if(m != null) {
          handleMessage(m);
        }
      }
     
    };
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[128], null, false, null, (short) 0, false, false), 1024);

    Thread.sleep(PacketSender.MAX_COALESCING_DELAY*2);
    NPFPacket packet1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assert(packet1.getLossyMessages().size() == 0);
    assert(packet1.getFragments().size() == 2);
    synchronized(gotMessage) {
      assert(!gotMessage.value);
    }
    List<byte[]> finished = receiver.handleDecryptedPacket(packet1, receiverKey);
    assertEquals(2, finished.size());
    DecodingMessageGroup decoder = receiverNode.startProcessingDecryptedMessages(finished.size());
    for(byte[] buffer : finished) {
      decoder.processDecryptedMessage(buffer, 0, buffer.length, 0);
    }
    decoder.complete();
   
    synchronized(gotMessage) {
      assert(gotMessage.value);
    }
  }
 
  // Test sending it as a per-packet lossy message.
  public void testLoadStatsLowLevel() throws BlockedTooLongException, InterruptedException {
    final byte[] loadMessage =
      new byte[] { (byte)0xFF, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBB, (byte)0xAA};
    final SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    NullBasePeerNode senderNode = new NullBasePeerNode() {
     
      @Override
      public MessageItem makeLoadStats(boolean realtime, boolean highPriority, boolean noRemember) {
        return new MessageItem(loadMessage, null, false, null, (short) 0, false, false);
      }

      @Override
      public SessionKey getCurrentKeyTracker() {
        return senderKey;
      }

    };
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
   
    senderQueue.queueAndEstimateSize(new MessageItem(new byte[128], null, false, null, (short) 0, false, true), 1024);

    Thread.sleep(PacketSender.MAX_COALESCING_DELAY*2);
    NPFPacket packet1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertTrue(packet1 != null);
    assertEquals(1, packet1.getFragments().size());
    assertEquals(1, packet1.getLossyMessages().size());
    NPFPacketTest.checkEquals(loadMessage, packet1.getLossyMessages().get(0));
    // Don't decode the packet because it's not a real message.
  }
 
  // Test sending load message as a per-packet lossy message, including message decoding.
  public void testLoadStatsHighLevel() throws BlockedTooLongException, InterruptedException {
    final Message loadMessage = DMT.createFNPVoid();
    final MutableBoolean gotMessage = new MutableBoolean();
    NullBasePeerNode senderNode = new NullBasePeerNode() {
     
      @Override
      public MessageItem makeLoadStats(boolean realtime, boolean highPriority, boolean noRemember) {
        return new MessageItem(loadMessage, null, null, (short)0);
      }

      @Override
      public void handleMessage(Message msg) {
        assert(msg.getSpec().equals(DMT.FNPVoid));
        synchronized(gotMessage) {
          gotMessage.value = true;
        }
      }

    };
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NullBasePeerNode receiverNode = new NullBasePeerNode() {
     
      @Override
      public void handleMessage(Message msg) {
        assert(msg.getSpec().equals(DMT.FNPVoid));
        synchronized(gotMessage) {
          gotMessage.value = true;
        }
      }
     
    };
    NewPacketFormat receiver = new NewPacketFormat(receiverNode, 0, 0);
    SessionKey senderKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);
    SessionKey receiverKey = new SessionKey(null, null, null, null, null, null, null, null, new NewPacketFormatKeyContext(0, 0), 1);

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[128], null, false, null, (short) 0, false, true), 1024);

    Thread.sleep(PacketSender.MAX_COALESCING_DELAY*2);
    NPFPacket packet1 = sender.createPacket(512, senderQueue, senderKey, false, true);
    assertEquals(1, packet1.getFragments().size());
    assertEquals(1, packet1.getLossyMessages().size());
    synchronized(gotMessage) {
      assert(!gotMessage.value);
    }
    assertEquals(1, receiver.handleDecryptedPacket(packet1, receiverKey).size());
    synchronized(gotMessage) {
      assert(gotMessage.value);
    }
  }
 
  /* This checks the output of the sequence number encryption function to
   * make sure it doesn't change accidentally. */
  public void testSequenceNumberEncryption() {
    BlockCipher ivCipher = new Rijndael();
    ivCipher.initialize(new byte[] {
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    });

    byte[] ivNonce = new byte[16];

    BlockCipher incommingCipher = new Rijndael();
    incommingCipher.initialize(new byte[] {
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    });

    SessionKey sessionKey = new SessionKey(null, null, null, incommingCipher, null, ivCipher, ivNonce, null, null, -1);

    byte[] encrypted = NewPacketFormat.encryptSequenceNumber(0, sessionKey);

    /* This result has not been checked, but it was the output when
     * this test was added and we are (in this test) only
     * interested in making sure the output doesn't change. */
    byte[] correct = new byte[] {(byte) 0xF7, (byte) 0x95, (byte) 0xBD, (byte) 0x4A};

    assertTrue(Arrays.equals(correct, encrypted));
  }
}
TOP

Related Classes of freenet.node.NewPacketFormatTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.