- Direct Known Subclasses:
QueuedClientConnectionRunner
As of release 0.9.21, multiple sessions are supported on a single I2CP connection. These sessions share tunnels and some configuration.
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final RouterContextRouter context.protected final LogLogger for the runner.protected final ClientManagerClient manager managing this runner.protected I2CPMessageReaderReads and processes incoming I2CP messages from the client.Constructor Summary
ConstructorsConstructorDescriptionClientConnectionRunner(RouterContext context, ClientManager manager, Socket socket) Create a new runner against the given socket.Method Summary
All MethodsModifier and TypeMethodDescription(package private) voidackSendMessage(SessionId sid, MessageId id, long nonce) Send a notification to the client that their message (id specified) was accepted for delivery (but not necessarily delivered) Doesn't do anything ifi2cp.messageReliability= "none" or if the nonce is 0.Allow override for testing.(package private) voiddisconnectClient(String reason) Send a DisconnectMessage and log with level Log.ERROR.(package private) voiddisconnectClient(String reason, int logLevel) Disconnect the client with the given reason and log level.(package private) voidThe client was disconnected.(package private) MessageIddistributeMessage(SendMessageMessage message) Distribute the message.(package private) voiddoSend(I2CPMessage msg) Actually send the I2CPMessage to the peer through the socket.(package private) voiddoSendWait(I2CPMessage msg, long timeoutMs) Send a message, allowing the transport up to timeoutMs to accept it.voidFail the given lease request and track consecutive failures.The address of the client socket.The client version.Current client's config, will be null if session not found IS subsession aware.Current client's config, will be null if session not found IS subsession aware.Equivalent to getConfig().getDestination().calculateHash(); will be null before session is established Not subsession aware.getDestHash(SessionId id) Return the hash for the given ID.Return the dest for the given ID.(package private) List<Destination> Subsession aware.The FloodfillNetworkDatabaseFacade for this runner, the client netDb.(package private) booleanCheck if the runner is dead.(package private) LeaseRequestStateData for the current leaseRequest, or null if there is no active leaseSet request.getLeaseSet(Hash h) Currently allocated leaseSet.intGet the next message id.(package private) PayloadgetPayload(MessageId id) Only call if _dontSendMSMOnReceive is false, otherwise will always be null.Primary client's config, will be null if session not set up.(package private) SessionIdgetSessionId(Hash h) Subsession aware.Subsession aware.The current client's SessionKeyManager.(package private) booleanisDead()Already closed?(package private) voidCalled after a new leaseSet is granted by the client and the NetworkDb has been updated.(package private) booleanreceiveMessage(Destination toDest, Destination fromDest, Payload payload) Synchronously deliver the message to the current runner(package private) booleanreceiveMessage(Hash toHash, Destination fromDest, Payload payload) Synchronously deliver the message to the current runnerbooleanregisterEncryptedLS(Hash hash) Call after destinationEstablished(), when an encrypted leaseset is created, so we know it's local.(package private) voidOnly call if _dontSendMSMOnReceive is false.(package private) voidKill the session.voidreportAbuse(Destination dest, String reason, int severity) Send async abuse message to the client.(package private) voidrequestLeaseSet(Hash h, LeaseSet set, long expirationTime, Job onCreateJob, Job onFailedJob) Request that a particular client authorize the Leases contained in the LeaseSet, after which the onCreateJob is queued up.(package private) booleanRe-queue the pending lease request after netdb publish() rejected the client's LeaseSet as expired (client clock skew or slow signing).intsessionEstablished(SessionConfig config) Caller must send a SessionStatusMessage to the client with the returned code.voidsetClientVersion(String version) The client version.(package private) voidsetPayload(MessageId id, Payload payload) Only call if _dontSendMSMOnReceive is false.(package private) voidsetSessionId(Hash hash, SessionId id) To be called only by ClientManager.voidActually run the connection - listen for I2CP messages and respond.voidDie a horrible death.(package private) voidupdateMessageDeliveryStatus(Destination dest, MessageId id, long messageNonce, int status) Send a notification to the client that their message (id specified) was delivered (or failed delivery) Note that this sends the Guaranteed status codes, even though we only support best effort.(package private) voidwriteMessage(I2CPMessage msg) Not thread-safe.
Field Details
_log
Logger for the runner._context
Router context._manager
Client manager managing this runner._reader
Reads and processes incoming I2CP messages from the client.
Constructor Details
ClientConnectionRunner
Create a new runner against the given socket.- Parameters:
context- the router contextmanager- the client managersocket- the I2CP socket
Method Details
startRunning
Actually run the connection - listen for I2CP messages and respond. This is the main driver for this class, though it gets all its meat from theI2CPMessageReader.- Throws:
IOException- if the socket I/O fails
createListener
Allow override for testing.- Returns:
- the message event listener
stopRunning
public void stopRunning()Die a horrible death. Cannot be restarted.getAddress
getConfig
Current client's config, will be null if session not found IS subsession aware.- Parameters:
h- the session hash- Returns:
- the config, or null if session not found
getConfig
Current client's config, will be null if session not found IS subsession aware. Returns null if id is null.- Parameters:
id- the session id- Returns:
- the config, or null if not found or id is null
getPrimaryConfig
Primary client's config, will be null if session not set up.- Returns:
- the primary config, or null if not set up
setClientVersion
The client version.- Parameters:
version- the client version string
getClientVersion
getSessionKeyManager
The current client's SessionKeyManager. As of 0.9.44, returned implementation varies based on supported encryption types.- Returns:
- the session key manager
getLeaseSet
getDestHash
Equivalent to getConfig().getDestination().calculateHash(); will be null before session is established Not subsession aware. Returns primary session hash. Don't use if you can help it.- Returns:
- primary hash or null if not yet set
getDestHash
getDestination
Return the dest for the given ID.- Parameters:
id- the session id- Returns:
- dest or null if unknown
getSessionId
getSessionIds
getDestinations
List<Destination> getDestinations()Subsession aware.- Returns:
- all current client's destinations, non-null
setSessionId
To be called only by ClientManager.- Parameters:
hash- for the sessionid- the session id to set- Throws:
IllegalStateException- if already set
removeSession
Kill the session. Caller must kill runner if none left. If the session is primary and there are subsessions, this removes all subsessions also.- Parameters:
id- the session id to remove
getLeaseRequest
Data for the current leaseRequest, or null if there is no active leaseSet request. Not subsession aware. Returns primary ID only.- Parameters:
h- the session hash- Returns:
- the lease request state, or null if none
failLeaseRequest
Fail the given lease request and track consecutive failures. The counter decays afterLEASE_FAIL_DECAY_MSof no failures, so a brief I2CP stall does not permanently prime a disconnect. Counter resets to zero on successful LeaseSet receipt. All null states (request, requested LeaseSet, or its destination) are guarded before any dereference; RequestLeaseSetJob calls this with a null LeaseSet or null destination on its early-failure paths.- Parameters:
req- the failed request, or null to ignore
isDead
boolean isDead()Already closed?- Returns:
- true if the runner is dead
getPayload
setPayload
removePayload
Only call if _dontSendMSMOnReceive is false.- Parameters:
id- the message id to remove
sessionEstablished
Caller must send a SessionStatusMessage to the client with the returned code. Caller must call disconnectClient() on failure. Side effect: Sets the session ID.- Parameters:
config- the session config- Returns:
- SessionStatusMessage return code, 1 for success, != 1 for failure
updateMessageDeliveryStatus
Send a notification to the client that their message (id specified) was delivered (or failed delivery) Note that this sends the Guaranteed status codes, even though we only support best effort. Doesn't do anything ifi2cp.messageReliability= "none"Do not use for status = STATUS_SEND_ACCEPTED; use ackSendMessage() for that.
- Parameters:
dest- the client whose session is notified; no notification if it has noneid- the router's ID for this messagemessageNonce- the client's ID for this message, greater than zerostatus- see I2CP MessageStatusMessage for success/failure codes
leaseSetCreated
Called after a new leaseSet is granted by the client and the NetworkDb has been updated. This takes care of all the LeaseRequestState stuff (including firing any jobs).- Parameters:
ls- if encrypted, the encrypted LS, not the decrypted one
registerEncryptedLS
Call after destinationEstablished(), when an encrypted leaseset is created, so we know it's local. Add to the clients list. Check for a dup hash. Caller must call runner.disconnectClient() on failure.- Parameters:
hash- the location of the encrypted LS, will change every day- Returns:
- success, false on dup
disconnectClient
Send a DisconnectMessage and log with level Log.ERROR. This is always bad. SeeClientMessageEventListener.handleCreateSession(CreateSessionMessage)for why we don't send a SessionStatusMessage when we do this.- Parameters:
reason- will be truncated to 255 bytes
disconnectClient
Disconnect the client with the given reason and log level.- Parameters:
reason- will be truncated to 255 byteslogLevel- accepted but never read; the disconnect is logged at WARN
distributeMessage
Distribute the message. If the dest is local, it blocks until its passed to the target ClientConnectionRunner (which then fires it into a MessageReceivedJob). If the dest is remote, it blocks until it is added into the ClientMessagePool.- Parameters:
message- the message to distribute- Returns:
- the message id assigned
ackSendMessage
Send a notification to the client that their message (id specified) was accepted for delivery (but not necessarily delivered) Doesn't do anything ifi2cp.messageReliability= "none" or if the nonce is 0.- Parameters:
sid- the session idid- OUR id for the messagenonce- HIS id for the message
receiveMessage
Synchronously deliver the message to the current runnerFailure indication is available as of 0.9.29. Fails on e.g. queue overflow to client, client dead, etc.
- Parameters:
toDest- non-nullfromDest- generally null when from remote, non-null if from localpayload- the payload to deliver- Returns:
- true if the client was told about the message
receiveMessage
Synchronously deliver the message to the current runnerFailure indication is available as of 0.9.29. Fails on e.g. queue overflow to client, client dead, etc.
- Parameters:
toHash- non-nullfromDest- generally null when from remote, non-null if from localpayload- the payload to deliver- Returns:
- true if a session existed for
toHashand the client was told
reportAbuse
Send async abuse message to the client.- Parameters:
dest- the offending destinationreason- the human-readable description of the abuseseverity- the severity level
rerequestAfterTransientPublishFailure
Re-queue the pending lease request after netdb publish() rejected the client's LeaseSet as expired (client clock skew or slow signing). The same LeaseRequestState is re-run so the session slot, callbacks, and deadline stay intact while the job recomputes lease end times against the current clock, instead of leaving the request to wait out the full timeout check. Bounded byLeaseRequestState.MAX_TRANSIENT_PUBLISH_RETRIESso a persistently skewed client cannot re-request forever.- Parameters:
dest- the session destination, null for no session- Returns:
- true if a retry was queued
requestLeaseSet
Request that a particular client authorize the Leases contained in the LeaseSet, after which the onCreateJob is queued up. If that doesn't occur within the timeout specified, queue up the onFailedJob. This call does not block.Job args are always null, may need some fixups if we start using them.
- Parameters:
h- the Destination's hashset- LeaseSet with requested leases - this object must be updated to contain the signed version (as well as any changed/added/removed Leases) The LeaseSet contains Leases only, it is unsigned. Must be unique for this hash, do not reuse for subsessions.expirationTime- ms to wait before failingonCreateJob- Job to run after the LeaseSet is authorized, null OKonFailedJob- Job to run after the timeout passes without receiving authorization, null OK
disconnected
void disconnected()The client was disconnected.getIsDead
boolean getIsDead()Check if the runner is dead.- Returns:
- true if the runner is dead
writeMessage
Not thread-safe. Blocking. Only used for external sockets. ClientWriterRunner thread is the only caller. Others must use doSend().- Parameters:
msg- the message to write
doSend
Actually send the I2CPMessage to the peer through the socket.- Parameters:
msg- the message to send- Throws:
I2CPMessageException- if the message could not be sent
doSendWait
Send a message, allowing the transport up to timeoutMs to accept it.For messages whose loss costs more than a short wait. The default is
doSend(I2CPMessage): a socket-backed runner hands the message to a writer thread that buffers it regardless, so there is nothing to wait for here. Subclasses that write straight into a bounded queue override this.- Parameters:
msg- the message to sendtimeoutMs- how long to wait for the transport to accept the message- Throws:
I2CPMessageException- if the message could not be sent
getNextMessageId
public int getNextMessageId()Get the next message id.- Returns:
- the next id
getFloodfillNetworkDatabaseFacade
The FloodfillNetworkDatabaseFacade for this runner, the client netDb.If a session has not been created yet, it will return null.
- Returns:
- the client netdb or null if no session was created yet