net.i2p.client.streaming.impl
Class Connection

java.lang.Object
  extended by net.i2p.client.streaming.impl.Connection

 class Connection
extends Object

Maintain the state controlling a streaming connection between two destinations.


Nested Class Summary
(package private)  class Connection.ConEvent
          fired to reschedule event notification
(package private)  class Connection.ResendPacketEvent
          Coordinate the resends of a given packet
 
Field Summary
static int DEFAULT_CONNECT_TIMEOUT
           
static int DISCONNECT_TIMEOUT
          Wait up to 5 minutes after disconnection so we can ack/close packets.
(package private) static int FAST_RETRANSMIT_THRESHOLD
          If we have been explicitly NACKed three times, retransmit the packet even if there are other packets in flight.
static long MAX_RESEND_DELAY
           
static int MAX_WINDOW_SIZE
           
static long MIN_RESEND_DELAY
           
 
Constructor Summary
Connection(I2PAppContext ctx, ConnectionManager manager, I2PSession session, SchedulerChooser chooser, SimpleTimer2 timer, PacketQueue queue, ConnectionPacketHandler handler, ConnectionOptions opts, boolean isInbound)
           
 
Method Summary
(package private)  void ackImmediately()
           
 List<PacketLocal> ackPackets(long ackThrough, long[] nacks)
          Process the acks and nacks received in a packet
 void closeReceived()
          Notify that a close was received.
 void disconnect(boolean cleanDisconnect)
          Must be called when we are done with this connection.
 void disconnect(boolean cleanDisconnect, boolean removeFromConMgr)
          Must be called when we are done with this connection.
 void disconnectComplete()
          Must be called when we are done with this connection.
(package private)  void eventOccurred()
           
 long getAckedPackets()
          how many packets have we sent and the other side has ACKed?
 long getCloseReceivedOn()
           
 long getCloseSentOn()
           
 long getCongestionWindowEnd()
           
 String getConnectionError()
           
 ConnectionManager getConnectionManager()
           
 long getCreatedOn()
           
 long getDisconnectScheduledOn()
           
 boolean getHardDisconnected()
           
 long getHighestAckedThrough()
           
 MessageInputStream getInputStream()
          stream that the local peer receives data on
 boolean getIsConnected()
          Always true at the start, even if we haven't gotten a reply on an outbound connection.
 long getLastActivityOn()
           
 int getLastCongestionSeenAt()
           
 long getLastSendId()
          What was the last packet Id sent to the peer?
 long getLastSendTime()
          When did we last send anything to the peer?
 long getLifetime()
           
 long getLifetimeBytesReceived()
           
 long getLifetimeBytesSent()
           
 long getLifetimeDupMessagesReceived()
           
 long getLifetimeDupMessagesSent()
           
 int getLocalPort()
           
 long getNextOutboundPacketNum()
           
 long getNextSendTime()
          Time when the scheduler next want to send a packet, or -1 if never.
 ConnectionOptions getOptions()
          Retrieve the current ConnectionOptions.
 MessageOutputStream getOutputStream()
          stream that the local peer sends data to the remote peer on
 ConnectionPacketHandler getPacketHandler()
           
 int getPort()
          The remote port.
 long getReceiveStreamId()
          The stream ID of a peer connection that sends data to us, or zero if unknown.
 Destination getRemotePeer()
          who are we talking with
 boolean getResetReceived()
           
 boolean getResetSent()
           
 long getResetSentOn()
           
 long getSendStreamId()
          What stream do we send data to the peer on?
 I2PSession getSession()
           
 I2PSocketFull getSocket()
           
 int getUnackedPacketsReceived()
           
 int getUnackedPacketsSent()
          how many packets have we sent but not yet received an ACK for?
 void incrementBytesReceived(int bytes)
           
 void incrementBytesSent(int bytes)
           
 void incrementDupMessagesReceived(int msgs)
           
 void incrementDupMessagesSent(int msgs)
           
 void incrementUnackedPacketsReceived()
           
 boolean isInbound()
           
 void notifyCloseSent()
          Notify that a close was sent.
 void notifyLastPacketAcked()
          Notify that a close that we sent, and all previous packets, were acked.
