net.i2p.router.transport.udp
Class PeerState

java.lang.Object
  extended by net.i2p.router.transport.udp.PeerState

 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.


Field Summary
static int INIT_RTT
           
static int LARGE_MTU
           
static int MAX_IPV6_MTU
           
static int MIN_IPV6_MTU
          IPv6/UDP header is 48 bytes, so we want MTU % 16 == 0.
static int MIN_MTU
           
(package private) static long RETRANSMISSION_PERIOD_WIDTH
          how many packets will be considered within the retransmission rate calculation
 
Constructor Summary
PeerState(RouterContext ctx, UDPTransport transport, byte[] remoteIP, int remotePort, Hash remotePeer, boolean isInbound)
           
 
Method Summary
 boolean acked(ACKBitfield bitfield)
          A partial ACK was received.
 boolean acked(long messageId)
          A full ACK was received.
 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.
 void adjustClockSkew(long skew)
          Update the moving-average clock skew based on the current difference.
 List<OutboundMessageState> allocateSend()
          Pick one or more messages we want to send and allocate them out of our window High usage - OutboundMessageFragments.getNextVolley() calls this 2nd, if finishMessages() returned > 0.
 void changePort(int newPort)
          Caller should sync; UDPTransport must remove and add to peersByRemoteHost map
 void dataReceived()
           
 void dropOutbound()
          drop all outbound messages
 void ECNReceived()
          We received a backoff request, so cut our send window.
 int expireInboundMessages()
          Expire partially received inbound messages, returning how many are still pending.
(package private)  void fetchPartialACKs(List<ACKBitfield> rv)
           
 int finishMessages()
          Expire / complete any outbound messages High usage - OutboundMessageFragments.getNextVolley() calls this 1st.
 int fragmentSize()
          how much payload data can we shove in there?
 long getClockSkew()
          How far off is the remote peer from our clock, in milliseconds? A positive number means our clock is ahead of theirs.
 int getConcurrentSends()
           
 int getConcurrentSendWindow()
           
 int getConsecutiveFailedSends()
          how many seconds have we sent packets without any ACKs received?
 int getConsecutiveSendRejections()
           
 SessionKey getCurrentCipherKey()
          The AES key used to encrypt/decrypt packets, set only after the connection is established.
 List<Long> getCurrentFullACKs()
          Grab a list of message ids (Long) that we want to send to the remote peer, regardless of the packet size, but don't remove it from our "want to send" list.
 SessionKey getCurrentMACKey()
          The AES key used to verify packets, set only after the connection is established.
 long getCurrentReceiveSecond()
          what is the current receive second, for congestion control?
 List<Long> getCurrentResendACKs()
          Grab a list of message ids (Long) that we want to send to the remote peer, regardless of the packet size, but don't remove it from our "want to send" list.
 boolean getCurrentSecondECNReceived()
          Deprecated. unused, ECNs are never sent, always returns false
 long getInactivityTime()
           
 Map<Long,InboundMessageState> getInboundMessages()
          Fetch the internal id (Long) to InboundMessageState for incomplete inbound messages.
 long getIntroducerTime()
           
 long getKeyEstablishedTime()
          when were the current cipher and MAC keys established/rekeyed?
 long getLastACKSend()
          when did we last send an ACK to the peer?
 long getLastReceiveTime()
          when did we last receive a packet from them?
 long getLastSendFullyTime()
          when did we last send them a message that was ACKed?
 long getLastSendOrPingTime()
          Latest of last sent, last ACK, last ping
 long getLastSendTime()
          when did we last send them a packet?
 int getMessagesReceived()
           
 int getMessagesSent()
           
 int getMTU()
          what is the largest packet we can send to the peer?
 SessionKey getNextCipherKey()
          The pending AES key for encrypting/decrypting packets if we are rekeying the connection, or null if we are not in the process of rekeying.
 int getNextDelay()
          High usage - OutboundMessageFragments.getNextVolley() calls this 3rd, if allocateSend() returned null.
 SessionKey getNextMACKey()
          The pending AES key for verifying packets if we are rekeying the connection, or null if we are not in the process of rekeying.
 int getOutboundMessageCount()
           
 int getPacketsReceived()
          avg number of packets retransmitted for every 100 packets
 int getPacketsReceivedDuplicate()
           
 int getPacketsRetransmitted()
           
 int getPacketsTransmitted()
           
 int getReceiveBps()
           
 int getReceiveMTU()
          Estimate how large the other side's MTU is.
