/** * Send a block of encoded bytes to a peer. This is called by send, and by * IncomingPacketFilter.processOutgoing(..). * * @param blockToSend The data block to send. * @param destination The peer to send it to. */ public void sendPacket(byte[] blockToSend, Peer destination, boolean allowLocalAddresses) throws LocalAddressException { assert (blockToSend != null); if (!_active) { Logger.error(this, "Trying to send packet but no longer active"); // It is essential that for recording accurate AddressTracker data that we don't send any more // packets after shutdown. return; } // there should be no DNS needed here, but go ahead if we can, but complain doing it if (destination.getAddress(false, allowLocalAddresses) == null) { Logger.error( this, "Tried sending to destination without pre-looked up IP address(needs a real Peer.getHostname()): null:" + destination.getPort(), new Exception("error")); if (destination.getAddress(true, allowLocalAddresses) == null) { Logger.error( this, "Tried sending to bad destination address: null:" + destination.getPort(), new Exception("error")); return; } } if (_dropProbability > 0) { if (dropRandom.nextInt() % _dropProbability == 0) { Logger.normal(this, "DROPPED: " + _sock.getLocalPort() + " -> " + destination.getPort()); return; } } InetAddress address = destination.getAddress(false, allowLocalAddresses); assert (address != null); int port = destination.getPort(); DatagramPacket packet = new DatagramPacket(blockToSend, blockToSend.length); packet.setAddress(address); packet.setPort(port); try { _sock.send(packet); tracker.sentPacketTo(destination); collector.addInfo(address + ":" + port, 0, blockToSend.length + UDP_HEADERS_LENGTH); if (logMINOR) Logger.minor( this, "Sent packet length " + blockToSend.length + " to " + address + ':' + port); } catch (IOException e) { if (packet.getAddress() instanceof Inet6Address) { Logger.normal( this, "Error while sending packet to IPv6 address: " + destination + ": " + e, e); } else { Logger.error(this, "Error while sending packet to " + destination + ": " + e, e); } } }
/** * 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; }