public void onGeneratedURI(FreenetURI uri, BaseClientPutter state, ObjectContainer container) { if (logMINOR) Logger.minor(this, "Generated URI for " + darknetOpennetString + " ARK: " + uri); long l = uri.getSuggestedEdition(); if (l < crypto.myARKNumber) { Logger.error( this, "Inserted " + darknetOpennetString + " ARK edition # lower than attempted: " + l + " expected " + crypto.myARKNumber); } else if (l > crypto.myARKNumber) { if (logMINOR) Logger.minor( this, darknetOpennetString + " ARK number moving from " + crypto.myARKNumber + " to " + l); crypto.myARKNumber = l; if (crypto.isOpennet) node.writeOpennetFile(); else node.writeNodeFile(); // We'll broadcast the new ARK edition to our connected peers via a differential node // reference SimpleFieldSet fs = new SimpleFieldSet(true); fs.putSingle("ark.number", Long.toString(crypto.myARKNumber)); node.peers.locallyBroadcastDiffNodeRef(fs, !crypto.isOpennet, crypto.isOpennet); } }
/** * Combine the NodeIPDetector's output with any per-port information we may have to get a * definitive (for that port/NodeCrypto) list of IP addresses (still without port numbers). */ FreenetInetAddress[] detectPrimaryIPAddress() { FreenetInetAddress addr = crypto.getBindTo(); if (addr.isRealInternetAddress(false, true, false)) { // Binding to a real internet address => don't want us to use the others, most likely // he is on a multi-homed box where only one IP can be used for Freenet. return new FreenetInetAddress[] {addr}; } return ipDetector.detectPrimaryIPAddress(!crypto.config.includeLocalAddressesInNoderefs); }
public void update() { logMINOR = Logger.shouldLog(Logger.MINOR, this); if (logMINOR) Logger.minor(this, "update()"); if (!checkIPUpdated()) return; // We'll broadcast the new physical.udp entry to our connected peers via a differential node // reference // We'll err on the side of caution and not update our peer to an empty physical.udp entry using // a differential node reference SimpleFieldSet nfs = crypto.exportPublicFieldSet(false, false, true); String[] entries = nfs.getAll("physical.udp"); if (entries != null) { SimpleFieldSet fs = new SimpleFieldSet(true); fs.putOverwrite("physical.udp", entries); if (logMINOR) Logger.minor(this, darknetOpennetString + " ref's physical.udp is '" + fs.toString() + "'"); node.peers.locallyBroadcastDiffNodeRef(fs, !crypto.isOpennet, crypto.isOpennet); } else { if (logMINOR) Logger.minor(this, darknetOpennetString + " ref's physical.udp is null"); } // Proceed with inserting the ARK if (logMINOR) Logger.minor(this, "Inserting " + darknetOpennetString + " ARK because peers list changed"); if (inserter != null) { // Already inserting. // Re-insert after finished. synchronized (this) { shouldInsert = true; } return; } // Otherwise need to start an insert if (node.noConnectedPeers()) { // Can't start an insert yet synchronized (this) { shouldInsert = true; } return; } startInserter(); }
private void startInserter() { if (!canStart) { if (logMINOR) Logger.minor(this, darknetOpennetString + " ARK inserter can't start yet"); return; } if (logMINOR) Logger.minor(this, "starting " + darknetOpennetString + " ARK inserter"); SimpleFieldSet fs = crypto.exportPublicFieldSet(false, false, true); // Remove some unnecessary fields that only cause collisions. // Delete entire ark.* field for now. Changing this and automatically moving to the new may be // supported in future. fs.removeSubset("ark"); fs.removeValue("location"); fs.removeValue("sig"); // fs.remove("version"); - keep version because of its significance in reconnection String s = fs.toString(); byte[] buf; try { buf = s.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new Error("Impossible: JVM doesn't support UTF-8: " + e, e); } Bucket b = new SimpleReadOnlyArrayBucket(buf); long number = crypto.myARKNumber; InsertableClientSSK ark = crypto.myARK; FreenetURI uri = ark.getInsertURI().setKeyType("USK").setSuggestedEdition(number); if (logMINOR) Logger.minor( this, "Inserting " + darknetOpennetString + " ARK: " + uri + " contents:\n" + s); inserter = new ClientPutter( this, b, uri, new ClientMetadata("text/plain") /* it won't quite fit in an SSK anyway */, node.clientCore.makeClient((short) 0, true).getInsertContext(true), RequestStarter.INTERACTIVE_PRIORITY_CLASS, false, false, this, null, null, false); try { node.clientCore.clientContext.start(inserter, false); synchronized (this) { if (fs.get("physical.udp") == null) lastInsertedPeers = null; else { try { String[] all = fs.getAll("physical.udp"); Peer[] peers = new Peer[all.length]; for (int i = 0; i < all.length; i++) peers[i] = new Peer(all[i], false); lastInsertedPeers = peers; } catch (PeerParseException e1) { Logger.error( this, "Error parsing own " + darknetOpennetString + " ref: " + e1 + " : " + fs.get("physical.udp"), e1); } catch (UnknownHostException e1) { Logger.error( this, "Error parsing own " + darknetOpennetString + " ref: " + e1 + " : " + fs.get("physical.udp"), e1); } } } } catch (InsertException e) { onFailure(e, inserter, null); } catch (DatabaseDisabledException e) { // Impossible } }
/** * 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; }