Пример #1
0
  /**
   * Make a new PushRequest object to represent a push packet we read from the network. This is the
   * packet parser.
   *
   * @param guid The GUID that uniquely identifies this Gnutella message
   * @param ttl The message TTL, the number of times it will travel across the Internet
   * @param hops The number of times this Gnutella message has traveled across the Internet
   * @param payload The 26 byte payload
   * @param network The Internet protocol that brought us this message, like 1 N_TCP or 2 N_UDP
   * @return A new PushRequest object with that information
   */
  public PushRequest(byte[] guid, byte ttl, byte hops, byte[] payload, int network)
      throws BadPacketException {

    // Call the Message constructor to save information from the packet header in the Message
    // members this PushRequest inherits
    super(guid, Message.F_PUSH, ttl, hops, payload.length, network);

    // Make sure the payload is at least 26 bytes
    if (payload.length < STANDARD_PAYLOAD_SIZE) {
      ReceivedErrorStat.PUSH_INVALID_PAYLOAD.incrementStat();
      throw new BadPacketException("Payload too small: " + payload.length);
    }

    // Save the payload data
    this.payload = payload;

    // Make sure the port number isn't 0
    if (!NetworkUtils.isValidPort(getPort())) {
      ReceivedErrorStat.PUSH_INVALID_PORT.incrementStat();
      throw new BadPacketException("invalid port");
    }

    // Make sure the IP address doesn't start 0 or 255
    String ip = NetworkUtils.ip2string(payload, 20);
    if (!NetworkUtils.isValidAddress(ip)) {
      ReceivedErrorStat.PUSH_INVALID_ADDRESS.incrementStat();
      throw new BadPacketException("invalid address: " + ip);
    }
  }
Пример #2
0
  /**
   * Creates a new Endpoint instance
   *
   * @param hostBytes IP address of the host (MSB first)
   * @param port The port number for the host
   */
  public Endpoint(byte[] hostBytes, int port) {
    if (!NetworkUtils.isValidPort(port))
      throw new IllegalArgumentException("invalid port: " + port);
    if (!NetworkUtils.isValidAddress(hostBytes))
      throw new IllegalArgumentException("invalid address");

    this.port = port;
    this.hostname = NetworkUtils.ip2string(hostBytes);
  }
Пример #3
0
  /**
   * Constructs a new endpoint using the specific hostname & port. If strict is true, this does a
   * DNS lookup against the name, failing if the lookup couldn't complete.
   */
  public Endpoint(String hostname, int port, boolean strict) {
    if (!NetworkUtils.isValidPort(port))
      throw new IllegalArgumentException("invalid port: " + port);
    if (strict && !NetworkUtils.isValidAddress(hostname))
      throw new IllegalArgumentException("invalid address: " + hostname);

    this.hostname = hostname;
    this.port = port;
  }
  public void writeMessageHeaders(OutputStream ostream) throws IOException {
    LOG.debug("writing headers");

    byte[] clientGUID = GUID.fromHexString(UPLOADER.getFileName());
    InetAddress hostAddress = UPLOADER.getNodeAddress();
    int hostPort = UPLOADER.getNodePort();

    if (clientGUID.length != 16
        || hostAddress == null
        || !NetworkUtils.isValidPort(hostPort)
        || !NetworkUtils.isValidAddress(hostAddress)) {
      // send back a 400
      String str = "HTTP/1.1 400 Push Proxy: Bad Request\r\n\r\n";
      ostream.write(str.getBytes());
      ostream.flush();
      debug("PPUS.doUpload(): unknown host.");
      UploadStat.PUSH_PROXY_REQ_BAD.incrementStat();
      return;
    }

    Map params = UPLOADER.getParameters();
    int fileIndex = 0; // default to 0.
    Object index = params.get(P_FILE);
    // set the file index if we know it...
    if (index != null) fileIndex = ((Integer) index).intValue();

    PushRequest push =
        new PushRequest(
            GUID.makeGuid(), (byte) 0, clientGUID, fileIndex, hostAddress.getAddress(), hostPort);
    try {
      RouterService.getMessageRouter().sendPushRequest(push);

    } catch (IOException ioe) {
      // send back a 410
      String str = "HTTP/1.1 410 Push Proxy: Servent not connected\r\n\r\n";
      ostream.write(str.getBytes());
      ostream.flush();
      debug("PPUS.doUpload(): push failed.");
      debug(ioe);
      UploadStat.PUSH_PROXY_REQ_FAILED.incrementStat();
      return;
    }

    UploadStat.PUSH_PROXY_REQ_SUCCESS.incrementStat();

    String str;
    str = "HTTP/1.1 202 Push Proxy: Message Sent\r\n";
    ostream.write(str.getBytes());
    str = "Server: " + CommonUtils.getHttpServer() + "\r\n";
    ostream.write(str.getBytes());
    str = "Content-Type: " + Constants.QUERYREPLY_MIME_TYPE + "\r\n";
    ostream.write(str.getBytes());
    str = "Content-Length: " + BAOS.size() + "\r\n";
    ostream.write(str.getBytes());
    str = "\r\n";
    ostream.write(str.getBytes());
  }
