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 msgnos and the host that received the association must use only odd-numbered msgnos.

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.