net.i2p.router.transport.ntcp
Class NTCPConnection

java.lang.Object
  extended by net.i2p.router.transport.ntcp.NTCPConnection
All Implemented Interfaces:
FIFOBandwidthLimiter.CompleteListener

public class NTCPConnection
extends java.lang.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
static int BUFFER_SIZE
          Why this is 16K, and where it is documented, good question?
static int MAX_MSG_SIZE
          2 bytes for length and 4 for CRC
 
Constructor Summary
NTCPConnection(RouterContext ctx, NTCPTransport transport, RouterIdentity remotePeer, NTCPAddress remAddr)
          Create an outbound unconnected NTCP connection
NTCPConnection(RouterContext ctx, NTCPTransport transport, java.nio.channels.SocketChannel chan, java.nio.channels.SelectionKey key)
          Create an inbound connected (though not established) NTCP connection
 
Method Summary
 void close()
           
 void close(boolean allowRequeue)
           
 void complete(FIFOBandwidthLimiter.Request req)
           
 void enqueueInfoMessage()
           
 boolean equals(java.lang.Object obj)
           
 void finishInboundEstablishment(SessionKey key, long clockSkew, byte[] prevWriteEnd, byte[] prevReadEnd)
           
 void finishOutboundEstablishment(SessionKey key, long clockSkew, byte[] prevWriteEnd, byte[] prevReadEnd)
           
 java.nio.channels.SocketChannel getChannel()
           
 long getClockSkew()
           
 int getConsecutiveBacklog()
           
 EstablishState getEstablishState()
           
 java.nio.channels.SelectionKey getKey()
           
 long getMessagesReceived()
           
 long getMessagesSent()
           
 java.nio.ByteBuffer getNextReadBuf()
           
 java.nio.ByteBuffer getNextWriteBuf()
           
 long getOutboundQueueSize()
           
 long getReadTime()
           
 float getRecvRate()
           
 NTCPAddress getRemoteAddress()
           
 RouterIdentity getRemotePeer()
           
 float getSendRate()
           
 long getTimeSinceCreated()
           
 long getTimeSinceReceive()
           
 long getTimeSinceSend()
           
 long getUptime()
           
 int getWriteBufCount()
           
 int hashCode()
           
 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(java.nio.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(java.nio.ByteBuffer buf, FIFOBandwidthLimiter.Request req)
           
 void recv(java.nio.ByteBuffer buf)
          The contents of the buffer have been read and can be processed asap.
(package private)  void recvEncryptedI2NP(java.nio.ByteBuffer buf)
          the contents of the buffer include some fraction of one or more encrypted and encoded I2NP messages.
 void removeReadBuf(java.nio.ByteBuffer buf)
          since getNextReadBuf() removes, this should not be necessary
 void removeWriteBuf(java.nio.ByteBuffer buf)
           
 void send(OutNetMessage msg)
          toss the message onto the connection's send queue
 void setChannel(java.nio.channels.SocketChannel chan)
           
 void setKey(java.nio.channels.SelectionKey key)
           
 void setRemotePeer(RouterIdentity ident)
           
 boolean tooBacklogged()
           
 java.lang.String toString()
           
 void write(java.nio.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, finalize, getClass, 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,
                      java.nio.channels.SocketChannel chan,
                      java.nio.channels.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 java.nio.channels.SocketChannel getChannel()

getKey

public java.nio.channels.SelectionKey getKey()

setChannel

public void setChannel(java.nio.channels.SocketChannel chan)

setKey

public void setKey(java.nio.channels.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()

getUptime

public long getUptime()

getMessagesSent

public long getMessagesSent()

getMessagesReceived

public long getMessagesReceived()

getOutboundQueueSize

public long getOutboundQueueSize()

getTimeSinceSend

public long getTimeSinceSend()

getTimeSinceReceive

public long getTimeSinceReceive()

getTimeSinceCreated

public long getTimeSinceCreated()

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(java.nio.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(java.nio.ByteBuffer buf,
                        FIFOBandwidthLimiter.Request req)

recv

public void recv(java.nio.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(java.nio.ByteBuffer buf)
The contents of the buffer have been encrypted / padded / etc and have been fully allocated for the bandwidth limiter.


getNextReadBuf

public java.nio.ByteBuffer getNextReadBuf()
Returns:
null if none available

removeReadBuf

public void removeReadBuf(java.nio.ByteBuffer buf)
since getNextReadBuf() removes, this should not be necessary


getWriteBufCount

public int getWriteBufCount()

getNextWriteBuf

public java.nio.ByteBuffer getNextWriteBuf()
Returns:
null if none available

removeWriteBuf

public void removeWriteBuf(java.nio.ByteBuffer buf)

getSendRate

public float getSendRate()

getRecvRate

public float getRecvRate()

recvEncryptedI2NP

void recvEncryptedI2NP(java.nio.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


hashCode

public int hashCode()
Overrides:
hashCode in class java.lang.Object

equals

public boolean equals(java.lang.Object obj)
Overrides:
equals in class java.lang.Object

getReadTime

public long getReadTime()

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object