net.i2p.client.impl
Class I2PSessionImpl

java.lang.Object
  extended by net.i2p.client.impl.I2PSessionImpl
All Implemented Interfaces:
I2PSession, I2CPMessageReader.I2CPMessageEventListener
Direct Known Subclasses:
I2PSessionImpl2

public abstract class I2PSessionImpl
extends Object
implements I2PSession, I2CPMessageReader.I2CPMessageEventListener

Implementation of an I2P session running over TCP. This class is NOT thread safe - only one thread should send messages at any given time Public only for clearCache(). Except for methods defined in I2PSession and I2CPMessageEventListener, not maintained as a public API, not for external use. Use I2PClientFactory to get an I2PClient and then createSession().

Author:
jrandom

Nested Class Summary
protected  class I2PSessionImpl.AvailabilityNotifier
          This notifies the client of payload messages.
protected static class I2PSessionImpl.State
           
 
Field Summary
protected  I2PSessionImpl.AvailabilityNotifier _availabilityNotifier
          thread that we tell when new messages are available who then tells us to fetch them.
protected  Map<Long,MessagePayloadMessage> _availableMessages
          map of Long --> MessagePayloadMessage
protected  int[] _bwLimits
           
protected  Object _bwReceivedLock
           
protected  I2PAppContext _context
          used to separate things out so we can get rid of singletons
protected  I2PClientMessageHandlerMap _handlerMap
           
protected  String _hostname
          hostname of router - will be null if in RouterContext
protected  LeaseSet _leaseSet
          currently granted lease set, or null
protected  Object _leaseSetWait
          monitor for waiting until a lease set has been granted
protected  Log _log
           
protected  LinkedBlockingQueue<net.i2p.client.impl.I2PSessionImpl.LookupWaiter> _pendingLookups
          hashes of lookups we are waiting for
protected  int _portNum
          port num to router - will be 0 if in RouterContext
protected  I2CPMessageProducer _producer
          class that generates new messages
protected  I2CPMessageQueue _queue
          Used for internal connections to the router.
protected  I2CPMessageReader _reader
          reader that always searches for messages
protected  I2PSessionListener _sessionListener
          who we send events to
protected  Socket _socket
          socket for comm
protected  I2PSessionImpl.State _state
           
protected  Object _stateLock
           
protected  ClientWriterRunner _writer
          writer message queue
static int LISTEN_PORT
           
protected static String PROP_DOMAIN_SOCKET
          Use Unix domain socket (or similar) to connect to a router
protected static String PROP_ENABLE_SSL
          SSL interface (only) @since 0.8.3
protected static String PROP_PW
           
protected static String PROP_USER
           
 
Fields inherited from interface net.i2p.client.I2PSession
PORT_ANY, PORT_UNSPECIFIED, PROTO_ANY, PROTO_DATAGRAM, PROTO_DATAGRAM_RAW, PROTO_STREAMING, PROTO_UNSPECIFIED
 
Constructor Summary
  I2PSessionImpl(I2PAppContext context, InputStream destKeyStream, Properties options)
          Create a new session, reading the Destination, PrivateKey, and SigningPrivateKey from the destKeyStream, and using the specified options to connect to the router As of 0.9.19, defaults in options are honored.
protected I2PSessionImpl(I2PAppContext context, Properties options, I2PClientMessageHandlerMap handlerMap)
          for extension by SimpleSession (no dest)
protected I2PSessionImpl(I2PSessionImpl primary, InputStream destKeyStream, Properties options)
           
 
Method Summary
 void addNewMessage(MessagePayloadMessage msg)
          Recieve a payload message and let the app know its available
 I2PSession addSubsession(InputStream privateKeyStream, Properties opts)
          Router must be connected or was connected...
 int[] bandwidthLimits()
          Blocking.
(package private)  void bwReceived(int[] i)
          called by the message handler
protected  void changeState(I2PSessionImpl.State state)
           
static void clearCache()
           
 void connect()
          Connect to the router and establish a session.
(package private)  void dateUpdated(String routerVersion)
           
