java.lang.Object
net.i2p.sam.SAMHandler
net.i2p.sam.SAMv1Handler
net.i2p.sam.SAMv3Handler
- All Implemented Interfaces:
Runnable, Handler, SAMDatagramReceiver, SAMRawReceiver, SAMStreamReceiver
Class able to handle a SAM version 3 client connection.
Field Summary
Modifier and TypeFieldDescriptionprivate static final StringAuthentication error message.(package private) final booleanPackage-visible soSAMHandlerPoolcan read it.private SessionI2P session.private booleanTrue once the SESSION CREATE has fully initialized; guards against race in execStreamMessage.static final SessionsDBGlobal session-id to handler map shared by every SAMv3 bridge.(package private) booleanStolen socket.(package private) booleanStream forwarding socket.Fields inherited from class SAMv1Handler
_id, datagramSession, rawSession, SESSION_ERROR, streamSessionModifier and TypeFieldDescriptionprotected final longIdentifier of this connection, unique among a router's SAM handlers.protected SAMMessageSessThe session used for datagram style messages.protected SAMMessageSessThe SAM raw and datagram session, held after a successful HELLO.protected static final StringReply sent to a SESSION CREATE whose stream could not be established.protected SAMStreamSessionThe session used for STREAM CONNECT connections.Fields inherited from class SAMHandler
_log, bridge, i2cpProps, socket, stopHandler, stopLock, thread, verMajor, verMinorModifier and TypeFieldDescriptionprotected final LogLog scoped to this handler's class.protected final SAMBridgeRouter bridge this handler routes sessions over.protected final PropertiesI2CP options configuring the I2CP connection (port, host, numHops, etc).protected final SocketChannelClient channel this handler reads commands from.protected booleanWhether shutdown has been requested for this handler.protected final ObjectMonitor guarding the stop flag.protected I2PAppThreadThread running the SAM protocol loop for this connection.final intMajor version this handler was negotiated at.final intMinor version this handler was negotiated at.Constructor Summary
ConstructorsConstructorDescriptionSAMv3Handler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps, SAMBridge parent) Create a new SAM version 3 handler.SAMv3Handler(SocketChannel s, int verMajor, int verMinor, SAMBridge parent) Create a new SAM version 3 handler.Method Summary
Modifier and TypeMethodDescriptionprivate voiddie()Terminate the handler.private booleanexecAuthMessage(String opcode, Properties props) Handle the AUTH message.private booleanexecSessionAddRemove(String opcode, String nick, Properties props) Execute SESSION ADD or REMOVE for MASTER sessions.private booleanexecSessionCreate(String nick, Properties props) Execute SESSION CREATE — generates or validates a destination, registers the nick, builds tunnels, and creates the session object.protected booleanexecSessionMessage(String opcode, Properties props) Parse and execute a SESSION message.private booleanexecStreamAccept(Properties props) Execute STREAM ACCEPT.protected booleanexecStreamConnect(Properties props) Parse and execute a STREAM CONNECT message.private booleanExec stream forward incoming.protected booleanexecStreamMessage(String opcode, Properties props) Parse and execute a STREAM message.(package private) SAMBridgeFor SAMv3StreamSession.Get the IP address of the connected SAM client.(package private) SessionFor SAMv3DatagramServer.voidhandle()Legacy handle() method.(package private) booleanWhether a client data stream has been taken over by this handler.private static StringinitDestination(String dest, Properties props) Resolve TRANSIENT or validate a user-supplied private key.private voidinstantiateSession(String style, String nick, Properties allProps, Properties props) Create and start the session object for the given style.(package private) booleanDetermine whether this connection may change the bridge's authentication configuration.(package private) static booleanmayManageAuth(boolean fromLoopback, String authUser, boolean authEnabled) Decide whether an AUTH command may be issued from a connection.(package private) booleanDetermine whether this connection may operate on a session created by another connection.private static SAMv3StreamSessionnewSAMStreamSession(String login) Create a stream session for a login.static voidNotify the SAM client of an incoming stream connection on a static channel.static voidnotifyStreamIncomingConnection(SocketChannel client, Destination d, int fromPort, int toPort) Notify the SAM client of an incoming stream connection with port information.voidnotifyStreamIncomingConnection(Destination d, int fromPort, int toPort) Tells the SAM client a new stream connection arrived, naming the ports when requested.voidnotifyStreamResult(boolean verbose, String result, String message) Send a STREAM STATUS RESULT line to the SAM client, unless verbose is false.(package private) booleanprocessLine(String line) Process a single complete command line dispatched by the pool or the legacyhandle()loop.(package private) voidFor subsessions created by MasterSession.(package private) voidsetSession(SAMv3RawSession sess) For subsessions created byMasterSession.(package private) voidsetSession(SAMv3StreamSession sess) For subsessions created by MasterSession.voidFor SAMv3StreamSession connect and accept.voidStop the SAM handler, close the socket (unless stolen), unregister from the bridge and the handler pool.booleanVerify the SAM protocol version is supported by this handler.Methods inherited from class SAMv1Handler
createMessageString, execDatagramMessage, execDestMessage, execNamingMessage, execRawMessage, execStreamClose, execStreamSend, getDatagramSession, getRawSession, getStreamSession, notifyStreamDisconnection, notifyStreamIncomingConnection, notifyStreamOutgoingConnection, notifyStreamSendBufferFree, receiveDatagramBytes, receiveRawBytes, receiveStreamBytes, stopDatagramReceiving, stopRawReceiving, stopStreamReceiving, streamSendAnswer, writeStringModifier and TypeMethodDescriptionprotected static StringCreate a string to be appended to a status.protected booleanexecDatagramMessage(String opcode, Properties props) Parse and execute a DATAGRAM message.protected booleanexecDestMessage(String opcode, Properties props) Parse and execute a DEST message.protected booleanexecNamingMessage(String opcode, Properties props) Parse and execute a NAMING message.protected booleanexecRawMessage(String opcode, Properties props) Parse and execute a RAW message.protected booleanexecStreamClose(Properties props) Parse and execute a STREAM CLOSE message.protected booleanexecStreamSend(Properties props) Parse and execute a STREAM SEND message.protected final SAMMessageSessReturn the datagram session.protected final SAMMessageSessReturn the raw session.protected final SAMStreamSessionReturn the stream session.voidnotifyStreamDisconnection(int id, String result, String msg) Notify the SAM client that a stream connection has been disconnected.voidnotifyStreamIncomingConnection(int id, Destination d) Notify the SAM client of an incoming stream connection.voidnotifyStreamOutgoingConnection(int id, String result, String msg) Report the result of an outgoing stream connection.voidnotifyStreamSendBufferFree(int id) Notify the SAM client that the stream send buffer is free for more data.voidreceiveDatagramBytes(Destination sender, byte[] data, int proto, int fromPort, int toPort) Receive datagram bytes from the network and forward them to the SAM client.voidreceiveRawBytes(byte[] data, int proto, int fromPort, int toPort) Receive raw bytes from the network and forward them to the SAM client.voidreceiveStreamBytes(int id, ByteBuffer data) Receive stream bytes from the network and forward them to the SAM client.voidStop receiving datagram bytes and close the client socket.voidStop receiving raw bytes and close the client socket.voidStop receiving stream bytes and close the client socket.voidstreamSendAnswer(int id, String result, String bufferState) Notify the SAM client of the result of a stream SEND operation.protected booleanwriteString(String s, String msg) Write a string and message, escaping the message.Methods inherited from class SAMHandler
closeClientSocket, getAuthUser, getClientSocket, getRemoteAddrPort, getWriteLock, isLoopbackAddress, logSessionError, run, sameClient, sameClient, setAuthUser, shouldStop, startHandling, toString, writeBytes, writeString, writeStringModifier and TypeMethodDescriptionprotected final voidClose the socket connected to the SAM client.(package private) final StringGet the username this connection authenticated with, if any.protected final SocketChannelGet the channel of the socket connected to the SAM client.(package private) final StringGet the remote address and port of this connection, bracketing IPv6, for rejection and ban logging.protected ObjectIf you're crazy enough to write to the raw socket, grab the write lock withSAMHandler.getWriteLock(), synchronize against it, and write to the getOut().(package private) static booleanisLoopbackAddress(String host) Determine whether an address is a loopback address, in any of the forms the platform may report it.protected voidlogSessionError(String msg, Exception e) Log a session startup failure.final voidrun()Register with the bridge, callSAMHandler.handle(), unregister with the bridge.(package private) static booleansameClient(String myAuthUser, String otherAuthUser, String myHost, String otherHost) Decide whether two SAM connections belong to the same client.(package private) final booleansameClient(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.(package private) final voidsetAuthUser(String user) Record the username this connection authenticated with.protected final booleanShould the handler be stopped?voidStart handling the SAM connection, detaching a handling thread.final StringtoString()Get a string describing the handler.protected final voidwriteBytes(ByteBuffer data) Write a byte array on the handler's socket.protected final booleanwriteString(String str) Write a string to the handler's socket.static booleanwriteString(String str, SocketChannel out) Unsynchronized, use with caution.
Field Details
session
I2P session.sSessionsHash
Global session-id to handler map shared by every SAMv3 bridge.stolenSocket
volatile boolean stolenSocketStolen socket.streamForwardingSocket
volatile boolean streamForwardingSocketStream forwarding socket.sessionReady
private volatile boolean sessionReadyTrue once the SESSION CREATE has fully initialized; guards against race in execStreamMessage.sendPorts
final boolean sendPortsPackage-visible soSAMHandlerPoolcan read it.AUTH_ERROR
Constructor Details
SAMv3Handler
public SAMv3Handler(SocketChannel s, int verMajor, int verMinor, SAMBridge parent) throws SAMException, IOException Create a new SAM version 3 handler. This constructor expects that the SAM HELLO message has been still answered (and stripped) from the socket input stream.- Parameters:
s- Socket attached to a SAM clientverMajor- SAM major version to manage (should be 3)verMinor- SAM minor version to manageparent- the bridge owning this handler and the handler pool it came from- Throws:
SAMException- if the version is not supportedIOException- if an I/O error occurs
SAMv3Handler
public SAMv3Handler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps, SAMBridge parent) throws SAMException, IOException Create a new SAM version 3 handler. This constructor expects that the SAM HELLO message has been still answered (and stripped) from the socket input stream.- Parameters:
s- Socket attached to a SAM clientverMajor- SAM major version to manage (should be 3)verMinor- SAM minor version to managei2cpProps- properties to configure the I2CP connection (host, port, etc)parent- the bridge owning this handler and the handler pool it came from- Throws:
SAMException- if the version is not supportedIOException- if an I/O error occurs
Method Details
verifVersion
public boolean verifVersion()Verify the SAM protocol version is supported by this handler.- Overrides:
verifVersionin classSAMv1Handler- Returns:
- true if the major version matches this handler's version
getClientIP
Get the IP address of the connected SAM client.- Returns:
- the client's IP address as a string
hasActiveStream
boolean hasActiveStream()Whether a client data stream has been taken over by this handler.- Returns:
- true if the handler has an active data stream (stolen or forwarding)
stealSocket
public void stealSocket()For SAMv3StreamSession connect and accept.getBridge
getSession
setSession
For subsessions created byMasterSession.- Parameters:
sess- the raw session to route reply traffic to
setSession
For subsessions created by MasterSession.- Parameters:
sess- the datagram session to route reply traffic to
setSession
For subsessions created by MasterSession.- Parameters:
sess- the stream session to route reply traffic to; setting it also marks the session ready
processLine
Process a single complete command line dispatched by the pool or the legacyhandle()loop. Returns false to signal the caller that the handler should stop.- Parameters:
line- the complete command line (without trailing newline)- Returns:
- true if the handler should continue processing commands
handle
public void handle()Legacy handle() method. Not used when the handler is managed bySAMHandlerPool, which dispatches via processLine(). Retained to fulfill the abstract contract inSAMHandler.- Overrides:
handlein classSAMv1Handler
stopHandling
public void stopHandling()Stop the SAM handler, close the socket (unless stolen), unregister from the bridge and the handler pool.- Specified by:
stopHandlingin interfaceHandler- Overrides:
stopHandlingin classSAMHandler
die
private void die()Terminate the handler.execSessionMessage
Parse and execute a SESSION message.- Overrides:
execSessionMessagein classSAMv1Handler- Parameters:
opcode- the SESSION sub-command (e.g. CREATE, ADD, REMOVE)props- the parsed message properties- Returns:
- true if the handler should continue processing commands
execSessionCreate
Execute SESSION CREATE — generates or validates a destination, registers the nick, builds tunnels, and creates the session object.- Parameters:
nick- validated session IDprops- parsed message properties- Returns:
- true if the handler should continue processing
initDestination
Resolve TRANSIENT or validate a user-supplied private key.- Parameters:
dest- DESTINATION value, may be "TRANSIENT"props- properties (SIGNATURE_TYPE consumed if TRANSIENT)- Returns:
- Base64-encoded private key
- Throws:
DataFormatException- if SIGNATURE_TYPE names an unsupported type, or the supplied DESTINATION is not a valid private destination
instantiateSession
private void instantiateSession(String style, String nick, Properties allProps, Properties props) throws DataFormatException, I2PSessionException, IOException, SAMException Create and start the session object for the given style. Blocks in the session constructors while tunnels are built.- Parameters:
style- session style: RAW, DATAGRAM, STREAM, MASTER or PRIMARYnick- session nickname, used as the session IDallProps- all message properties, handed to a MASTER sessionprops- message properties, used to build the datagram server- Throws:
DataFormatException- if stored destination or key data is malformedI2PSessionException- if the underlying I2P session cannot be createdIOException- if the datagram server cannot bind its host and port, or the session constructors hit an I/O errorSAMException- if the style is not one of the recognized values, or the I2P session cannot be created
execSessionAddRemove
Execute SESSION ADD or REMOVE for MASTER sessions.- Parameters:
opcode- the sub-command, ADD or REMOVEnick- session ID of the sub-session to add or removeprops- message properties, STYLE consumed when adding- Returns:
- true if the handler should continue processing commands
newSAMStreamSession
private static SAMv3StreamSession newSAMStreamSession(String login) throws IOException, DataFormatException, SAMException Create a stream session for a login.- Parameters:
login- nickname of the registered session to reuse- Returns:
- the new, not yet started, stream session
- Throws:
NullPointerException- if login nickname is not registeredIOException- if the stored key stream cannot be read or the I2CP connection failsDataFormatException- if the stored destination or key data is malformedSAMException- if the I2CP port property is not a number, or the I2P session cannot be created
execStreamMessage
Parse and execute a STREAM message.- Overrides:
execStreamMessagein classSAMv1Handler- Parameters:
opcode- the STREAM sub-command (e.g. CONNECT, ACCEPT, FORWARD)props- the parsed message properties- Returns:
- true if the handler should continue processing commands
execStreamConnect
Parse and execute a STREAM CONNECT message. Dispatches the blocking I2P socket connect to a shared connector pool so the caller's worker thread is never blocked. Error responses (CONNECTION_REFUSED, CANT_REACH_PEER, TIMEOUT, etc.) are sent asynchronously by the ConnectTask.Supports SILENT mode to suppress status messages.
- Overrides:
execStreamConnectin classSAMv1Handler- Parameters:
props- the parsed message properties- Returns:
- true if the handler should continue processing commands
execStreamForwardIncoming
Exec stream forward incoming.- Parameters:
props- the parsed message properties, including the receiver PORT and SILENT flag- Returns:
- true if forwarding was started, false when it failed
execStreamAccept
Execute STREAM ACCEPT. Sends "OK" synchronously and starts the blocking accept in a background thread. Result (TIMEOUT, I2P_ERROR, or the actual streaming data) arrives asynchronously.- Parameters:
props- the parsed message properties, SILENT flag read- Returns:
- true if accept was launched, false on immediate error
notifyStreamResult
Send a STREAM STATUS RESULT line to the SAM client, unless verbose is false.- Parameters:
verbose- if false, does nothingresult- non-nullmessage- may be null- Throws:
IOException- if writing the status line to the SAM client socket fails
notifyStreamIncomingConnection
public void notifyStreamIncomingConnection(Destination d, int fromPort, int toPort) throws IOException Tells the SAM client a new stream connection arrived, naming the ports when requested.- Parameters:
d- the destination of the incoming connectionfromPort- the remote port the connection arrived ontoPort- the local port the connection was accepted on- Throws:
IOException- if writing to the SAM client socket fails
notifyStreamIncomingConnection
public static void notifyStreamIncomingConnection(SocketChannel client, Destination d) throws IOException Notify the SAM client of an incoming stream connection on a static channel.- Parameters:
client- the channel to the SAM client the notification is written tod- the destination of the remote peer- Throws:
IOException- if writing to the client socket fails
notifyStreamIncomingConnection
public static void notifyStreamIncomingConnection(SocketChannel client, Destination d, int fromPort, int toPort) throws IOException Notify the SAM client of an incoming stream connection with port information.- Parameters:
client- the channel to the SAM client the notification is written tod- the destination of the remote peerfromPort- the source porttoPort- the destination port- Throws:
IOException- if writing to the client socket fails
mayManageAuth
boolean mayManageAuth()Determine whether this connection may change the bridge's authentication configuration. AUTH commands rewrite the credentials every future connection must present and are persisted to disk, so they are accepted only from the local host, or from a connection that authenticated when it connected.- Returns:
- true if AUTH commands from this connection are accepted
mayManageAuth
Decide whether an AUTH command may be issued from a connection.- Parameters:
fromLoopback- whether the connection is from the local hostauthUser- the user the connection authenticated as, may be nullauthEnabled- whether bridge authentication is currently enabled- Returns:
- true if AUTH commands from such a connection are accepted
mayUseSession
Determine whether this connection may operate on a session created by another connection. STREAM commands are issued from a connection other than the one that created the session, and nicknames are shared by the whole bridge, so access is allowed to the owning connection itself and to connections belonging to the same client: the same authenticated user, or the same address when authentication is disabled.- Parameters:
rec- the looked-up session record, may be null- Returns:
- true if this connection may use that session
execAuthMessage
Handle the AUTH message.- Parameters:
opcode- the AUTH sub-command: ENABLE, DISABLE, ADD or REMOVEprops- the parsed message properties, USER and PASSWORD read for ADD and REMOVE- Returns:
- true if the handler should continue processing commands