package com.limegroup.gnutella.messages;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import junit.framework.Test;
import com.limegroup.gnutella.ConnectionManager;
import com.limegroup.gnutella.Endpoint;
import com.limegroup.gnutella.GUID;
import com.limegroup.gnutella.RouterService;
import com.limegroup.gnutella.guess.QueryKey;
import com.limegroup.gnutella.util.IpPort;
import com.limegroup.gnutella.util.IpPortImpl;
import com.limegroup.gnutella.util.PrivilegedAccessor;
public class PingReplyTest extends com.limegroup.gnutella.util.BaseTestCase {
/**
* A non blank IP
*/
private static final byte[] IP = new byte[] { 1, 1, 1, 1 };
public PingReplyTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(PingReplyTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
/**
* Tests the methods for getting the leaf and ultrapeer slots from the
* pong.
*
* @throws Exception if an error occurs
*/
public void testHasFreeSlots() throws Exception {
byte[] guid = GUID.makeGuid();
byte[] ip = {1,1,1,1};
PingReply pr = PingReply.create(guid, (byte)3, 6346, ip,
(long)10, (long)10, true, 100, true);
//All values are determined based on connection status, and because
// we haven't set up connections yet, we don't have free anything.
assertTrue("slots unexpectedly empty", !pr.hasFreeSlots());
assertEquals("unexpected number leaf slots", 0, pr.getNumLeafSlots());
assertTrue("slots unexpectedly not empty", !pr.hasFreeLeafSlots());
assertTrue("slots unexpectedly empty", !pr.hasFreeUltrapeerSlots());
assertEquals("slots unexpectedly empty", 0, pr.getNumUltrapeerSlots());
// Switch ConnectionManager to report different values for free leaf
// and ultrapeer slots.
ConnectionManager manager = new TestConnectionManager(7, 10);
PrivilegedAccessor.setValue(RouterService.class, "manager", manager);
pr = PingReply.create(guid, (byte)3, 6346, ip,
(long)10, (long)10, true, 100, true);
assertTrue("slots unexpectedly full", pr.hasFreeSlots());
assertTrue("slots unexpectedly full", pr.hasFreeLeafSlots());
assertTrue("slots unexpectedly full", pr.hasFreeUltrapeerSlots());
// Should now have leaf slots
assertEquals("unexpected number leaf slots",
manager.getNumFreeLimeWireLeafSlots(),
pr.getNumLeafSlots());
assertEquals("unexpected number ultrapeer slots",
manager.getNumFreeLimeWireNonLeafSlots(),
pr.getNumUltrapeerSlots());
}
/**
* Tests the method for creating a new pong with a changed GUID out
* of an existing pong
*/
public void testMutateGUID() throws Exception {
byte[] guid = new GUID().bytes();
byte ttl = 4;
int port = 6444;
byte[] ip = {1, 1, 1, 1};
long files = 500L;
long kbytes = 75580L;
boolean isUltrapeer = false;
int dailyUptime = 10;
boolean isGUESSCapable = false;
PingReply pr =
PingReply.create(guid, ttl, port, ip, files, kbytes,
isUltrapeer, dailyUptime, isGUESSCapable);
PingReply testPR = pr.mutateGUID(new GUID().bytes());
assertNotEquals(pr.getGUID(), testPR.getGUID());
assertEquals(pr.getTTL(), testPR.getTTL());
assertEquals(pr.getPort(), testPR.getPort());
assertEquals(pr.getInetAddress(), testPR.getInetAddress());
assertEquals(pr.getFiles(), testPR.getFiles());
assertEquals(pr.getKbytes(), testPR.getKbytes());
assertEquals(pr.isUltrapeer(), testPR.isUltrapeer());
assertEquals(pr.getDailyUptime(), testPR.getDailyUptime());
assertEquals(pr.supportsUnicast(), testPR.supportsUnicast());
}
/**
* Tests the method for creating a pong from the network.
*/
public void testCreatePongFromNetwork() throws Exception {
byte[] guid = new GUID().bytes();
byte[] payload = new byte[2];
// make sure we reject invalid payload sizes
try {
PingReply.createFromNetwork(guid, (byte)4, (byte)3,
payload);
fail("should have not accepted payload size");
} catch(BadPacketException e) {
// expected because the payload size is invalid
}
// make sure we reject null guids
payload = new byte[PingReply.STANDARD_PAYLOAD_SIZE];
addIP(payload);
try {
PingReply.createFromNetwork(null, (byte)4, (byte)3,
payload);
fail("should have not accepted null guid");
} catch(NullPointerException e) {
// expected because the payload size is invalid
}
// make sure we reject null payloads
try {
PingReply.createFromNetwork(guid, (byte)4, (byte)3,
null);
fail("should have not accepted null payload");
} catch(NullPointerException e) {
// expected because the payload size is invalid
}
// make sure we reject bad ggep
GGEP ggep = new GGEP(true);
payload = new byte[3];
// set 'LIM' -- incorrect value to make sure it fails
System.arraycopy("LIM".getBytes(),
0, payload, 0,
2);
// add it
ggep.put(GGEP.GGEP_HEADER_VENDOR_INFO, payload);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ggep.write(baos);
byte[] extensions = baos.toByteArray();
payload =
new byte[PingReply.STANDARD_PAYLOAD_SIZE+extensions.length];
addIP(payload);
System.arraycopy(extensions, 0,
payload, PingReply.STANDARD_PAYLOAD_SIZE,
extensions.length);
try {
PingReply.createFromNetwork(guid, (byte)4, (byte)3,
payload);
fail("should have not accepted bad GGEP in payload");
} catch(BadPacketException e) {
// expected because the payload size is invalid
}
// test one that should go through fine
payload = new byte[PingReply.STANDARD_PAYLOAD_SIZE];
payload[0] = 1;
addIP(payload);
// this one should go through
PingReply.createFromNetwork(guid, (byte)4, (byte)3,
payload);
}
public void testNewPong() {
long u4=0x00000000FFFFFFFFl;
int u2=0x0000FFFF;
byte[] ip={(byte)0xFE, (byte)0x00, (byte)0x00, (byte)0x1};
PingReply pr = PingReply.create(new byte[16], (byte)0,
u2, ip, u4, u4);
assertEquals(u2, pr.getPort());
assertEquals(u4, pr.getFiles());
long kbytes=pr.getKbytes();
assertEquals(Long.toHexString(kbytes), u4, kbytes);
String ip2=pr.getAddress();
assertEquals("254.0.0.1", ip2);
assertTrue(! pr.isUltrapeer());
}
//TODO: check construction from raw bytes
public void testPongMarking() {
PingReply pr =
PingReply.createExternal(new byte[16], (byte)2, 6346, IP,
false);
assertTrue(! pr.isUltrapeer());
// all pongs should have a GGEP extension now....
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
pr = PingReply.createExternal(new byte[16], (byte)2, 6346, IP,
true);
assertTrue(pr.isUltrapeer());
// all pongs should have a GGEP extension now....
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
pr = PingReply.create(new byte[16], (byte)2, 6346, IP,
5, 2348, false, 0, false);
assertTrue(! pr.isUltrapeer());
assertEquals(2348, pr.getKbytes());
// all pongs should have a GGEP extension now....
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
pr = PingReply.create(new byte[16], (byte)2, 6346, IP,
5, 2348, true, 0, true);
assertTrue(pr.isUltrapeer());
// all pongs should have a GGEP extension now....
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
pr = PingReply.create(new byte[16], (byte)2, 6346, IP,
5, 345882, false, 0, false);
assertTrue(! pr.isUltrapeer());
// all pongs should have a GGEP extension now....
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
pr = PingReply.create(new byte[16], (byte)2, 6346, IP,
5, 345882, true, -1, true);
assertTrue(pr.isUltrapeer());
// after added unicast support, all Ultrapeer Pongs have GGEP extension
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
assertEquals("pong should not have a daily uptime", -1,
pr.getDailyUptime());
}
public void testPowerOf2() {
assertTrue(! PingReply.isPowerOf2(-1));
assertTrue(! PingReply.isPowerOf2(0));
assertTrue(PingReply.isPowerOf2(1));
assertTrue(PingReply.isPowerOf2(2));
assertTrue(! PingReply.isPowerOf2(3));
assertTrue(PingReply.isPowerOf2(4));
assertTrue(PingReply.isPowerOf2(16));
assertTrue(! PingReply.isPowerOf2(18));
assertTrue(PingReply.isPowerOf2(64));
assertTrue(! PingReply.isPowerOf2(71));
}
public void testNonGGEPBigPong() throws Exception {
//Will this pass big pongs--even if the contents are not GGEP?
byte[] payload = new byte[14+2];
//add the port
payload[0] = 0x0F;
payload[1] = 0x00;//port
payload[2] = 0x10;
payload[3] = 0x10;
payload[4] = 0x10;
payload[5] = 0x10;//ip = 16.16.16.16
payload[6] = 0x0F;//
payload[7] = 0x00;//
payload[8] = 0x00;//
payload[9] = 0x00;//15 files shared
payload[10] = 0x0F;//
payload[11] = 0x00;//
payload[12] = 0x00;//
payload[13] = 0x00;//15 KB
//OK Now for the big pong part
payload[14] = (byte) 65;
payload[15] = (byte) 66;
PingReply pr=null;
pr = PingReply.createFromNetwork(new byte[16], (byte)2, (byte)4, payload);
assertTrue(! pr.hasGGEPExtension());
assertEquals("pong should not have a daily uptime", -1,
pr.getDailyUptime());
//Start testing
assertEquals("wrong port", 15, pr.getPort());
String ip = pr.getAddress();
assertEquals("wrong IP", "16.16.16.16", ip);
assertEquals("wrong files", 15, pr.getFiles());
assertEquals("Wrong share size", 15, pr.getKbytes());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
pr.write(stream);
byte[] op = stream.toByteArray();
byte[] big = new byte[2];
big[0] = op[op.length-2];
big[1] = op[op.length-1];
String out = new String(big);
assertEquals("Big part of pong lost", "AB", out);
//come this far means its OK
}
public void testBasicGGEP() throws Exception {
// create a pong
PingReply pr =
PingReply.createExternal(new byte[16], (byte)3, 6349, IP, false);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
pr.write(baos);
byte[] bytes=baos.toByteArray();
//Decode and check contents.
Message m=Message.read(new ByteArrayInputStream(bytes));
PingReply pong=(PingReply)m;
assertTrue(m instanceof PingReply);
assertTrue(pong.getPort()==6349);
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
assertTrue(pong.supportsUnicast()==false);
assertTrue(pong.getVendor().equals("LIME"));
assertTrue("Major Version = " + pong.getVendorMajorVersion(),
pong.getVendorMajorVersion()==2);
assertTrue("Minor Version = " + pong.getVendorMinorVersion(),
pong.getVendorMinorVersion()==7);
}
/** Test the raw bytes of an encoded GGEP'ed pong. Then checks that
* these can be decoded. Note that this will need to be changed if
* more extensions are added. */
public void testGGEPEncodeDecode() throws Exception {
//Create pong
PingReply pr = PingReply.create(new byte[16], (byte)3, 6349, IP,
0l, 0l, true, 523, true);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
try {
pr.write(baos);
} catch (IOException e) {
assertTrue("Couldn't write stream.", false);
}
//Encode and check raw bytes.
//UDP is the last extension, so it is DUPTIME and then UDP. should take
//this into account....
byte[] bytes=baos.toByteArray();
int idLength=GGEP.GGEP_HEADER_DAILY_AVERAGE_UPTIME.length();
int udpLength=GGEP.GGEP_HEADER_UNICAST_SUPPORT.length();
int vcLength=GGEP.GGEP_HEADER_VENDOR_INFO.length();
int upLength=GGEP.GGEP_HEADER_UP_SUPPORT.length();
int ggepLength=1 //magic number
+1 //"DUPTIME" extension flags
+idLength //ID
+1 //data length
+2 //data bytes
+1 //"UDP" extension flags
+udpLength // ID
+1 //data length
+1 //data bytes
+1 //"UP" extension flags
+upLength // ID
+1 // data length
+3 // data bytes
+1 //"VC" extension flags
+vcLength // ID
+1 // data length
+5; // data bytes
assertTrue("Length: "+bytes.length, bytes.length==(23+14+ggepLength));
int offset=23+14; //GGEP offset
assertTrue(bytes[offset]==(byte)0xc3); //GGEP magic number
assertTrue("Got: "+(0xFF&bytes[offset+1]),
bytes[offset+1]==(byte)(0x00 | idLength)); //extension flags
assertTrue(bytes[offset+2]==(byte)'D');
assertTrue(bytes[offset+3]==(byte)'U');
assertTrue(bytes[offset+2+idLength+4]==(byte)'G');
assertTrue(bytes[offset+2+idLength+5]==(byte)'U');
assertTrue(bytes[offset+2+idLength+6]==(byte)'E');
assertTrue(bytes[offset+2+idLength+4+udpLength+3]==(byte)'U');
assertTrue(bytes[offset+2+idLength+4+udpLength+4]==(byte)'P');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+5]==(byte)'V');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+6]==(byte)'C');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+8]==(byte)'L');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+9]==(byte)'I');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+10]==(byte)'M');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+11]==(byte)'E');
assertTrue(bytes[offset+2+idLength+4+udpLength+3+upLength+12]==39);
//...etc.
assertTrue(bytes[bytes.length-2-(3+udpLength)-(5+upLength)-(7+vcLength)]==(byte)0x0B); //little byte of 523
assertTrue(bytes[bytes.length-1-(3+udpLength)-(5+upLength)-(7+vcLength)]==(byte)0x02); //big byte of 523
//Decode and check contents.
Message m=Message.read(new ByteArrayInputStream(bytes));
PingReply pong=(PingReply)m;
assertTrue(m instanceof PingReply);
assertTrue(pong.getPort()==6349);
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
assertTrue(pong.getDailyUptime()==523);
assertTrue(pong.supportsUnicast()==true);
assertTrue(pong.getVendor().equals("LIME"));
assertTrue("Major Version = " + pong.getVendorMajorVersion(),
pong.getVendorMajorVersion()==2);
assertTrue("Minor Version = " + pong.getVendorMinorVersion(),
pong.getVendorMinorVersion()==7);
}
/** Test the raw bytes of an encoded GGEP'ed pong. Then checks that
* these can be decoded. Note that this will need to be changed if
* more extensions are added. */
public void testGGEPEncodeDecodeNoGUESS() throws Exception {
//Create pong
PingReply pr=PingReply.create(new byte[16], (byte)3, 6349, IP,
0l, 0l, true, 523, false);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
try {
pr.write(baos);
} catch (IOException e) {
assertTrue("Couldn't write stream.", false);
}
//Encode and check raw bytes.
//UDP is the last extension, so it is DUPTIME and then UDP. should take
//this into account....
byte[] bytes=baos.toByteArray();
int idLength=GGEP.GGEP_HEADER_DAILY_AVERAGE_UPTIME.length();
int vcLength=GGEP.GGEP_HEADER_VENDOR_INFO.length();
int upLength=GGEP.GGEP_HEADER_UP_SUPPORT.length();
int ggepLength=1 //magic number
+1 //"DUPTIME" extension flags
+idLength //ID
+1 //data length
+2 //data bytes
+1 //"UP" extension flags
+upLength // ID
+1 // data length
+3 // data bytes
+1 //"VC" extension flags
+vcLength // ID
+1 // data length
+5; // data bytes
assertTrue("Length: "+bytes.length, bytes.length==(23+14+ggepLength));
int offset=23+14; //GGEP offset
assertTrue(bytes[offset]==(byte)0xc3); //GGEP magic number
assertTrue("Got: "+(0xFF&bytes[offset+1]),
bytes[offset+1]==(byte)(0x00 | idLength)); //extension flags
assertTrue(bytes[offset+2]==(byte)'D');
assertTrue(bytes[offset+3]==(byte)'U');
assertTrue(bytes[offset+2+idLength+4]==(byte)'U');
assertTrue(bytes[offset+2+idLength+5]==(byte)'P');
assertTrue(bytes[offset+2+idLength+4+upLength+5]==(byte)'V');
assertTrue(bytes[offset+2+idLength+4+upLength+6]==(byte)'C');
assertTrue(bytes[offset+2+idLength+4+upLength+8]==(byte)'L');
assertTrue(bytes[offset+2+idLength+4+upLength+9]==(byte)'I');
assertTrue(bytes[offset+2+idLength+4+upLength+10]==(byte)'M');
assertTrue(bytes[offset+2+idLength+4+upLength+11]==(byte)'E');
assertTrue(bytes[offset+2+idLength+4+upLength+12]==39);
//...etc.
assertTrue(bytes[bytes.length-2-(5+upLength)-(7+vcLength)]==(byte)0x0B); //little byte of 523
assertTrue(bytes[bytes.length-1-(5+upLength)-(7+vcLength)]==(byte)0x02); //big byte of 523
//Decode and check contents.
Message m=Message.read(new ByteArrayInputStream(bytes));
PingReply pong=(PingReply)m;
assertTrue(m instanceof PingReply);
assertTrue(pong.getPort()==6349);
assertTrue("pong should have GGEP ext", pr.hasGGEPExtension());
assertTrue(pong.getDailyUptime()==523);
assertTrue(pong.supportsUnicast()==false);
assertTrue(pong.getVendor().equals("LIME"));
assertTrue("Major Version = " + pong.getVendorMajorVersion(),
pong.getVendorMajorVersion()==2);
assertTrue("Minor Version = " + pong.getVendorMinorVersion(),
pong.getVendorMinorVersion()==7);
}
public void testStripGGEP2() throws Exception {
byte[] guid=GUID.makeGuid();
byte[] ip={(byte)18, (byte)239, (byte)3, (byte)144};
PingReply pr1 = PingReply.create(guid, (byte)3, 6349, ip,
13l, 14l, false, 4321, false);
PingReply pr2=(PingReply)pr1.stripExtendedPayload();
assertTrue(Arrays.equals(pr1.getGUID(), pr2.getGUID()));
assertEquals(pr1.getHops(), pr2.getHops());
assertEquals(pr1.getTTL(), pr2.getTTL());
assertEquals(pr1.getFiles(), pr2.getFiles());
assertEquals(pr1.getKbytes(), pr2.getKbytes());
assertEquals(pr1.getPort(), pr2.getPort());
assertEquals(pr1.getInetAddress(), pr2.getInetAddress());
assertTrue(! pr2.hasGGEPExtension());
assertEquals("pong should not have a daily uptime", -1,
pr2.getDailyUptime());
ByteArrayOutputStream out=new ByteArrayOutputStream();
pr2.write(out);
assertTrue(out.toByteArray().length==(23+14));
//Check no aliasing
pr1.hop();
assertTrue(pr1.getHops()!=pr2.getHops());
assertTrue(pr1.getTTL()!=pr2.getTTL());
}
public void testPongTooSmall() throws Exception {
byte[] bytes=new byte[23+25]; //one byte too small
bytes[16]=Message.F_PING_REPLY;
bytes[17]=(byte)3; //hops
bytes[18]=(byte)3; //ttl
bytes[19]=(byte)13; //payload length
ByteArrayInputStream in=new ByteArrayInputStream(bytes);
try {
Message.read(in);
fail("No exception thrown");
} catch (BadPacketException pass) {
//Pass!
}
}
public void testQueryKeyPong() throws Exception {
byte[] randBytes = new byte[8];
(new Random()).nextBytes(randBytes);
QueryKey qk = null;
GUID guid = new GUID(GUID.makeGuid());
byte[] ip={(byte)18, (byte)239, (byte)3, (byte)144};
qk = QueryKey.getQueryKey(randBytes, true);
PingReply pr =
PingReply.createQueryKeyReply(guid.bytes(), (byte) 1, 6346, ip,
2, 2, true, qk);
assertTrue(pr.getQueryKey().equals(qk));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pr.write(baos);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
PingReply prStreamed = (PingReply) Message.read(bais);
assertTrue(prStreamed.getQueryKey().equals(qk));
}
public void testIpRequestPong() throws Exception {
RouterService.getAcceptor().setAddress(InetAddress.getLocalHost());
// a pong carrying an ip:port
Endpoint e = new Endpoint("1.2.3.4",5);
PingReply p = PingReply.create(GUID.makeGuid(),(byte)1,e);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
p.write(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
PingReply fromNet = (PingReply)Message.read(bais);
assertEquals("1.2.3.4",fromNet.getMyInetAddress().getHostAddress());
assertEquals(5,fromNet.getMyPort());
// a pong carrying invalid port
e = new Endpoint("1.2.3.4",5) {
public int getPort() {
return 0;
}
};
p = PingReply.create(GUID.makeGuid(),(byte)1,e);
baos = new ByteArrayOutputStream();
p.write(baos);
bais = new ByteArrayInputStream(baos.toByteArray());
fromNet = (PingReply)Message.read(bais);
assertNull(fromNet.getMyInetAddress());
assertEquals(0,fromNet.getMyPort());
//a pong carrying private ip
e = new Endpoint("192.168.0.1",20);
p = PingReply.create(GUID.makeGuid(),(byte)1,e);
baos = new ByteArrayOutputStream();
p.write(baos);
bais = new ByteArrayInputStream(baos.toByteArray());
fromNet = (PingReply)Message.read(bais);
assertNull(fromNet.getMyInetAddress());
assertEquals(0,fromNet.getMyPort());
// a pong not carrying ip:port
p = PingReply.create(GUID.makeGuid(),(byte)1);
baos = new ByteArrayOutputStream();
p.write(baos);
bais = new ByteArrayInputStream(baos.toByteArray());
fromNet = (PingReply)Message.read(bais);
assertNull(fromNet.getMyInetAddress());
assertEquals(0,fromNet.getMyPort());
}
public void testUDPHostCacheExtension() throws Exception {
GGEP ggep = new GGEP(true);
ggep.put(GGEP.GGEP_HEADER_UDP_HOST_CACHE);
PingReply pr = PingReply.create(GUID.makeGuid(), (byte)1, 1,
new byte[] { 1, 1, 1, 1 },
(long)0, (long)0, false, ggep);
assertTrue(pr.isUDPHostCache());
assertEquals("1.1.1.1", pr.getUDPCacheAddress());
ByteArrayOutputStream out = new ByteArrayOutputStream();
pr.write(out);
byte[] b = out.toByteArray();
PingReply read = (PingReply)Message.read(new ByteArrayInputStream(b));
assertTrue(read.isUDPHostCache());
assertEquals("1.1.1.1", read.getUDPCacheAddress());
ggep = new GGEP(true);
ggep.put(GGEP.GGEP_HEADER_UDP_HOST_CACHE, "www.nowhere.org");
pr = PingReply.create(GUID.makeGuid(), (byte)1, 1,
new byte[] { 1, 1, 1, 1 },
(long)0, (long)0, false, ggep);
assertTrue(pr.isUDPHostCache());
assertEquals("www.nowhere.org", pr.getUDPCacheAddress());
out = new ByteArrayOutputStream();
pr.write(out);
b = out.toByteArray();
read = (PingReply)Message.read(new ByteArrayInputStream(b));
assertTrue(read.isUDPHostCache());
assertEquals("www.nowhere.org", read.getUDPCacheAddress());
}
public void testPackedIPsInPong() throws Exception {
GGEP ggep = new GGEP(true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[] { 1, 1, 1, 1, 1, 0 } );
out.write(new byte[] { 1, 2, 3, 4, 2, 0 } );
out.write(new byte[] { 3, 4, 2, 3, 3, 0 } );
out.write(new byte[] { (byte)0xFE, 0, 0, 3, 4, 0 } );
ggep.put(GGEP.GGEP_HEADER_PACKED_IPPORTS, out.toByteArray());
PingReply pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
List l = pr.getPackedIPPorts();
assertEquals(4, l.size());
IpPort ipp = (IpPort)l.get(0);
assertEquals("1.1.1.1", ipp.getAddress());
assertEquals(1, ipp.getPort());
ipp = (IpPort)l.get(1);
assertEquals("1.2.3.4", ipp.getAddress());
assertEquals(2, ipp.getPort());
ipp = (IpPort)l.get(2);
assertEquals("3.4.2.3", ipp.getAddress());
assertEquals(3, ipp.getPort());
ipp = (IpPort)l.get(3);
assertEquals("254.0.0.3", ipp.getAddress());
assertEquals(4, ipp.getPort());
// Try with invalid list of IPs (invalid by not being multiple of 6)
ggep = new GGEP(true);
out = new ByteArrayOutputStream();
out.write(new byte[] { 1, 1, 1, 1, 1, 0 } );
out.write(new byte[] { 1, 2, 3, 4, 2, 0 } );
out.write(new byte[] { 3, 4, 2, 3, /* no port */ } );
ggep.put(GGEP.GGEP_HEADER_PACKED_IPPORTS, out.toByteArray());
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
l = pr.getPackedIPPorts();
assertTrue(l.isEmpty());
// Try with invalid IPs (invalid by invalid IP addr)
ggep = new GGEP(true);
out = new ByteArrayOutputStream();
out.write(new byte[] { 0, 0, 0, 0, 1, 0 } );
out.write(new byte[] { 1, 2, 3, 4, 2, 0 } );
out.write(new byte[] { 3, 4, 2, 3, 3, 0 } );
ggep.put(GGEP.GGEP_HEADER_PACKED_IPPORTS, out.toByteArray());
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
l = pr.getPackedIPPorts();
assertTrue(l.isEmpty());
// Try with invalid IPs (invalid by invalid port)
ggep = new GGEP(true);
out = new ByteArrayOutputStream();
out.write(new byte[] { 1, 1, 1, 1, 0, 0 } );
out.write(new byte[] { 1, 2, 3, 4, 2, 0 } );
out.write(new byte[] { 3, 4, 2, 3, 3, 0 } );
ggep.put(GGEP.GGEP_HEADER_PACKED_IPPORTS, out.toByteArray());
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
l = pr.getPackedIPPorts();
assertTrue(l.isEmpty());
// Make sure the extension works with other GGEP flags (like UDP Host Cache)
ggep = new GGEP(true);
out = new ByteArrayOutputStream();
out.write(new byte[] { 1, 1, 1, 1, 1, 0 } );
out.write(new byte[] { 1, 2, 3, 4, 2, 0 } );
out.write(new byte[] { 3, 4, 2, 3, 3, 0 } );
out.write(new byte[] { (byte)0xFE, 0, 0, 3, 4, 0 } );
ggep.put(GGEP.GGEP_HEADER_PACKED_IPPORTS, out.toByteArray());
ggep.put(GGEP.GGEP_HEADER_UDP_HOST_CACHE);
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
assertTrue(pr.isUDPHostCache());
l = pr.getPackedIPPorts();
assertEquals(4, l.size());
ipp = (IpPort)l.get(0);
assertEquals("1.1.1.1", ipp.getAddress());
assertEquals(1, ipp.getPort());
ipp = (IpPort)l.get(1);
assertEquals("1.2.3.4", ipp.getAddress());
assertEquals(2, ipp.getPort());
ipp = (IpPort)l.get(2);
assertEquals("3.4.2.3", ipp.getAddress());
assertEquals(3, ipp.getPort());
ipp = (IpPort)l.get(3);
assertEquals("254.0.0.3", ipp.getAddress());
assertEquals(4, ipp.getPort());
// and make sure we can read from network data.
out = new ByteArrayOutputStream();
pr.write(out);
pr = (PingReply)Message.read(new ByteArrayInputStream(out.toByteArray()));
assertTrue(pr.isUDPHostCache());
l = pr.getPackedIPPorts();
assertEquals(4, l.size());
ipp = (IpPort)l.get(0);
assertEquals("1.1.1.1", ipp.getAddress());
assertEquals(1, ipp.getPort());
ipp = (IpPort)l.get(1);
assertEquals("1.2.3.4", ipp.getAddress());
assertEquals(2, ipp.getPort());
ipp = (IpPort)l.get(2);
assertEquals("3.4.2.3", ipp.getAddress());
assertEquals(3, ipp.getPort());
ipp = (IpPort)l.get(3);
assertEquals("254.0.0.3", ipp.getAddress());
assertEquals(4, ipp.getPort());
// Try with one of the constructors.
l = new LinkedList(l);
l.add(new Endpoint("1.5.3.5", 5));
pr = PingReply.create(GUID.makeGuid(), (byte)1, l);
l = pr.getPackedIPPorts();
assertFalse(pr.isUDPHostCache());
l = pr.getPackedIPPorts();
assertEquals(5, l.size());
ipp = (IpPort)l.get(0);
assertEquals("1.1.1.1", ipp.getAddress());
assertEquals(1, ipp.getPort());
ipp = (IpPort)l.get(1);
assertEquals("1.2.3.4", ipp.getAddress());
assertEquals(2, ipp.getPort());
ipp = (IpPort)l.get(2);
assertEquals("3.4.2.3", ipp.getAddress());
assertEquals(3, ipp.getPort());
ipp = (IpPort)l.get(3);
assertEquals("254.0.0.3", ipp.getAddress());
assertEquals(4, ipp.getPort());
ipp = (IpPort)l.get(4);
assertEquals("1.5.3.5", ipp.getAddress());
assertEquals(5, ipp.getPort());
}
public void testPackedHostCachesInPong() throws Exception {
// test with compression.
GGEP ggep = new GGEP(true);
List addrs = new LinkedList();
addrs.add("1.2.3.4:81");
addrs.add("www.limewire.com:6379");
addrs.add("www.eff.org");
addrs.add("www.test.org:1&something=somethingelse¬hing=this");
ggep.putCompressed(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, toBytes(addrs));
PingReply pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
Set s = new TreeSet(IpPort.COMPARATOR);
s.addAll(pr.getPackedUDPHostCaches());
assertEquals(4, s.size());
IpPort ipp = new IpPortImpl("1.2.3.4", 81);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.limewire.com", 6379);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.eff.org", 6346);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.test.org", 1);
assertContains(s, ipp);
s.remove(ipp);
assertEquals(0, s.size());
// test without compression
ggep = new GGEP(true);
addrs.clear();
addrs.add("1.2.3.4:81");
addrs.add("www.limewire.com:6379");
addrs.add("www.eff.org");
addrs.add("www.test.org:1&something=somethingelse¬hing=this");
ggep.put(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, toBytes(addrs));
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
s.clear();
s.addAll(pr.getPackedUDPHostCaches());
assertEquals(4, s.size());
ipp = new IpPortImpl("1.2.3.4", 81);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.limewire.com", 6379);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.eff.org", 6346);
assertContains(s, ipp);
s.remove(ipp);
ipp = new IpPortImpl("www.test.org", 1);
assertContains(s, ipp);
s.remove(ipp);
assertEquals(0, s.size());
ggep = new GGEP(true);
addrs.clear();
addrs.add("1.2.3.4:");
addrs.add("3.4.2.3");
addrs.add("5.4.3.2:1:1");
addrs.add("13.13.1.1:notanumber");
ggep.putCompressed(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, toBytes(addrs));
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
s.addAll(pr.getPackedUDPHostCaches());
assertEquals(1, s.size());
ipp = new IpPortImpl("3.4.2.3", 6346);
assertContains(s, ipp);
s.remove(ipp);
assertEquals(0, s.size());
ggep = new GGEP(true);
ggep.put(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, new byte[0]);
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
assertEquals(0, pr.getPackedUDPHostCaches().size());
ggep = new GGEP(true);
ggep.putCompressed(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, new byte[] { 1, 1, 1, 1 } );
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
assertEquals(0, pr.getPackedUDPHostCaches().size());
ggep = new GGEP(true);
ggep.put(GGEP.GGEP_HEADER_PACKED_HOSTCACHES, new byte[] { 1, 1, 1, 1 } );
pr = PingReply.create(
GUID.makeGuid(), (byte)1, 1, new byte[] { 1, 1, 1, 1 },
0, 0, false, ggep);
assertEquals(0, pr.getPackedUDPHostCaches().size());
}
private final byte[] toBytes(List l) throws Exception {
StringBuffer sb = new StringBuffer();
for(Iterator i = l.iterator(); i.hasNext(); ) {
sb.append(i.next().toString());
if(i.hasNext())
sb.append("\n");
}
return sb.toString().getBytes();
}
private final void addIP(byte[] payload) {
// fill up the ip so its not blank.
payload[2] = 1;
payload[3] = 1;
payload[4] = 1;
payload[5] = 1;
}
/**
* Utility class that overrides ConnectionManager methods for getting the
* number of free leaf and ultrapeer slots.
*/
private static class TestConnectionManager extends ConnectionManager {
private final int NUM_FREE_NON_LEAF_SLOTS;
private final int NUM_FREE_LEAF_SLOTS;
TestConnectionManager(int numFreeNonLeafSlots, int numFreeLeafSlots) {
super();
NUM_FREE_NON_LEAF_SLOTS = numFreeNonLeafSlots;
NUM_FREE_LEAF_SLOTS = numFreeLeafSlots;
}
public int getNumFreeNonLeafSlots() {
return NUM_FREE_NON_LEAF_SLOTS;
}
public int getNumFreeLeafSlots() {
return NUM_FREE_LEAF_SLOTS;
}
}
// TODO: build a test to test multiple GGEP blocks in the payload!! the
// implementation does not cover this it seems, so it should fail ;)
}