Ejemplo n.º 1
0
 public InetAddress getAddress(boolean doDNSRequest, boolean allowLocal)
     throws LocalAddressException {
   InetAddress a = addr.getAddress(doDNSRequest);
   if (a == null) return null;
   if (allowLocal || IPUtil.isValidAddress(a, false)) return a;
   throw new LocalAddressException();
 }
  /**
   * Get our Peer's. This is a list of IP:port's at which we might be contactable. Some of them will
   * have the same port as the listenPort, but if we are behind a NAT which rewrites our port
   * number, some of them may not. (If we're behind a symmetric NAT which rewrites it differently
   * for each connection, we're stuffed, and we tell the user).
   */
  Peer[] detectPrimaryPeers() {
    final boolean logMINOR = NodeIPPortDetector.logMINOR;
    ArrayList<Peer> addresses = new ArrayList<Peer>();
    FreenetInetAddress[] addrs = detectPrimaryIPAddress();
    for (FreenetInetAddress addr : addrs) {
      addresses.add(new Peer(addr, crypto.portNumber));
      if (logMINOR) Logger.minor(this, "Adding " + addr);
    }
    // Now try to get the rewritten port number from our peers.
    // Only considering those within this crypto port, this time.

    PeerNode[] peerList = crypto.getPeerNodes();

    if (peerList != null) {
      HashMap<Peer, Integer> countsByPeer = new HashMap<Peer, Integer>();
      // FIXME use a standard mutable int object, we have one somewhere
      for (PeerNode pn : peerList) {
        Peer p = pn.getRemoteDetectedPeer();
        if ((p == null) || p.isNull()) continue;
        // DNSRequester doesn't deal with our own node
        if (!IPUtil.isValidAddress(p.getAddress(true), false)) continue;
        if (logMINOR) Logger.minor(this, "Peer " + pn.getPeer() + " thinks we are " + p);
        if (countsByPeer.containsKey(p)) {
          countsByPeer.put(p, countsByPeer.get(p) + 1);
        } else {
          countsByPeer.put(p, 1);
        }
      }
      if (countsByPeer.size() == 1) {
        Iterator<Peer> it = countsByPeer.keySet().iterator();
        Peer p = (it.next());
        Logger.minor(this, "Everyone agrees we are " + p);
        if (!addresses.contains(p)) {
          addresses.add(p);
        }
      } else if (countsByPeer.size() > 1) {
        // Take two most popular addresses.
        Peer best = null;
        Peer secondBest = null;
        int bestPopularity = 0;
        int secondBestPopularity = 0;
        for (Map.Entry<Peer, Integer> entry : countsByPeer.entrySet()) {
          Peer cur = entry.getKey();
          int curPop = entry.getValue();
          Logger.normal(this, "Detected peer: " + cur + " popularity " + curPop);
          if (curPop >= bestPopularity) {
            secondBestPopularity = bestPopularity;
            bestPopularity = curPop;
            secondBest = best;
            best = cur;
          }
        }
        if (best != null) {
          if ((bestPopularity > 1) || (addrs.length == 0)) {
            if (!addresses.contains(best)) {
              Logger.normal(this, "Adding best peer " + best + " (" + bestPopularity + ')');
              addresses.add(best);
            }
            if ((secondBest != null) && (secondBestPopularity > 1)) {
              if (!addresses.contains(secondBest)) {
                Logger.normal(
                    this, "Adding second best peer " + secondBest + " (" + secondBest + ')');
                addresses.add(secondBest);
              }
              if (best.getAddress().equals(secondBest.getAddress()) && bestPopularity == 1) {
                Logger.error(
                    this, "Hrrrm, maybe this is a symmetric NAT? Expect trouble connecting!");
                System.err.println(
                    "Hrrrm, maybe this is a symmetric NAT? Expect trouble connecting!");

                ipDetector.setMaybeSymmetric();

                Peer p = new Peer(best.getFreenetAddress(), crypto.portNumber);
                if (!addresses.contains(p)) addresses.add(p);
              }
            }
          }
        }
      }
    }
    lastPeers = addresses.toArray(new Peer[addresses.size()]);
    if (logMINOR)
      Logger.minor(
          this, "Returning for port " + crypto.portNumber + " : " + Arrays.toString(lastPeers));
    return lastPeers;
  }