3
2
Fork
You've already forked channeler
0
This library provides a reference implementation for a multi-channel and -link protocol for peer-to-peer communications.
  • C++ 96%
  • Meson 2.4%
  • Python 1.2%
  • C 0.3%
2024年10月17日 17:15:16 +02:00
.well-known Add wellknown funding url 2024年10月17日 17:15:16 +02:00
changelog.d Add news fragment 2022年10月17日 09:41:24 +02:00
docs Add logo 2022年07月05日 18:12:11 +02:00
include Add SPDX identifier 2022年07月25日 12:34:27 +02:00
lib Disambiguate constructor choice 2023年05月04日 10:21:43 +02:00
scripts Update conan build script 2023年05月04日 09:52:13 +02:00
subprojects #35 don't use SSH git urls in subprojects 2022年05月19日 11:33:58 +02:00
test Update build files 2022年10月17日 09:34:31 +02:00
.appveyor.yml #35 Update appveyor config 2022年05月19日 11:19:07 +02:00
.appveyor_account.yml #35 Update appveyor config 2022年05月19日 11:19:07 +02:00
.gitignore #35 update Pipfile* 2022年05月19日 09:28:35 +02:00
.oclint Add .oclint file 2022年01月14日 09:57:26 +01:00
.semgrepignore Update copyright notice; there was an error 2022年06月09日 14:47:06 +02:00
.woodpecker.yml Basic tooling update 2023年05月04日 09:50:54 +02:00
AUTHORS Add SPDX header 2022年07月25日 12:32:14 +02:00
build-config.h.in WIP for #2 : created new FSM to deal with congestion in a simple fashion 2022年03月18日 10:41:52 +01:00
CODE_OF_CONDUCT.md #35 : links & metadata 2022年05月19日 09:52:53 +02:00
codemeta.json Add SPDX header 2022年07月25日 12:32:14 +02:00
conandata.yml Conan build files 2022年10月17日 09:34:46 +02:00
conanfile.py Update conanfile.py 2023年05月04日 09:54:05 +02:00
CONTRIBUTING.md Update copyright notice; there was an error 2022年06月09日 14:47:06 +02:00
DCO.txt #35 : links & metadata 2022年05月19日 09:52:53 +02:00
LICENSE Fix/update copyright header in source files 2022年06月14日 11:25:25 +02:00
meson.build Update build files 2022年10月17日 09:34:31 +02:00
meson_options.txt Update build files 2022年10月17日 09:34:31 +02:00
Pipfile Basic tooling update 2023年05月04日 09:50:54 +02:00
Pipfile.lock Basic tooling update 2023年05月04日 09:50:54 +02:00
protoid.py Simple protocol identifier generator while we're not including any hash libraries 2021年02月10日 12:33:45 +01:00
README.md Update readme to refer to the new blog, and clarify a couple of minor points 2023年03月31日 13:43:29 +02:00
towncrier.toml Prior to copyright update, update pipenv/towncrier config 2022年06月02日 14:25:06 +02:00

Channeler

status-badge Build status

This library provides a reference implementation for a multi-channel and -link protocol for peer-to-peer communications.

The rationale for this has several dimensions:

  • NAT-piercing is prone to failure. Additionally, the number of available ports on a NAT limits how many peers behind the NAT can be served. To compensate for this, a multi-channel approach effectively allows multiplexing of independent "connections" (aka channels) along the same port.
  • In a multi-link (or multi-homed) device, e.g. on mobile devices, application connections should be kept stable even when the link technology changes (e.g. from WiFi to LTE, etc.)
  • Finally, encryption parameters can be kept separate per channel, improving recovery times, when the encryption protocol is aware of both of the above.

The library is implemented with readability and extensibility in mind. Other implementations may well opt for stronger optimization instead.

Note: the library is under heavy development, and the README will be updated when the first stab is implemented.

For more details on the protocol design, Connection Reset by Peer has blog posts on the design rationale. Additionally, the architecture overview contains the rationale for the pipe-and-filter approach chosen in the protocol implementation.

