public void testSendsPushRequest() throws Exception {
    BlockingConnectionUtils.drain(testUP[0]);
    // some setup
    final byte[] clientGUID = GUID.makeGuid();

    // construct and send a query
    byte[] guid = GUID.makeGuid();
    searchServices.query(guid, "anita");

    // the testUP[0] should get it
    Message m = null;
    do {
      m = testUP[0].receive(TIMEOUT);
    } while (!(m instanceof QueryRequest));

    // send a reply with some BAD PushProxy info
    final IpPortSet proxies = new IpPortSet(new IpPortImpl("127.0.0.1", 7001));
    Response[] res =
        new Response[] {responseFactory.createResponse(10, 10, "anita.yay", UrnHelper.SHA1)};
    m =
        queryReplyFactory.createQueryReply(
            m.getGUID(),
            (byte) 1,
            7000,
            InetAddress.getLocalHost().getAddress(),
            0,
            res,
            clientGUID,
            new byte[0],
            true,
            false,
            true,
            true,
            false,
            false,
            proxies);
    testUP[0].send(m);
    testUP[0].flush();

    // wait a while for Leaf to process result
    assertNotNull(callback.getRFD());

    // tell the leaf to browse host the file,
    searchServices.doAsynchronousBrowseHost(
        new MockFriendPresence(
            new MockFriend(), null, new AddressFeature(callback.getRFD().getAddress())),
        new GUID(),
        new BrowseListener() {
          public void handleBrowseResult(SearchResult searchResult) {
            // To change body of implemented methods use File | Settings | File Templates.
          }

          public void browseFinished(boolean success) {
            // To change body of implemented methods use File | Settings | File Templates.
          }
        });
    // nothing works for the guy, we should get a PushRequest
    do {
      m = testUP[0].receive(TIMEOUT * 30);
    } while (!(m instanceof PushRequest));

    // awesome - everything checks out!
  }
  public void testHTTPRequest() throws Exception {

    BlockingConnectionUtils.drain(testUP[0]);
    // some setup
    final byte[] clientGUID = GUID.makeGuid();

    // construct and send a query
    byte[] guid = GUID.makeGuid();
    searchServices.query(guid, "boalt.org");

    // the testUP[0] should get it
    Message m = null;
    do {
      m = testUP[0].receive(TIMEOUT);
    } while (!(m instanceof QueryRequest));

    // set up a server socket
    ServerSocket ss = new ServerSocket(7000);
    try {
      ss.setReuseAddress(true);
      ss.setSoTimeout(TIMEOUT);

      // send a reply
      Response[] res = new Response[1];
      res[0] = responseFactory.createResponse(10, 10, "boalt.org", UrnHelper.SHA1);
      m =
          queryReplyFactory.createQueryReply(
              m.getGUID(),
              (byte) 1,
              7000,
              InetAddress.getLocalHost().getAddress(),
              0,
              res,
              clientGUID,
              new byte[0],
              false,
              false,
              true,
              true,
              false,
              false,
              null);
      testUP[0].send(m);
      testUP[0].flush();

      // wait a while for Leaf to process result
      assertNotNull(callback.getRFD());

      // tell the leaf to browse host the file, should result in direct HTTP
      // request
      searchServices.doAsynchronousBrowseHost(
          new MockFriendPresence(
              new MockFriend(), null, new AddressFeature(callback.getRFD().getAddress())),
          new GUID(),
          new BrowseListener() {
            public void handleBrowseResult(SearchResult searchResult) {
              // To change body of implemented methods use File | Settings | File Templates.
            }

            public void browseFinished(boolean success) {
              // To change body of implemented methods use File | Settings | File Templates.
            }
          });

      // wait for the incoming HTTP request
      Socket httpSock = ss.accept();
      try {
        assertIsBrowse(httpSock, 7000);
      } finally {
        httpSock.close();
      }

      try {
        do {
          m = testUP[0].receive(TIMEOUT);
          assertTrue(!(m instanceof PushRequest));
        } while (true);
      } catch (InterruptedIOException expected) {
      }
    } finally {
      // awesome - everything checks out!
      ss.close();
    }
  }
  public void testPushProxyRequest() throws Exception {
    // wait for connections to process any messages
    Thread.sleep(6000);

    BlockingConnectionUtils.drain(testUP[0]);
    // some setup
    final byte[] clientGUID = GUID.makeGuid();

    // construct and send a query
    byte[] guid = GUID.makeGuid();
    searchServices.query(guid, "nyu.edu");

    // the testUP[0] should get it
    Message m = null;
    do {
      m = testUP[0].receive(TIMEOUT);
    } while (!(m instanceof QueryRequest));

    // set up a server socket to wait for proxy request
    ServerSocket ss = new ServerSocket(7000);
    try {
      ss.setReuseAddress(true);
      ss.setSoTimeout(TIMEOUT * 4);

      // send a reply with some PushProxy info
      final IpPortSet proxies = new IpPortSet();
      proxies.add(new IpPortImpl("127.0.0.1", 7000));
      Response[] res = new Response[1];
      res[0] = responseFactory.createResponse(10, 10, "nyu.edu", UrnHelper.SHA1);
      m =
          queryReplyFactory.createQueryReply(
              m.getGUID(),
              (byte) 1,
              6999,
              InetAddress.getLocalHost().getAddress(),
              0,
              res,
              clientGUID,
              new byte[0],
              true,
              false,
              true,
              true,
              false,
              false,
              proxies);
      testUP[0].send(m);
      testUP[0].flush();

      // wait a while for Leaf to process result
      assertNotNull(callback.getRFD());

      // tell the leaf to browse host the file, should result in PushProxy
      // request
      searchServices.doAsynchronousBrowseHost(
          new MockFriendPresence(
              new MockFriend(), null, new AddressFeature(callback.getRFD().getAddress())),
          new GUID(),
          new BrowseListener() {
            public void handleBrowseResult(SearchResult searchResult) {
              // To change body of implemented methods use File | Settings | File Templates.
            }

            public void browseFinished(boolean success) {
              // To change body of implemented methods use File | Settings | File Templates.
            }
          });

      // wait for the incoming PushProxy request
      // increase the timeout since we send udp pushes first
      ss.setSoTimeout(7000);
      Socket httpSock = ss.accept();
      try {
        BufferedWriter sockWriter =
            new BufferedWriter(
                new OutputStreamWriter(httpSock.getOutputStream(), HTTP.DEFAULT_PROTOCOL_CHARSET));
        sockWriter.write("HTTP/1.1 202 OK\r\n");
        sockWriter.flush();

        // start reading and confirming the HTTP request
        String currLine = null;
        BufferedReader reader =
            new BufferedReader(
                new InputStreamReader(httpSock.getInputStream(), HTTP.DEFAULT_PROTOCOL_CHARSET));

        // confirm a GET/HEAD pushproxy request
        currLine = reader.readLine();
        assertTrue(
            currLine.startsWith("GET /gnutella/push-proxy")
                || currLine.startsWith("HEAD /gnutella/push-proxy"));

        // make sure it sends the correct client GUID
        int beginIndex = currLine.indexOf("ID=") + 3;
        String guidString = currLine.substring(beginIndex, beginIndex + 26);
        GUID guidFromBackend = new GUID(clientGUID);
        GUID guidFromNetwork = new GUID(Base32.decode(guidString));
        assertEquals(guidFromNetwork, guidFromBackend);

        // make sure the node sends the correct X-Node
        currLine = reader.readLine();
        assertTrue(currLine.startsWith("X-Node:"));
        StringTokenizer st = new StringTokenizer(currLine, ":");
        assertEquals(st.nextToken(), "X-Node");
        InetAddress addr = InetAddress.getByName(st.nextToken().trim());
        Arrays.equals(addr.getAddress(), networkManagerStub.getAddress());
        assertEquals(SERVER_PORT, Integer.parseInt(st.nextToken()));

        // now we need to GIV
        Socket push = new Socket(InetAddress.getLocalHost(), SERVER_PORT);
        try {
          BufferedWriter writer =
              new BufferedWriter(
                  new OutputStreamWriter(push.getOutputStream(), HTTP.DEFAULT_PROTOCOL_CHARSET));
          writer.write("GIV 0:" + new GUID(clientGUID).toHexString() + "/\r\n");
          writer.write("\r\n");
          writer.flush();

          assertIsBrowse(push, push.getLocalPort());
        } finally {
          push.close();
        }
      } finally {
        httpSock.close();
      }

      try {
        do {
          m = testUP[0].receive(TIMEOUT);
          assertNotInstanceof(m.toString(), PushRequest.class, m);
        } while (true);
      } catch (InterruptedIOException expected) {
      }
    } finally {
      ss.close();
    }
  }