Skip navigation

SAM V1 Specification

This page was last updated in June 2014 and is accurate for router version 0.9.14.

SAM V1 Specification

Specified below is version 1 of a simple client protocol for interacting with I2P. Newer alternatives: SAM V2, SAM V3, BOB.

I2P 0.9.14 Changes

The reported version remains "1.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 1 Protocol

----------------------------------------------------------------------
Simple Anonymous Messaging (SAM version 1.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.

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=1.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 "1" and
less than "2" to use version 1.

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 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.

The DIRECTION can be specified for STREAM sessions, 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 should 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.

----------------------------------------------------------------------
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=$base64key

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 SAM bridge must reply 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=$base64key
         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).

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 adds 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 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]

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 31KB in size 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.

After establishing a SAM session with STYLE=DATAGRAM, the client can
send the SAM bridge:

  DATAGRAM SEND
           DESTINATION=$base64key
           SIZE=$numBytes\n[$numBytes of data]

When a datagram arrives, the bridge delivers it to the client via:

  DATAGRAM RECEIVED
           DESTINATION=$base64key
           SIZE=$numBytes\n[$numBytes of data]

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 32KB in size.

After establishing a SAM session with STYLE=RAW, the client can
send the SAM bridge:

  RAW SEND
      DESTINATION=$base64key
      SIZE=$numBytes\n[$numBytes of data]

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=$base64key]
        [MESSAGE=$message]


The RESULT value may be one of:

    OK
    INVALID_KEY
    KEY_NOT_FOUND

If NAME=ME, then the reply will contain the base64key 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.

Public and private base64 keys can be generated using the following
message:

 DEST GENERATE

which is answered by

 DEST REPLY
      PUB=$pubkey
      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.

----------------------------------------------------------------------
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.


----------------------------------------------------------------------
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.