Status

This repository is heavily work-in-progress. Currently implemented is:

  • Channel negotiation
  • Resend/reliability features
  • Basic congestion management
  • Encryption
  • Mult-Link capabilities
    • Connection management
  • Advanced congestion management
  • Finalized API

Quick Background

The reason for this protocol is the realization that in comparison to UDP or plain IP, TCP adds reliablity characteristics that may better be separated along several axes, which are:

  • Are packets consumed by the API in-order or out-of-order?
  • Are packets resent when lost?
  • When a packet is irrecoverably lost, do we close the connection?

Channeler allows to configure each axis separately, leading to configurations that are essentially equivalent to plain UDP, or to TCP - but also allowing for other modes.

The core concern, therefore, is not actually a protocol concern as much as it is a question of how packet buffers are handled: is it overfull? are there gaps in it that indicate a lost packet? etc.

Usage

The current API is for internal use only. It does provide the main parts for verifying the protocol logic.

The following examples are similar to the InternalAPI test suite.

// A transport address type *placeholder*; this one is enough for IPv4
using address = uint32_t;
// The memmory management allocates packet buffer in blocks of N packets;
// this is that POOL_BLOCK_SIZE.
constexpr std::size_t POOL_BLOCK_SIZE = 20;
// How large are packets? This is currently static, and should be chosen to
// fit the path MTU.
constexpr std::size_t PACKET_SIZE = 1500;
// The node context contains the local peer identifier, and other per-node
// data.
using node = ::channeler::context::node<POOL_BLOCK_SIZE>;
// The connection context contains per-connection data, e.g. the number of
// registered channels, etc.
using connection = ::channeler::context::connection<address, node>;
// Internal API instance
using api = ::channeler::internal::connection_api<connection>;

With these types and constants defined, we can create an API instance:

// Node information
::channeler::peerid self;
node self_node{
 self,
 PACKET_SIZE,
 // A callback returning std::vector<std::byte>; this is a secret used
 // for cookie generation.
 &secret_callback,
 // The sleep function should accept a duration to sleep for, and return
 // the duration actually slept for.
 &sleep_function
};
// Connection from self to peer
::channeler::peerid peer;
connection conn{self_node, peer};
// API instance
api conn_api{
 conn,
 // The callback is invoked when a channel is established.
 &channel_established_callback,
 // The callback is invoked when the API has produced a packet that should be
 // sent to the peer.
 &packet_available_callback,
 // The last callback is invoked when there is data to read from a channel.
 &data_to_read_callback
};

First, we need to establish a channel.

auto err = conn_api.establish_channel(now(), peer);

The callback when a packet is available is going to be invoked.

void packet_available_callback(channeler::channeld const & id)
{
 // Read the packet from the API instance.
 auto packet = conn_api->packet_to_send(id);
 // Write the packet to the I/O, e.g. a socket.
 write(sockfd, entry.packet.buffer(), entry.packet.buffer_size());
}

When the peer responds, the channel establishment callback is going to be invoked (skipped here). You can now write to the channel.

channelid id; // from callback

size_t written = 0;
auto err = conn_api.write(id, message.c_str(), message.size(), written);
assert(written == message.size());

You can create many channels per connection, and each channel is handled separately. This means that packet loss on one channel will not stall packets on other channels.

When establishing a channel, it is possible to request certain cabilities. These are a bitset composed of individual flags, but shorthands exist for TCP-like, stream-oriented behaviour and UDP-like, datagram-oriented behaviour:

conn_api.establish_channel(now(), peer, capabilities_stream());
conn_api.establish_channel(now(), peer, capabilities_datagram());

Finally, congestion control is more transparent than with TCP, and applies to UDP as well. You can register a callback for being notified when the peer's receive window changes, which also changes the own node's send window:

conn_api.set_channel_window_changed_callback([] (time_point, channelid, std::size_t window_size)
 {
 // window_size is the number of *packets* the peer can currently receive.
 }
);