net.i2p.router.transport.ntcp

## Class NTCPConnection

- java.lang.Object
- - net.i2p.router.transport.ntcp.NTCPConnection

- All Implemented Interfaces:
    FIFOBandwidthLimiter.CompleteListener

       class NTCPConnection
      extends Object
      implements FIFOBandwidthLimiter.CompleteListener

  Coordinate the connection to a single peer. The NTCP transport sends individual I2NP messages AES/256/CBC encrypted with a simple checksum. The unencrypted message is encoded as follows:

        +-------+-------+--//--+---//----+-------+-------+-------+-------+
        | sizeof(data)  | data | padding | adler checksum of sz+data+pad |
        +-------+-------+--//--+---//----+-------+-------+-------+-------+

  That message is then encrypted with the DH/2048 negotiated session key (station to station authenticated per the EstablishState class) using the last 16 bytes of the previous encrypted message as the IV. One special case is a metadata message where the sizeof(data) is 0. In that case, the unencrypted message is encoded as:

        +-------+-------+-------+-------+-------+-------+-------+-------+
        |       0       |      timestamp in seconds     | uninterpreted
        +-------+-------+-------+-------+-------+-------+-------+-------+
                uninterpreted           | adler checksum of sz+data+pad |
        +-------+-------+-------+-------+-------+-------+-------+-------+

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static int` | `BUFFER_SIZE` Why this is 16K, and where it is documented, good question? We claim we can do 32K datagrams so this is a problem.
    `static int` | `MAX_MSG_SIZE` 2 bytes for length and 4 for CRC

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `NTCPConnection(RouterContext ctx, NTCPTransport transport, RouterIdentity remotePeer, NTCPAddress remAddr)` Create an outbound unconnected NTCP connection
    `NTCPConnection(RouterContext ctx, NTCPTransport transport, SocketChannel chan, SelectionKey key)` Create an inbound connected (though not established) NTCP connection

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `close()`
    `void` | `close(boolean allowRequeue)`
    `void` | `complete(FIFOBandwidthLimiter.Request req)`
    `void` | `enqueueInfoMessage()`
    `void` | `finishInboundEstablishment(SessionKey key, long clockSkew, byte[] prevWriteEnd, byte[] prevReadEnd)`
    `void` | `finishOutboundEstablishment(SessionKey key, long clockSkew, byte[] prevWriteEnd, byte[] prevReadEnd)`
    `SocketChannel` | `getChannel()`
    `long` | `getClockSkew()`
    `int` | `getConsecutiveBacklog()`
    `EstablishState` | `getEstablishState()`
    `SelectionKey` | `getKey()`
    `long` | `getMessagesReceived()`
    `long` | `getMessagesSent()`
    `ByteBuffer` | `getNextReadBuf()`
    `ByteBuffer` | `getNextWriteBuf()`
    `long` | `getOutboundQueueSize()`
    `long` | `getReadTime()`
    `float` | `getRecvRate()`
    `NTCPAddress` | `getRemoteAddress()`
    `RouterIdentity` | `getRemotePeer()`
    `float` | `getSendRate()`
    `long` | `getTimeSinceCreated()`
    `long` | `getTimeSinceReceive()`
    `long` | `getTimeSinceSend()`
    `long` | `getUptime()`
    `int` | `getWriteBufCount()`
    `boolean` | `isClosed()`
    `boolean` | `isEstablished()`
    `boolean` | `isInbound()`
    `void` | `outboundConnected()` async callback after the outbound connection was completed (this should NOT block, as it occurs in the selector thread)
    `(package private) void` | `prepareNextWrite()` prepare the next i2np message for transmission.
    `(package private) void` | `prepareNextWriteFast()` prepare the next i2np message for transmission.
    `void` | `queuedRecv(ByteBuffer buf, FIFOBandwidthLimiter.Request req)` We have read the data in the buffer, but we can't process it locally yet, because we're choked by the bandwidth limiter.
    `void` | `queuedWrite(ByteBuffer buf, FIFOBandwidthLimiter.Request req)` ditto for writes
    `void` | `recv(ByteBuffer buf)` The contents of the buffer have been read and can be processed asap.
    `(package private) void` | `recvEncryptedI2NP(ByteBuffer buf)` the contents of the buffer include some fraction of one or more encrypted and encoded I2NP messages.
    `void` | `removeReadBuf(ByteBuffer buf)` since getNextReadBuf() removes, this should not be necessary
    `void` | `removeWriteBuf(ByteBuffer buf)`
    `void` | `send(OutNetMessage msg)` toss the message onto the connection's send queue
    `void` | `setChannel(SocketChannel chan)`
    `void` | `setKey(SelectionKey key)`
    `void` | `setRemotePeer(RouterIdentity ident)`
    `boolean` | `tooBacklogged()`
    `String` | `toString()`
    `void` | `write(ByteBuffer buf)` The contents of the buffer have been encrypted / padded / etc and have been fully allocated for the bandwidth limiter.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### BUFFER_SIZE

          public static final int BUFFER_SIZE

      Why this is 16K, and where it is documented, good question? We claim we can do 32K datagrams so this is a problem. Needs to be fixed. But SSU can handle it? In the meantime, don't let the transport bid on big messages.
      See Also:
        Constant Field Values

    - #### MAX_MSG_SIZE

          public static final int MAX_MSG_SIZE

      2 bytes for length and 4 for CRC
      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### NTCPConnection

          public NTCPConnection(RouterContext ctx,
                        NTCPTransport transport,
                        SocketChannel chan,
                        SelectionKey key)

      Create an inbound connected (though not established) NTCP connection

    - #### NTCPConnection

          public NTCPConnection(RouterContext ctx,
                        NTCPTransport transport,
                        RouterIdentity remotePeer,
                        NTCPAddress remAddr)

      Create an outbound unconnected NTCP connection

  - ### Method Detail

    - #### getChannel

          public SocketChannel getChannel()

    - #### getKey

          public SelectionKey getKey()

    - #### setChannel

          public void setChannel(SocketChannel chan)

    - #### setKey

          public void setKey(SelectionKey key)

    - #### isInbound

          public boolean isInbound()

    - #### isEstablished

          public boolean isEstablished()

    - #### getEstablishState

          public EstablishState getEstablishState()

    - #### getRemoteAddress

          public NTCPAddress getRemoteAddress()

    - #### getRemotePeer

          public RouterIdentity getRemotePeer()

    - #### setRemotePeer

          public void setRemotePeer(RouterIdentity ident)

    - #### finishInboundEstablishment

          public void finishInboundEstablishment(SessionKey key,
                                        long clockSkew,
                                        byte[] prevWriteEnd,
                                        byte[] prevReadEnd)

      Parameters:
        `clockSkew` - alice's clock minus bob's clock in seconds (may be negative, obviously, but |val| should be under 1 minute)

    - #### getClockSkew

          public long getClockSkew()

      Returns:
        seconds

    - #### getUptime

          public long getUptime()

      Returns:
        milliseconds

    - #### getMessagesSent

          public long getMessagesSent()

    - #### getMessagesReceived

          public long getMessagesReceived()

    - #### getOutboundQueueSize

          public long getOutboundQueueSize()

    - #### getTimeSinceSend

          public long getTimeSinceSend()

      Returns:
        milliseconds

    - #### getTimeSinceReceive

          public long getTimeSinceReceive()

      Returns:
        milliseconds

    - #### getTimeSinceCreated

          public long getTimeSinceCreated()

      Returns:
        milliseconds

    - #### getConsecutiveBacklog

          public int getConsecutiveBacklog()

    - #### isClosed

          public boolean isClosed()

    - #### close

          public void close()

    - #### close

          public void close(boolean allowRequeue)

    - #### send

          public void send(OutNetMessage msg)

      toss the message onto the connection's send queue

    - #### tooBacklogged

          public boolean tooBacklogged()

    - #### enqueueInfoMessage

          public void enqueueInfoMessage()

    - #### finishOutboundEstablishment

          public void finishOutboundEstablishment(SessionKey key,
                                         long clockSkew,
                                         byte[] prevWriteEnd,
                                         byte[] prevReadEnd)

      Parameters:
        `clockSkew` - alice's clock minus bob's clock in seconds (may be negative, obviously, but |val| should be under 1 minute)

    - #### prepareNextWrite

          void prepareNextWrite()

      prepare the next i2np message for transmission. this should be run from the Writer thread pool. Todo: remove synchronization?

    - #### prepareNextWriteFast

          void prepareNextWriteFast()

      prepare the next i2np message for transmission. this should be run from the Writer thread pool. Todo: remove synchronization?

    - #### outboundConnected

          public void outboundConnected()

      async callback after the outbound connection was completed (this should NOT block, as it occurs in the selector thread)

    - #### complete

          public void complete(FIFOBandwidthLimiter.Request req)

      Specified by:
        `complete` in interface `FIFOBandwidthLimiter.CompleteListener`

    - #### queuedRecv

          public void queuedRecv(ByteBuffer buf,
                        FIFOBandwidthLimiter.Request req)

      We have read the data in the buffer, but we can't process it locally yet, because we're choked by the bandwidth limiter. Cache the contents of the buffer (not copy) and register ourselves to be notified when the contents have been fully allocated

    - #### queuedWrite

          public void queuedWrite(ByteBuffer buf,
                         FIFOBandwidthLimiter.Request req)

      ditto for writes

    - #### recv

          public void recv(ByteBuffer buf)

      The contents of the buffer have been read and can be processed asap. This should not block, and the NTCP connection now owns the buffer to do with as it pleases.

    - #### write

          public void write(ByteBuffer buf)

      The contents of the buffer have been encrypted / padded / etc and have been fully allocated for the bandwidth limiter.

    - #### getNextReadBuf

          public ByteBuffer getNextReadBuf()

      Returns:
        null if none available

    - #### removeReadBuf

          public void removeReadBuf(ByteBuffer buf)

      since getNextReadBuf() removes, this should not be necessary

    - #### getWriteBufCount

          public int getWriteBufCount()

    - #### getNextWriteBuf

          public ByteBuffer getNextWriteBuf()

      Returns:
        null if none available

    - #### removeWriteBuf

          public void removeWriteBuf(ByteBuffer buf)

    - #### getSendRate

          public float getSendRate()

    - #### getRecvRate

          public float getRecvRate()

    - #### recvEncryptedI2NP

          void recvEncryptedI2NP(ByteBuffer buf)

      the contents of the buffer include some fraction of one or more encrypted and encoded I2NP messages. individual i2np messages are encoded as "sizeof(data)+data+pad+crc", and those are encrypted with the session key and the last 16 bytes of the previous encrypted i2np message. the contents of the buffer is owned by the EventPumper, so data should be copied out

    - #### getReadTime

          public long getReadTime()

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`