SCTPBinding
Update: This binding makes no real use of SCTP streams, and so TCP is probably a simpler choice. See TCPBinding.
SCTP is lower-level than XMPP, and has better features for Ripple. Message transport should be handled at the "transport" networking layer, so this is the thing to do...
- More of the application-level messaging semantics need to be specified than with XMPP, but those can easily be borrowed from BEEP, which even has an SCTP binding.
- SCTP is P2P while XMPP is peer <-> server <-> server <-> peer.
- Connection-level encryption = end-to-end encryption for SCTP, unlike XMPP.
- There is an RFC for TLS over SCTP.
- XMPP allows firewalled peers to connect via servers, while SCTP does not. But generally Ripple host operators should be able to open ports for Ripple.
- XMPP over TCP is well supported for NAT traversal, while SCTP as yet is not. But by the time that multiple hosts behind a single NAT want to use Ripple, NATs should be SCTP-friendly. NATs should not be a concern with most Ripple hosts.
- SCTP does multiple streams within one connection
- Stream 0 for host control messages (connection time, etc.)
- Stream 1 for routing advertisement/control messages (may be bandwidth-heavy and don't want to block stream 0)
- Streams 2-n (16 bits) for node-node connections (neighbour and payer-recipient connections)
- 1:1 relationship between streams and internode connections
- need special message for starting/closing internode connections?
- SCTP does message framing.
- SCTP has heartbeat messages.
Host Connections
Ripple hosts connect to each other by opening an SCTP association. (Need to specify a standard port for hosts to listen on.)
Hosts should ensure that sufficient streams are reserved for the number of concurrent messages expected over the association.
Only one SCTP association is permitted between two given hosts.
Connection Security
There is an RFC for TLS over SCTP.
Node Identification
Nodes are identified in standard node@host.com email-address style.
Host Messages
Host messages are sent in BEEP-style frames as follows:
(type) (version) (msgno) (more) (size)(CRLF) (content) END(CRLF)
where
(type) = MSG | RPY | ERR (version) = (string) (msgno) = 0..2147483647 (more) = . | * (size) = (integer)
Message types MSG
, RPY
, and ERR
correspond to the Ripple message types message
, reply
, and error
.
The version
indicates the Ripple protocol version.
The msgno
must be unique among MSG
-type messages in the session (not stream/channel as in the BEEP specification) that have not yet received a complete response. For RPY
and ERR
types, msgno
must be identical to the original MSG
. The host that initiated the association must use only even-numbered msgno
s and the host that received the association must use only odd-numbered msgno
s.
If more
is "*", it signifies there are more frames in the message; if it is ".", this is the final frame. This allows a host to chunk messages into discrete bits in order to interleave messages in the same stream. This is not required for SCTP, since hosts may simply use SCTP's streams to interleave messages, but it is included for consistency with the TCP binding, where it is necessary.
size
is the number of content bytes between, but not including, the CRLF
at the end of the header line, and the END
at the end of the frame.
Node Messages
Node messages are sent in frames of the following format:
(type) (version) (msgno) (more) (size) (to-user) (from-user)(CRLF) (content) END(CRLF)
The to-user
and from-user
fields need only specify usernames, since the host names are exchanged at the beginning of a session as described below.
Streams
Hosts may send a message frame on any permitted SCTP stream. Reply/error frames do not need to be sent back over the same stream as the original message frame.
Errors
If a received frame does not meet either the host or node message format, the association must be immediately closed.
Host Identification
This is probably not be necessary. Hosts know each other's IP address. If a user of one host requests a message be sent to a certain hostname, it can be resolved by DNS to see if a connection already exists to that host.
Upon starting a session and negotiating TLS, the initiating host must send a host-id
message:
{
"type": "host-id", "hostname": (string)
}
The hostname
is what comes after the @ in the
user@host.com
user ID form. Hostnames can be verified against DNS lookup of IP address, or, more securely, by comparing to a public-key certificate offered in TLS negotiation.
Upon receiving a host-id
message, the accepting host must reply with its own host-id
message.