(package private)  void destLookupFailed(Hash h)
          Called by the message handler on reception of DestReplyMessage
(package private)  void destLookupFailed(long nonce)
          Called by the message handler on reception of HostReplyMessage
(package private)  void destReceived(Destination d)
          Called by the message handler on reception of DestReplyMessage
(package private)  void destReceived(long nonce, Destination d)
          Called by the message handler on reception of HostReplyMessage
 void destroySession()
          Tear down the session, and do NOT reconnect.
 void destroySession(boolean sendDisconnect)
          Tear down the session, and do NOT reconnect.
protected  void disconnect()
          Will interrupt a connect in progress.
 void disconnected(I2CPMessageReader reader)
          The I2CPMessageEventListener callback.
(package private)  I2PAppContext getContext()
          For Subsessions
 PrivateKey getDecryptionKey()
          Retrieve the decryption PrivateKey
 boolean getFastReceive()
           
(package private)  I2PClientMessageHandlerMap getHandlerMap()
          For Subsessions
(package private)  LeaseSet getLeaseSet()
           
 Destination getMyDestination()
          Retrieve the destination of the session
(package private)  Properties getOptions()
          Retrieve the configuration options, filtered.
protected  String getPrefix()
          try hard to make a decent identifier as this will appear in error logs
 SigningPrivateKey getPrivateKey()
          Retrieve the signing SigningPrivateKey
(package private)  I2CPMessageProducer getProducer()
          Retrieve the helper that generates I2CP messages
(package private)  SessionId getSessionId()
          Retrieve the session's ID
 List<I2PSession> getSubsessions()
           
 boolean isClosed()
          Has the session been closed (or not yet connected)? False when open and during transitions.
 long lastActivity()
           
 Destination lookupDest(Hash h)
          Blocking.
 Destination lookupDest(Hash h, long maxWait)
          Blocking.
 Destination lookupDest(String name)
          Ask the router to lookup a Destination by host name.
 Destination lookupDest(String name, long maxWait)
          Ask the router to lookup a Destination by host name.
 void messageReceived(I2CPMessageReader reader, I2CPMessage message)
          The I2CPMessageEventListener callback.
(package private)  void propogateError(String msg, Throwable error)
          Pass off the error to the listener Misspelled, oh well.
 void readError(I2CPMessageReader reader, Exception error)
          The I2CPMessageEventListener callback.
 byte[] receiveMessage(int msgId)
          Pull the unencrypted data from the message that we've already prefetched and notified the user that its available.
abstract  void receiveStatus(int msgId, long nonce, int status)
           
protected  boolean reconnect()
           
 void removeSubsession(I2PSession session)
           
 void reportAbuse(int msgId, int severity)
          Report abuse with regards to the given messageId
(package private)  void sendMessage(I2CPMessage message)
          Deliver an I2CP message to the router As of 0.9.3, may block for several seconds if the write queue to the router is full
(package private)  void setLeaseSet(LeaseSet ls)
           
 void setReduced()
           
(package private)  void setSessionId(SessionId id)
           
 void setSessionListener(I2PSessionListener lsnr)
          configure the listener
protected  boolean shouldReconnect()
           
protected  void startVerifyUsage()
          Fire up a periodic task to check for unclaimed messages
 String toString()
           
protected  void updateActivity()
           
 void updateOptions(Properties options)
          Update the tunnel and bandwidth settings
protected  void waitForDate()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface net.i2p.client.I2PSession
addMuxedSessionListener, addSessionListener, removeListener, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage
 

Field Detail

_log

protected final Log _log

_leaseSet

protected volatile LeaseSet _leaseSet
currently granted lease set, or null


_hostname

protected final String _hostname
hostname of router - will be null if in RouterContext


_portNum

protected final int _portNum
port num to router - will be 0 if in RouterContext


_socket

protected Socket _socket
socket for comm


_reader

protected I2CPMessageReader _reader
reader that always searches for messages


_writer

protected ClientWriterRunner _writer
writer message queue


_queue

protected I2CPMessageQueue _queue
Used for internal connections to the router. If this is set, _socket and _writer will be null.

Since:
0.8.3

