Specified below is a simple client protocol for interacting with I2P.
SAM V2 was introduced in I2P release 0.6.1.31. Significant differences from SAM V1 are marked with "***". Alternatives: SAM V1, SAM V3, BOB.
Version 2 Changes
SAM V2 was introduced in I2P release 0.6.1.31. Compared to version 1, SAM v2 provides a way to manage several sockets on the same I2P destination in parallel, i.e. the client does not have to wait for data being successfully sent on one socket before sending data on another socket. All data transits through the same client<-->SAM socket. For multiple sockets, see SAM V3.
I2P 0.9.14 Changes
The reported version remains "2.0".
- DEST GENERATE now supports a SIGNATURE_TYPE parameter.
- The MIN parameter in HELLO VERSION is now optional.
- The MIN and MAX parameters in HELLO VERSION now support single-digit versions such as "3".
Version 2 Protocol
---------------------------------------------------------------------- Simple Anonymous Messaging (SAM version 2.0) Specification ---------------------------------------------------------------------- Client application talks to SAM bridge, which deals with all of the I2P functionality (using the streaming lib for virtual streams, or I2CP directly for async messages). All client<-->SAM bridge communication is unencrypted and unauthenticated over a single TCP socket. Access to the SAM bridge should be protected through firewalls or other means (perhaps the bridge may have ACLs on what IPs it accepts connections from). All of these SAM messages are sent on a single line in plain ASCII, terminated by the newline character (\n). The formatting shown below is merely for readability, and while the first two words in each message must stay in their specific order, the ordering of the key=value pairs can change (e.g. "ONE TWO A=B C=D" or "ONE TWO C=D A=B" are both perfectly valid constructions). In addition, the protocol is case-sensitive. SAM messages are interpreted in UTF-8. Key=value pairs must be separated by a single space. Values may be enclosed in double quotes if they contain spaces, e.g. key="long value text". There is no escaping mechanism. Communication can take three distinct forms: * Virtual streams * Repliable datagrams (messages with a FROM field) * Anonymous datagrams (raw anonymous messages) ---------------------------------------------------------------------- SAM connection handshake ---------------------------------------------------------------------- No SAM communication can occur until after the client and bridge have agreed on a protocol version, which is done by the client sending a HELLO and the bridge sending a HELLO REPLY: HELLO VERSION MIN=$min MAX=$max and *** HELLO REPLY RESULT=$result VERSION=2.0 As of I2P 0.9.14, the MIN parameter is optional. The MAX parameter must be provided and be greater than or equal to "2" and less than "3" to use version 2. The RESULT value may be one of: OK NOVERSION ---------------------------------------------------------------------- SAM sessions ---------------------------------------------------------------------- A SAM session is created by a client opening a socket to the SAM bridge, operating a handshake, and sending a SESSION CREATE message, and the session terminates when the socket is disconnected. Each I2P Destination can only be used for one SAM session at a time, and can only use one of those forms (messages received through other forms are dropped). The SESSION CREATE message sent by the client to the bridge is as follows: SESSION CREATE STYLE={STREAM,DATAGRAM,RAW} DESTINATION={$name,TRANSIENT} [DIRECTION={BOTH,RECEIVE,CREATE}] [option=value]* DESTINATION specifies what destination should be used for sending and receiving messages/streams. If a $name is given, the SAM bridge looks through its own local storage (the sam.keys file) for an associated destination (and private key). If no association exists matching that name, it creates a new one. If the destination is specified as TRANSIENT, it always creates a new one. Note that DESTINATION is an identifier, not Base 64 encoded data. To specify the Destination, you must use SAM V3. The DIRECTION can be specified for STREAM sessions only, instructing the bridge that the client will either be creating or receiving streams, or both. If this is not specified, BOTH will be assumed. Attempting to create an outbound stream when DIRECTION=RECEIVE should result in an error, and incoming streams when DIRECTION=CREATE will be ignored. Additional options given should be fed into the I2P session configuration if not interpreted by the SAM bridge (e.g. "tunnels.depthInbound=0"). These options are documented below. The SAM bridge itself should already be configured with what router it should communicate over I2P through (though if need be there may be a way to provide an override, e.g. i2cp.tcp.host=localhost and i2cp.tcp.port=7654). After receiving the session create message, the SAM bridge will reply with a session status message, as follows: SESSION STATUS RESULT=$result DESTINATION={$name,TRANSIENT} [MESSAGE=...] The RESULT value may be one of: OK DUPLICATED_DEST I2P_ERROR INVALID_KEY If it's not OK, the MESSAGE should contain human-readable information as to why the session could not be created. Note that there is no warning given if the $name is not found and a transient destination is created instead. Note that the actual transient base 64 destination is not output in the reply; it is the $name or TRANSIENT as supplied in SESSION CREATE. If you need these features, you must use SAM V3. ---------------------------------------------------------------------- SAM virtual streams ---------------------------------------------------------------------- Virtual streams are guaranteed to be sent reliably and in order, with failure and success notification as soon as it is available. After establishing the session with STYLE=STREAM, both the client and the SAM bridge may asynchronously send various messages back and forth to manage the streams, as listed below: STREAM CONNECT ID=$id DESTINATION=$destination This establishes a new virtual connection from the local destination to the specified peer, marking it with the session-scoped unique ID. The unique ID is an ASCII base 10 integer from 1 through (2^31-1). The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. The SAM bridge replies to this with a stream status message: STREAM STATUS RESULT=$result ID=$id [MESSAGE=...] The RESULT value may be one of: OK CANT_REACH_PEER I2P_ERROR INVALID_KEY TIMEOUT If the RESULT is OK, the destination specified is up and authorized the connection; if the connection was not possible (timeout, etc), RESULT will contain the appropriate error value (accompanied by an optional human-readable MESSAGE). On the receiving end, the SAM bridge simply notifies the client as follows: STREAM CONNECTED DESTINATION=$destination ID=$id This tells the client that the given destination has created a virtual connection with them. The following data stream will be marked with the given unique ID, that is an ASCII base 10 integer from -1 through -(2^31-1). The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. When the client wants to send data on the virtual connection, they do so as follows: STREAM SEND ID=$id SIZE=$numBytes\n[$numBytes of data] This asks the SAM bridge to add the specified data to the buffer being sent to the peer over the virtual connection. The send size $numBytes is how many 8bit bytes are included after the newline, which may be 1 through 32768 (32KB). *** The SAM bridge immediately replies with: *** *** STREAM SEND *** ID=$id *** RESULT=$result *** STATE=$bufferState *** *** where $bufferState can be : *** - BUFFER_FULL : SAM's buffer has 32 or more KB of data *** to send, and subsequent SEND requests *** will fail ; *** - READY : SAM's buffer is not full, and the next SEND *** request is granted to be successful. *** *** and $result is one of : *** - OK : the data has been buffered successfully *** - FAILED : the buffer was full, no data has been buffered *** *** If the SAM bridge replied with BUFFER_FULL, it will send another *** message as soon as its buffer is available again : *** *** STREAM READY_TO_SEND ID=$id *** *** *** *** When the result is OK, the SAM bridge will then do its best to deliver *** the message as quickly and efficiently as possible, perhaps buffering *** multiple SEND messages together. If there is an error delivering the *** data, or if the remote side closes the connection, the SAM bridge will *** tell the client: STREAM CLOSED RESULT=$result ID=$id [MESSAGE=...] The RESULT value may be one of: OK CANT_REACH_PEER I2P_ERROR PEER_NOT_FOUND TIMEOUT If the connection has been cleanly closed by the other peer, $result is set to OK. If $result is not OK, MESSAGE may convey a descriptive message, such as "peer unreachable", etc. Whenever a client would like to close the connection, they send the SAM bridge the close message: STREAM CLOSE ID=$id The bridge then cleans up what it needs to and discards that ID - no further messages can be sent or received on it. For the other side of the communication, whenever the peer has sent some data and it is available for the client, the SAM bridge will promptly deliver it: STREAM RECEIVED ID=$id SIZE=$numBytes\n[$numBytes of data] *** With SAM version 2.0, though, the client has first to tell the SAM *** bridge how much incoming data is allowed for the whole session, by *** sending a message : *** *** STREAM RECEIVE *** ID=$id *** LIMIT=$limit\n *** *** where $limit can be : *** *** - NONE : the SAM bridge will keep on listening and deliver *** incoming data (same behavior as in version 1.0) *** *** - an integer (less than 2^64) : the number of received bytes *** after which the SAM bridge will stop listening on *** the incoming stream. *** *** Whenever the client is ready to accept more bytes *** from the stream, it has to send such a message again, *** with a greater $limit. *** *** The client has to send such STREAM RECEIVE messages after the *** connection to the peer has been established, i.e. after the client *** has received a "STREAM CONNECTED" or a "STREAM STATUS RESULT=OK" *** from the SAM bridge. All streams are implicitly closed by the connection between the SAM bridge and the client being dropped. ---------------------------------------------------------------------- SAM repliable datagrams ---------------------------------------------------------------------- While I2P doesn't inherently contain a FROM address, for ease of use an additional layer is provided as repliable datagrams - unordered and unreliable messages of up to 31744 bytes that include a FROM address (leaving up to 1KB for header material). This FROM address is authenticated internally by SAM (making use of the destination's signing key to verify the source) and includes replay prevention. Minimum size is 1. For best delivery reliability, recommended maximum size is approximately 11 KB. After establishing a SAM session with STYLE=DATAGRAM, the client can send the SAM bridge: DATAGRAM SEND DESTINATION=$destination SIZE=$numBytes\n[$numBytes of data] When a datagram arrives, the bridge delivers it to the client via: DATAGRAM RECEIVED DESTINATION=$destination SIZE=$numBytes\n[$numBytes of data] The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. The SAM bridge never exposes to the client the authentication headers or other fields, merely the data that the sender provided. This continues until the session is closed (by the client dropping the connection). ---------------------------------------------------------------------- SAM anonymous datagrams ---------------------------------------------------------------------- Squeezing the most out of I2P's bandwidth, SAM allows clients to send and receive anonymous datagrams, leaving authentication and reply information up to the client themselves. These datagrams are unreliable and unordered, and may be up to 32768 bytes. Minimum size is 1. For best delivery reliability, recommended maximum size is approximately 11 KB. After establishing a SAM session with STYLE=RAW, the client can send the SAM bridge: RAW SEND DESTINATION=$destination SIZE=$numBytes\n[$numBytes of data] The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. When a raw datagram arrives, the bridge delivers it to the client via: RAW RECEIVED SIZE=$numBytes\n[$numBytes of data] ---------------------------------------------------------------------- SAM utility functionality ---------------------------------------------------------------------- The following message can be used by the client to query the SAM bridge for name resolution: NAMING LOOKUP NAME=$name which is answered by NAMING REPLY RESULT=$result NAME=$name [VALUE=$destination] [MESSAGE=$message] The RESULT value may be one of: OK INVALID_KEY KEY_NOT_FOUND If NAME=ME, then the reply will contain the destnation used by the current session (useful if you're using a TRANSIENT one). If $result is not OK, MESSAGE may convey a descriptive message, such as "bad format", etc. The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. Public and private base64 keys can be generated using the following message: DEST GENERATE which is answered by DEST REPLY PUB=$destination PRIV=$privkey As of I2P 0.9.14, an optional parameter SIGNATURE_TYPE is supported. The SIGNATURE_TYPE value may be any name (e.g. ECDSA_SHA256_P256, case insensitive) or number (e.g. 1) that is supported by Key Certificates. The default is DSA_SHA1. The $destination is the base 64 of the Destination, which is 516 or more base 64 characters (387 or more bytes in binary), depending on signature type. The $privkey is the base 64 of the concatenation of the Destination followed by the Private Key followed by the Signing Private Key, which is 884 or more base 64 characters (663 or more bytes in binary), depending on signature type. The binary format is specified in Private Key File. ---------------------------------------------------------------------- RESULT values ---------------------------------------------------------------------- These are the values that can be carried by the RESULT field, with their meaning: OK Operation completed successfully CANT_REACH_PEER The peer exists, but cannot be reached DUPLICATED_DEST The specified Destination is already in use I2P_ERROR A generic I2P error (e.g. I2CP disconnection, etc.) INVALID_KEY The specified key is not valid (bad format, etc.) KEY_NOT_FOUND The naming system can't resolve the given name PEER_NOT_FOUND The peer cannot be found on the network TIMEOUT Timeout while waiting for an event (e.g. peer answer) ---------------------------------------------------------------------- Tunnel, I2CP, and Streaming Options ---------------------------------------------------------------------- These options may be passed in as name=value pairs at the end of a SAM SESSION CREATE line. All sessions may include I2CP options such as tunnel lengths. STREAM sessions may include Streaming lib options. See those references for option names and defaults. ---------------------------------------------------------------------- BASE 64 Notes ---------------------------------------------------------------------- Base 64 encoding must use the I2P standard Base 64 alphabet "A-Z, a-z, 0-9, -, ~". ---------------------------------------------------------------------- Client library implementations: ---------------------------------------------------------------------- Client libraries are available for C, C++, C#, Perl, and Python. These are in the apps/sam/ directory in the I2P Source Package. Some may be older and have not been updated for SAMv2 support. ---------------------------------------------------------------------- Default SAM Setup ---------------------------------------------------------------------- The default SAM port is 7656. SAM is not enabled by default in the I2P Router; it must be started manually, or configured to start automatically, on the configure clients page in the router console, or in the clients.config file.