Class PeerState

  • Direct Known Subclasses:
    PeerState2

    public class PeerState
    extends Object
    Contain all of the state about a UDP connection to a peer. This is instantiated only after a connection is fully established. Public only for UI peers page. Not a public API, not for external use.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      protected RouterContext _context  
      protected boolean _dead
      have we migrated away from this peer to another newer one?
      protected Map<Long,​InboundMessageState> _inboundMessages
      list of InboundMessageState for active message
      protected boolean _isInbound
      is it inbound?
      protected long _keyEstablishedTime  
      protected long _lastACKSend
      when did we last send ACKs to the peer?
      protected Log _log  
      protected int _mtu
      what is the largest packet we can currently send to the peer?
      protected int _packetsReceivedDuplicate
      how many dup packets were received within the last RETRANSMISSION_PERIOD_WIDTH packets
      protected RemoteHostId _remoteHostId
      cached RemoteHostId, used to find the peerState by remote info
      protected byte[] _remoteIP
      what IP is the peer sending and receiving packets on?
      protected InetAddress _remoteIPAddress
      cached IP address
      protected Hash _remotePeer
      The peer are we talking to.
      protected int _remotePort
      what port is the peer sending and receiving packets on?
      protected int _rtt
      current round trip time estimate
      protected UDPTransport _transport  
      protected long _wantACKSendSince
      when did we decide we need to ACK to this peer?
      protected static int ACK_FREQUENCY
      how frequently do we want to send ACKs to a peer?
      protected static int CLOCK_SKEW_FUDGE  
      static int LARGE_MTU
      IPv4 Max MTU based on measurements, 1350 fits nearly all reasonably small I2NP messages (larger I2NP messages may be up to 1900B-4500B, which isn't going to fit into a live network MTU anyway) TODO VTBM is 2646, it would be nice to fit in two large 2646 / 2 = 1323 1323 + 74 + 46 + 1 + (4 * 9) = 1480 So why not make it 1492 (old ethernet is 1492, new is 1500) Changed to 1492 in 0.8.9 BUT through 0.8.11, size estimate was bad, actual packet was up to 48 bytes bigger To be figured out.
      static int MAX_IPV6_MTU  
      static int MAX_MTU
      Max of IPv4 and IPv6 max MTUs
      static int MIN_IPV6_MTU
      IPv6/UDP header is 48 bytes, so we want MTU % 16 == 0.
      static int MIN_MTU
      IPv4 Min MTU 596 gives us 588 IP byes, 568 UDP bytes, and with an SSU data message, 522 fragment bytes, which is enough to send a tunnel data message in 2 packets.
      (package private) static long RETRANSMISSION_PERIOD_WIDTH
      how many packets will be considered within the retransmission rate calculation
    • Field Detail

      • _log

        protected final Log _log
      • _remotePeer

        protected final Hash _remotePeer
        The peer are we talking to. This should be set as soon as this state is created if we are initiating a connection, but if we are receiving the connection this will be set only after the connection is established.
      • _keyEstablishedTime

        protected final long _keyEstablishedTime
      • _lastACKSend

        protected volatile long _lastACKSend
        when did we last send ACKs to the peer?
      • _wantACKSendSince

        protected volatile long _wantACKSendSince
        when did we decide we need to ACK to this peer?
      • _remoteIP

        protected final byte[] _remoteIP
        what IP is the peer sending and receiving packets on?
      • _remoteIPAddress

        protected volatile InetAddress _remoteIPAddress
        cached IP address
      • _remotePort

        protected volatile int _remotePort
        what port is the peer sending and receiving packets on?
      • _remoteHostId

        protected volatile RemoteHostId _remoteHostId
        cached RemoteHostId, used to find the peerState by remote info
      • _mtu

        protected int _mtu
        what is the largest packet we can currently send to the peer?
      • _rtt

        protected int _rtt
        current round trip time estimate
      • RETRANSMISSION_PERIOD_WIDTH

        static final long RETRANSMISSION_PERIOD_WIDTH
        how many packets will be considered within the retransmission rate calculation
        See Also:
        Constant Field Values
      • _packetsReceivedDuplicate

        protected int _packetsReceivedDuplicate
        how many dup packets were received within the last RETRANSMISSION_PERIOD_WIDTH packets
      • _inboundMessages

        protected final Map<Long,​InboundMessageState> _inboundMessages
        list of InboundMessageState for active message
      • _dead

        protected volatile boolean _dead
        have we migrated away from this peer to another newer one?
      • _isInbound

        protected final boolean _isInbound
        is it inbound?
      • MIN_MTU

        public static final int MIN_MTU
        IPv4 Min MTU 596 gives us 588 IP byes, 568 UDP bytes, and with an SSU data message, 522 fragment bytes, which is enough to send a tunnel data message in 2 packets. A tunnel data message sent over the wire is 1044 bytes, meaning we need 522 fragment bytes to fit it in 2 packets - add 46 for SSU, 20 for UDP, and 8 for IP, giving us 596. round up to mod 16, giving a total of 608 Well, we really need to count the acks as well, especially 1 + (4 * MAX_RESEND_ACKS_SMALL) which can take up a significant amount of space. We reduce the max acks when using the small MTU but it may not be enough... Goal: VTBM msg fragments 2646 / (620 - 87) fits nicely. Assuming that we can enforce an MTU correctly, this % 16 should be 12, as the IP/UDP header is 28 bytes and data max should be mulitple of 16 for padding efficiency, and so PacketBuilder.buildPacket() works correctly.
        See Also:
        Constant Field Values
      • MIN_IPV6_MTU

        public static final int MIN_IPV6_MTU
        IPv6/UDP header is 48 bytes, so we want MTU % 16 == 0.
        See Also:
        Constant Field Values
      • LARGE_MTU

        public static final int LARGE_MTU
        IPv4 Max MTU based on measurements, 1350 fits nearly all reasonably small I2NP messages (larger I2NP messages may be up to 1900B-4500B, which isn't going to fit into a live network MTU anyway) TODO VTBM is 2646, it would be nice to fit in two large 2646 / 2 = 1323 1323 + 74 + 46 + 1 + (4 * 9) = 1480 So why not make it 1492 (old ethernet is 1492, new is 1500) Changed to 1492 in 0.8.9 BUT through 0.8.11, size estimate was bad, actual packet was up to 48 bytes bigger To be figured out. Curse the ACKs. Assuming that we can enforce an MTU correctly, this % 16 should be 12, as the IP/UDP header is 28 bytes and data max should be mulitple of 16 for padding efficiency, and so PacketBuilder.buildPacket() works correctly.
        See Also:
        Constant Field Values
      • MAX_MTU

        public static final int MAX_MTU
        Max of IPv4 and IPv6 max MTUs
        Since:
        0.9.28
      • ACK_FREQUENCY

        protected static final int ACK_FREQUENCY
        how frequently do we want to send ACKs to a peer?
        See Also:
        Constant Field Values
    • Method Detail

      • getVersion

        public int getVersion()
        Since:
        0.9.54
      • changePort

        void changePort​(int newPort)
        Caller should sync; UDPTransport must remove and add to peersByRemoteHost map
        Since:
        0.9.3
      • getRemotePeer

        public Hash getRemotePeer()
        The peer are we talking to. Non-null.
      • getKeyEstablishedTime

        public long getKeyEstablishedTime()
        When were the current cipher and MAC keys established/rekeyed? This is the connection uptime.
      • getClockSkew

        public long getClockSkew()
        How far off is the remote peer from our clock, in milliseconds? A positive number means our clock is ahead of theirs.
      • getLastSendTime

        public long getLastSendTime()
        When did we last send them a packet? Set for data, relay, and peer test, but not acks, pings, or termination
      • getLastSendFullyTime

        public long getLastSendFullyTime()
        when did we last send them a message that was ACKed?
      • getLastReceiveTime

        public long getLastReceiveTime()
        When did we last receive a packet from them? Set for data, relay, and peer test, but not acks, pings, or termination
      • getConsecutiveFailedSends

        public int getConsecutiveFailedSends()
        how many seconds have we sent packets without any ACKs received?
      • getSendWindowBytes

        public int getSendWindowBytes()
        how many bytes should we send to the peer in a second 1st stat in CWND column, otherwise unused, candidate for removal
      • getSendWindowBytesRemaining

        public int getSendWindowBytesRemaining()
        how many bytes can we send to the peer in the current second
      • getRemoteIP

        public byte[] getRemoteIP()
        what IP is the peer sending and receiving packets on?
      • getRemoteIPAddress

        public InetAddress getRemoteIPAddress()
        Returns:
        may be null if IP is invalid
      • getRemotePort

        public int getRemotePort()
        what port is the peer sending and receiving packets on?
      • getWeRelayToThemAs

        public long getWeRelayToThemAs()
        if we are serving as an introducer to them, this is the the tag that they can publish that, when presented to us, will cause us to send a relay introduction to the current peer
        Returns:
        0 (no relay) if unset previously
      • getTheyRelayToUsAs

        public long getTheyRelayToUsAs()
        If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
        Returns:
        0 (no relay) if unset previously
      • getMTU

        public int getMTU()
        what is the largest packet we can send to the peer?
      • getReceiveMTU

        public int getReceiveMTU()
        Estimate how large the other side's MTU is. This could be wrong. It is used only for the HTML status.
      • adjustClockSkew

        void adjustClockSkew​(long skew)
        Update the moving-average clock skew based on the current difference. The raw skew will be adjusted for RTT/2 here. A positive number means our clock is ahead of theirs.
        Parameters:
        skew - milliseconds, NOT adjusted for RTT.
      • setLastSendTime

        void setLastSendTime​(long when)
        When did we last send them a packet? Set for data, relay, and peer test, but not acks, pings, or termination
      • setLastReceiveTime

        void setLastReceiveTime​(long when)
        When did we last receive a packet from them? Set for data, relay, and peer test, but not acks, pings, or termination
      • setLastPingTime

        void setLastPingTime​(long when)
        Note ping sent. Does not update last send time.
        Since:
        0.9.3
      • getLastSendOrPingTime

        long getLastSendOrPingTime()
        Latest of last sent, last ACK, last ping
        Since:
        0.9.3
      • getSendBps

        public int getSendBps​(long now)
        The Westwood+ bandwidth estimate
        Returns:
        the smoothed send transfer rate
      • getReceiveBps

        public int getReceiveBps​(long now)
        An approximation, for display only
        Returns:
        the smoothed receive transfer rate
      • incrementConsecutiveFailedSends

        int incrementConsecutiveFailedSends()
      • getInactivityTime

        public long getInactivityTime()
      • setWeRelayToThemAs

        void setWeRelayToThemAs​(long tag)
        if we are serving as an introducer to them, this is the the tag that they can publish that, when presented to us, will cause us to send a relay introduction to the current peer
        Parameters:
        tag - 1 to Integer.MAX_VALUE, or 0 if relaying disabled
      • setTheyRelayToUsAs

        void setTheyRelayToUsAs​(long tag)
        If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
        Parameters:
        tag - 1 to Integer.MAX_VALUE, or 0 if relaying disabled
      • getSlowStartThreshold

        public int getSlowStartThreshold()
        stat in SST column, otherwise unused, candidate for removal
      • getConcurrentSends

        public int getConcurrentSends()
        2nd stat in CWND column, otherwise unused, candidate for removal
      • getConcurrentSendWindow

        public int getConcurrentSendWindow()
        3rd stat in CWND column, otherwise unused, candidate for removal
      • getConsecutiveSendRejections

        public int getConsecutiveSendRejections()
        4th stat in CWND column, otherwise unused, candidate for removal
      • isInbound

        public boolean isInbound()
      • isIPv6

        public boolean isIPv6()
        Since:
        IPv6
      • getIntroducerTime

        long getIntroducerTime()
        the last time we used them as an introducer, or 0
      • setIntroducerTime

        void setIntroducerTime()
        set the last time we used them as an introducer to now
      • messageFullyReceived

        void messageFullyReceived​(Long messageId,
                                  int bytes)
        We received the message specified completely.
        Parameters:
        bytes - if less than or equal to zero, message is a duplicate.
      • messagePartiallyReceived

        void messagePartiallyReceived()
        We received a partial message, or we want to send some acks.
      • messagePartiallyReceived

        protected void messagePartiallyReceived​(long now)
        We received a partial message, or we want to send some acks. SSU1 only, see override
        Since:
        0.9.52
      • getInboundMessages

        Map<Long,​InboundMessageState> getInboundMessages()
        Fetch the internal id (Long) to InboundMessageState for incomplete inbound messages. Access to this map must be synchronized explicitly!
      • expireInboundMessages

        int expireInboundMessages()
        Expire partially received inbound messages, returning how many are still pending. This should probably be fired periodically, in case a peer goes silent and we don't try to send them any messages (and don't receive any messages from them either)
      • setHisMTU

        void setHisMTU​(int mtu)
        Since:
        0.9.2
      • messageRetransmitted

        void messageRetransmitted​(int packets,
                                  int maxPktSz)
        we are resending a packet, so lets jack up the rto
      • packetsTransmitted

        void packetsTransmitted​(int packets)
      • getRTT

        public int getRTT()
        how long does it usually take to get a message ACKed?
      • getRTO

        public int getRTO()
        how soon should we retransmit an unacked packet?
      • getRTTDeviation

        public int getRTTDeviation()
        how skewed are the measured RTTs?
      • getMessagesSent

        public int getMessagesSent()
        I2NP messages sent. Does not include duplicates. As of 0.9.24, incremented when bandwidth is allocated just before sending, not when acked.
      • getMessagesReceived

        public int getMessagesReceived()
        I2NP messages received. As of 0.9.24, does not include duplicates.
      • getPacketsTransmitted

        public int getPacketsTransmitted()
      • getPacketsRetransmitted

        public int getPacketsRetransmitted()
      • getPacketsReceived

        public int getPacketsReceived()
      • getPacketsReceivedDuplicate

        public int getPacketsReceivedDuplicate()
      • packetReceived

        void packetReceived​(int size)
        Parameters:
        size - not including IP header, UDP header, MAC or IV
      • ECNReceived

        void ECNReceived()
        We received a backoff request, so cut our send window. NOTE: ECN sending is unimplemented, this is never called.
      • dataReceived

        void dataReceived()
        Same as setLastReceivedTime(now)
      • getLastACKSend

        public long getLastACKSend()
        when did we last send an ACK to the peer?
      • clearWantedACKSendSince

        void clearWantedACKSendSince()
        All acks have been sent. SSU 1 only, see override
        Since:
        0.9.52
      • getRemoteHostId

        public RemoteHostId getRemoteHostId()
        Returns:
        non-null
        Since:
        public since 0.9.57 for SSU2Sender interface only
      • add

        void add​(OutboundMessageState state)
        TODO should this use a queue, separate from the list of msgs pending an ack? TODO bring back tail drop? TODO priority queue? (we don't implement priorities in SSU now) TODO backlog / pushback / block instead of dropping? Can't really block here. TODO SSU does not support isBacklogged() now
      • dropOutbound

        void dropOutbound()
        drop all outbound messages
      • getOutboundMessageCount

        public int getOutboundMessageCount()
        Returns:
        number of active outbound messages remaining (unsynchronized)
      • setMayDisconnect

        public void setMayDisconnect()
        Sets to true.
        Since:
        0.9.24
      • getMayDisconnect

        public boolean getMayDisconnect()
        Since:
        0.9.24
      • finishMessages

        int finishMessages​(long now)
        Expire / complete any outbound messages High usage - OutboundMessageFragments.getNextVolley() calls this 1st. TODO combine finishMessages(), allocateSend(), and getNextDelay() so we don't iterate 3 times.
        Returns:
        number of active outbound messages remaining
      • allocateSend

        List<OutboundMessageState> allocateSend​(long now)
        Pick one or more messages we want to send and allocate them out of our window Adjusts the retransmit timer if necessary. High usage - OutboundMessageFragments.getNextVolley() calls this 2nd, if finishMessages() returned > 0. TODO combine finishMessages() and allocateSend() so we don't iterate 2 times.
        Returns:
        allocated messages to send (never empty), or null if no messages or no resources
      • getNextDelay

        int getNextDelay​(long now)
        High usage - OutboundMessageFragments.getNextVolley() calls this 3rd, if allocateSend() returned null. TODO combine finishMessages(), allocateSend() so we don't iterate 2 times.
        Parameters:
        now - what time it is now
        Returns:
        how long to wait before sending, or Integer.MAX_VALUE if we have nothing to send. If ready now, will return 0.
      • isBacklogged

        public boolean isBacklogged()
        Since:
        0.9.3
      • fragmentSize

        int fragmentSize()
        how much payload data can we shove in there?
        Returns:
        MTU - 87, i.e. 533 or 1397 (IPv4), MTU - 107 (IPv6)
      • fragmentOverhead

        int fragmentOverhead()
        Packet overhead plus room for acks
        Returns:
        87 (IPv4), 107 (IPv6)
        Since:
        0.9.49
      • acked

        protected boolean acked​(PacketBuilder.Fragment f)
        An ACK of a fragment was received. SSU 2 only.
        Returns:
        true if this fragment of the message was acked for the first time
      • highestSeqNumAcked

        boolean highestSeqNumAcked​(long highest)
        Enter or leave fast retransmit mode, and adjust SST and window variables accordingly. See RFC 5681 sec. 2.4
        Parameters:
        highest - the highest sequence number that was acked
        Returns:
        true if we have something to fast-retransmit
        Since:
        0.9.49
      • shouldRequestImmediateAck

        protected boolean shouldRequestImmediateAck()
        SSU 2 only
        Since:
        0.9.56
      • loadFrom

        void loadFrom​(PeerState oldPeer)
        Transfer the basic activity/state from the old peer to the current peer SSU 1 or 2.
        Parameters:
        oldPeer - non-null
      • getTransport

        UDPTransport getTransport()
        Convenience for OutboundMessageState so it can fail itself
        Since:
        0.9.3