_sessionListener

protected I2PSessionListener _sessionListener
who we send events to


_producer

protected final I2CPMessageProducer _producer
class that generates new messages


_availableMessages

protected Map<Long,MessagePayloadMessage> _availableMessages
map of Long --> MessagePayloadMessage


_pendingLookups

protected final LinkedBlockingQueue<net.i2p.client.impl.I2PSessionImpl.LookupWaiter> _pendingLookups
hashes of lookups we are waiting for


_bwReceivedLock

protected final Object _bwReceivedLock

_bwLimits

protected volatile int[] _bwLimits

_handlerMap

protected final I2PClientMessageHandlerMap _handlerMap

_context

protected final I2PAppContext _context
used to separate things out so we can get rid of singletons


_leaseSetWait

protected final Object _leaseSetWait
monitor for waiting until a lease set has been granted


_state

protected I2PSessionImpl.State _state

_stateLock

protected final Object _stateLock

_availabilityNotifier

protected I2PSessionImpl.AvailabilityNotifier _availabilityNotifier
thread that we tell when new messages are available who then tells us to fetch them. The point of this is so that the fetch doesn't block the reading of other messages (in turn, potentially leading to deadlock)


PROP_ENABLE_SSL

protected static final String PROP_ENABLE_SSL
SSL interface (only) @since 0.8.3

See Also:
Constant Field Values

PROP_USER

protected static final String PROP_USER
See Also:
Constant Field Values

PROP_PW

protected static final String PROP_PW
See Also:
Constant Field Values

PROP_DOMAIN_SOCKET

protected static final String PROP_DOMAIN_SOCKET
Use Unix domain socket (or similar) to connect to a router

Since:
0.9.14
See Also:
Constant Field Values

LISTEN_PORT

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

I2PSessionImpl

protected I2PSessionImpl(I2PAppContext context,
                         Properties options,
                         I2PClientMessageHandlerMap handlerMap)
for extension by SimpleSession (no dest)


I2PSessionImpl

protected I2PSessionImpl(I2PSessionImpl primary,
                         InputStream destKeyStream,
                         Properties options)
                  throws I2PSessionException
Throws:
I2PSessionException

I2PSessionImpl

public I2PSessionImpl(I2PAppContext context,
                      InputStream destKeyStream,
                      Properties options)
               throws I2PSessionException
Create a new session, reading the Destination, PrivateKey, and SigningPrivateKey from the destKeyStream, and using the specified options to connect to the router As of 0.9.19, defaults in options are honored.

Parameters:
destKeyStream - stream containing the private key data, format is specified in PrivateKeyFile
options - set of options to configure the router with, if null will use System properties
Throws:
I2PSessionException - if there is a problem loading the private keys
Method Detail

dateUpdated

void dateUpdated(String routerVersion)
Parameters:
routerVersion - as rcvd in the SetDateMessage, may be null for very old routers

addSubsession

public I2PSession addSubsession(InputStream privateKeyStream,
                                Properties opts)
                         throws I2PSessionException
Router must be connected or was connected... for now.

Specified by:
addSubsession in interface I2PSession
Parameters:
privateKeyStream - null for transient, if non-null must have same encryption keys as primary session and different signing keys
opts - subsession options if any, may be null
Returns:
a new subsession, non-null
Throws:
I2PSessionException
Since:
0.9.21

removeSubsession

public void removeSubsession(I2PSession session)
Specified by:
removeSubsession in interface I2PSession
Since:
0.9.21

getSubsessions

public List<I2PSession> getSubsessions()
Specified by:
getSubsessions in interface I2PSession
Returns:
a list of subsessions, non-null, does not include the primary session
Since:
0.9.21

updateOptions

public void updateOptions(Properties options)
Update the tunnel and bandwidth settings

Specified by:
updateOptions in interface I2PSession
Parameters:
options - non-null
Since:
0.8.4

getFastReceive

public boolean getFastReceive()
Since:
0.9.4

setLeaseSet

void setLeaseSet(LeaseSet ls)

getLeaseSet

LeaseSet getLeaseSet()

changeState

