1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//
// Copyright 2022 Sebastian Urban <surban@surban.net>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/surban/aggligator/master/.misc/aggligator.png",
    html_favicon_url = "https://raw.githubusercontent.com/surban/aggligator/master/.misc/aggligator.png",
    issue_tracker_base_url = "https://github.com/surban/aggligator/issues/"
)]

//! Aggregates multiple links into one connection.
//!
//! Aggligator takes multiple network links (for example [TCP] connections) between two
//! endpoints and combines them into one connection that has the combined bandwidth
//! of all links. Additionally it provides resiliency against failure of individual
//! links and allows adding and removing of links on-the-fly.
//!
//! It serves the same purpose as [Multipath TCP] and [SCTP] but works over existing,
//! widely adopted protocols such as TCP, HTTPS, TLS and WebSockets and is completely
//! implemented in user space without the need for any support from the operating system.
//!
//! Aggligator is written in 100% safe Rust and builds upon the [Tokio](tokio)
//! asynchronous runtime.
//!
//! [TCP]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
//! [Multipath TCP]: https://en.wikipedia.org/wiki/Multipath_TCP
//! [SCTP]: https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol
//!
//! # Link requirements
//!
//! A link can either be stream-based (implementing the [AsyncRead] and [AsyncWrite] traits)
//! or packet-based (implementing the [Sink] and [Stream] traits).
//! In both cases the implementation of the link must ensure data integrity and deliver data
//! in the same order as it was sent.
//! If data has been lost or corrupted underway, the link must handle retransmission
//! and, if that is unsuccessful, fail by disconnecting itself.
//!
//! In the case of TCP this is handled by the operating system and thus
//! a [TcpStream] or protocols building on top of that (such as TLS or WebSockets)
//! can be directly used as links.
//!
//! Other then the requirements stated above, Aggligator makes no assumption about
//! the type of links and can work over any networking methodology such as
//! TCP/IP, Bluetooth, and serial links. It never interfaces directly with the
//! operating system and only uses links provided by the user.
//!
//! [AsyncRead]: tokio::io::AsyncRead
//! [AsyncWrite]: tokio::io::AsyncWrite
//! [Sink]: futures::sink::Sink
//! [Stream]: futures::stream::Stream
//! [TcpStream]: https://docs.rs/tokio/1/tokio/net/struct.TcpStream.html
//!
//! # Connection security
//!
//! Aggligator does *not* perform cryptographic authentication of the remote endpoint or encryption of data.
//! If you are sending sensitive data over an untrusted connection you should encrypt it
//! and authenticate the remote endpoint, for example using [TLS].
//! The implementation provided in the [tokio-rustls] crate works nicely with Aggligator.
//!
//! However, the unique identifier of each connection is encrypted using a shared
//! secret that is exchanged via [Diffie-Hellman key exchange].
//! Thus, an eavesdropper cannot inject fake links to an existing connection by using
//! the spoofed connection identifier.
//! This provides the same security level against insertion of malicious data and connection
//! termination by an adversary as you would have when using a single unencrypted
//! TCP connection.
//!
//! [TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
//! [tokio-rustls]: https://docs.rs/tokio-rustls/
//! [Diffie-Hellman key exchange]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
//!
//! # Basic usage and utility functions
//!
//! See the [connect module](mod@connect) on how to accept incoming connections
//! and establish outgoing connections. This is agnostic of the underlying protocol.
//!
//! Useful functions for working with TCP-based links, encryption and authentication using TLS,
//! a visualizing link monitor and a completely worked out example are provided in the
//! **[aggligator-util]** crate.
//!
//! [aggligator-util]: https://docs.rs/aggligator-util/latest/aggligator_util/
//!

mod agg;
pub mod alc;
pub mod cfg;
pub mod connect;
pub mod control;
pub mod id;
pub mod io;
mod msg;
mod peekable_mpsc;
mod seq;

#[cfg(feature = "dump")]
#[cfg_attr(docsrs, doc(cfg(feature = "dump")))]
pub use agg::dump;

pub use agg::task::Task;

/// Link aggregator protocol error.
macro_rules! protocol_err {
    ($($t:tt)*) => {
        std::io::Error::new(std::io::ErrorKind::InvalidData, format!($($t)*))
    };
}

pub(crate) use protocol_err;

pub use cfg::Cfg;
pub use connect::{connect, Incoming, Listener, Outgoing, Server};
pub use control::{Control, Link};
pub use io::{IoRxBox, IoTxBox};