(package private)  void packetReceived()
           
 boolean packetSendChoke(long timeoutMs)
          This doesn't "send a choke".
 void resetReceived()
          Notify that a reset was received.
 void schedule(SimpleTimer.TimedEvent event, long msToWait)
          Schedule something on our timer.
 void scheduleConnectionEvent(long msToWait)
          Called from SchedulerImpl
(package private)  void sendAvailable()
          Flush any data that we can.
(package private)  void sendPacket(PacketLocal packet)
           
 void setCongestionWindowEnd(long endMsg)
           
 void setConnectionError(String err)
           
 void setLastSendId(long id)
          Set the packet Id that was sent to a peer.
 void setNextSendTime(long when)
          If the next send time is currently >= 0 (i.e.
 void setOptions(ConnectionOptions opts)
          Set the ConnectionOptions.
 void setReceiveStreamId(long id)
           
 void setRemotePeer(Destination peer)
           
 void setSendStreamId(long id)
           
 void setSocket(I2PSocketFull socket)
           
 String toString()
           
 void updateShareOpts()
           
(package private)  void waitForConnect()
          wait until a connection is made or the connection fails within the timeout period, setting the error accordingly.
(package private)  void windowAdjusted()
          Notify all threads waiting in packetSendChoke()
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

MAX_RESEND_DELAY

public static final long MAX_RESEND_DELAY
See Also:
Constant Field Values

MIN_RESEND_DELAY

public static final long MIN_RESEND_DELAY
See Also:
Constant Field Values

DISCONNECT_TIMEOUT

public static final int DISCONNECT_TIMEOUT
Wait up to 5 minutes after disconnection so we can ack/close packets. Roughly equal to the TIME-WAIT time in RFC 793, where the recommendation is 4 minutes (2 * MSL)

See Also:
Constant Field Values

DEFAULT_CONNECT_TIMEOUT

public static final int DEFAULT_CONNECT_TIMEOUT
See Also:
Constant Field Values

MAX_WINDOW_SIZE

public static final int MAX_WINDOW_SIZE
See Also:
Constant Field Values

FAST_RETRANSMIT_THRESHOLD

static final int FAST_RETRANSMIT_THRESHOLD
If we have been explicitly NACKed three times, retransmit the packet even if there are other packets in flight. 3 takes forever, let's try 2.

See Also:
Constant Field Values
Constructor Detail

Connection

public Connection(I2PAppContext ctx,
                  ConnectionManager manager,
                  I2PSession session,
                  SchedulerChooser chooser,
                  SimpleTimer2 timer,
                  PacketQueue queue,
                  ConnectionPacketHandler handler,
                  ConnectionOptions opts,
                  boolean isInbound)
Parameters:
opts - may be null
Method Detail

getNextOutboundPacketNum

public long getNextOutboundPacketNum()

packetSendChoke

public boolean packetSendChoke(long timeoutMs)
                        throws IOException,
                               InterruptedException
This doesn't "send a choke". Rather, it blocks if the outbound window is full, thus choking the sender that calls this. Block until there is an open outbound packet slot or the write timeout expires. PacketLocal is the only caller, generally with -1.

Parameters:
timeoutMs - 0 or negative means wait forever, 5 minutes max
Returns:
true if the packet should be sent, false for a fatal error will return false after 5 minutes even if timeoutMs is <= 0.
Throws:
IOException
InterruptedException

windowAdjusted

void windowAdjusted()
Notify all threads waiting in packetSendChoke()


ackImmediately

void ackImmediately()

sendAvailable

void sendAvailable()
Flush any data that we can. Non-blocking.


sendPacket

void sendPacket(PacketLocal packet)

ackPackets

public List<PacketLocal> ackPackets(long ackThrough,
                                    long[] nacks)
Process the acks and nacks received in a packet

Returns:
List of packets acked for the first time, or null if none

eventOccurred

void eventOccurred()

notifyCloseSent

public void notifyCloseSent()
Notify that a close was sent. Called by CPH. May be called multiple times... but shouldn't be.


closeReceived

public void closeReceived()
Notify that a close was received. Called by CPH. May be called multiple times.


notifyLastPacketAcked

public void notifyLastPacketAcked()
Notify that a close that we sent, and all previous packets, were acked. Called by CPH. Only call this once.

Since:
0.9.9

resetReceived

public void resetReceived()
Notify that a reset was received. May be called multiple times.


getResetReceived

public boolean getResetReceived()

isInbound

public boolean isInbound()

getIsConnected

public boolean getIsConnected()
Always true at the start, even if we haven't gotten a reply on an outbound connection. Only set to false on disconnect. For outbound, use getHighestAckedThrough() >= 0 also, to determine if the connection is up. In general, this is true until either: - CLOSE received and CLOSE sent and our CLOSE is acked - RESET received or sent - closed on the socket side


getHardDisconnected

public boolean getHardDisconnected()

getResetSent

public boolean getResetSent()

getResetSentOn

public long getResetSentOn()
Returns:
0 if not sent

getDisconnectScheduledOn

public long getDisconnectScheduledOn()
Returns:
0 if not scheduled

disconnect

public void disconnect(boolean cleanDisconnect)
Must be called when we are done with this connection. Enters TIME-WAIT if necessary, and removes from connection manager. May be called multiple times. This closes the socket side. In normal operation, this is called when a CLOSE has been received, AND a CLOSE has been sent, AND EITHER: received close before sent close AND our CLOSE has been acked OR received close after sent close.

Parameters:
cleanDisconnect - if true, normal close; if false, send a RESET

disconnect

public void disconnect(boolean cleanDisconnect,
                       boolean removeFromConMgr)
Must be called when we are done with this connection. May be called multiple times. This closes the socket side. In normal operation, this is called when a CLOSE has been received, AND a CLOSE has been sent, AND EITHER: received close before sent close AND our CLOSE has been acked OR received close after sent close.

Parameters:
cleanDisconnect - if true, normal close; if false, send a RESET
removeFromConMgr - if true, enters TIME-WAIT if necessary. if false, MUST call disconnectComplete() later. Should always be true unless called from ConnectionManager.

disconnectComplete

public void disconnectComplete()
Must be called when we are done with this connection. Final disconnect. Remove from conn manager. May be called multiple times.


scheduleConnectionEvent

public void scheduleConnectionEvent(long msToWait)
Called from SchedulerImpl

Since:
0.9.23 moved here so we can use our timer

schedule

public void schedule(SimpleTimer.TimedEvent event,
                     long msToWait)
Schedule something on our timer.

Since:
0.9.23

getRemotePeer

public Destination getRemotePeer()
who are we talking with

Returns:
peer Destination

setRemotePeer

public void setRemotePeer(Destination peer)

getSendStreamId

public long getSendStreamId()
What stream do we send data to the peer on?

Returns:
non-global stream sending ID, or 0 if unknown

setSendStreamId

public void setSendStreamId(long id)
Parameters:
id - 0 to 0xffffffff
Throws:
RuntimeException - if already set to nonzero

getReceiveStreamId

public long getReceiveStreamId()
The stream ID of a peer connection that sends data to us, or zero if unknown.

Returns:
receive stream ID, or 0 if unknown

setReceiveStreamId

public void setReceiveStreamId(long id)
Parameters:
id - 0 to 0xffffffff
Throws:
RuntimeException - if already set to nonzero

getLastSendTime

public long getLastSendTime()
When did we last send anything to the peer?

Returns:
Last time we sent data

getLastSendId

public long getLastSendId()
What was the last packet Id sent to the peer?

Returns:
The last sent packet ID

setLastSendId

public void setLastSendId(long id)
Set the packet Id that was sent to a peer.

Parameters:
id - The packet ID

getOptions

public ConnectionOptions getOptions()
Retrieve the current ConnectionOptions.

Returns:
the current ConnectionOptions

setOptions

public void setOptions(ConnectionOptions opts)
Set the ConnectionOptions.

Parameters:
opts - ConnectionOptions

getConnectionManager

public ConnectionManager getConnectionManager()
Since:
0.9.21

getSession

public I2PSession getSession()

getSocket

public I2PSocketFull getSocket()

setSocket

public void setSocket(I2PSocketFull socket)

getPort

public int getPort()
The remote port.

Returns:
Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
Since:
0.8.9

getLocalPort

public int getLocalPort()
Returns:
Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
Since:
0.8.9

getConnectionError

public String getConnectionError()

setConnectionError

public void setConnectionError(String err)

getLifetime

public long getLifetime()

getPacketHandler

public ConnectionPacketHandler getPacketHandler()

getLifetimeBytesSent

public long getLifetimeBytesSent()

getLifetimeBytesReceived

public long getLifetimeBytesReceived()

getLifetimeDupMessagesSent

public long getLifetimeDupMessagesSent()

getLifetimeDupMessagesReceived

public long getLifetimeDupMessagesReceived()

incrementBytesSent

public void incrementBytesSent(int bytes)

incrementDupMessagesSent

public void incrementDupMessagesSent(int msgs)

incrementBytesReceived

public void incrementBytesReceived(int bytes)

incrementDupMessagesReceived

public void incrementDupMessagesReceived(int msgs)

getNextSendTime

public long getNextSendTime()
Time when the scheduler next want to send a packet, or -1 if never. This should be set when we want to send on timeout, for instance, or want to delay an ACK.

Returns:
the next time the scheduler will want to send a packet, or -1 if never.

setNextSendTime

public void setNextSendTime(long when)
If the next send time is currently >= 0 (i.e. not "never"), this may make the next time sooner but will not make it later. If the next send time is currently < 0 (i.e. "never"), this will set it to the time specified, but not later than options.getSendAckDelay() from now (1000 ms)


getAckedPackets

public long getAckedPackets()
how many packets have we sent and the other side has ACKed?

Returns:
Count of how many packets ACKed.

getCreatedOn

public long getCreatedOn()

getCloseSentOn

public long getCloseSentOn()
Returns:
0 if not sent

getCloseReceivedOn

public long getCloseReceivedOn()
Returns:
0 if not received

updateShareOpts

public void updateShareOpts()

incrementUnackedPacketsReceived

public void incrementUnackedPacketsReceived()

getUnackedPacketsReceived

public int getUnackedPacketsReceived()

getUnackedPacketsSent

public int getUnackedPacketsSent()
how many packets have we sent but not yet received an ACK for?

Returns:
Count of packets in-flight.

getCongestionWindowEnd

public long getCongestionWindowEnd()

setCongestionWindowEnd

public void setCongestionWindowEnd(long endMsg)

getHighestAckedThrough

public long getHighestAckedThrough()
Returns:
the highest outbound packet we have recieved an ack for

getLastActivityOn

public long getLastActivityOn()

getLastCongestionSeenAt

public int getLastCongestionSeenAt()

packetReceived

void packetReceived()

waitForConnect

void waitForConnect()
wait until a connection is made or the connection fails within the timeout period, setting the error accordingly.


getInputStream

public MessageInputStream getInputStream()
stream that the local peer receives data on

Returns:
the inbound message stream, non-null

getOutputStream

public MessageOutputStream getOutputStream()
stream that the local peer sends data to the remote peer on

Returns:
the outbound message stream, non-null

toString

public String toString()
Overrides:
toString in class Object