- All Implemented Interfaces:
Closeable, AutoCloseable, SAMMessageSess, Session
- Direct Known Subclasses:
MasterSession
Manages I2P streaming connections via the SAM v3 bridge. Supports three modes: outgoing CONNECT, incoming ACCEPT (via a queue fed by MasterSession), and FORWARD (proxy to a local host:port).
For subsessions created under a MasterSession, incoming I2P sockets are placed on _acceptQueue by the master's acceptor thread and consumed by dedicated per-subsession accept threads. This decouples the I2P accept loop from the per-client SAM handler and allows multiple concurrent ACCEPT commands.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate classRunnable that performs the blocking I2P socket connect in a connector pool thread, then sets up pipes on success or reports the error to the SAM client.private static classBidirectional byte copier between a local socket and an I2P socket.private classForwards incoming I2P connections to a local TCP host:port.Nested classes/interfaces inherited from class SAMStreamSession
SAMStreamSession.DisconnectListener, SAMStreamSession.SAMStreamSessionServer, SAMStreamSession.SAMStreamSessionSocketReader, SAMStreamSession.SAMv1StreamSessionSocketReader, SAMStreamSession.StreamSenderModifier and TypeClassDescriptionprotected classCloses SAM session when the underlying I2P manager disconnects.classSAM STREAM session server, running in its own thread.static classReads bytes off one tunnel socket and pushes them to the SAM client.classSAMv1StreamSessionSocketReader.protected static classLets us push data through the stream without blocking, (even after exceeding the I2PSocket's buffer).Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AtomicIntegerThis is the count of active ACCEPT sockets.private final LinkedBlockingQueue<I2PSocket> For subsession only, null otherwise.private static final intSeconds to wait for a queued socket before returning null.private static final intBuffer size for the stream forwarding, in bytes.private static final intLargest accept queue allowed.private final StringNickname of the session, for the logs.private I2PServerSocketThis is ONLY set for FORWARD, not for ACCEPT.private final ObjectLock for the socket server state.private static I2PSSLSocketFactoryShared factory for the SSL forwarder sockets.Fields inherited from class SAMStreamSession
_isOwnSession, _log, canCreate, DEFAULT_FORCE_FLUSH, forceFlush, PROP_FORCE_FLUSH, recv, server, SOCKET_HANDLER_BUF_SIZE, socketMgrModifier and TypeFieldDescriptionprotected final booleanWhether this is our own session, as opposed to a remote peer's.protected final LogLogger for this session's messages.protected final booleanWhether this session may create outgoing connections.static final StringDefault forSAMStreamSession.PROP_FORCE_FLUSH.protected final booleanShould we flush every time we get a STREAM SEND, or leave that up to the streaming lib to decide?static final StringConfig key for flushing on every STREAM SEND.protected final SAMStreamReceiverThe receiver that decodes incoming SAM messages.protected final SAMStreamSession.SAMStreamSessionServerThe server this session belongs to.protected static final intRead buffer size for each socket reader.protected final I2PSocketManagerThe socket manager used for outgoing connections.Constructor Summary
ConstructorsConstructorDescriptionSAMv3StreamSession(String login) Create a new SAM STREAM session, according to information registered with the given nicknameSAMv3StreamSession(String login, Properties props, SAMv3Handler handler, I2PSocketManager mgr, int listenPort) Build a Stream Session on an existing I2P session registered with the given nicknameMethod Summary
Modifier and TypeMethodDescriptionvoidaccept(SAMv3Handler handler, boolean verbose) Accept a single incoming I2P stream and pipe data through the handler's socket.private I2PSocketTake a socket from the accept queue, with a timeout to avoid indefinite blocking on stale connections.voidclose()Close the stream session.voidconnectAsync(SAMv3Handler handler, String dest, Properties props) Initiate an async STREAM CONNECT.private voiddoAccept(SAMv3Handler handler, boolean verbose) Blocking accept executed in a dedicated thread so pool workers are never blocked waiting for incoming I2P connections.intReturn how many accepted sockets are waiting to be handed to the client.static SessionsDBgetDB()Get the global sessions database shared by all SAM handlers.getNick()Return the nickname this session is registered under.protected I2PServerSocketReturn the server socket this session accepts incoming I2P connections on.booleanqueueSocket(I2PSocket sock) Put a socket on the accept queue.voidstartForwardingIncoming(Properties props, boolean sendPorts) Forward sockets from I2P to the host/port provided.voidStop forwarding an incoming connection coming from I2P.private static StringNickname truncated to four characters.Methods inherited from class SAMStreamSession
checkSocketHandlerId, closeConnection, connect, createSocketHandler, getDestination, getListenPort, getListenProtocol, getSocketReader, isDestroyed, lookupDest, newSAMStreamSessionSocketReader, newStreamSender, removeSocketHandler, sendBytes, sendBytes, sendBytes, setReceiveLimit, startModifier and TypeMethodDescriptionprotected booleancheckSocketHandlerId(int id) Check whether a SAM STREAM session socket handler id is still in use.booleancloseConnection(int id) Close a connection managed by the SAM STREAM session.booleanconnect(int id, String dest, Properties props) Connect the SAM STREAM session to the specified Destination.protected intcreateSocketHandler(I2PSocket s, int id) Create a new SAM STREAM session socket handler, detaching its thread.Get the SAM STREAM session Destination.intGet the port for this session's listener.intGet the I2CP protocol for this session's listener.getSocketReader(int id) Get a SAM STREAM session socket handler.booleanIs the underlying streaming socket manager destroyed?lookupDest(String name) Lookup a destination through the I2CP session.newSAMStreamSessionSocketReader(I2PSocket s, int id) Create a new SAM STREAM session socket reader.protected SAMStreamSession.StreamSendernewStreamSender(I2PSocket s, int id) Creates the sender that writes this socket's outgoing data.protected voidremoveSocketHandler(int id) Remove and gracefully close a SAM STREAM session socket handler.booleansendBytes(int id, InputStream in, int size) Send bytes through a SAM STREAM session.booleanSending bytes is not supported in a STREAM or MASTER session; always throws.booleansendBytes(String s, byte[] b, int pr, int fp, int tp, boolean sendLeaseSet, int sendTags, int tagThreshold, int expiration) Sending bytes is not supported in a STREAM or MASTER session; always throws.(package private) booleansetReceiveLimit(int id, long limit, boolean nolimit) Set a receive limit for a stream.voidstart()Start the SAM STREAM session server, if applicable.
Field Details
BUFFER_SIZE
private static final int BUFFER_SIZEBuffer size for the stream forwarding, in bytes.- See Also:
MAX_ACCEPT_QUEUE
private static final int MAX_ACCEPT_QUEUELargest accept queue allowed.- See Also:
ACCEPT_POLL_TIMEOUT_SECS
private static final int ACCEPT_POLL_TIMEOUT_SECSSeconds to wait for a queued socket before returning null.- See Also:
socketServerLock
Lock for the socket server state.socketServer
This is ONLY set for FORWARD, not for ACCEPT._acceptors
This is the count of active ACCEPT sockets._acceptQueue
For subsession only, null otherwise.sslSocketFactory
Shared factory for the SSL forwarder sockets.nick
Nickname of the session, for the logs.
Constructor Details
SAMv3StreamSession
Create a new SAM STREAM session, according to information registered with the given nicknameCaller MUST call start().
- Parameters:
login- the nickname this session is registered under- Throws:
IOException- declared on this constructor, but not raised by the bodyDataFormatException- likewise declared, but not raised by the bodySAMException- if the destination or properties read from the record name no known direction or cannot build a sessionNullPointerException- if the login nickname is not registered
SAMv3StreamSession
public SAMv3StreamSession(String login, Properties props, SAMv3Handler handler, I2PSocketManager mgr, int listenPort) Build a Stream Session on an existing I2P session registered with the given nicknameCaller MUST call start().
- Parameters:
login- nickname of the sessionprops- STREAM command arguments, read by the superclasshandler- handler used to send STREAM replies back to the clientmgr- socket manager used to create the stream socketslistenPort- local port to accept on, 0 for any port
Method Details
getNick
queueSocket
Put a socket on the accept queue. Called byMasterSession.StreamAcceptorwhen an I2P connection arrives and matches this subsession's listen protocol and port.Only for subsessions created with the 5-arg constructor; the 1-arg constructor sets
_acceptQueueto null and this method throwsIllegalStateException.- Parameters:
sock- the accepted I2P socket- Returns:
- true if queued; false if the queue is full (caller must reset the socket)
- Throws:
IllegalStateException- if called on a non-subsession
getAcceptQueueSize
public int getAcceptQueueSize()Return how many accepted sockets are waiting to be handed to the client.- Returns:
- the number of sockets waiting in the accept queue, 0 if not a subsession
acceptSocket
Take a socket from the accept queue, with a timeout to avoid indefinite blocking on stale connections. Under heavy tracker traffic, sockets may accumulate faster than the client can consume them. A timeout ensures the acceptor thread can check for shutdown and avoid leaking threads on idle sessions.- Returns:
- the next queued socket, or null if the queue is empty after the timeout (caller must handle null)
- Throws:
ConnectException- if the thread is interrupted
getDB
Get the global sessions database shared by all SAM handlers.- Returns:
- the sessions database
connectAsync
public void connectAsync(SAMv3Handler handler, String dest, Properties props) throws DataFormatException Initiate an async STREAM CONNECT. Validates parameters synchronously, unregisters from the pool, then hands the blocking connect to a shared connector thread pool. Returns immediately — the caller's worker is never blocked by an I2P connection attempt.The ConnectTask handles all error reporting and pipe setup so the calling worker is free to process other commands immediately.
- Parameters:
handler- handler whose socket becomes the I2P data pipedest- the Base64-encoded destination to connect toprops- the connection options read from the STREAM CONNECT command- Throws:
DataFormatException- if dest is invalid
truncNick
accept
public void accept(SAMv3Handler handler, boolean verbose) throws SAMException, InterruptedIOException Accept a single incoming I2P stream and pipe data through the handler's socket. Validation is synchronous; the blocking accept runs in a dedicated thread so pool workers are never blocked waiting for an incoming I2P connection.Multiple simultaneous accepts are allowed (v3.2+). Accepts and forwarding may not be done at the same time.
- Parameters:
handler- handler whose socket becomes the I2P data pipeverbose- if true, send peer Destination as first line- Throws:
SAMException- if a forwarding server is already activeInterruptedIOException- if session is gone
doAccept
Blocking accept executed in a dedicated thread so pool workers are never blocked waiting for incoming I2P connections.- Parameters:
handler- the handler whose bridge accepts the connectionverbose- true to report the incoming connection back to the SAM client
startForwardingIncoming
public void startForwardingIncoming(Properties props, boolean sendPorts) throws SAMException, InterruptedIOException Forward sockets from I2P to the host/port provided. Accepts and forwarding may not be done at the same time.- Parameters:
props- session properties supplying HOST, PORT, SSL, and SILENTsendPorts- true to report the local port back to the client- Throws:
SAMException- if PORT is missing or invalid, or a server is already definedInterruptedIOException- if this session is no longer registered
getSocketServer
Return the server socket this session accepts incoming I2P connections on.- Returns:
- the socket server
stopForwardingIncoming
Stop forwarding an incoming connection coming from I2P.- Throws:
SAMException- if no socket server has been defined for this destinationInterruptedIOException- if the session record for this nickname has already been removed
close
public void close()Close the stream session.- Specified by:
closein interfaceAutoCloseable- Specified by:
closein interfaceCloseable- Specified by:
closein interfaceSAMMessageSess- Overrides:
closein classSAMStreamSession