protected void changeState(I2PSessionImpl.State state)

connect

public void connect()
             throws I2PSessionException
Connect to the router and establish a session. This call blocks until a session is granted. Should be threadsafe, other threads will block until complete. Disconnect / destroy from another thread may be called simultaneously and will (should?) interrupt the connect.

Specified by:
connect in interface I2PSession
Throws:
I2PSessionException - if there is a configuration error or the router is not reachable

waitForDate

protected void waitForDate()
                    throws InterruptedException,
                           IOException
Throws:
InterruptedException
IOException
Since:
0.9.11 moved from connect()

receiveMessage

public byte[] receiveMessage(int msgId)
                      throws I2PSessionException
Pull the unencrypted data from the message that we've already prefetched and notified the user that its available.

Specified by:
receiveMessage in interface I2PSession
Parameters:
msgId - message to fetch
Returns:
unencrypted body of the message, or null if not found
Throws:
I2PSessionException

reportAbuse

public void reportAbuse(int msgId,
                        int severity)
                 throws I2PSessionException
Report abuse with regards to the given messageId

Specified by:
reportAbuse in interface I2PSession
Parameters:
msgId - message that was abusive (or -1 for not message related)
severity - how abusive
Throws:
I2PSessionException

receiveStatus

public abstract void receiveStatus(int msgId,
                                   long nonce,
                                   int status)

addNewMessage

public void addNewMessage(MessagePayloadMessage msg)
Recieve a payload message and let the app know its available


startVerifyUsage

protected void startVerifyUsage()
Fire up a periodic task to check for unclaimed messages

Since:
0.9.1

messageReceived

public void messageReceived(I2CPMessageReader reader,
                            I2CPMessage message)
The I2CPMessageEventListener callback. Recieve notification of some I2CP message and handle it if possible. We route the message based on message type AND session ID. The following types never contain a session ID and are not routable to a subsession: BandwidthLimitsMessage, DestReplyMessage The following types may not contain a valid session ID even when intended for a subsession, so we must take special care: SessionStatusMessage

Specified by:
messageReceived in interface I2CPMessageReader.I2CPMessageEventListener
Parameters:
reader - unused
message - the I2CPMessage

readError

public void readError(I2CPMessageReader reader,
                      Exception error)
The I2CPMessageEventListener callback. Recieve notifiation of an error reading the I2CP stream.

Specified by:
readError in interface I2CPMessageReader.I2CPMessageEventListener
Parameters:
reader - unused
error - non-null

getMyDestination

public Destination getMyDestination()
Retrieve the destination of the session

Specified by:
getMyDestination in interface I2PSession

getDecryptionKey

public PrivateKey getDecryptionKey()
Retrieve the decryption PrivateKey

Specified by:
getDecryptionKey in interface I2PSession

getPrivateKey

public SigningPrivateKey getPrivateKey()
Retrieve the signing SigningPrivateKey

Specified by:
getPrivateKey in interface I2PSession

getProducer

I2CPMessageProducer getProducer()
Retrieve the helper that generates I2CP messages


getHandlerMap

I2PClientMessageHandlerMap getHandlerMap()
For Subsessions

Since:
0.9.21

getContext

I2PAppContext getContext()
For Subsessions

Since:
0.9.21

getOptions

Properties getOptions()
Retrieve the configuration options, filtered. All defaults passed in via constructor have been promoted to the primary map.

Returns:
non-null, if insantiated with null options, this will be the System properties.

getSessionId

SessionId getSessionId()
Retrieve the session's ID


setSessionId

void setSessionId(SessionId id)

setSessionListener

public void setSessionListener(I2PSessionListener lsnr)
configure the listener

Specified by:
setSessionListener in interface I2PSession
Parameters:
lsnr - listener to retrieve events

isClosed

public boolean isClosed()
Has the session been closed (or not yet connected)? False when open and during transitions. Synchronized.

Specified by:
isClosed in interface I2PSession
Returns:
true if the session is closed, OR connect() has not been called yet

sendMessage

void sendMessage(I2CPMessage message)
           throws I2PSessionException
