All Implemented Interfaces:
Closeable, AutoCloseable, I2PSessionListener, I2PSessionMuxedListener, SAMDatagramReceiver, SAMMessageSess, SAMRawReceiver, Session

The primary (mux) session for a SAMv3 client, sharing a single I2P destination across multiple protocol subsessions (STREAM, DATAGRAM, RAW).

Extends SAMv3StreamSession to inherit the I2PSession setup; the streaming acceptor thread (StreamAcceptor) accepts I2P connections and dispatches them to the correct subsession by protocol and port, via SAMv3StreamSession.queueSocket(I2PSocket).

The master session itself is not directly usable for data transfer. All streaming, datagram, and raw operations are delegated to registered subsessions. Calling connectAsync(SAMv3Handler, String, Properties), accept(SAMv3Handler, boolean), or startForwardingIncoming(Properties, boolean) on this instance throws unconditionally.

Under heavy tracker traffic, the accept loop may see thousands of connections per minute. Overflow logging is rate-limited to avoid flooding the router log when subsession queues fill faster than clients can consume.

  • Field Details

    • handler

      private final SAMv3Handler handler
      The handler serving the SAM sessions.
    • dgs

      private final SAMv3DatagramServer dgs
      The server for the datagram sessions.
    • sessions

      private final Map<String, SAMMessageSess> sessions
      The message sessions, by name.
    • streamAcceptor

      private final MasterSession.StreamAcceptor streamAcceptor
      The thread accepting the stream connections.
    • INVALID_OPTS

      private static final String[] INVALID_OPTS
      Session options that are not allowed.
    • OVERFLOW_LOG_INTERVAL_MS

      private static final long OVERFLOW_LOG_INTERVAL_MS
      Log overflow warnings at most once per 5 seconds to avoid flooding.
      See Also:
    • _lastOverflowLog

      private volatile long _lastOverflowLog
      When the session overflow was last logged.
    • _overflowCount

      private volatile int _overflowCount
      Sessions over the limit since the last log.
  • Constructor Details

    • MasterSession

      public MasterSession(String nick, SAMv3DatagramServer dgServer, SAMv3Handler handler, Properties props) throws IOException, DataFormatException, SAMException
      Build a Session according to information registered with the given nickname.

      Caller MUST call start().

      Parameters:
      nick - nickname of the session
      dgServer - the datagram server that raw and datagram subsessions register with
      handler - the SAMv3 handler this session answers commands from
      props - the MASTER session options, which may not include any of the subsession-only keys such as PORT or PROTOCOL
      Throws:
      IOException - declared by the SAMv3StreamSession constructor called here, but not raised by this body
      DataFormatException - likewise declared but not raised by this body
      SAMException - if props names an option that only a subsession may set
  • Method Details

    • start

      public void start()
      Start the stream acceptor thread. Must be called after construction.
      Specified by:
      start in interface SAMMessageSess
      Overrides:
      start in class SAMStreamSession
    • add

      public String add(String nick, String style, Properties props)
      Add a protocol subsession (STREAM, DATAGRAM, or RAW) to this master session. The subsession gets its own protocol/port binding and is registered in the global sessions database so incoming connections can be dispatched to it.

      Sessions are mutually exclusive on (protocol, port) — two subsessions may not listen on the same protocol and port.

      Parameters:
      nick - unique nickname for this subsession
      style - protocol style: "STREAM", "DATAGRAM", or "RAW"
      props - session properties (PORT required for DATAGRAM/RAW; LISTEN_PORT, LISTEN_PROTOCOL optional)
      Returns:
      null on success, or a descriptive error message
    • remove

      public String remove(String nick, Properties props)
      Remove a protocol subsession by nickname. The session is closed, removed from the global sessions database, and its port binding is released.
      Parameters:
      nick - nickname of the subsession to remove
      props - session properties (unused, may be null)
      Returns:
      null on success, or a descriptive error message
    • receiveDatagramBytes

      public void receiveDatagramBytes(Destination sender, byte[] data, int proto, int fromPort, int toPort) throws IOException
      Throws IOException — the master session does not handle datagram data directly; use a DATAGRAM subsession instead.
      Specified by:
      receiveDatagramBytes in interface SAMDatagramReceiver
      Parameters:
      sender - the destination the datagram arrived from
      data - Byte array to be received
      proto - I2CP protocol
      fromPort - I2CP from port
      toPort - I2CP to port
      Throws:
      IOException - always, on every call
    • stopDatagramReceiving

      public void stopDatagramReceiving()
      No-op — master delegates datagram handling to subsessions.
      Specified by:
      stopDatagramReceiving in interface SAMDatagramReceiver
    • receiveRawBytes

      public void receiveRawBytes(byte[] data, int proto, int fromPort, int toPort) throws IOException
      Throws IOException — the master session does not handle raw data directly; use a RAW subsession instead.
      Specified by:
      receiveRawBytes in interface SAMRawReceiver
      Parameters:
      data - Byte array to be received
      proto - I2CP protocol
      fromPort - I2CP from port
      toPort - I2CP to port
      Throws:
      IOException - always, on every call
    • stopRawReceiving

      public void stopRawReceiving()
      No-op, the master session does not receive raw data.
      Specified by:
      stopRawReceiving in interface SAMRawReceiver
    • connectAsync

      public void connectAsync(SAMv3Handler handler, String dest, Properties props) throws DataFormatException
      Throws, use a STREAM subsession instead.
      Overrides:
      connectAsync in class SAMv3StreamSession
      Parameters:
      handler - handler whose socket becomes the I2P data pipe
      dest - the Base64-encoded destination to connect to
      props - the connection options read from the STREAM CONNECT command
      Throws:
      DataFormatException - always, the master session does not connect
    • accept

      public void accept(SAMv3Handler handler, boolean verbose) throws SAMException
      Throws, use a STREAM subsession instead.
      Overrides:
      accept in class SAMv3StreamSession
      Parameters:
      handler - handler whose socket becomes the I2P data pipe
      verbose - if true, send peer Destination as first line
      Throws:
      SAMException - always, the master session does not do this
    • startForwardingIncoming

      public void startForwardingIncoming(Properties props, boolean sendPorts) throws SAMException
      Throws, use a STREAM subsession instead.
      Overrides:
      startForwardingIncoming in class SAMv3StreamSession
      Parameters:
      props - session properties supplying HOST, PORT, SSL, and SILENT
      sendPorts - true to report the local port back to the client
      Throws:
      SAMException - always, the master session does not do this
    • stopForwardingIncoming

      public void stopForwardingIncoming()
      Does nothing.
      Overrides:
      stopForwardingIncoming in class SAMv3StreamSession
    • getListenProtocol

      public int getListenProtocol()
      // SAMMessageSess interface
      Specified by:
      getListenProtocol in interface SAMMessageSess
      Overrides:
      getListenProtocol in class SAMStreamSession
      Returns:
      the I2CP protocol
    • getListenPort

      public int getListenPort()
      Description copied from class: SAMStreamSession
      Get the port for this session's listener.
      Specified by:
      getListenPort in interface SAMMessageSess
      Overrides:
      getListenPort in class SAMStreamSession
      Returns:
      the listen port
    • close

      public void close()
      Close the master session and all registered subsessions. Stops the stream acceptor thread, removes all subsessions from the global sessions database, and destroys the underlying I2PSocketManager.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Specified by:
      close in interface SAMMessageSess
      Overrides:
      close in class SAMv3StreamSession
    • disconnected

      public void disconnected(I2PSession session)
      Called when the I2P session is disconnected, from the session muxed interface.
      Specified by:
      disconnected in interface I2PSessionListener
      Specified by:
      disconnected in interface I2PSessionMuxedListener
      Parameters:
      session - the disconnected session
    • errorOccurred

      public void errorOccurred(I2PSession session, String message, Throwable error)
      Called when an I2P error occurs.
      Specified by:
      errorOccurred in interface I2PSessionListener
      Specified by:
      errorOccurred in interface I2PSessionMuxedListener
      Parameters:
      session - the session that reported the error
      message - human-readable description of the failure, logged
      error - the exception, if any
    • messageAvailable

      public void messageAvailable(I2PSession session, int msgId, long size)
      Called when a message is available (unmuxed).
      Specified by:
      messageAvailable in interface I2PSessionListener
      Specified by:
      messageAvailable in interface I2PSessionMuxedListener
      Parameters:
      session - the session the message arrived on
      msgId - the message ID
      size - the message size
    • messageAvailable

      public void messageAvailable(I2PSession session, int msgId, long size, int proto, int fromPort, int toPort)
      Called when a muxed message is available.
      Specified by:
      messageAvailable in interface I2PSessionMuxedListener
      Parameters:
      session - the session the muxed message arrived on
      msgId - the message ID
      size - the message size
      proto - the protocol number
      fromPort - the source port
      toPort - the destination port
    • reportAbuse

      public void reportAbuse(I2PSession session, int severity)
      Called when abuse is reported on the session.
      Specified by:
      reportAbuse in interface I2PSessionListener
      Specified by:
      reportAbuse in interface I2PSessionMuxedListener
      Parameters:
      session - the session the abuse was reported on
      severity - the abuse severity level
    • messageReceived

      private void messageReceived(byte[] msg, int proto, int fromPort, int toPort)
      Handle a received message. Logs a warning for unhandled messages.
      Parameters:
      msg - the message bytes
      proto - the protocol number
      fromPort - the source port
      toPort - the destination port