Exemplo n.º 1
0
    /** Adds a GGEP block with the specified alternate locations to the output stream. */
    static void addGGEP(OutputStream out, GGEPContainer ggep) throws IOException {
      if (ggep == null || (ggep.locations.size() == 0 && ggep.createTime <= 0))
        throw new NullPointerException("null or empty locations");

      GGEP info = new GGEP();
      if (ggep.locations.size() > 0) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
          for (Iterator i = ggep.locations.iterator(); i.hasNext(); ) {
            try {
              Endpoint ep = (Endpoint) i.next();
              baos.write(ep.getHostBytes());
              ByteOrder.short2leb((short) ep.getPort(), baos);
            } catch (UnknownHostException uhe) {
              continue;
            }
          }
        } catch (IOException impossible) {
          ErrorService.error(impossible);
        }
        info.put(GGEP.GGEP_HEADER_ALTS, baos.toByteArray());
      }

      if (ggep.createTime > 0) info.put(GGEP.GGEP_HEADER_CREATE_TIME, ggep.createTime / 1000);

      info.write(out);
    }
  /**
   * Parses a new ExtendedEndpoint. Strictly validates all data. For example, addresses MUST be in
   * dotted quad format.
   *
   * @param line a single line read from the stream
   * @return the endpoint constructed from the line
   * @exception IOException problem reading from in, e.g., EOF reached prematurely
   * @exception ParseException data not in proper format. Does NOT necessarily set the offset of the
   *     exception properly.
   * @see write
   */
  public static ExtendedEndpoint read(String line) throws ParseException {
    // Break the line into fields.  Skip if badly formatted.  Note that
    // subsequent delimiters are NOT coalesced.
    String[] linea = StringUtils.splitNoCoalesce(line, FIELD_SEPARATOR);
    if (linea.length == 0) throw new ParseException("Empty line", 0);

    // 1. Host and port.  As a dirty trick, we use existing code in Endpoint.
    // Note that we strictly validate the address to work around corrupted
    // gnutella.net files from an earlier version
    boolean pureNumeric;

    String host;
    int port;
    try {
      Endpoint tmp = new Endpoint(linea[0], true); // require numeric.
      host = tmp.getAddress();
      port = tmp.getPort();
      pureNumeric = true;
    } catch (IllegalArgumentException e) {
      // Alright, pure numeric failed -- let's try constructing without
      // numeric & without requiring a DNS lookup.
      try {
        Endpoint tmp = new Endpoint(linea[0], false, false);
        host = tmp.getAddress();
        port = tmp.getPort();
        pureNumeric = false;
      } catch (IllegalArgumentException e2) {
        ParseException e3 =
            new ParseException("Couldn't extract address and port from: " + linea[0], 0);
        e3.initCause(e2);
        throw e3;
      }
    }

    // Build endpoint without any optional data.  (We'll set it if possible
    // later.)
    ExtendedEndpoint ret = new ExtendedEndpoint(host, port, false);

    // 2. Average uptime (optional)
    if (linea.length >= 2) {
      try {
        ret.dailyUptime = Integer.parseInt(linea[1].trim());
      } catch (NumberFormatException e) {
      }
    }

    // 3. Time of pong (optional).  Do NOT use current system tome
    //   if not set.
    ret.timeRecorded = DEFAULT_TIME_RECORDED;
    if (linea.length >= 3) {
      try {
        ret.timeRecorded = Long.parseLong(linea[2].trim());
      } catch (NumberFormatException e) {
      }
    }

    // 4. Time of successful connects (optional)
    if (linea.length >= 4) {
      try {
        String times[] = StringUtils.split(linea[3], LIST_SEPARATOR);
        for (int i = times.length - 1; i >= 0; i--)
          ret.recordConnectionAttempt(ret.connectSuccesses, Long.parseLong(times[i].trim()));
      } catch (NumberFormatException e) {
      }
    }

    // 5. Time of failed connects (optional)
    if (linea.length >= 5) {
      try {
        String times[] = StringUtils.split(linea[4], LIST_SEPARATOR);
        for (int i = times.length - 1; i >= 0; i--)
          ret.recordConnectionAttempt(ret.connectFailures, Long.parseLong(times[i].trim()));
      } catch (NumberFormatException e) {
      }
    }

    // 6. locale of the connection (optional)
    if (linea.length >= 6) {
      ret.setClientLocale(linea[5]);
    }

    // 7. udp-host
    if (linea.length >= 7) {
      try {
        int i = Integer.parseInt(linea[6]);
        if (i >= 0) ret.udpHostCacheFailures = i;
      } catch (NumberFormatException nfe) {
      }
    }

    // validate address if numeric.
    if (pureNumeric && !NetworkUtils.isValidAddress(host))
      throw new ParseException("invalid dotted addr: " + ret, 0);

    // validate that non UHC addresses were numeric.
    if (!ret.isUDPHostCache() && !pureNumeric)
      throw new ParseException("illegal non-UHC endpoint: " + ret, 0);

    return ret;
  }