java.lang.Object
net.i2p.sam.SAMBridge
SAM bridge — listens on TCP, dispatches each client to a
SAMHandlerFactory handler via SAMHandlerPool, and tracks sessions in SessionsDB. Entry point for all SAM v1/v2/v3 STREAM/DATAGRAM/RAW/MASTER sessions.Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class/// end ClientApp helpersprivate static classParsed command-line options for the SAM bridge.Field Summary
Modifier and TypeFieldDescriptionprivate final FileConfig file holding the SAM keys.private SAMHandlerPoolThe shared handler pool, while in use.The handlers serving open connections.private final StringHost the bridge listens on.private final intPort the bridge listens on.private final LogLogger for the SAM bridge.private static final LogLogger usable before the context exists.private final ClientAppManagerThe app manager that started the bridge.private ThreadThe thread running the accept loop.private final SAMSecureSessionInterfacePluggable "Secure Session Manager" for interactive, GUI-based session confirmation.private final longWhen this bridge was instantiated, for the session-error grace window.private ClientAppStateCurrent state of the bridge app.private final booleanTrue if the bridge connections use SSL.private SAMv3DatagramServerThe v3 datagram server, while running.private final ObjectLock for the v3 datagram server state.private booleanTrue while the bridge accepts new connections.protected static final StringDefault listen address for the SAM datagram socket.protected static final StringDefault port string for the SAM datagram socket.protected static final intDefault port for the SAM datagram socket.(package private) static final StringDefault filename for the SAM configuration file.static final StringDefault filename for persistent SAM private key storage.protected static final StringDefault listen address for the SAM TCP socket.protected static final StringDefault port for the SAM TCP socket.private final PropertiesI2CP properties passed to the sessions.App designated destination name to the base64 of the I2P formatted destination keys (Destination+PrivateKey+SigningPrivateKey).private final StringFilename in which the name to private key mapping should be stored (and loaded from).static final StringProperty to enable SAM bridge authentication.static final StringProperty for the SAM datagram listen address.static final StringProperty for the SAM datagram listen port.static final StringProperty prefix for SAM password hash entries.static final StringProperty suffix for SAM password hash entries.private static final StringConfig key naming the SAM key file.private static final StringConfig key enabling SSL for the bridge.static final StringProperty for the SAM TCP listen address.static final StringProperty for the SAM TCP listen port.private ServerSocketChannelThe listening channel for client connections.Constructor Summary
ConstructorsConstructorDescriptionSAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps, String persistFile, File configFile) Build a new SAM bridge.SAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps, String persistFile, File configFile, SAMSecureSessionInterface secureSession) Build a new SAM bridge.SAMBridge(I2PAppContext context, ClientAppManager mgr, String[] args) For ClientApp interface.Method Summary
Modifier and TypeMethodDescriptionvoidaddKeystream(String name, String stream) Specify that the given keystream should be used for the given name.(package private) static StringbuildSessionTable(List<String[]> rows) Build the session table from rows of {nickname, style, destination, handler IP, state, last accessed}.private voidchangeState(ClientAppState state) Record a state change with no associated error.private voidchangeState(ClientAppState state, Exception e) Record the new state and tell the ClientAppManager about it, if there is one.Return the display name.intCount the handlers currently serving a SAM connection, for the console status page.(package private) SAMHandlerPoolAccess the shared handler pool for v3 connections.getKeystream(String name) Retrieve the I2P private keystream for the given name, formatted as a base64 string (Destination+PrivateKey+SessionPrivateKey, as I2CP stores it).getName()Report the constant service name, without the listen address.private static SAMBridge.OptionsgetOptions(String[] args) Usage:intCount the handler-pool threads running a command, for the console status page.intCount the handlers registered with the pool, whether or not they are currently running.intCount every thread in the handler pool, busy or not, for the console status page.intCount the commands waiting for a free pool thread, for the console status page.intCount the named v3 sessions held in the SessionsDB, for the console status page.getState()Report the bridge's position in the ClientApp lifecycle.intCount handlers whose socket has been stolen for data streaming.longMilliseconds since this bridge was instantiated, minimum 1000 while racing on startup, mirroring Router.getUptime().(package private) SAMv3DatagramServergetV3DatagramServer(Properties props) Was a static singleton, now a singleton for this bridge.private voidloadKeys()Load up the keys from the persistFilename.static voidUsage:private voidOpen and bind the server socket (TCP or SSL).private static voidparseOptions(String[] args, int startArgs, Properties props) Parse key=value options starting at startArgs.voidHandlers must call on startup.voidRender the session table and handler summary as HTML.voidrun()Accept incoming SAM connections and dispatch to handlers.voidSave the current configuration to disk.Returns the interactive Secure Session manager which requires SAM applications to seek "approval" for their initial connections from the user before they can start the session.voidStop the bridge, shutting down the handler pool and the handlers and sessions running on it.private voidStart the listener thread and schedule periodic stale-session sweeps.voidstartup()Start the bridge.(package private) static StringstateDotClass(String state) Dot color for a session state: control is a live session, forwarding and stolen are data paths, idle has no session yet, orphan lost its handler.private voidStop all the handlers.private voidStore the current keys to disk in the location specified on creation.voidunregister(Handler handler) Handlers must call on stop.(package private) voidunregisterHandlerFromPool(SAMv3Handler handler) Remove a v3 handler from the shared handler pool.private static voidusage()Prints the command line usage text.
Field Details
_logStatic
Logger usable before the context exists._log
Logger for the SAM bridge._started
private final long _startedWhen this bridge was instantiated, for the session-error grace window.serverSocket
The listening channel for client connections._listenHost
Host the bridge listens on._listenPort
private final int _listenPortPort the bridge listens on.i2cpProps
I2CP properties passed to the sessions._useSSL
private final boolean _useSSLTrue if the bridge connections use SSL._configFile
Config file holding the SAM keys._runner
The thread running the accept loop._v3DGServerLock
Lock for the v3 datagram server state._v3DGServer
The v3 datagram server, while running._secureSession
Pluggable "Secure Session Manager" for interactive, GUI-based session confirmation. This will block the SAM Handler Factory at the HELLO phase. during the createSAMHandler call. If it's null, then no interactive session will be used and SAM will work without it.persistFilename
Filename in which the name to private key mapping should be stored (and loaded from).nameToPrivKeys
_handlers
_handlerPool
The shared handler pool, while in use.acceptConnections
private volatile boolean acceptConnectionsTrue while the bridge accepts new connections._mgr
The app manager that started the bridge._state
Current state of the bridge app.DEFAULT_SAM_KEYFILE
Default filename for persistent SAM private key storage.- See Also:
DEFAULT_SAM_CONFIGFILE
Default filename for the SAM configuration file.- See Also:
PROP_SAM_KEYFILE
Config key naming the SAM key file.- See Also:
PROP_SAM_SSL
Config key enabling SSL for the bridge.- See Also:
PROP_TCP_HOST
Property for the SAM TCP listen address.- See Also:
PROP_TCP_PORT
Property for the SAM TCP listen port.- See Also:
PROP_AUTH
Property to enable SAM bridge authentication.- See Also:
PROP_PW_PREFIX
Property prefix for SAM password hash entries.- See Also:
PROP_PW_SUFFIX
Property suffix for SAM password hash entries.- See Also:
DEFAULT_TCP_HOST
Default listen address for the SAM TCP socket.- See Also:
DEFAULT_TCP_PORT
Default port for the SAM TCP socket.- See Also:
PROP_DATAGRAM_HOST
Property for the SAM datagram listen address.- See Also:
PROP_DATAGRAM_PORT
Property for the SAM datagram listen port.- See Also:
DEFAULT_DATAGRAM_HOST
Default listen address for the SAM datagram socket.- See Also:
DEFAULT_DATAGRAM_PORT_INT
protected static final int DEFAULT_DATAGRAM_PORT_INTDefault port for the SAM datagram socket.- See Also:
DEFAULT_DATAGRAM_PORT
Default port string for the SAM datagram socket.
Constructor Details
SAMBridge
SAMBridge
public SAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps, String persistFile, File configFile) Build a new SAM bridge. NOT recommended for external use.Opens the listener socket but does NOT start the thread, and there's no way to do that externally. Use
main(String[]), or use the other constructor and call startup().Deprecated for external use, to be made private.
- Parameters:
listenHost- hostname to listen for SAM connections on ("0.0.0.0" for all)listenPort- port number to listen for SAM connections onisSSL- true to serve SAM connections over TLSi2cpProps- set of I2CP properties for finding and communicating with the routerpersistFile- location to store/load named keys to/fromconfigFile- location of the config file to load settings from- Throws:
RuntimeException- if a server socket can't be opened
SAMBridge
public SAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps, String persistFile, File configFile, SAMSecureSessionInterface secureSession) Build a new SAM bridge. NOT recommended for external use.Opens the listener socket but does NOT start the thread, and there's no way to do that externally. Use main(), or use the other constructor and call startup().
Deprecated for external use, to be made private.
- Parameters:
listenHost- hostname to listen for SAM connections on ("0.0.0.0" for all)listenPort- port number to listen for SAM connections onisSSL- true to serve SAM connections over TLSi2cpProps- set of I2CP properties for finding and communicating with the routerpersistFile- location to store/load named keys to/fromconfigFile- location of the config file to load settings fromsecureSession- an instance of a Secure Session to use- Throws:
RuntimeException- if a server socket can't be opened
Method Details
openSocket
Open and bind the server socket (TCP or SSL).- Throws:
IOException- if the socket cannot be bound to the host and port
getKeystream
addKeystream
loadKeys
private void loadKeys()Load up the keys from the persistFilename.storeKeys
private void storeKeys()Store the current keys to disk in the location specified on creation.register
Handlers must call on startup.- Parameters:
handler- the connection handler to add to the set stopped and started with this bridge
unregister
Handlers must call on stop.- Parameters:
handler- the connection handler to drop from the set of handlers started and stopped with this bridge
getHandlerPool
SAMHandlerPool getHandlerPool()Access the shared handler pool for v3 connections.- Returns:
- the handler pool, or null if not started
getSessionCount
public int getSessionCount()Count the named v3 sessions held in the SessionsDB, for the console status page.- Returns:
- number of registered streams from
SessionsDB
getHandlerCount
public int getHandlerCount()Count the handlers currently serving a SAM connection, for the console status page.- Returns:
- number of connected handlers
getPoolActiveCount
public int getPoolActiveCount()Count the handler-pool threads running a command, for the console status page. Zero until the pool has been started.- Returns:
- active pool worker threads, or 0 if pool not started
getPoolSize
public int getPoolSize()Count every thread in the handler pool, busy or not, for the console status page. Zero until the pool has been started.- Returns:
- total pool worker threads, or 0 if pool not started
getQueueSize
public int getQueueSize()Count the commands waiting for a free pool thread, for the console status page. Zero until the pool has been started.- Returns:
- commands queued in the pool, or 0 if pool not started
getPoolRegisteredCount
public int getPoolRegisteredCount()Count the handlers registered with the pool, whether or not they are currently running. Zero until the pool has been started.- Returns:
- handlers registered in the pool, or 0 if pool not started
getStolenSocketCount
public int getStolenSocketCount()Count handlers whose socket has been stolen for data streaming.- Returns:
- the stolen socket count
unregisterHandlerFromPool
Remove a v3 handler from the shared handler pool. Called bySAMv3Handler.stopHandling().- Parameters:
handler- non-null
stopHandlers
private void stopHandlers()Stop all the handlers.getV3DatagramServer
Was a static singleton, now a singleton for this bridge. Instantiate and start server if it doesn't exist. We only listen on one host and port, as specified in thesam.udp.hostandsam.udp.portproperties.- Parameters:
props- non-null instantiate and start server if it doesn't exist- Returns:
- non-null
- Throws:
IOException- if can't bind to host/port, or if different than existing
getUptime
public long getUptime()Milliseconds since this bridge was instantiated, minimum 1000 while racing on startup, mirroring Router.getUptime(). The bridge is started by the router app manager during router startup, so this is a close proxy for router uptime.- Returns:
- the uptime in ms, minimum 1000
startup
Start the bridge.- Specified by:
startupin interfaceClientApp- Throws:
IOException
shutdown
getState
Report the bridge's position in the ClientApp lifecycle.getName
getDisplayName
Return the display name.- Specified by:
getDisplayNamein interfaceClientApp- Returns:
- the display name
changeState
Record a state change with no associated error.- Parameters:
state- the new state of this client app
changeState
Record the new state and tell the ClientAppManager about it, if there is one.- Parameters:
state- the new state of this client appe- the error associated with the change, or null if none
main
Usage:SAMBridge [ keyfile [listenHost ] listenPort [ name=val ]* ]
or:
SAMBridge [ name=val ]*
name=val options are passed to the I2CP code to build a session, allowing the bridge to specify an alternate I2CP host and port, tunnel depth, etc.
- Parameters:
args- [ keyfile [ listenHost ] listenPort [ name=val ]* ]
startThread
private void startThread()Start the listener thread and schedule periodic stale-session sweeps.getOptions
Usage:SAMBridge [ keyfile [listenHost ] listenPort [ name=val ]* ]
or:
SAMBridge [ name=val ]*
name=val options are passed to the I2CP code to build a session, allowing the bridge to specify an alternate I2CP host and port, tunnel depth, etc.
- Parameters:
args- [ keyfile [ listenHost ] listenPort [ name=val ]* ]- Returns:
- non-null Options or throws Exception
- Throws:
SAMBridge.HelpRequestedException- on command line problemsIllegalArgumentException- if specified config file does not existIOException- if specified config file cannot be read, or on SSL keystore problemsException
parseOptions
private static void parseOptions(String[] args, int startArgs, Properties props) throws SAMBridge.HelpRequestedException Parse key=value options starting at startArgs.- Parameters:
args- the command line arguments to parsestartArgs- index of the first option to parseprops- out parameter, any options found are added- Throws:
SAMBridge.HelpRequestedException- on any item not of the form key=value.
usage
private static void usage()Prints the command line usage text.run
saveConfig
Save the current configuration to disk.- Throws:
IOException- if the config file cannot be written
renderSessionTableHTML
Render the session table and handler summary as HTML. Called by the router console debug page.- Parameters:
out- non-null- Throws:
IOException- if the writer fails
buildSessionTable
Build the session table from rows of {nickname, style, destination, handler IP, state, last accessed}. The state cell carries a colored dot so the table reads at a glance. Package-visible for testing.- Parameters:
rows- one entry per session- Returns:
- the table html, never null
stateDotClass
Dot color for a session state: control is a live session, forwarding and stolen are data paths, idle has no session yet, orphan lost its handler.- Parameters:
state- one of control, forwarding, stolen, idle, orphan- Returns:
- the css modifier class, empty for the grey default
secureSession
Returns the interactive Secure Session manager which requires SAM applications to seek "approval" for their initial connections from the user before they can start the session.- Returns:
- the secure session interface, or null if not configured