Пример #5
0
  /**
   * @return true if I am not a multicast host and have a hash. also, if I am firewalled I must have
   *     at least one push proxy, otherwise my port and address need to be valid.
   */
  public final boolean isAltLocCapable() {
    boolean ret = getSHA1Urn() != null && !_replyToMulticast;

    if (_firewalled) ret = ret && _pushAddr != null && _pushAddr.getProxies().size() > 0;
    else
      ret =
          ret
              && NetworkUtils.isValidPort(_port)
              && !NetworkUtils.isPrivateAddress(_host)
              && NetworkUtils.isValidAddress(_host);

    return ret;
  }
Пример #6
0
  /** @return whether a push should be sent tho this rfd. */
  public boolean needsPush() {

    // if replying to multicast, do a push.
    if (isReplyToMulticast()) return true;
    // Return true if rfd is private or unreachable
    if (isPrivate()) {
      // Don't do a push for magnets in case you are in a private network.
      // Note to Sam: This doesn't mean that isPrivate should be true.
      if (this instanceof URLRemoteFileDesc) return false;
      else // Otherwise obey push rule for private rfds.
      return true;
    } else if (!NetworkUtils.isValidPort(getPort())) return true;

    // make sure we have some push proxies.
    else return _firewalled && _pushAddr != null;
  }
Пример #7
0
  /**
   * Make a new PushRequest object for us to send with the given information. This is the packet
   * maker.
   *
   * @param guid For the header, the message GUID that will mark this packet unique
   * @param ttl For the header, the TTL
   * @param clientGUID For the payload, the client ID GUID of the firewalled computer that has the
   *     file and will push open the connection
   * @param index For the payload, the ID number the firewalled computer has assigned the file the
   *     downloading computer wants
   * @param ip For the payload, the downloading computer's IP address the firewalled computer will
   *     push open a connection to
   * @param port For the payload, the downloading computer's port number the firewalled computer
   *     will push open a connection to
   * @param network The Internet protocol this push packet will travel on, like 1 N_TCP or 2 N_UDP,
   *     this is not a part of the packet that's sent
   * @return A new PushRequest object with that information
   */
  public PushRequest(
      byte[] guid, byte ttl, byte[] clientGUID, long index, byte[] ip, int port, int network) {

    // Call the Message constructor to save packet header information
    super(
        guid, // The message GUID
        Message.F_PUSH, // 0x40, this is a push message
        ttl, // The number of times this push will be able to travel between ultrapeers
        (byte) 0, // This push message hasn't traveled any hops yet
        STANDARD_PAYLOAD_SIZE, // The payload length will be 26 bytes
        network); // The Internet protocol we'll use to send, the Message object keeps this
                  // information but it is not part of the packet that's sent

    // Make sure the GUID is 16 bytes, the file id fits in 4 bytes, the IP is 4 bytes, the IP
    // address doesn't start 0 or 255, and the port number fits in 2 bytes
    if (clientGUID.length != 16)
      throw new IllegalArgumentException("invalid guid length: " + clientGUID.length);
    else if ((index & 0xFFFFFFFF00000000l) != 0)
      throw new IllegalArgumentException("invalid index: " + index);
    else if (ip.length != 4) throw new IllegalArgumentException("invalid ip length: " + ip.length);
    else if (!NetworkUtils.isValidAddress(ip))
      throw new IllegalArgumentException("invalid ip " + NetworkUtils.ip2string(ip));
    else if (!NetworkUtils.isValidPort(port))
      throw new IllegalArgumentException("invalid port: " + port);

    /*
     * The 26 byte pong payload has this structure:
     *
     * [client ID GUID]  At  0, 16 bytes  The client ID GUID of the computer that will get this packet and push open a new connection
     * FILE              At 16,  4 bytes  The number the pushing computer has given the file the wanting computer wants
     * IPIPPP            At 20,  6 bytes  The IP address and port number of the wanting computer
     */

    // Compose the 26 byte push payload
    payload = new byte[STANDARD_PAYLOAD_SIZE]; // Make a byte array that can hold 26 bytes
    System.arraycopy(clientGUID, 0, payload, 0, 16); // Copy the client ID GUID into the first 16
    ByteOrder.int2leb((int) index, payload, 16); // 16 bytes into the array, copy the 4 byte file id
    payload[20] = ip[0]; // 20 bytes into the array, copy the 4 bytes of the IP address
    payload[21] = ip[1];
    payload[22] = ip[2];
    payload[23] = ip[3];
    ByteOrder.short2leb(
        (short) port, payload, 24); // 24 bytes into the array, place the 2 byte port number
  }
