Files
i2p.www/www.i2p2/pages/i2cp_spec.html

892 lines
22 KiB
HTML
Raw Normal View History

2010-09-09 13:44:16 +00:00
{% extends "_layout.html" %}
{% block title %}I2CP Specification{% endblock %}
{% block content %}
2011-05-05 14:45:25 +00:00
Updated May 2011, current as of router version 0.8.5
2010-09-09 13:44:16 +00:00
<h1>I2P Control Protocol (I2CP) Specification</h1>
<h2>Overview</h2>
<p>
This page specified the I2P Control Protocol (I2CP),
which is the interface between clients and the router.
Java clients will use the I2CP client API, which implements this protocol.
Non-Java clients will most likely use a higher-layer protocol
such as SAM or BOB.
More information is on the <a href="i2cp.html">I2CP Overview page</a>.
</p>
<h2>Sessions</h2>
<p>
The protocol was designed to handle multiple "sessions", each with a 2-byte session ID,
over a single TCP connection.
This does not appear to be fully implemented.
Do not attempt to use multiple sessions on a single I2CP connection.
</p>
<p>
It also appears that there are some provisions for a single client to talk to multiple
routers over separate connections. This is also untested,
and probably not useful.
</p>
<p>
It does not appear that there is currently a way for a session to be
maintained after a disconnect, or to be
recovered on a different
I2CP connection.
</p>
<h2>Example Message Sequences</h2>
<h3>Standard Session Establish</h3>
<pre>
{% filter escape %}
Client Router
---------------------> Protocol Byte (0x2a)
---------------------> Get Date Message
Set Date Message <---------------------
---------------------> Create Session Message
Session Status Message <---------------------
Request LeaseSet Message <---------------------
---------------------> Create LeaseSet Message
{% endfilter %}
</pre>
<h3>Get Bandwidth Limits (Simple Session)</h3>
<pre>
{% filter escape %}
Client Router
---------------------> Protocol Byte (0x2a)
---------------------> Get Bandwidth Limits Message
Bandwidth Limits Message <---------------------
{% endfilter %}
</pre>
<h3>Destination Lookup (Simple Session)</h3>
<pre>
{% filter escape %}
Client Router
---------------------> Protocol Byte (0x2a)
---------------------> Dest Lookup Message
Dest Reply Message <---------------------
{% endfilter %}
</pre>
<h3>Outgoing Message</h3>
<p>(existing session)</p>
<pre>
{% filter escape %}
Client Router
---------------------> Send Message Message
Message Status Message <---------------------
(accepted)
Message Status Message <---------------------
(succeeded)
{% endfilter %}
</pre>
2010-10-11 16:11:49 +00:00
<p>
Note: As of release 0.8.1, the router does not send either Message Status Message if
i2cp.messageReliability=none.
</p>
2010-09-09 13:44:16 +00:00
<h3>Incoming Message</h3>
<p>(existing session)</p>
<pre>
{% filter escape %}
Client Router
Message Status Message <---------------------
(available)
---------------------> Receive Message Begin Message
Message Payload Message <---------------------
---------------------> Receive Message End Message
{% endfilter %}
</pre>
<h2 id="structures">Common structures</h2>
<h3 id="struct_header">I2CP message header</h3>
<h4>Description</h4>
<p>
Common header to all I2CP messages, containing the message length and message type.
</p>
<h4>Contents</h4>
<ol><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> specifying the length of the message body
</li><li>
1 byte <a href="common_structures_spec#type_Integer">Integer</a> specifying the message type.
</li><li>
The I2CP message body, 0 or more bytes
</li></ol>
<h4>Notes</h4>
<p>
Actual message length limit is about 64 KB.
</p>
<h3 id="struct_MessageId">Message ID</h3>
<h4>Description</h4>
<p>
Uniquely identifies a message waiting on a particular router at a
point in time.
</p>
<h4>Contents</h4>
<ol><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
</li></ol>
<h4>Notes</h4>
<p>
Message IDs are unique within a session only; they are not globally unique.
</p>
<h3 id="struct_Payload">Payload</h3>
<h4>Description</h4>
<p>
This structure is the content of a message being delivered from one
Destination to another.
</p>
<h4>Contents</h4>
<ol><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> length
</li><li>
That many bytes
</li></ol>
<h4>Notes</h4>
<p>
The payload is in a gzip format as specified on the
<a href="i2cp.html#format">I2CP Overview page</a>.
</p>
<h3 id="struct_SessionConfig">Session Config</h3>
<h4>Description</h4>
<p>
Defines the configuration options for a particular client session.
</p>
<h4>Contents</h4>
<ol><li>
<a href="common_structures_spec#struct_Destination">Destination</a>
</li><li>
<a href="common_structures_spec#type_Mapping">Mapping</a> of options
</li><li>
Creation <a href="common_structures_spec#type_Date">Date</a>
</li><li>
DSA <a href="common_structures_spec#type_Signature">Signature</a> of the previous 3 fields, signed by the
<a href="common_structures_spec#type_SigningPrivateKey">Signing Private Key</a>
</li></ol>
<h4>Notes</h4>
<p>
The options are specified on the
<a href="i2cp.html#options">I2CP Overview page</a>.
</p>
<h3 id="struct_SessionId">Session ID</h3>
<h4>Description</h4>
<p>
Uniquely identifies a session on a particular router at a point in
time.
</p>
<h4>Contents</h4>
<ol><li>
2 byte <a href="common_structures_spec#type_Integer">Integer</a>
</li></ol>
<h4>Notes</h4>
<p>
</p>
<h2 id="messages">Messages</h2>
<h3 id="types">Message Types</h3>
<table border=1>
<tr><th>Message<th>Direction<th>Type
<tr><td>
<a href="#msg_BandwidthLimits">
BandwidthLimitsMessage
</a>
</a>
<td align="center">R-&gt;C
<td align=right>23
<tr><td>
<a href="#msg_CreateLeaseSet">
CreateLeaseSetMessage
</a>
<td align="center">C-&gt;R
<td align=right>4
<tr><td>
<a href="#msg_CreateSession">
CreateSessionMessage
</a>
<td align="center">C-&gt;R
<td align=right>1
<tr><td>
<a href="#msg_DestLookup">
DestLookupMessage
</a>
<td align="center">C-&gt;R
<td align=right>34
<tr><td>
<a href="#msg_DestReply">
DestReplyMessage
</a>
<td align="center">R-&gt;C
<td align=right>35
<tr><td>
<a href="#msg_DestroySession">
DestroySessionMessage
</a>
<td align="center">C-&gt;R
<td align=right>3
<tr><td>
<a href="#msg_Disconnect">
DisconnectMessage
</a>
<td align="center">bidir.
<td align=right>30
<tr><td>
<a href="#msg_GetBandwidthLimits">
GetBandwidthLimitsMessage
</a>
<td align="center">C-&gt;R
<td align=right>8
<tr><td>
<a href="#msg_GetDate">
GetDateMessage
</a>
<td align="center">C-&gt;R
<td align=right>32
<tr><td>
<a href="#msg_MessagePayload">
MessagePayloadMessage
</a>
<td align="center">R-&gt;C
<td align=right>31
<tr><td>
<a href="#msg_MessageStatus">
MessageStatusMessage
</a>
<td align="center">R-&gt;C
<td align=right>22
<tr><td>
<a href="#msg_ReceiveMessageBegin">
ReceiveMessageBeginMessage
</a>
<td align="center">C-&gt;R
<td align=right>6
<tr><td>
<a href="#msg_ReceiveMessageEnd">
ReceiveMessageEndMessage
</a>
<td align="center">C-&gt;R
<td align=right>7
<tr><td>
<a href="#msg_ReconfigureSession">
ReconfigureSessionMessage
</a>
<td align="center">C-&gt;R
<td align=right>2
<tr><td>
<a href="#msg_ReportAbuse">
ReportAbuseMessage
</a>
<td align="center">bidir.
<td align=right>29
<tr><td>
<a href="#msg_RequestLeaseSet">
RequestLeaseSetMessage
</a>
<td align="center">R-&gt;C
<td align=right>21
<tr><td>
<a href="#msg_SendMessage">
SendMessageMessage
</a>
<td align="center">C-&gt;R
<td align=right>5
<tr><td>
<a href="#msg_SendMessageExpires">
SendMessageExpiresMessage
</a>
<td align="center">C-&gt;R
<td align=right>36
<tr><td>
<a href="#msg_SessionStatus">
SessionStatusMessage
</a>
<td align="center">R-&gt;C
<td align=right>20
<tr><td>
<a href="#msg_SetDate">
SetDateMessage
</a>
<td align="center">R-&gt;C
<td align=right>33
</table>
<h3 id="msg_BandwidthLimits">Bandwidth Limits</h3>
<h4>Description</h4>
<p>
Tell the client what the bandwidth limits are.
Sent from Router to Client in response to a Get Bandwidth Limits Message.
</p>
<h4>Contents</h4>
<ol><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Client inbound limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Client outbound limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Router inbound limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Router inbound burst limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Router outbound limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Router outbound burst limit (KBps)
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a>
Router burst time (seconds)
</li><li>
Nine 4-byte <a href="common_structures_spec#type_Integer">Integers</a>
undefined
</li></ol>
<h4>Notes</h4>
<p>
Currently, the client limits are the only values set,
and are actually the router limits. All the values labeled as router limits are always 0.
As of release 0.7.2.
</p>
<h3 id="msg_CreateLeaseSet">Create Lease Set</h3>
<h4>Description</h4>
<p>
This message is sent in response to a RequestLeaseSetMessage and contains all
of the Lease structures that should be published to the I2NP Network Database.
Sent from Client to Router.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="common_structures_spec#type_SigningPrivateKey">Signing Private Key</a>
</li><li>
<a href="common_structures_spec#type_PrivateKey">Private Key</a>
</li><li>
<a href="common_structures_spec#struct_LeaseSet">LeaseSet</a>
</li></ol>
<h4>Notes</h4>
<p>
The SigningPrivateKey matches the SigningPublicKey from within the
LeaseSet, as does the PrivateKey with the PublicKey. The Signing keys are
necessary to allow the router to revoke the LeaseSet if the client goes offline,
and the normal keys are necessary for decrypting garlic routed messages. The
LeaseSet granted may include Lease structures for tunnels pointing at another
router if the client is actively connected to multiple routers with Leases granted
to each.
Really?
Revocation is unimplemented.
Connection to multiple routers is untested.
</p>
<h3 id="msg_CreateSession">Create Session</h3>
<h4>Description</h4>
<p>
This message is sent from a client to initiate a session, where a session is defined
as a single Destination's connection to the network, to which all messages for
that Destination will be delivered and from which all messages that
Destination sends to any other Destination will be sent through.
Sent from Client to Router.
The router responds with a <a href="#msg_SessionStatus">Session Status Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionConfig">Session Config</a>
</li></ol>
<h4>Notes</h4>
<p>
The second message sent by the client after sending the Get Date Message and receiving the Set Date Message response.
If the Date in the Session Config is too far from the router's current time, the session will be rejected.
If there is already a session on the router for this Destination, the session will be rejected.
</p>
<h3 id="msg_DestLookup">Dest Lookup</h3>
<h4>Description</h4>
<p>
Sent from Client to Router.
The router responds with a <a href="#msg_DestReply">Dest Reply Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="common_structures_spec#struct_Hash">SHA-256 Hash</a>
</li></ol>
<h4>Notes</h4>
<p>
As of release 0.7.
2011-05-05 14:45:25 +00:00
As of release 0.8.3, multiple outstanding lookups are supported,
and lookups are supported in both I2PSimpleSession and in standard sessions.
2010-09-09 13:44:16 +00:00
</p>
<h3 id="msg_DestReply">Dest Reply</h3>
<h4>Description</h4>
<p>
Sent from Router to Client in response to a Dest Lookup Message.
</p>
<h4>Contents</h4>
<ol><li>
2011-05-05 14:45:25 +00:00
<a href="common_structures_spec#struct_Destination">Destination</a>
on success, or
<a href="common_structures_spec#struct_Hash">Hash</a>
on failure
2010-09-09 13:44:16 +00:00
</li></ol>
<h4>Notes</h4>
<p>
As of release 0.7.
2011-05-05 14:45:25 +00:00
As of release 0.8.3,
the requested Hash is returned if the lookup failed,
so that the client may have multiple lookups outstanding and correlate the replies to the lookups.
Prior to release 0.8.3, the response was empty on failure.
2010-09-09 13:44:16 +00:00
</p>
<h3 id="msg_Destroy Session">Destroy Session</h3>
<h4>Description</h4>
<p>
This message is sent from a client to destroy a session.
Sent from Client to Router.
The router responds with a <a href="#msg_SessionStatus">Session Status Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li></ol>
<h4>Notes</h4>
<p>
The router at this point should release all resources related to the session.
</p>
<h3 id="msg_Disconnect">Disconnect</h3>
<h4>Description</h4>
<p>
Tell the other party that there are problems and the current connection is about to
be destroyed. This does not necessarily end a session.
Sent either from router to client or from client to router.
</p>
<h4>Contents</h4>
<ol><li>
Reason <a href="common_structures_spec#struct_String">String</a>
</li></ol>
<h4>Notes</h4>
<p>
Only implemented in the router-to-client direction.
Disconnecting probably does end a session, in practice.
</p>
<h3 id="msg_GetBandwidthLimits">Get Bandwidth Limits</h3>
<h4>Description</h4>
<p>
Request that the router state what its current bandwidth limits are.
Sent from Client to Router.
The router responds with a <a href="#msg_BandwidthLimits">Bandwidth Limits Message</a>.
</p>
<h4>Contents</h4>
<i>None</i>
<h4>Notes</h4>
<p>
As of release 0.7.2.
2011-05-05 14:45:25 +00:00
As of release 0.8.3,
supported in both I2PSimpleSession and in standard sessions.
2010-09-09 13:44:16 +00:00
</p>
<h3 id="msg_GetDate">Get Date</h3>
<h4>Description</h4>
<p>
Sent from Client to Router.
The router responds with a <a href="#msg_SetDate">Set Date Message</a>.
</p>
<h4>Contents</h4>
<i>None</i>
<h4>Notes</h4>
<p>
Generally the first message sent by the client after sending the protocol version byte.
</p>
<h3 id="msg_MessagePayload">Message Payload</h3>
<h4>Description</h4>
<p>
Deliver the payload of a message to the client.
Sent from Router to Client.
The client responds with a <a href="#msg_ReceiveMessageEnd">Receive Message End Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="#struct_MessageId">Message ID</a>
</li><li>
<a href="#struct_Payload">Payload</a>
</li></ol>
<h4>Notes</h4>
<p>
</p>
<h3 id="msg_MessageStatus">Message Status</h3>
<h4>Description</h4>
<p>
Notify the client of the delivery status of an incoming or outgoing message.
Sent from Router to Client.
If this message indicates that an incoming message is available,
the client responds with a <a href="#msg_ReceiveMessageBegin">Receive Message Begin Message</a>.
For an outgoing message, this is a response to a
<a href="#msg_SendMessage">Send Message Message</a> or
<a href="#msg_SendMessageExpires">Send Message Expires Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="#struct_MessageId">Message ID</a>
</li><li>
1 byte <a href="common_structures_spec#type_Integer">Integer</a> status
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> size
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> nonce
</li></ol>
<h4>Notes</h4>
<p>
The known status values are 0 for message is available, 1 for accepted, 2 for best
effort succeeded, 3 for best effort failed, 4 for guaranteed succeeded, 5 for
guaranteed failed. The size Integer specifies the size of the available
message and is only relevant for status = 0.
Even though guaranteed is unimplemented, (best effort is the only service), the current
router implementation uses the guaranteed status codes, not the best effort codes.
</p>
<p>
When status = 1 (accepted), the nonce matches the nonce in the
Send Message Message, and the included Message ID
will be used for subsequent success or failure notification.
Otherwise, the nonce may be ignored.
</p>
<h3 id="msg_ReceiveMessageBegin">Receive Message Begin</h3>
<h4>Description</h4>
<p>
Request the router to deliver a message that it was previously notified of.
Sent from Client to Router.
The router responds with a <a href="#msg_MessagePayload">Message Payload Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="#struct_MessageId">Message ID</a>
</li></ol>
<h4>Notes</h4>
<p>
The ReceiveMessageBeginMessage is sent as a response to a
MessageStatusMessage stating that a new message is available for pickup. If the
message id specified in the ReceiveMessageBeginMessage is invalid or
incorrect, the router may simply not reply, or it may send back a
DisconnectMessage.
</p>
<h3 id="msg_ReceiveMessageEnd">Receive Message End</h3>
<h4>Description</h4>
<p>
Tell the router that delivery of a message was completed successfully and that
the router can discard the message.
Sent from Client to Router.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="#struct_MessageId">Message ID</a>
</li></ol>
<h4>Notes</h4>
<p>
The ReceiveMessageBeginMessage is sent after a MessagePayloadMessage fully
delivers a message's payload.
</p>
<h3 id="msg_RecconfigureSession">Reconfigure Session</h3>
<h4>Description</h4>
<p>
Sent from Client to Router to update the session configuration.
The router responds with a <a href="#msg_SessionStatus">Session Status Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="#struct_SessionConfig">Session Config</a>
</li></ol>
<h4>Notes</h4>
<p>
As of release 0.7.1.
</p>
<h3 id="msg_ReportAbuse">Report Abuse</h3>
<h4>Description</h4>
<p>
Tell the other party (client or router) that they are under attack, potentially with reference to a
particular messageId. If the router is under attack, the client may decide to
migrate to another router, and if a client is under attack, the router may rebuild
its routers or shitlist some of the peers that sent it messages delivering the attack.
Sent either from router to client or from client to router.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
1 byte <a href="common_structures_spec#type_Integer">Integer</a> abuse severity
(0 is minimally abusive, 255 being extremely abusive)
</li><li>
Reason <a href="common_structures_spec#struct_String">String</a>
</li><li>
<a href="#struct_MessageId">Message ID</a>
</li></ol>
<h4>Notes</h4>
<p>
Unused.
Not fully implemented. Both router and client can generate Report Abuse Messages,
but neither has a handler for the message when received.
</p>
<h3 id="msg_RequestLeaseSet">Request LeaseSet</h3>
<h4>Description</h4>
<p>
Request that a client authorize the inclusion of a particular set of inbound tunnels.
Sent from Router to Client.
The client responds with a <a href="#msg_SessionStatus">Create LeaseSet Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
1 byte <a href="common_structures_spec#type_Integer">Integer</a> number of tunnels
</li><li>
That many pairs of:
<ol><li>
<a href="common_structures_spec#struct_RouterIdentity">Router Identity</a>
</li><li>
<a href="common_structures_spec#type_TunnelId">Tunnel ID</a>
</li></ol>
</li><li>
End <a href="common_structures_spec#type_Date">Date</a>
</li></ol>
<h4>Notes</h4>
<p>
</p>
<h3 id="msg_SendMessage">Send Message</h3>
<h4>Description</h4>
<p>
This is how a client sends a message (the payload) to the Destination.
The router will use a default expiration.
Sent from Client to Router.
The router responds with a <a href="#msg_MessageStatus">Message Status Message</a>.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="common_structures_spec#struct_Destination">Destination</a>
</li><li>
<a href="#struct_Payload">Payload</a>
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> nonce
</li></ol>
<h4>Notes</h4>
<p>
As soon as the SendMessageMessage arrives fully intact, the router should return
a MessageStatusMessage stating that it has been accepted for delivery.
That message will contain the same nonce sent here.
Later on,
based on the delivery guarantees of the session configuration, the router may
additionally send back another MessageStatusMessage updating the status.
2010-10-11 16:11:49 +00:00
Note: As of release 0.8.1, the router does not send either Message Status Message if
i2cp.messageReliability=none.
2010-09-09 13:44:16 +00:00
</p>
<h3 id="msg_SendMessageExpires">Send Message Expires</h3>
<h4>Description</h4>
<p>
Sent from Client to Router. Same as Send Message Message, except includes an expiration.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
<a href="common_structures_spec#struct_Destination">Destination</a>
</li><li>
<a href="#struct_Payload">Payload</a>
</li><li>
4 byte <a href="common_structures_spec#type_Integer">Integer</a> nonce
</li><li>
2 bytes of flags (options)
</li><li>
2010-09-09 13:44:16 +00:00
Expiration <a href="common_structures_spec#type_Date">Date</a>
truncated from 8 bytes to 6 bytes
2010-09-09 13:44:16 +00:00
</li></ol>
<h4>Notes</h4>
<p>
As of release 0.7.1.
</p><p>
As of release 0.8.4, the upper two bytes of the Date are redefined to contain
flags. The flags must default to all zeros for backward compatibility.
The individual flag bits will be defined in a future release.
The Date will not encroach on the flags field until the year 10889.
2010-09-09 13:44:16 +00:00
</p>
<h3 id="msg_SessionStatus">Session Status</h3>
<h4>Description</h4>
<p>
Instruct the client as to the status of its session.
Sent from Router to Client.
</p>
<h4>Contents</h4>
<ol><li>
<a href="#struct_SessionId">Session ID</a>
</li><li>
1 byte <a href="common_structures_spec#type_Integer">Integer</a> status
</li></ol>
<h4>Notes</h4>
<p>
Status values include 0 for destroyed, 1 for created, 2 for updated, and
3 for invalid session.
If created, the Session ID is the identifier to be used for the rest of the session.
</p>
<h3 id="msg_SetDate">Set Date</h3>
<h4>Description</h4>
<p>
The current date and time.
Sent from Router to Client as a part of the initial handshake.
</p>
<h4>Contents</h4>
<ol><li>
<a href="common_structures_spec#type_Date">Date</a>
</li></ol>
<h4>Notes</h4>
<p>
This is generally the first message sent by the router.
</p>
{% endblock %}