(package private)  RemoteHostId getRemoteHostId()
           
 byte[] getRemoteIP()
          what IP is the peer sending and receiving packets on?
 InetAddress getRemoteIPAddress()
           
 Hash getRemotePeer()
          The peer are we talking to.
 int getRemotePort()
          what port is the peer sending and receiving packets on?
 int getRTO()
          how soon should we retransmit an unacked packet?
 int getRTT()
          how long does it usually take to get a message ACKed?
 int getRTTDeviation()
          how skewed are the measured RTTs?
 int getSendBps()
          return the smoothed send transfer rate
 int getSendWindowBytes()
          how many bytes should we send to the peer in a second
 int getSendWindowBytesRemaining()
          how many bytes can we send to the peer in the current second
 int getSlowStartThreshold()
          public void setMTU(int mtu) { _mtu = mtu; _mtuLastChecked = _context.clock().now(); }
 long getTheyRelayToUsAs()
          If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
 UDPTransport getTransport()
          Convenience for OutboundMessageState so it can fail itself
 long getWantedACKSendSince()
           
 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
 int incrementConsecutiveFailedSends()
           
 boolean isBacklogged()
           
 boolean isInbound()
           
 boolean isIPv6()
           
 void loadFrom(PeerState oldPeer)
          Transfer the basic activity/state from the old peer to the current peer
 void messageFullyReceived(Long messageId, int bytes)
          we received the message specified completely
 void messageFullyReceived(Long messageId, int bytes, boolean isForACK)
           
 void messagePartiallyReceived()
           
 void messageRetransmitted(int packets)
          we are resending a packet, so lets jack up the rto
 void packetReceived(int size)
           
 void packetsTransmitted(int packets)
           
 void removeACKMessage(Long messageId)
          The ack was sent.
 List<ACKBitfield> retrieveACKBitfields()
          Deprecated. unused
 List<ACKBitfield> retrieveACKBitfields(boolean alwaysIncludeRetransmissions)
          See above.
 void setCurrentCipherKey(SessionKey key)
          The AES key used to encrypt/decrypt packets, set only after the connection is established.
 void setCurrentMACKey(SessionKey key)
          The AES key used to verify packets, set only after the connection is established.
 void setCurrentReceiveSecond(long sec)
          what is the current receive second, for congestion control?
 void setHisMTU(int mtu)
           
 void setIntroducerTime()
           
 void setKeyEstablishedTime(long when)
          Deprecated. unused
 void setLastACKSend(long when)
          Deprecated. unused
 void setLastPingTime(long when)
          Note ping sent.
 void setLastReceiveTime(long when)
          when did we last receive a packet from them?
 void setLastSendTime(long when)
          when did we last send them a packet?
 void setNextCipherKey(SessionKey key)
          Deprecated. unused
 void setNextMACKey(SessionKey key)
          Deprecated. unused
 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.
 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
 String toString()
           
 boolean unsentACKThresholdReached()
          Are we out of room to send all the current unsent acks in a single packet? This is a huge threshold (134 for small MTU and 255 for large MTU) that is rarely if ever exceeded in practice.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

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

MIN_MTU

public static final int MIN_MTU
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

MAX_IPV6_MTU

public static final int MAX_IPV6_MTU
See Also:
Constant Field Values

LARGE_MTU

public static final int LARGE_MTU
See Also:
Constant Field Values

INIT_RTT

public static final int INIT_RTT
See Also:
Constant Field Values
Constructor Detail

PeerState

public PeerState(RouterContext ctx,
                 UDPTransport transport,
                 byte[] remoteIP,
                 int remotePort,
                 Hash remotePeer,
                 boolean isInbound)
Method Detail

changePort

public 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. 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.


getCurrentMACKey

public SessionKey getCurrentMACKey()
The AES key used to verify packets, set only after the connection is established.


getCurrentCipherKey

public SessionKey getCurrentCipherKey()
The AES key used to encrypt/decrypt packets, set only after the connection is established.


getNextMACKey

public SessionKey getNextMACKey()
The pending AES key for verifying packets if we are rekeying the connection, or null if we are not in the process of rekeying.

Returns:
null always, rekeying unimplemented

