net.i2p.client.streaming.impl

## Class Connection

- java.lang.Object
- - net.i2p.client.streaming.impl.Connection

-     class Connection
      extends Object

  Maintain the state controlling a streaming connection between two destinations.

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `(package private) class` | `Connection.ConEvent` fired to reschedule event notification
    `(package private) class` | `Connection.ResendPacketEvent` This is not normally scheduled.
    `(package private) class` | `Connection.RetransmitEvent` A single retransmit timer for all packets.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `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 int` | `MAX_RESEND_DELAY`
    `static int` | `MAX_WINDOW_SIZE` This is the default maximum.
    `static int` | `MIN_RESEND_DELAY`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Connection(I2PAppContext ctx, ConnectionManager manager, I2PSession session, SchedulerChooser chooser, SimpleTimer2 timer, PacketQueue queue, ConnectionPacketHandler handler, ConnectionOptions opts, boolean isInbound)`

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `(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()`
    `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
    `SigningPublicKey` | `getRemoteSPK()` The key to verify signatures with.
    `boolean` | `getResetReceived()`
    `boolean` | `getResetSent()`
    `long` | `getResetSentOn()`
    `long` | `getSendStreamId()` What stream do we send data to the peer on?
    `I2PSession` | `getSession()`
    `I2PSocketFull` | `getSocket()`
    `(package private) int` | `getSSThresh()`
    `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` | `isChoked()` Is the other side choking us?
    `boolean` | `isInbound()`
    `(package private) Connection.ResendPacketEvent` | `newResendPacketEvent(PacketLocal packet)` A new ResendPacketEvent.
    `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)` This sends all 'normal' packets (acks and data) for the first time.
    `void` | `setChoked(boolean on)` Set or clear if we are being choked by the other side.
    `void` | `setChoking(boolean on)` Set or clear if we are choking the other side.
    `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` | `setRemoteTransientSPK(SigningPublicKey transientSPK)`
    `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

    - #### DEFAULT_CONNECT_TIMEOUT

          public static final int DEFAULT_CONNECT_TIMEOUT

      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

    - #### 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.
      See Also:
        Constant Field Values

    - #### MAX_RESEND_DELAY

          public static final int MAX_RESEND_DELAY

      See Also:
        Constant Field Values

    - #### MAX_WINDOW_SIZE

          public static final int MAX_WINDOW_SIZE

      This is the default maximum. See ConnectionOptions.setMaxWindowSize() where the configured maximum is enforced. Increased for better throughput on high-bandwidth I2P connections.

    - #### MIN_RESEND_DELAY

          public static final int MIN_RESEND_DELAY

  - ### 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

    - #### ackImmediately

          void ackImmediately()

    - #### 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

    - #### closeReceived

          public void closeReceived()

      Notify that a close was received. Called by CPH. May be called multiple times.

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

    - #### eventOccurred

          void eventOccurred()

    - #### getAckedPackets

          public long getAckedPackets()

      how many packets have we sent and the other side has ACKed?
      Returns:
        Count of how many packets ACKed.

    - #### getCloseReceivedOn

          public long getCloseReceivedOn()

      Returns:
        0 if not received

    - #### getCloseSentOn

          public long getCloseSentOn()

      Returns:
        0 if not sent

    - #### getCongestionWindowEnd

          public long getCongestionWindowEnd()

    - #### getConnectionError

          public String getConnectionError()

    - #### getConnectionManager

          public ConnectionManager getConnectionManager()

    - #### getCreatedOn

          public long getCreatedOn()

    - #### getDisconnectScheduledOn

          public long getDisconnectScheduledOn()

      Returns:
        0 if not scheduled

    - #### getHardDisconnected

          public boolean getHardDisconnected()

    - #### getHighestAckedThrough

          public long getHighestAckedThrough()

      Returns:
        the highest outbound packet we have received an ack for

    - #### getInputStream

          public MessageInputStream getInputStream()

      stream that the local peer receives data on
      Returns:
        the inbound message stream, non-null

    - #### 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

    - #### getLastActivityOn

          public long getLastActivityOn()

    - #### getLastSendId

          public long getLastSendId()

      What was the last packet Id sent to the peer?
      Returns:
        The last sent packet ID

    - #### getLastSendTime

          public long getLastSendTime()

      When did we last send anything to the peer?
      Returns:
        Last time we sent data

    - #### getLifetime

          public long getLifetime()

    - #### getLifetimeBytesReceived

          public long getLifetimeBytesReceived()

    - #### getLifetimeBytesSent

          public long getLifetimeBytesSent()

    - #### getLifetimeDupMessagesReceived

          public long getLifetimeDupMessagesReceived()

    - #### getLifetimeDupMessagesSent

          public long getLifetimeDupMessagesSent()

    - #### getLocalPort

          public int getLocalPort()

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

    - #### getNextOutboundPacketNum

          public long getNextOutboundPacketNum()

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

    - #### getOptions

          public ConnectionOptions getOptions()

      Retrieve the current ConnectionOptions.
      Returns:
        the current ConnectionOptions, 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

    - #### getPacketHandler

          public ConnectionPacketHandler getPacketHandler()

    - #### getPort

          public int getPort()

      The remote port.
      Returns:
        Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)

    - #### 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

    - #### getRemotePeer

          public Destination getRemotePeer()

      who are we talking with
      Returns:
        peer Destination or null if unset

    - #### getRemoteSPK

          public SigningPublicKey getRemoteSPK()

      The key to verify signatures with. The transient SPK if previously received, else getRemotePeer().getSigningPublicKey() if previously received, else null.
      Returns:
        peer Destination or null if unset

    - #### getResetReceived

          public boolean getResetReceived()

    - #### getResetSent

          public boolean getResetSent()

    - #### getResetSentOn

          public long getResetSentOn()

      Returns:
        0 if not sent

    - #### getSendStreamId

          public long getSendStreamId()

      What stream do we send data to the peer on?
      Returns:
        non-global stream sending ID, or 0 if unknown

    - #### getSession

          public I2PSession getSession()

    - #### getSocket

          public I2PSocketFull getSocket()

    - #### getSSThresh

          int getSSThresh()

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

    - #### incrementBytesReceived

          public void incrementBytesReceived(int bytes)

    - #### incrementBytesSent

          public void incrementBytesSent(int bytes)

    - #### incrementDupMessagesReceived

          public void incrementDupMessagesReceived(int msgs)

    - #### incrementDupMessagesSent

          public void incrementDupMessagesSent(int msgs)

    - #### incrementUnackedPacketsReceived

          public void incrementUnackedPacketsReceived()

    - #### isChoked

          public boolean isChoked()

      Is the other side choking us?
      Returns:
        if choked

    - #### isInbound

          public boolean isInbound()

    - #### newResendPacketEvent

          Connection.ResendPacketEvent newResendPacketEvent(PacketLocal packet)

      A new ResendPacketEvent.

    - #### notifyCloseSent

          public void notifyCloseSent()

      Notify that a close was sent. Called by CPH. May be called multiple times... but shouldn't be.

    - #### notifyLastPacketAcked

          public void notifyLastPacketAcked()

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

    - #### packetReceived

          void packetReceived()

    - #### 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`

    - #### resetReceived

          public void resetReceived()

      Notify that a reset was received. May be called multiple times.

    - #### schedule

          public void schedule(SimpleTimer.TimedEvent event,
                               long msToWait)

      Schedule something on our timer.

    - #### scheduleConnectionEvent

          public void scheduleConnectionEvent(long msToWait)

      Called from SchedulerImpl

    - #### sendAvailable

          void sendAvailable()

      Flush any data that we can. Non-blocking.

    - #### sendPacket

          void sendPacket(PacketLocal packet)

      This sends all 'normal' packets (acks and data) for the first time. Retransmits are done in ResendPacketEvent below. Resets, pings, and pongs are done elsewhere in this class, or in ConnectionManager or ConnectionHandler.

    - #### setChoked

          public void setChoked(boolean on)

      Set or clear if we are being choked by the other side.
      Parameters:
        `on` - true for choked

    - #### setChoking

          public void setChoking(boolean on)

      Set or clear if we are choking the other side. If on is true or the value has changed, this will call ackImmediately().
      Parameters:
        `on` - true for choking

    - #### setCongestionWindowEnd

          public void setCongestionWindowEnd(long endMsg)

    - #### setConnectionError

          public void setConnectionError(String err)

    - #### setLastSendId

          public void setLastSendId(long id)

      Set the packet Id that was sent to a peer.
      Parameters:
        `id` - The packet ID

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

    - #### setOptions

          public void setOptions(ConnectionOptions opts)

      Set the ConnectionOptions.
      Parameters:
        `opts` - ConnectionOptions non-null

    - #### setReceiveStreamId

          public void setReceiveStreamId(long id)

      Parameters:
        `id` - 0 to 0xffffffff
      Throws:
        `IllegalStateException` - if already set to nonzero

    - #### setRemotePeer

          public void setRemotePeer(Destination peer)

      Parameters:
        `peer` - non-null

    - #### setRemoteTransientSPK

          public void setRemoteTransientSPK(SigningPublicKey transientSPK)

      Parameters:
        `transientSPK` - null ok

    - #### setSendStreamId

          public void setSendStreamId(long id)

      Parameters:
        `id` - 0 to 0xffffffff
      Throws:
        `IllegalStateException` - if already set to nonzero

    - #### setSocket

          public void setSocket(I2PSocketFull socket)

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`

    - #### updateShareOpts

          public void updateShareOpts()

    - #### waitForConnect

          void waitForConnect()

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

    - #### windowAdjusted

          void windowAdjusted()

      Notify all threads waiting in packetSendChoke()