Пример #8
0
  /**
   * Constructs a new endpoint. If requireNumeric is true, or strict is false, no DNS lookups are
   * ever involved. If requireNumeric is false or strict is true, a DNS lookup MAY be performed if
   * the hostname is not numeric.
   *
   * <p>To never block, make sure strict is false.
   */
  public Endpoint(String hostAndPort, boolean requireNumeric, boolean strict) {
    final int DEFAULT = 6346;
    int j = hostAndPort.indexOf(":");
    if (j < 0) {
      this.hostname = hostAndPort;
      this.port = DEFAULT;
    } else if (j == 0) {
      throw new IllegalArgumentException();
    } else if (j == (hostAndPort.length() - 1)) {
      this.hostname = hostAndPort.substring(0, j);
      this.port = DEFAULT;
    } else {
      this.hostname = hostAndPort.substring(0, j);
      try {
        this.port = Integer.parseInt(hostAndPort.substring(j + 1));
      } catch (NumberFormatException e) {
        throw new IllegalArgumentException();
      }

      if (!NetworkUtils.isValidPort(getPort())) throw new IllegalArgumentException("invalid port");
    }

    if (requireNumeric) {
      // TODO3: implement with fewer allocations
      String[] numbers = StringUtils.split(hostname, '.');
      if (numbers.length != 4) throw new IllegalArgumentException();
      for (int i = 0; i < numbers.length; i++) {
        try {
          int x = Integer.parseInt(numbers[i]);
          if (x < 0 || x > 255) throw new IllegalArgumentException();
        } catch (NumberFormatException fail) {
          throw new IllegalArgumentException();
        }
      }
    }

    if (strict && !NetworkUtils.isValidAddress(hostname))
      throw new IllegalArgumentException("invalid address: " + hostname);
  }
Пример #9
0
    private static Set parseLocations(byte[] locBytes) {
      Set locations = null;
      IPFilter ipFilter = IPFilter.instance();

      if (locBytes.length % 6 == 0) {
        for (int j = 0; j < locBytes.length; j += 6) {
          int port = ByteOrder.ushort2int(ByteOrder.leb2short(locBytes, j + 4));
          if (!NetworkUtils.isValidPort(port)) continue;
          byte[] ip = new byte[4];
          ip[0] = locBytes[j];
          ip[1] = locBytes[j + 1];
          ip[2] = locBytes[j + 2];
          ip[3] = locBytes[j + 3];
          if (!NetworkUtils.isValidAddress(ip)
              || !ipFilter.allow(ip)
              || NetworkUtils.isMe(ip, port)) continue;
          if (locations == null) locations = new HashSet();
          locations.add(new Endpoint(ip, port));
        }
      }
      return locations;
    }
Пример #10
0
  public RemoteFileDesc(
      String host,
      int port,
      long index,
      String filename,
      int size,
      int speed,
      boolean chat,
      int quality,
      boolean browseHost,
      Set urns,
      boolean replyToMulticast,
      boolean firewalled,
      String vendor,
      long timestamp,
      long createTime,
      PushEndpoint pe) {

    if (!NetworkUtils.isValidPort(port)) {
      throw new IllegalArgumentException("invalid port: " + port);
    }
    if ((speed & 0xFFFFFFFF00000000L) != 0) {
      throw new IllegalArgumentException("invalid speed: " + speed);
    }
    if (filename == null) {
      throw new NullPointerException("null filename");
    }
    if (filename.equals("")) {
      throw new IllegalArgumentException("cannot accept empty string file name");
    }
    if ((size & 0xFFFFFFFF00000000L) != 0) {
      throw new IllegalArgumentException("invalid size: " + size);
    }
    if ((index & 0xFFFFFFFF00000000L) != 0) {
      throw new IllegalArgumentException("invalid index: " + index);
    }
    if (host == null) {
      throw new NullPointerException("null host");
    }

    _speed = speed;
    _host = host;
    _port = port;
    _index = index;
    _filename = filename;
    _size = size;

    _pushAddr = pe;
    if (pe != null) _clientGUID = pe.getClientGUID();
    else _clientGUID = null;

    _chatEnabled = chat;
    _quality = quality;
    _browseHostEnabled = browseHost;
    _replyToMulticast = replyToMulticast;
    _firewalled = firewalled;
    _vendor = vendor;
    _creationTime = createTime;

    if (urns == null) {
      _urns = Collections.EMPTY_SET;
    } else {
      _urns = Collections.unmodifiableSet(urns);
    }
    _http11 = (!_urns.isEmpty());
  }