Cargo Relay over TCP/Unix Sockets (CoSocket)

  • Id: RS-004.
  • Status: Working draft.
  • Type: Implementation.
  • Proof of concept: https://github.com/relaynet/poc/tree/master/CoSocket

Abstract

This document describes CoSocket, a cargo relay binding on top of TCP or Unix sockets. As a purpose-built Application Layer protocol, this is the most efficient binding to relay cargo.

Table of contents

  1. Introduction
  2. Binding Hint
  3. Primitives
  4. Packets
    1. Handshake Packets
      1. Handshake Challenge
      2. Handshake Response
      3. Handshake Complete
    2. Operation Packets
      1. Cargo Collection Request
      2. Cargo Delivery
      3. Cargo Delivery (File Descriptor Version)
      4. Cargo Collection
      5. Cargo Delivery Completion
      6. Quit
  5. Persistent Connections
  6. Examples
    1. Relayer as TCP Server
    2. Relayer as Unix Socket Client
    3. Cargo Forwarding
  7. Relevant Specifications

Introduction

As a cargo relay binding, CoSocket’s objective is to provide the basis for a gateway to exchange cargo with a relayer or another gateway.

Gateways and relayers can act as client and servers. One of them has to be the server so that the other can connect to it via TCP or a Unix socket, but once communication has been established, they become peers and can send packets to each other indistinctively.

CoSocket is a binary protocol with little-endian byte order.

Binding Hint

The hint for this binding MUST be socket. For example, rng+socket://example.com would be a valid public gateway address.

Primitives

The packets in this protocol use the following primitives:

  • Varchar: A UTF-8 string, length-prefixed with a 8-bit unsigned integer (1 octet). Consequently, the string can have a length of up to 255 octets.
  • Payload length: A 32-bit unsigned integer (4 octets), used as a length-prefix for a payload.

Packets

Each packet starts with a tag that identifies the type of packet. The tag itself is serialized as a 16-bit unsigned integer (2 octets).

Handshake Packets

Per Relaynet Core, the handshake involves three steps:

  1. The relayer challenges the gateway to sign a nonce with its key(s).
  2. The gateway signs the nonce with each of its keys and sends the signatures to the relayer.
  3. The relayer verifies the signatures and confirms the end of the handshake.

Handshake Challenge

This packet contains the nonce that the gateway has to sign. The packet comprises the following sequence:

  • Tag: 0xf0.
  • The nonce, as a random sequence of exactly 32 octets.

Handshake Response

This packet contains the signatures for the nonce and comprises the following sequence:

  • Tag: 0xf1.
  • The total payload length for all the signatures and their length prefixes included in the packet.
  • The payload with the sequence of signatures, where each is prefixed with its payload length.

Handshake Complete

This packet is sent by the relayer when the signatures were successfully verified. This packet is empty – It only contains its tag (0xf2).

Operation Packets

Cargo Collection Request

This packet encapsulates a Cargo Collection Authorization (CCA) and represents a request to collect cargo for a specific gateway.

A relayer MUST send this packet to a gateway to indicate it is ready to receive cargo and to prove it is authorized to receive cargo for the gateway in the CCA.

The packet comprises the following sequence:

  1. Tag: 0x00.
  2. The payload length for the CCA.
  3. The CCA.

Cargo Delivery

This packet encapsulates a cargo and has the following sequence:

  1. Tag: 0x01.
  2. A string that uniquely identifies this cargo delivery, serialized as a varchar. This MAY be different from the cargo id, so it could be a UUID4 value, for example.
  3. The payload length for the cargo.
  4. The cargo.

Cargo Delivery (File Descriptor Version)

This is an alternative to Cargo Delivery using file descriptors, so this is only available on Unix sockets. The sequence is as follows:

  1. Tag: 0x02.
  2. The string that uniquely identifies this cargo delivery, serialized as a varchar.
  3. (TODO: Define how the file descriptor is actually passed)

Cargo Collection

This packet represents an acknowledgement that a cargo delivery was successfully received and has the following sequence:

  1. Tag: 0x03.
  2. The cargo delivery id, serialized as varchar.

Cargo Delivery Completion

Used to signal that there are no further cargoes for the specified gateway. It has the following sequence:

  1. Tag: 0x04.
  2. The address of the gateway for which there are no further cargoes, serialized as varchar.

The sender of this packet MUST also quit if its peer has already confirmed that it will not send any further cargoes.

Quit

Used by a peer to indicate that it is about to close the connection. The sender MUST close the connection immediately after sending this packet.

The packet has the following sequence:

  1. Tag: 0xff.
  2. Reason: A 16-bit unsigned integer representing the reason why the connection was terminated:
    • 0x00: Operation completed without errors.
    • 0x01: Invalid packet.
    • 0x02: Handshake error.
    • 0x03: Quota reached.
    • 0x04: Internal error.

Persistent Connections

Two gateways MAY maintain a persistent connection to exchange cargo in near-real time. This could be necessary when the target gateway is not a server that can be reached by the other gateway (e.g., the target is behind a NAT gateway).

Relayers MUST always quit the connection as soon as no further cargoes are expected in either direction.

Examples

Relayer as TCP Server

TODO: Upload sequence diagram.

Relayer as Unix Socket Client

TODO: Upload sequence diagram.

Cargo Forwarding

TODO: Upload sequence diagram.

Relevant Specifications

Relaynet Core (RS-000) defines the requirements for message transport bindings in general and cargo relay bindings specifically, all of which apply to CoSocket. Amongst other things, it defines the use Transport Layer Security (TLS).