getNextCipherKey

public SessionKey getNextCipherKey()
The pending AES key for encrypting/decrypting packets if we are rekeying the connection, or null if we are not in the process of rekeying.

Returns:
null always, rekeying unimplemented

getKeyEstablishedTime

public long getKeyEstablishedTime()
when were the current cipher and MAC keys established/rekeyed?


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.


getCurrentReceiveSecond

public long getCurrentReceiveSecond()
what is the current receive second, for congestion control?


getLastSendTime

public long getLastSendTime()
when did we last send them a packet?


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?


getConsecutiveFailedSends

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


getCurrentSecondECNReceived

public boolean getCurrentSecondECNReceived()
Deprecated. unused, ECNs are never sent, always returns false

have we received a packet with the ECN bit set in the current second?

Returns:
false always

getSendWindowBytes

public int getSendWindowBytes()
how many bytes should we send to the peer in a second


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.


setCurrentMACKey

public void setCurrentMACKey(SessionKey key)
The AES key used to verify packets, set only after the connection is established.


setCurrentCipherKey

public void setCurrentCipherKey(SessionKey key)
The AES key used to encrypt/decrypt packets, set only after the connection is established.


setNextMACKey

public void setNextMACKey(SessionKey key)
Deprecated. unused

The pending AES key for verifying packets if we are rekeying the connection, or null if we are not in the process of rekeying.


setNextCipherKey

public void setNextCipherKey(SessionKey key)
Deprecated. unused

The pending AES key for encrypting/decrypting packets if we are rekeying the connection, or null if we are not in the process of rekeying.


setKeyEstablishedTime

public void setKeyEstablishedTime(long when)
Deprecated. unused

when were the current cipher and MAC keys established/rekeyed?


adjustClockSkew

public 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.

setCurrentReceiveSecond

public void setCurrentReceiveSecond(long sec)
what is the current receive second, for congestion control?


setLastSendTime

public void setLastSendTime(long when)
when did we last send them a packet?


setLastReceiveTime

public void setLastReceiveTime(long when)
when did we last receive a packet from them?


setLastPingTime

public void setLastPingTime(long when)
Note ping sent. Does not update last send time.

Since:
0.9.3

getLastSendOrPingTime

public long getLastSendOrPingTime()
Latest of last sent, last ACK, last ping

Since:
0.9.3

getSendBps

public int getSendBps()
return the smoothed send transfer rate


getReceiveBps

public int getReceiveBps()

incrementConsecutiveFailedSends

public int incrementConsecutiveFailedSends()

getInactivityTime

public long getInactivityTime()

setWeRelayToThemAs

public 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

public 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()
public void setMTU(int mtu) { _mtu = mtu; _mtuLastChecked = _context.clock().now(); }


getConcurrentSends

public int getConcurrentSends()

getConcurrentSendWindow

public int getConcurrentSendWindow()

getConsecutiveSendRejections

public int getConsecutiveSendRejections()

isInbound

public boolean isInbound()

isIPv6

public boolean isIPv6()
Since:
IPv6

getIntroducerTime

public long getIntroducerTime()

setIntroducerTime

public void setIntroducerTime()

messageFullyReceived

public void messageFullyReceived(Long messageId,
                                 int bytes)
we received the message specified completely


messageFullyReceived

public void messageFullyReceived(Long messageId,
                                 int bytes,
                                 boolean isForACK)

messagePartiallyReceived

public void messagePartiallyReceived()

getInboundMessages

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


expireInboundMessages

public 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)


getCurrentFullACKs

public List<Long> getCurrentFullACKs()
Grab a list of message ids (Long) that we want to send to the remote peer, regardless of the packet size, but don't remove it from our "want to send" list. If the message id is transmitted to the peer, removeACKMessage(Long) should be called. The returned list contains acks not yet sent only. The caller should NOT transmit all of them all the time, even if there is room, or the packets will have way too much overhead.

Returns:
a new list, do as you like with it

getCurrentResendACKs

public List<Long> getCurrentResendACKs()
Grab a list of message ids (Long) that we want to send to the remote peer, regardless of the packet size, but don't remove it from our "want to send" list. The returned list contains a random assortment of acks already sent. The caller should NOT transmit all of them all the time, even if there is room, or the packets will have way too much overhead.

