private void sendPacket(byte[] data, Peer replyTo, PeerNode pn) throws LocalAddressException { if(pn != null) { if(pn.isIgnoreSource()) { Peer p = pn.getPeer(); if(p != null) replyTo = p; } } sock.sendPacket(data, replyTo, pn == null ? crypto.config.alwaysAllowLocalAddresses() : pn.allowLocalAddresses()); if(pn != null) pn.reportOutgoingBytes(data.length); if(PeerNode.shouldThrottle(replyTo, node)) { node.outputThrottle.forceGrab(data.length); } }
public int setPeerNodeStatus(long now, boolean noLog) { long localRoutingBackedOffUntilRT = getRoutingBackedOffUntil(true); long localRoutingBackedOffUntilBulk = getRoutingBackedOffUntil(true); int oldPeerNodeStatus; long threshold = maxPeerPingTime(); boolean noLoadStats = noLoadStats(); synchronized(this) { oldPeerNodeStatus = peerNodeStatus; peerNodeStatus = getPeerNodeStatus(now, localRoutingBackedOffUntilRT, localRoutingBackedOffUntilBulk, averagePingTime() > threshold, noLoadStats); if(peerNodeStatus != oldPeerNodeStatus && recordStatus()) { peers.changePeerNodeStatus(this, oldPeerNodeStatus, peerNodeStatus, noLog); } } if(logMINOR) Logger.minor(this, "Peer node status now "+peerNodeStatus+" was "+oldPeerNodeStatus); if(peerNodeStatus!=oldPeerNodeStatus){ if(oldPeerNodeStatus == PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF) { outputLoadTrackerRealTime.maybeNotifySlotWaiter(); outputLoadTrackerBulk.maybeNotifySlotWaiter(); } notifyPeerNodeStatusChangeListeners(); } if(peerNodeStatus == PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF) { long delta = Math.max(localRoutingBackedOffUntilRT, localRoutingBackedOffUntilBulk) - now + 1; if(delta > 0) node.ticker.queueTimedJob(checkStatusAfterBackoff, "Update status for "+this, delta, true, true); } return peerNodeStatus; }
/** * Call this method when a handshake request could not be sent (i.e. no IP address available) * sent. */ public void couldNotSendHandshake(boolean notRegistered) { if(logMINOR) Logger.minor(this, "couldNotSendHandshake(): " + this); calcNextHandshake(false, false, notRegistered); }
public boolean isRoutingBackedOff(boolean realTime) { long now = System.currentTimeMillis(); double pingTime; synchronized(this) { long routingBackedOffUntil = realTime ? routingBackedOffUntilRT : routingBackedOffUntilBulk; long transferBackedOffUntil = realTime ? transferBackedOffUntilRT : transferBackedOffUntilBulk; if(now < routingBackedOffUntil || now < transferBackedOffUntil) return true; pingTime = averagePingTime(); } if(pingTime > maxPeerPingTime()) return true; return false; }
public boolean isRoutingBackedOff(long ignoreBackoffUnder, boolean realTime) { long now = System.currentTimeMillis(); double pingTime; synchronized(this) { long routingBackedOffUntil = realTime ? routingBackedOffUntilRT : routingBackedOffUntilBulk; if(now < routingBackedOffUntil) { if(routingBackedOffUntil - now >= ignoreBackoffUnder) return true; } long transferBackedOffUntil = realTime ? transferBackedOffUntilRT : transferBackedOffUntilBulk; if(now < transferBackedOffUntil) { if(transferBackedOffUntil - now >= ignoreBackoffUnder) return true; } if(isInMandatoryBackoff(now, realTime)) return true; pingTime = averagePingTime(); } if(pingTime > maxPeerPingTime()) return true; return false; }
@Override public void sendEncryptedPacket(byte[] data) throws LocalAddressException { crypto.socket.sendPacket(data, getPeer(), allowLocalAddresses()); }
PeerNodeStatus(PeerNode peerNode, boolean noHeavy) { Peer p = peerNode.getPeer(); if(p == null) { peerAddress = null; this.selectionRate = peerNode.selectionRate(); this.statusValue = peerNode.getPeerNodeStatus(); this.statusName = peerNode.getPeerNodeStatusString(); this.statusCSSName = peerNode.getPeerNodeStatusCSSClassName(); this.location = peerNode.getLocation(); this.peersLocation = peerNode.getPeersLocationArray(); this.version = peerNode.getVersion(); this.simpleVersion = peerNode.getSimpleVersion(); this.routingBackoffLengthRT = peerNode.getRoutingBackoffLength(true); this.routingBackoffLengthBulk = peerNode.getRoutingBackoffLength(false); this.routingBackedOffUntilRT = peerNode.getRoutingBackedOffUntil(true); this.routingBackedOffUntilBulk = peerNode.getRoutingBackedOffUntil(false); this.connected = peerNode.isConnected(); this.routable = peerNode.isRoutable(); this.isFetchingARK = peerNode.isFetchingARK(); this.isOpennet = peerNode.isOpennet(); this.averagePingTime = peerNode.averagePingTime(); this.averagePingTimeCorrected = peerNode.averagePingTimeCorrected(); this.publicInvalidVersion = peerNode.publicInvalidVersion(); this.publicReverseInvalidVersion = peerNode.publicReverseInvalidVersion(); this.backedOffPercentRT = peerNode.backedOffPercentRT.currentValue(); this.backedOffPercentBulk = peerNode.backedOffPercentBulk.currentValue(); this.lastBackoffReasonRT = peerNode.getLastBackoffReason(true); this.lastBackoffReasonBulk = peerNode.getLastBackoffReason(false); this.timeLastRoutable = peerNode.timeLastRoutable();
if(!(isSeed() && this instanceof SeedServerPeerNode)) calcNextHandshake(true, true, false); stopARKFetcher(); try { processNewNoderef(data, offset, length); } catch(FSParseException e1) { synchronized(this) { boolean newer = false; boolean older = false; if(isSeed()) { routable = false; if(logMINOR) Logger.minor(this, "Not routing traffic to " + this + " it's for announcement."); } else if(reverseInvalidVersion()) { Logger.normal(this, "Not routing traffic to " + this + " - reverse invalid version " + Version.getVersionString() + " for peer's lastGoodversion: " + getLastGoodVersion()); newer = true; } else newer = false; if(forwardInvalidVersion()) { Logger.normal(this, "Not routing traffic to " + this + " - invalid version " + getVersion()); older = true; routable = false; } else older = false; changedIP(replyTo); boolean bootIDChanged = false;
next.outputLoadTracker(realTimeFlag).tryRouteTo(origTag, RequestLikelyAcceptedState.LIKELY, false); Logger.warning(this, "Rejected overload (last time) yet expected state was "+lastExpectedAcceptState+" is now "+expectedAcceptState+" from "+next.shortToString()+" ("+next.getVersionNumber()+")"); next.rejectedGuaranteed(realTimeFlag); next.noLongerRoutingTo(origTag, false); expectedAcceptState = null; dontDecrementHTLThisTime = true; waitedForLoadManagement = true; if(waiter == null) waiter = PeerNode.createSlotWaiter(origTag, type, false, realTimeFlag, source); if(next != null) { if(!waiter.addWaitingFor(next)) { if(next.isLowCapacity(realTimeFlag)) { if(waiter.waitingForCount() == 1 // if not, already accepted && canRerouteWhileWaiting) { next.reportRoutedTo(key.toNormalizedDouble(), source == null, realTimeFlag, source, nodesRoutedTo, htl); next.sendSync(req, this, realTimeFlag); } catch (NotConnectedException e) { Logger.minor(this, "Not connected"); next.noLongerRoutingTo(origTag, false); routeRequests(); return; } catch (SyncSendWaitedTooLongException e) { Logger.error(this, "Failed to send "+req+" to "+next+" in a reasonable time."); next.noLongerRoutingTo(origTag, false);
if(!shouldSendHandshake()) { if(logMINOR) Logger.minor(this, "Not sending handshake to "+getPeer()+" because pn.shouldSendHandshake() returned false"); return null; localHandshakeIPs = getHandshakeIPs(); long secondTime = System.currentTimeMillis(); if((secondTime - firstTime) > 1000) Logger.error(this, "getHandshakeIPs() took more than a second to execute ("+(secondTime - firstTime)+") working on "+userToString()); if(localHandshakeIPs.length == 0) { long thirdTime = System.currentTimeMillis(); if((thirdTime - secondTime) > 1000) Logger.error(this, "couldNotSendHandshake() (after getHandshakeIPs()) took more than a second to execute ("+(thirdTime - secondTime)+") working on "+userToString()); return null; boolean allowLocalAddresses = allowLocalAddresses(); for(Peer peer: localHandshakeIPs) { FreenetInetAddress addr = peer.getFreenetAddress(); if(peer.getAddress(false) == null) { if(logMINOR) Logger.minor(this, "Not sending handshake to "+peer+" for "+getPeer()+" because the DNS lookup failed or it's a currently unsupported IPv6 address"); continue; if(logMINOR) Logger.minor(this, "Not sending handshake to "+peer+" for "+getPeer()+" because it's not a real Internet address and metadata.allowLocalAddresses is not true"); continue; if(!isConnected()) { Logger.normal(this, "loopTime2 is more than a second after loopTime1 ("+(loopTime2 - loopTime1)+") working on "+userToString()); return ret;
/** * Export volatile data about the node as a SimpleFieldSet */ public SimpleFieldSet exportVolatileFieldSet() { SimpleFieldSet fs = new SimpleFieldSet(true); long now = System.currentTimeMillis(); synchronized(this) { fs.put("averagePingTime", averagePingTime()); long idle = now - lastReceivedPacketTime(); if(idle > SECONDS.toMillis(60) && -1 != lastReceivedPacketTime()) fs.put("idle", idle); if(peerAddedTime > 1) fs.put("peerAddedTime", peerAddedTime); fs.putSingle("lastRoutingBackoffReasonRT", lastRoutingBackoffReasonRT); fs.putSingle("lastRoutingBackoffReasonBulk", lastRoutingBackoffReasonBulk); fs.put("routingBackoffPercent", backedOffPercent.currentValue() * 100); fs.put("routingBackoffRT", Math.max(Math.max(routingBackedOffUntilRT, transferBackedOffUntilRT) - now, 0)); fs.put("routingBackoffBulk", Math.max(Math.max(routingBackedOffUntilBulk, transferBackedOffUntilBulk) - now, 0)); fs.put("routingBackoffLengthRT", routingBackoffLengthRT); fs.put("routingBackoffLengthBulk", routingBackoffLengthBulk); fs.put("overloadProbability", getPRejected() * 100); fs.put("percentTimeRoutableConnection", getPercentTimeRoutableConnection() * 100); } fs.putSingle("status", getPeerNodeStatusString()); return fs; }
if(logMINOR) Logger.minor(this, "Sending async: " + msg + " : " + cb + " on " + this+" for "+node.getDarknetPortNumber()+" priority "+msg.getPriority()); if(!isConnected()) { if(cb != null) cb.disconnected(); Logger.error(this, "Messages should NOT be relayed as-is, they should always be re-created to clear any sub-messages etc, see comments in Message.java!: "+msg, new Exception("error")); addToLocalNodeSentMessagesToStatistic(msg); MessageItem item = new MessageItem(msg, cb == null ? null : new AsyncMessageCallback[]{cb}, ctr); long now = System.currentTimeMillis(); reportBackoffStatus(now); int maxSize = getMaxPacketSize(); int x = messageQueue.queueAndEstimateSize(item, maxSize); if(x > maxSize || !node.enablePacketCoalescing) { wakeUpSender();
/** * Set sendHandshakeTime, and return whether to fetch the ARK. */ protected boolean innerCalcNextHandshake(boolean successfulHandshakeSend, boolean dontFetchARK, long now) { if(isBurstOnly()) return calcNextHandshakeBurstOnly(now); synchronized(this) { long delay; if(unroutableOlderVersion || unroutableNewerVersion || disableRouting) { // Let them know we're here, but have no hope of routing general data to them. delay = Node.MIN_TIME_BETWEEN_VERSION_SENDS + node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_SENDS); } else if(invalidVersion() && !firstHandshake) { delay = Node.MIN_TIME_BETWEEN_VERSION_PROBES + node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_PROBES); } else { delay = Node.MIN_TIME_BETWEEN_HANDSHAKE_SENDS + node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_HANDSHAKE_SENDS); } // FIXME proper multi-homing support! delay /= (handshakeIPs == null ? 1 : handshakeIPs.length); if(delay < 3000) delay = 3000; sendHandshakeTime = now + delay; if(logMINOR) Logger.minor(this, "Next handshake in "+delay+" on "+this); if(successfulHandshakeSend) firstHandshake = false; handshakeCount++; return handshakeCount == MAX_HANDSHAKE_COUNT; } }
@Override public void run() { PeerNode pn = ref.get(); if(pn == null) return; if(pn.cachedRemoved()) { if(logMINOR && pn.node.peers.havePeer(pn)) { Logger.error(this, "Removed flag is set yet is in peers table?!: "+pn); } else { return; } } if(!pn.node.peers.havePeer(pn)) { if(!pn.cachedRemoved()) Logger.error(this, "Not in peers table but not flagged as removed: "+pn); return; } pn.setPeerNodeStatus(System.currentTimeMillis(), true); } }
@Override public boolean allowLocalAddresses() { synchronized(this) { if(allowLocalAddresses) return true; } return super.allowLocalAddresses(); }
private double calculateMedianPing(PeerNode[] peers) { double[] allPeers = new double[peers.length]; for(int i = 0; i < peers.length; i++) { PeerNode peer = peers[i]; allPeers[i] = peer.averagePingTime(); } Arrays.sort(allPeers); return allPeers[peers.length / 2]; }
public int calculateMaxTransfersOut(PeerNode peer, boolean realTime, double nonOverheadFraction, int maxTransfersOutUpperLimit) { if(peer == null) return Integer.MAX_VALUE; else return Math.min(maxTransfersOutUpperLimit, peer.calculateMaxTransfersOut(getAcceptableBlockTime(realTime), nonOverheadFraction)); }
if ((m.getSource()) instanceof PeerNode) ((PeerNode)m.getSource()).addToLocalNodeReceivedMessagesFromStatistic(m);
public boolean isRoutingBackedOffEither() { long now = System.currentTimeMillis(); double pingTime; synchronized(this) { long routingBackedOffUntil = Math.max(routingBackedOffUntilRT, routingBackedOffUntilBulk); long transferBackedOffUntil = Math.max(transferBackedOffUntilRT, transferBackedOffUntilBulk); if(now < routingBackedOffUntil || now < transferBackedOffUntil) return true; pingTime = averagePingTime(); } if(pingTime > maxPeerPingTime()) return true; return false; }
/** * Call this method when a handshake request has been * sent. */ public void sentHandshake(boolean notRegistered) { if(logMINOR) Logger.minor(this, "sentHandshake(): " + this); calcNextHandshake(true, false, notRegistered); }