Deliver an I2CP message to the router As of 0.9.3, may block for several seconds if the write queue to the router is full

Throws:
I2PSessionException - if the message is malformed or there is an error writing it out

propogateError

void propogateError(String msg,
                    Throwable error)
Pass off the error to the listener Misspelled, oh well.

Parameters:
error - non-null

destroySession

public void destroySession()
Tear down the session, and do NOT reconnect. Blocks if session has not been fully started.

Specified by:
destroySession in interface I2PSession

destroySession

public void destroySession(boolean sendDisconnect)
Tear down the session, and do NOT reconnect. Will interrupt an open in progress.


disconnected

public void disconnected(I2CPMessageReader reader)
The I2CPMessageEventListener callback. Recieve notification that the I2CP connection was disconnected.

Specified by:
disconnected in interface I2CPMessageReader.I2CPMessageEventListener
Parameters:
reader - unused

disconnect

protected void disconnect()
Will interrupt a connect in progress.


shouldReconnect

protected boolean shouldReconnect()

reconnect

protected boolean reconnect()

getPrefix

protected String getPrefix()
try hard to make a decent identifier as this will appear in error logs


destReceived

void destReceived(Destination d)
Called by the message handler on reception of DestReplyMessage

Parameters:
d - non-null

destLookupFailed

void destLookupFailed(Hash h)
Called by the message handler on reception of DestReplyMessage

Parameters:
h - non-null

destReceived

void destReceived(long nonce,
                  Destination d)
Called by the message handler on reception of HostReplyMessage

Parameters:
d - non-null
Since:
0.9.11

destLookupFailed

void destLookupFailed(long nonce)
Called by the message handler on reception of HostReplyMessage

Since:
0.9.11

bwReceived

void bwReceived(int[] i)
called by the message handler


clearCache

public static void clearCache()
Since:
0.9.20

lookupDest

public Destination lookupDest(Hash h)
                       throws I2PSessionException
Blocking. Waits a max of 10 seconds by default. See lookupDest with maxWait parameter to change. Implemented in 0.8.3 in I2PSessionImpl; previously was available only in I2PSimpleSession. Multiple outstanding lookups are now allowed.

Specified by:
lookupDest in interface I2PSession
Returns:
null on failure
Throws:
I2PSessionException

lookupDest

public Destination lookupDest(Hash h,
                              long maxWait)
                       throws I2PSessionException
Blocking.

Specified by:
lookupDest in interface I2PSession
Parameters:
maxWait - ms
Returns:
null on failure
Throws:
I2PSessionException
Since:
0.8.3

lookupDest

public Destination lookupDest(String name)
                       throws I2PSessionException
Ask the router to lookup a Destination by host name. Blocking. Waits a max of 10 seconds by default. This only makes sense for a b32 hostname, OR outside router context. Inside router context, just query the naming service. Outside router context, this does NOT query the context naming service. Do that first if you expect a local addressbook. This will log a warning for non-b32 in router context. See interface for suggested implementation. Requires router side to be 0.9.11 or higher. If the router is older, this will return null immediately.

Specified by:
lookupDest in interface I2PSession
Throws:
I2PSessionException
Since:
0.9.11

lookupDest

public Destination lookupDest(String name,
                              long maxWait)
                       throws I2PSessionException
Ask the router to lookup a Destination by host name. Blocking. See above for details.

Specified by:
lookupDest in interface I2PSession
Parameters:
maxWait - ms
Returns:
null on failure
Throws:
I2PSessionException
Since:
0.9.11

bandwidthLimits

public int[] bandwidthLimits()
                      throws I2PSessionException
Blocking. Waits a max of 5 seconds. But shouldn't take long. Implemented in 0.8.3 in I2PSessionImpl; previously was available only in I2PSimpleSession. Multiple outstanding lookups are now allowed.

Specified by:
bandwidthLimits in interface I2PSession
Returns:
null on failure
Throws:
I2PSessionException

updateActivity

protected void updateActivity()

lastActivity

public long lastActivity()

setReduced

public void setReduced()

toString

public String toString()
Overrides:
toString in class Object