Returns:
a new list, do as you like with it
Since:
0.8.12 was included in getCurrentFullACKs()

removeACKMessage

public void removeACKMessage(Long messageId)
The ack was sent. Side effect - sets _lastACKSend


retrieveACKBitfields

public List<ACKBitfield> retrieveACKBitfields()
Deprecated. unused

grab a list of ACKBitfield instances, some of which may fully ACK a message while others may only partially ACK a message. the values returned are limited in size so that they will fit within the peer's current MTU as an ACK - as such, not all messages may be ACKed with this call. Be sure to check getWantedACKSendSince() which will be unchanged if there are ACKs remaining.

Returns:
non-null, possibly empty

retrieveACKBitfields

public List<ACKBitfield> retrieveACKBitfields(boolean alwaysIncludeRetransmissions)
See above. Only called by ACKSender with alwaysIncludeRetransmissions = false. So this is only for ACK-only packets, so all the size limiting is useless. FIXME. Side effect - sets _lastACKSend if rv is non-empty

Returns:
non-null, possibly empty

fetchPartialACKs

void fetchPartialACKs(List<ACKBitfield> rv)
Parameters:
rv - out parameter, populated with true partial ACKBitfields. no full bitfields are included.

setHisMTU

public void setHisMTU(int mtu)
Since:
0.9.2

messageRetransmitted

public void messageRetransmitted(int packets)
we are resending a packet, so lets jack up the rto


packetsTransmitted

public 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()

getMessagesReceived

public int getMessagesReceived()

getPacketsTransmitted

public int getPacketsTransmitted()

getPacketsRetransmitted

public int getPacketsRetransmitted()

getPacketsReceived

public int getPacketsReceived()
avg number of packets retransmitted for every 100 packets


getPacketsReceivedDuplicate

public int getPacketsReceivedDuplicate()

packetReceived

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

ECNReceived

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


dataReceived

public void dataReceived()

getLastACKSend

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


setLastACKSend

public void setLastACKSend(long when)
Deprecated. unused


getWantedACKSendSince

public long getWantedACKSendSince()

unsentACKThresholdReached

public boolean unsentACKThresholdReached()
Are we out of room to send all the current unsent acks in a single packet? This is a huge threshold (134 for small MTU and 255 for large MTU) that is rarely if ever exceeded in practice. So just use a fixed threshold of half the resend acks, so that if the packet is lost the acks have a decent chance of getting retransmitted. Used only by ACKSender.


getRemoteHostId

RemoteHostId getRemoteHostId()
Returns:
non-null

add

public 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

public void dropOutbound()
drop all outbound messages


getOutboundMessageCount

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

finishMessages

public int finishMessages()
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

public List<OutboundMessageState> allocateSend()
Pick one or more messages we want to send and allocate them out of our window High usage - OutboundMessageFragments.getNextVolley() calls this 2nd, if finishMessages() returned > 0. TODO combine finishMessages(), allocateSend(), and getNextDelay() so we don't iterate 3 times.

Returns:
allocated messages to send (never empty), or null if no messages or no resources

getNextDelay

public int getNextDelay()
High usage - OutboundMessageFragments.getNextVolley() calls this 3rd, if allocateSend() returned null. TODO combine finishMessages(), allocateSend(), and getNextDelay() so we don't iterate 3 times.

Returns:
how long to wait before sending, or Integer.MAX_VALUE if we have nothing to send. If ready now, will return 0 or a negative value.

isBacklogged

public boolean isBacklogged()
Since:
0.9.3

fragmentSize

public int fragmentSize()
how much payload data can we shove in there?

Returns:
MTU - 87, i.e. 533 or 1397 (IPv4), MTU - 107 (IPv6)

acked

public boolean acked(long messageId)
A full ACK was received. TODO if messages awaiting ack were a HashMap this would be faster.

Returns:
true if the message was acked for the first time

acked

public boolean acked(ACKBitfield bitfield)
A partial ACK was received. This is much less common than full ACKs.

Returns:
true if the message was completely acked for the first time

loadFrom

public void loadFrom(PeerState oldPeer)
Transfer the basic activity/state from the old peer to the current peer

Parameters:
oldPeer - non-null

getTransport

public UDPTransport getTransport()
Convenience for OutboundMessageState so it can fail itself

Since:
0.9.3

toString

public String toString()
Overrides:
toString in class Object