/* * Tests the server-side code for the udp crawler ping */ package com.limegroup.gnutella.messages.vendor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.List; import java.util.StringTokenizer; import java.util.zip.GZIPInputStream; import junit.framework.Test; import org.limewire.collection.FixedSizeExpiringSet; import org.limewire.core.settings.ApplicationSettings; import org.limewire.core.settings.ConnectionSettings; import org.limewire.core.settings.FilterSettings; import org.limewire.core.settings.NetworkSettings; import org.limewire.core.settings.UltrapeerSettings; import org.limewire.io.GUID; import org.limewire.io.IpPort; import org.limewire.io.NetworkUtils; import org.limewire.util.ByteUtils; import org.limewire.util.PrivilegedAccessor; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Stage; import com.limegroup.gnutella.BlockingConnectionUtils; import com.limegroup.gnutella.ConnectionManager; import com.limegroup.gnutella.ConnectionServices; import com.limegroup.gnutella.Constants; import com.limegroup.gnutella.Endpoint; import com.limegroup.gnutella.LifecycleManager; import com.limegroup.gnutella.LimeTestUtils; import com.limegroup.gnutella.MessageRouter; import com.limegroup.gnutella.NetworkManager; import com.limegroup.gnutella.Response; import com.limegroup.gnutella.ResponseFactory; import com.limegroup.gnutella.UDPService; import com.limegroup.gnutella.connection.CountingConnection; import com.limegroup.gnutella.connection.CountingConnectionFactory; import com.limegroup.gnutella.connection.RoutedConnection; import com.limegroup.gnutella.dht.DHTManager; import com.limegroup.gnutella.dht.DHTManagerStub; import com.limegroup.gnutella.handshaking.HeadersFactory; import com.limegroup.gnutella.helpers.UrnHelper; import com.limegroup.gnutella.messages.BadPacketException; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.messages.QueryReplyFactory; import com.limegroup.gnutella.messages.Message.Network; import com.limegroup.gnutella.messages.vendor.VendorMessageFactory.VendorMessageParser; import com.limegroup.gnutella.util.EmptyResponder; import com.limegroup.gnutella.util.LimeTestCase; import com.limegroup.gnutella.util.LimeWireUtils; public class UDPCrawlerMessagesTest extends LimeTestCase { /** * The port that the central Ultrapeer listens on, and that the other nodes * connect to it on. */ private static int PORT = 6669; private InetAddress _udpAddress; /** * The different connections to the ultrapeer. */ private CountingConnection LEAF_1,LEAF_2, LEAF_3, UP1, UP2, UP3; /** * the different kinds of queries */ private final UDPCrawlerPing msgAll = new UDPCrawlerPing(new GUID(GUID.makeGuid())); /** * Ultrapeer 1 UDP connection. */ private DatagramSocket UDP_ACCESS; private NetworkManager networkManager; private LifecycleManager lifecycleManager; private ConnectionServices connectionServices; private MessageRouter messageRouter; private VendorMessageFactory vendorMessageFactory; private HeadersFactory headersFactory; private UDPCrawlerPongFactory crawlerPongFactory; private ConnectionManager connectionManager; private ResponseFactory responseFactory; private QueryReplyFactory queryReplyFactory; private UDPService udpService; private CountingConnectionFactory countingConnectionFactory; public UDPCrawlerMessagesTest(String name) { super(name); } public static Test suite() { return buildTestSuite(UDPCrawlerMessagesTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * builds the connections between the entities in the test * @throws Exception something bad happened (?) */ private void buildConnections() throws Exception { LEAF_1 = countingConnectionFactory.createConnection("localhost", PORT); LEAF_2 = countingConnectionFactory.createConnection("localhost", PORT); LEAF_3 = countingConnectionFactory.createConnection("localhost", PORT); UP1 = countingConnectionFactory.createConnection("localhost", PORT); UP2 = countingConnectionFactory.createConnection("localhost", PORT); UP3 = countingConnectionFactory.createConnection("localhost", PORT); UDP_ACCESS = new DatagramSocket(); } public void setSettings() { String localIP = null; try { localIP = InetAddress.getLocalHost().getHostAddress(); } catch (Exception ignored) {} FilterSettings.BLACK_LISTED_IP_ADDRESSES.setValue( new String[] {"*.*.*.*"}); FilterSettings.WHITE_LISTED_IP_ADDRESSES.setValue( new String[] {localIP,"127.*.*.*"}); NetworkSettings.PORT.setValue(PORT); UltrapeerSettings.EVER_ULTRAPEER_CAPABLE.setValue(true); UltrapeerSettings.DISABLE_ULTRAPEER_MODE.setValue(false); UltrapeerSettings.FORCE_ULTRAPEER_MODE.setValue(true); UltrapeerSettings.MAX_LEAVES.setValue(30); ConnectionSettings.NUM_CONNECTIONS.setValue(30); ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false); ConnectionSettings.WATCHDOG_ACTIVE.setValue(false); } @Override public void setUp() throws Exception { PORT++; setSettings(); assertEquals("unexpected port", PORT, NetworkSettings.PORT.getValue()); Injector injector = LimeTestUtils.createInjector(Stage.PRODUCTION, new AbstractModule() { @Override protected void configure() { bind(DHTManager.class).toInstance(new DHTManagerStub()); } }); networkManager = injector.getInstance(NetworkManager.class); lifecycleManager = injector.getInstance(LifecycleManager.class); connectionServices = injector.getInstance(ConnectionServices.class); messageRouter = injector.getInstance(MessageRouter.class); vendorMessageFactory = injector.getInstance(VendorMessageFactory.class); headersFactory = injector.getInstance(HeadersFactory.class); crawlerPongFactory = injector.getInstance(UDPCrawlerPongFactory.class); connectionManager = injector.getInstance(ConnectionManager.class); responseFactory = injector.getInstance(ResponseFactory.class); queryReplyFactory = injector.getInstance(QueryReplyFactory.class); udpService = injector.getInstance(UDPService.class); countingConnectionFactory = injector.getInstance(CountingConnectionFactory.class); networkManager.setListeningPort(PORT); lifecycleManager.start(); connectionServices.connect(); connect(); assertEquals("unexpected port", PORT, NetworkSettings.PORT.getValue()); Object handler = messageRouter.getUDPMessageHandler(UDPCrawlerPing.class); PrivilegedAccessor.setValue(handler, "_UDPListRequestors", new FixedSizeExpiringSet(200,200)); UDP_ACCESS.connect(InetAddress.getLocalHost(),PORT); vendorMessageFactory.setParser(VendorMessage.F_CRAWLER_PONG, VendorMessage.F_LIME_VENDOR_ID, new UDPCrawlerPongParserStub()); } @Override public void tearDown() throws Exception { connectionServices.disconnect(); lifecycleManager.shutdown(); LEAF_1.close(); LEAF_2.close(); LEAF_3.close(); UP1.close(); UP2.close(); UP3.close(); UDP_ACCESS.close(); } private static void sleep() { try {Thread.sleep(300);}catch(InterruptedException e) {} } /** * Connects all of the nodes to the central test Ultrapeer. */ private void connect() throws Exception { buildConnections(); //ultrapeers UP1.initialize(headersFactory.createUltrapeerHeaders("localhost"), new EmptyResponder(), 1000); UP2.initialize(headersFactory.createUltrapeerHeaders("localhost"), new EmptyResponder(), 1000); UP3.initialize(headersFactory.createUltrapeerHeaders("localhost"), new EmptyResponder(), 1000); //leafs LEAF_1.initialize(headersFactory.createLeafHeaders("localhost"),new EmptyResponder(), 1000); LEAF_2.initialize(headersFactory.createLeafHeaders("localhost"), new EmptyResponder(), 1000); LEAF_3.initialize(headersFactory.createLeafHeaders("localhost"), new EmptyResponder(), 1000); assertTrue("ULTRAPEER_2 should be connected", UP2.isOpen()); assertTrue("ULTRAPEER_1 should be connected", UP1.isOpen()); assertTrue("ULTRAPEER_3 should be connected", UP3.isOpen()); assertTrue("LEAF should be connected", LEAF_1.isOpen()); assertTrue("LEAF should be connected", LEAF_2.isOpen()); assertTrue("LEAF should be connected", LEAF_3.isOpen()); // make sure we get rid of any initial ping pong traffic exchanges sleep(); drainAll(); sleep(); } /** * Drains all messages */ private void drainAll() throws Exception { if(UP1.isOpen()) { BlockingConnectionUtils.drain(UP1); } if(UP2.isOpen()) { BlockingConnectionUtils.drain(UP2); } if(UP3.isOpen()){ BlockingConnectionUtils.drain(UP3); } if(LEAF_1.isOpen()) { BlockingConnectionUtils.drain(LEAF_1); } if(LEAF_2.isOpen()) { BlockingConnectionUtils.drain(LEAF_2); } if(LEAF_3.isOpen()) { BlockingConnectionUtils.drain(LEAF_3); } } /** * sends out a message requesting all leafs + ups * @throws Exception */ public void testMsgAll() throws Exception { UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgAll); //test whether we got proper # of results byte[] payload = reply.getPayload(); assertEquals(3,payload[0]); assertEquals(3,payload[1]); assertEquals(LEAF_1.getInetAddress(),LEAF_2.getInetAddress()); assertEquals(LEAF_1.getInetAddress(),LEAF_3.getInetAddress()); assertEquals(UP1.getInetAddress(),UP2.getInetAddress()); assertEquals(UP1.getInetAddress(),UP3.getInetAddress()); int index = 3; //the index within the result block. byte [] current = new byte[6]; System.arraycopy(payload,index,current,0,6); IpPort e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(UP1.getInetAddress(),e.getInetAddress()); assertEquals(UP1.getPort(), e.getPort()); index +=6; System.arraycopy(payload,index,current,0,6); e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(UP2.getInetAddress(),e.getInetAddress()); assertEquals(UP2.getPort(), e.getPort()); index +=6; System.arraycopy(payload,index,current,0,6); e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(UP3.getInetAddress(),e.getInetAddress()); assertEquals(UP3.getPort(), e.getPort()); index +=6; System.arraycopy(payload,index,current,0,6); e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(LEAF_1.getInetAddress(),e.getInetAddress()); assertEquals(LEAF_1.getPort(), e.getPort()); index +=6; System.arraycopy(payload,index,current,0,6); e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(LEAF_2.getInetAddress(),e.getInetAddress()); assertEquals(LEAF_2.getPort(), e.getPort()); index +=6; System.arraycopy(payload,index,current,0,6); e = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); assertEquals(LEAF_3.getInetAddress(),e.getInetAddress()); assertEquals(LEAF_3.getPort(), e.getPort()); } /** * sends a message requesting 0 leafs and 0 ups. */ public void testMsgNone() throws Exception { UDPCrawlerPing msgNone = new UDPCrawlerPing(new GUID(GUID.makeGuid()), 0, 0,(byte)0); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgNone); byte[] payload = reply.getPayload(); assertEquals(0,payload[0]); assertEquals(0,payload[1]); } /** * sends a message requesting leafs only */ public void testMsgLeafs() throws Exception { UDPCrawlerPing msgLeafsOnly = new UDPCrawlerPing(new GUID(GUID.makeGuid()), 0, 2,(byte)0); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgLeafsOnly); byte[] payload = reply.getPayload(); assertEquals(2,payload[1]); assertEquals(0,payload[0]); } /** * sends a message requesting 1 leafs and 2 ups. */ public void testMsgSome() throws Exception { UDPCrawlerPing msgSome = new UDPCrawlerPing(new GUID(GUID.makeGuid()), 2, 1,(byte)0); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgSome); byte[] payload = reply.getPayload(); assertEquals(1,payload[1]); assertEquals(2,payload[0]); sleep(); } /** * sends a message requesting more UPs and Leafs that the host has. */ public void testMsgMore() throws Exception { UDPCrawlerPing msgMore = new UDPCrawlerPing(new GUID(GUID.makeGuid()), 20, 30,(byte)0); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgMore); byte[] payload = reply.getPayload(); //we should get the number we have connected. assertEquals(3,payload[1]); assertEquals(3,payload[0]); sleep(); } public void testUDPCrawlerPingMessage() throws Exception { try { tryMessage(); } catch (Exception ex) { fail("message should not fail"); throw ex; } sleep(); } /** * tests whether requesting too often will give us a reply */ public void testHammering() throws Exception { //first message should go through tryMessage(); //second shouldn't try { tryMessage(); fail("ioex expected"); }catch (IOException iox) {} sleep(); //third should tryMessage(); sleep(); } /** * tests a udp ping message requesting the connection lifetimes */ public void testConnectionTime() throws Exception{ PrivilegedAccessor.setValue(Constants.class,"MINUTE",new Long(1)); UDPCrawlerPing msgTimes = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)1); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgTimes); byte[] payload = reply.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertTrue((format & UDPCrawlerPing.CONNECTION_TIME) == UDPCrawlerPing.CONNECTION_TIME); assertFalse((format & UDPCrawlerPing.LOCALE_INFO) == UDPCrawlerPing.LOCALE_INFO); //see if the result we got had any uptime (it should!) short uptime = ByteUtils.leb2short(payload,9); assertGreaterThan(0,uptime); } /** * tests a message send from a newer peer that supports more options. */ public void testBadMask() throws Exception { PrivilegedAccessor.setValue(Constants.class,"MINUTE",new Long(1)); UDPCrawlerPing msgBadMask = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)0xFF); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgBadMask); byte[] payload = reply.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertTrue((format & UDPCrawlerPing.CONNECTION_TIME) == UDPCrawlerPing.CONNECTION_TIME); assertTrue((format & UDPCrawlerPing.LOCALE_INFO) == UDPCrawlerPing.LOCALE_INFO); assertTrue((format & UDPCrawlerPing.DHT_STATUS) == UDPCrawlerPing.DHT_STATUS); //see if the result we got had any uptime (it should!) short uptime = ByteUtils.leb2short(payload,14); assertGreaterThan(0,uptime); } /** * tests a ping message requesting locale info. */ public void testLocale() throws Exception { PrivilegedAccessor.setValue(Constants.class,"MINUTE",new Long(1)); UDPCrawlerPing msgLocale = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)2); UDPCrawlerPong reply = crawlerPongFactory.createUDPCrawlerPong(msgLocale); byte[] payload = reply.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertFalse((format & UDPCrawlerPing.CONNECTION_TIME) == UDPCrawlerPing.CONNECTION_TIME); assertTrue((format & UDPCrawlerPing.LOCALE_INFO) == UDPCrawlerPing.LOCALE_INFO); //see if any of the connections have the locale in them - they should String lang = new String(payload, 9, 2); assertEquals(ApplicationSettings.LANGUAGE.getValue(), lang); } /** * tests a ping message requesting only results that support * udp crawling themselves. */ public void testNewOnly() throws Exception { long savedMinute = Constants.MINUTE; try { Constants.MINUTE = 1; //make sure some of our connections support crawling. MessagesSupportedVendorMessage msvm = new MessagesSupportedVendorMessage(); assertGreaterThan(0,msvm.supportsUDPCrawling()); List<RoutedConnection> upCons = connectionManager.getInitializedConnections(); RoutedConnection notSupporting = upCons.get(0); RoutedConnection supporting = upCons.get(1); assertLessThanOrEquals(1,notSupporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); assertLessThanOrEquals(1,supporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); supporting.getConnectionCapabilities().setMessagesSupportedVendorMessage(msvm); assertLessThanOrEquals(1,notSupporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); assertGreaterThanOrEquals(1,supporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); //so now, only one UP should be in the result. UDPCrawlerPing msgNewOnly = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)0x4); UDPCrawlerPong pong = crawlerPongFactory.createUDPCrawlerPong(msgNewOnly); assertEquals(1, pong.getPayload()[0]); //now, make one other UP support that message as well notSupporting.getConnectionCapabilities().setMessagesSupportedVendorMessage(msvm); assertGreaterThan(0,notSupporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); assertGreaterThan(0,supporting.getConnectionCapabilities().remoteHostSupportsUDPCrawling()); pong = crawlerPongFactory.createUDPCrawlerPong(msgNewOnly); assertEquals(2,pong.getPayload()[0]); } finally { Constants.MINUTE = savedMinute; } } public void testMsgAgents() throws Exception { PrivilegedAccessor.setValue(Constants.class,"MINUTE",new Long(1)); UDPCrawlerPing msgAgents = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)0x8); UDPCrawlerPong pong = crawlerPongFactory.createUDPCrawlerPong(msgAgents); byte[] payload = pong.getPayload(); int agentsOffset=(payload[0]+payload[1])*6+3; int agentsSize = ByteUtils.leb2short(payload,agentsOffset); assertGreaterThan(0, agentsSize); ByteArrayInputStream bais = new ByteArrayInputStream(payload,agentsOffset+2,agentsSize); GZIPInputStream gais = null; gais = new GZIPInputStream(bais); DataInputStream dais = new DataInputStream(gais); byte [] length = new byte[2]; dais.readFully(length); int len = ByteUtils.leb2short(length,0); byte []agents = new byte[len]; dais.readFully(agents); String agentsString = new String(agents); //we should have 3 agents reported. StringTokenizer tok = new StringTokenizer(agentsString, UDPCrawlerPong.AGENT_SEP); assertEquals(7,tok.countTokens()); while(tok.hasMoreTokens()) assertEquals(LimeWireUtils.getHttpServer(),tok.nextToken()); } public void testMsgNodeConnectionUptime() throws Exception { ApplicationSettings.AVERAGE_CONNECTION_TIME.setValue(5); PrivilegedAccessor.setValue(Constants.class,"MINUTE",new Long(1)); UDPCrawlerPing msgNodeUptime = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte)0x10); UDPCrawlerPong pong = crawlerPongFactory.createUDPCrawlerPong(msgNodeUptime); byte[] payload = pong.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertFalse((format & UDPCrawlerPing.CONNECTION_TIME) == UDPCrawlerPing.CONNECTION_TIME); assertTrue((format & UDPCrawlerPing.NODE_UPTIME) == UDPCrawlerPing.NODE_UPTIME); //we should have an uptime > 5 assertGreaterThan(5,ByteUtils.leb2int(payload,3)); //the offset should be correctly set byte[] current = new byte[6]; System.arraycopy(payload,7,current,0,6); IpPort combo = NetworkUtils.getIpPort(current, java.nio.ByteOrder.LITTLE_ENDIAN); Endpoint e = new Endpoint(combo.getInetAddress(),combo.getPort()); assertEquals(UP1.getInetAddress(),e.getInetAddress()); assertTrue(e.getPort() == UP1.getPort()); } public void testQueryReplies() throws Exception { // try w/o any query replies UDPCrawlerPing repliesPing = new UDPCrawlerPing(new GUID(GUID.makeGuid()), UDPCrawlerPing.ALL, UDPCrawlerPing.ALL, UDPCrawlerPing.REPLIES); UDPCrawlerPong repliesPong = crawlerPongFactory.createUDPCrawlerPong(repliesPing); byte [] payload = repliesPong.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertTrue((format & UDPCrawlerPing.REPLIES) == UDPCrawlerPing.REPLIES); assertEquals((3 + 6 * (6 + 4)), payload.length); for (int i = 9; i < payload.length; i += 6) { assertEquals(0, ByteUtils.leb2int(payload, i)); i += 4; } // send a few query replies on each conn Response[] res = new Response[1]; for (int j = 0; j < res.length; j++) res[j] = responseFactory.createResponse(10, 10, "not proxied", UrnHelper.SHA1); Message reply = queryReplyFactory.createQueryReply(GUID.makeGuid(), (byte) 3, 6356, InetAddress.getLocalHost().getAddress(), 0, res, GUID.makeGuid(), new byte[0], false, false, true, true, false, false, null); int [] sent = new int[]{1,2,3,1,2,3}; LEAF_1.send(reply);LEAF_1.flush(); LEAF_2.send(reply); LEAF_2.send(reply);LEAF_2.flush(); LEAF_3.send(reply); LEAF_3.send(reply); LEAF_3.send(reply);LEAF_3.flush(); UP1.send(reply);UP1.flush(); UP2.send(reply); UP2.send(reply);UP2.flush(); UP3.send(reply); UP3.send(reply); UP3.send(reply);UP3.flush(); Thread.sleep(100); repliesPong = crawlerPongFactory.createUDPCrawlerPong(repliesPing); payload = repliesPong.getPayload(); int current = 0; for (int i = 9; i < payload.length; i += 6) { assertEquals(sent[current++], ByteUtils.leb2int(payload, i)); i += 4; } } public void testMsgDHTStatus() throws Exception { UDPCrawlerPing msgDHTStatus = new UDPCrawlerPing(new GUID(GUID.makeGuid()),3,3,(byte) (0x1 << 6)); UDPCrawlerPong pong = crawlerPongFactory.createUDPCrawlerPong(msgDHTStatus); byte[] payload = pong.getPayload(); byte format = (byte) (payload[2] & UDPCrawlerPing.FEATURE_MASK); assertFalse((format & UDPCrawlerPing.CONNECTION_TIME) == UDPCrawlerPing.CONNECTION_TIME); assertTrue((format & UDPCrawlerPing.DHT_STATUS) == UDPCrawlerPing.DHT_STATUS); byte status = payload[3]; assertFalse( (status & UDPCrawlerPong.DHT_WAITING_MASK) == UDPCrawlerPong.DHT_WAITING_MASK); assertFalse( (status & UDPCrawlerPong.DHT_PASSIVE_MASK) == UDPCrawlerPong.DHT_PASSIVE_MASK); assertTrue( (status & UDPCrawlerPong.DHT_ACTIVE_MASK) == UDPCrawlerPong.DHT_ACTIVE_MASK); } private void tryMessage() throws Exception { assertTrue(udpService.isListening()); UDP_ACCESS.setSoTimeout(5000); _udpAddress = UDP_ACCESS.getLocalAddress(); //send a packet ByteArrayOutputStream baos = new ByteArrayOutputStream(); msgAll.write(baos); DatagramPacket pack = new DatagramPacket(baos.toByteArray(), baos.toByteArray().length, _udpAddress, PORT); assertNotNull(baos.toByteArray()); assertNotNull(_udpAddress); UDP_ACCESS.send(pack); //now read the response //_udpPort = UDP_ACCESS.getLocalPort(); pack = new DatagramPacket(new byte[1000],1000); //not catching IOEx here because not replying is a valid scenario. UDP_ACCESS.receive(pack); //parse the response InputStream in = new ByteArrayInputStream(pack.getData()); byte[] buf = new byte[23]; in.read(buf,0,23); assertEquals((byte)0x31,buf[16]); byte vendorId[] = new byte[4]; in.read(vendorId, 0, 4); assertEquals(VendorMessage.F_LIME_VENDOR_ID, vendorId); byte rest[] = new byte[in.available()]; in.read(rest, 0, rest.length); //get the selector.... int selector = ByteUtils.ushort2int(ByteUtils.leb2short(rest, 0)); // get the version.... int version = ByteUtils.ushort2int(ByteUtils.leb2short(rest, 2)); assertEquals(VendorMessage.F_CRAWLER_PONG, selector); assertEquals(UDPCrawlerPong.VERSION, version); } private static class UDPCrawlerPongParserStub implements VendorMessageParser { public VendorMessage parse(byte[] guid, byte ttl, byte hops, int version, byte[] restOf, Network network) throws BadPacketException { return null; } } }