java.lang.Object
net.i2p.sam.SAMHandler
All Implemented Interfaces:
Runnable, Handler
Direct Known Subclasses:
SAMv1Handler

abstract class SAMHandlerextends Object implements Runnable, Handler
Base class for SAM protocol handlers. It implements common methods, but is not able to actually parse the protocol itself: this task is delegated to subclasses.
  • Field Summary

    Modifier and Type
    Field
    Description
    protected final Log
    Log scoped to this handler's class.
    private String
    Username this connection authenticated with during the HELLO handshake, or null when the bridge has authentication disabled or the connection was never authenticated.
    protected final SAMBridge
    Router bridge this handler routes sessions over.
    protected final Properties
    I2CP options configuring the I2CP connection (port, host, numHops, etc).
    protected final SocketChannel
    Client channel this handler reads commands from.
    private final Object
    Held while writing to the SAM socket.
    protected boolean
    Whether shutdown has been requested for this handler.
    protected final Object
    Monitor guarding the stop flag.
    protected I2PAppThread
    Thread running the SAM protocol loop for this connection.
    final int
    Major version this handler was negotiated at.
    final int
    Minor version this handler was negotiated at.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    SAMHandler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps, SAMBridge parent)
    SAMHandler constructor (to be called by subclasses).
  • Method Summary

    Modifier and Type
    Method
    Description
    protected final void
    Close the socket connected to the SAM client.
    (package private) final String
    Get the username this connection authenticated with, if any.
    protected final SocketChannel
    Get the channel of the socket connected to the SAM client.
    (package private) final String
    Get the remote address and port of this connection, bracketing IPv6, for rejection and ban logging.
    private String
    Get the remote address of this connection.
    protected Object
    If you're crazy enough to write to the raw socket, grab the write lock with getWriteLock(), synchronize against it, and write to the getOut().
    protected abstract void
    Actually handle the SAM protocol.
    (package private) static boolean
    Determine whether an address is a loopback address, in any of the forms the platform may report it.
    protected void
    Log a session startup failure.
    final void
    run()
    Register with the bridge, call handle(), unregister with the bridge.
    (package private) static boolean
    sameClient(String myAuthUser, String otherAuthUser, String myHost, String otherHost)
    Decide whether two SAM connections belong to the same client.
    (package private) final boolean
    Determine whether two connections belong to the same client, which is what decides whether one of them may use a session nickname owned by the other.
    (package private) final void
    Record the username this connection authenticated with.
    protected final boolean
    Should the handler be stopped?
    void
    Start handling the SAM connection, detaching a handling thread.
    void
    Stop the SAM handler, close the client socket, unregister with the bridge.
    final String
    Get a string describing the handler.
    protected final void
    Write a byte array on the handler's socket.
    private static void
    Caller must synch.
    protected final boolean
    Write a string to the handler's socket.
    static boolean
    Unsynchronized, use with caution.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • Field Details

    • _log

      protected final Log _log
      Log scoped to this handler's class.
    • thread

      protected I2PAppThread thread
      Thread running the SAM protocol loop for this connection.
    • bridge

      protected final SAMBridge bridge
      Router bridge this handler routes sessions over.
    • socketWLock

      private final Object socketWLock
      Held while writing to the SAM socket.
    • socket

      protected final SocketChannel socket
      Client channel this handler reads commands from.
    • verMajor

      public final int verMajor
      Major version this handler was negotiated at.
    • verMinor

      public final int verMinor
      Minor version this handler was negotiated at.
    • i2cpProps

      protected final Properties i2cpProps
      I2CP options configuring the I2CP connection (port, host, numHops, etc).
    • stopLock

      protected final Object stopLock
      Monitor guarding the stop flag.
    • stopHandler

      protected boolean stopHandler
      Whether shutdown has been requested for this handler.
    • authUser

      private volatile String authUser
      Username this connection authenticated with during the HELLO handshake, or null when the bridge has authentication disabled or the connection was never authenticated. Records created for sub-sessions copy the username of the control connection that created them.
  • Constructor Details

    • SAMHandler

      protected SAMHandler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps, SAMBridge parent)
      SAMHandler constructor (to be called by subclasses).
      Parameters:
      s - Socket attached to a SAM client
      verMajor - SAM major version to manage
      verMinor - SAM minor version to manage
      i2cpProps - properties to configure the I2CP connection (host, port, etc)
      parent - owning SAM bridge, which registers this handler as a live client on connect
  • Method Details

    • getAuthUser

      final String getAuthUser()
      Get the username this connection authenticated with, if any.
      Returns:
      the authenticated username, or null if not authenticated
    • setAuthUser

      final void setAuthUser(String user)
      Record the username this connection authenticated with.
      Parameters:
      user - the authenticated username, or null
    • getRemoteAddrPort

      final String getRemoteAddrPort()
      Get the remote address and port of this connection, bracketing IPv6, for rejection and ban logging.
      Returns:
      e.g. "127.0.0.1:54321" or "[::1]:1234", "unknown" if unavailable
    • getRemoteHost

      private String getRemoteHost()
      Get the remote address of this connection.
      Returns:
      the remote IP, or null if unavailable
    • sameClient

      final boolean sameClient(SAMHandler other)
      Determine whether two connections belong to the same client, which is what decides whether one of them may use a session nickname owned by the other. Connections that authenticated share their username; otherwise the remote address decides, so a session may be used by a second connection from the same host but not by a host that merely knows the nickname. All loopback addresses count as the same host.
      Parameters:
      other - the other connection's handler, may be null
      Returns:
      true if this connection may act on the other's sessions
    • sameClient

      static boolean sameClient(String myAuthUser, String otherAuthUser, String myHost, String otherHost)
      Decide whether two SAM connections belong to the same client. When both carry an authenticated user the user decides; otherwise the connections are the same only if they come from the same address, with any loopback address treated as the same host since the platform may report it in several forms.
      Parameters:
      myAuthUser - authenticated user of this connection, may be null
      otherAuthUser - authenticated user of the other connection, may be null
      myHost - address of this connection, may be null
      otherHost - address of the other connection, may be null
      Returns:
      true if the two connections belong to the same client
    • isLoopbackAddress

      static boolean isLoopbackAddress(String host)
      Determine whether an address is a loopback address, in any of the forms the platform may report it.
      Parameters:
      host - the address, may be null
      Returns:
      true if it is a loopback address
    • logSessionError

      protected void logSessionError(String msg, Exception e)
      Log a session startup failure. During the first minute of uptime these are expected - the router's client manager may not be listening yet - so log at warn level; after that they are errors.
      Parameters:
      msg - the message received
      e - the error that occurred
    • startHandling

      public void startHandling()
      Start handling the SAM connection, detaching a handling thread. Subclasses (e.g. SAMv3Handler) may override to use a shared thread pool instead of a dedicated thread.
    • handle

      protected abstract void handle()
      Actually handle the SAM protocol.
    • getClientSocket

      protected final SocketChannel getClientSocket()
      Get the channel of the socket connected to the SAM client.
      Returns:
      the client socket, or null before it is accepted
    • writeBytes

      protected final void writeBytes(ByteBuffer data) throws IOException
      Write a byte array on the handler's socket. This method must always be used when writing data, unless you really know what you're doing.
      Parameters:
      data - A byte array to be written
      Throws:
      IOException - if the client socket refuses or fails the write
    • writeBytes

      private static void writeBytes(ByteBuffer data, SocketChannel out) throws IOException
      Caller must synch.
      Parameters:
      data - the bytes to write
      out - the socket channel to write to
      Throws:
      IOException - on write errors
    • getWriteLock

      protected Object getWriteLock()
      If you're crazy enough to write to the raw socket, grab the write lock with getWriteLock(), synchronize against it, and write to the getOut().
      Returns:
      socket Write lock object
    • writeString

      protected final boolean writeString(String str)
      Write a string to the handler's socket. This method must always be used when writing strings, unless you really know what you're doing.
      Parameters:
      str - A string to be written
      Returns:
      True if the string was successfully written, false otherwise
    • writeString

      public static boolean writeString(String str, SocketChannel out)
      Unsynchronized, use with caution.
      Parameters:
      str - the string to write
      out - the socket channel to write to
      Returns:
      true on success
    • closeClientSocket

      protected final void closeClientSocket() throws IOException
      Close the socket connected to the SAM client.
      Throws:
      IOException - if the client socket cannot be closed
    • stopHandling

      public void stopHandling()
      Stop the SAM handler, close the client socket, unregister with the bridge.
      Specified by:
      stopHandling in interface Handler
    • shouldStop

      protected final boolean shouldStop()
      Should the handler be stopped?
      Returns:
      True if the handler should be stopped, false otherwise
    • toString

      public final String toString()
      Get a string describing the handler.
      Overrides:
      toString in class Object
      Returns:
      A String describing the handler;
    • run

      public final void run()
      Register with the bridge, call handle(), unregister with the bridge.
      Specified by:
      run in interface Runnable