Skip to main content

emissary_core/runtime/
mod.rs

1// Permission is hereby granted, free of charge, to any person obtaining a
2// copy of this software and associated documentation files (the "Software"),
3// to deal in the Software without restriction, including without limitation
4// the rights to use, copy, modify, merge, publish, distribute, sublicense,
5// and/or sell copies of the Software, and to permit persons to whom the
6// Software is furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19// TODO: documentation
20
21use futures::Stream;
22use rand_core::{CryptoRng, RngCore};
23
24use alloc::{boxed::Box, string::String, vec::Vec};
25use core::{
26    fmt,
27    future::Future,
28    net::SocketAddr,
29    pin::Pin,
30    task::{Context, Poll},
31    time::Duration,
32};
33
34#[cfg(test)]
35pub mod mock;
36#[cfg(test)]
37pub mod noop;
38
39pub trait AsyncRead {
40    fn poll_read(
41        self: Pin<&mut Self>,
42        cx: &mut Context<'_>,
43        buf: &mut [u8],
44    ) -> Poll<crate::Result<usize>>;
45}
46
47pub trait AsyncWrite {
48    fn poll_write(
49        self: Pin<&mut Self>,
50        cx: &mut Context<'_>,
51        buf: &[u8],
52    ) -> Poll<crate::Result<usize>>;
53    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<crate::Result<()>>;
54    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<crate::Result<()>>;
55}
56
57pub trait TcpStream: AsyncRead + AsyncWrite + Unpin + Send + Sync + Sized + 'static {
58    /// Establish connection to remote peer at `address`.
59    fn connect(address: SocketAddr) -> impl Future<Output = Option<Self>> + Send;
60}
61
62pub trait TcpListener<TcpStream>: Unpin + Send + Sized + 'static {
63    fn bind(address: SocketAddr) -> impl Future<Output = Option<Self>>;
64    fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Option<(TcpStream, SocketAddr)>>;
65    fn local_address(&self) -> Option<SocketAddr>;
66}
67
68pub trait UdpSocket: Unpin + Send + Sized + Clone {
69    fn bind(address: SocketAddr) -> impl Future<Output = Option<Self>>;
70    fn send_to(
71        &mut self,
72        buf: &[u8],
73        target: SocketAddr,
74    ) -> impl Future<Output = Option<usize>> + Send;
75    fn recv_from(
76        &mut self,
77        buf: &mut [u8],
78    ) -> impl Future<Output = Option<(usize, SocketAddr)>> + Send;
79    fn local_address(&self) -> Option<SocketAddr>;
80}
81
82pub trait JoinSet<T>: Stream<Item = T> + Unpin + Send {
83    /// Returns whether the `JoinSet` is empty.
84    fn is_empty(&self) -> bool;
85
86    /// Get the number of elements in `JoinSet`.
87    fn len(&self) -> usize;
88
89    /// Pushes `future` to `JoinSet`.
90    fn push<F>(&mut self, future: F)
91    where
92        F: Future<Output = T> + Send + 'static,
93        F::Output: Send;
94}
95
96pub trait Instant: fmt::Debug + Copy + Clone + Send + Unpin + Sync {
97    /// Return much time has passed since an `Instant` was created.
98    fn elapsed(&self) -> Duration;
99}
100
101pub trait Counter {
102    fn increment(&mut self, value: usize);
103}
104
105pub trait Gauge {
106    fn increment(&mut self, value: usize);
107    fn decrement(&mut self, value: usize);
108}
109
110pub trait Histogram {
111    fn record(&mut self, record: f64);
112}
113
114pub trait MetricsHandle: Clone + Send + Sync + Unpin {
115    fn counter(&self, name: &'static str) -> impl Counter;
116    fn gauge(&self, name: &'static str) -> impl Gauge;
117    fn histogram(&self, name: &'static str) -> impl Histogram;
118}
119
120/// Metric type.
121pub enum MetricType {
122    /// Counter.
123    Counter {
124        /// Counter name.
125        name: &'static str,
126
127        /// Counter description.
128        description: &'static str,
129    },
130
131    /// Gauge.
132    Gauge {
133        /// Gauge name.
134        name: &'static str,
135
136        /// Gauge description.
137        description: &'static str,
138    },
139
140    /// Histogram
141    Histogram {
142        /// Histogram name.
143        name: &'static str,
144
145        /// Histogram description.
146        description: &'static str,
147
148        /// Buckets.
149        buckets: Vec<f64>,
150    },
151}
152
153pub trait Runtime: Clone + Unpin + Send + 'static {
154    type TcpStream: TcpStream;
155    type UdpSocket: UdpSocket;
156    type TcpListener: TcpListener<Self::TcpStream>;
157    type JoinSet<T: Send + 'static>: JoinSet<T>;
158    type MetricsHandle: MetricsHandle;
159    type Instant: Instant;
160    type Timer: Future<Output = ()> + Send + Unpin;
161
162    /// Spawn `future` in the background.
163    fn spawn<F>(future: F)
164    where
165        F: Future + Send + 'static,
166        F::Output: Send;
167
168    /// Return duration since Unix epoch.
169    fn time_since_epoch() -> Duration;
170
171    /// Get current time.
172    fn now() -> Self::Instant;
173
174    /// Return opaque type for generating random bytes.
175    fn rng() -> impl RngCore + CryptoRng;
176
177    /// Create new instance of a join set which contains a collection
178    /// of futures that are polled together.
179    ///
180    /// For `tokio` this would be `tokio::task::join_set::JoinSet` and
181    /// for `futures` this would be `future::stream::FuturesUnordered`
182    fn join_set<T: Send + 'static>() -> Self::JoinSet<T>;
183
184    /// Register `metrics` and return handle for registering metrics.
185    ///
186    /// An optional port can be specified for the metrics server and if none is specified, the
187    /// runtime will bind to a default port or ignore it alltogether if it doesn't need it.
188    fn register_metrics(metrics: Vec<MetricType>, port: Option<u16>) -> Self::MetricsHandle;
189
190    /// Return pinned future which blocks for `duration` before returning.
191    fn timer(duration: Duration) -> Self::Timer;
192
193    /// Return a future which blocks for `duration` before returning.
194    fn delay(duration: Duration) -> impl Future<Output = ()> + Send;
195
196    /// GZIP-compress `bytes` and return the compressed byte vector.
197    fn gzip_compress(bytes: impl AsRef<[u8]>) -> Option<Vec<u8>>;
198
199    /// GZIP-decompress `bytes` and return the decompressed byte vector.
200    fn gzip_decompress(bytes: impl AsRef<[u8]>) -> Option<Vec<u8>>;
201}
202
203pub trait AddressBook: Unpin + Send + Sync + 'static {
204    /// Attempt to resolve `host` into a base64-encoded `Destination`.
205    fn resolve_base64(&self, host: String) -> Pin<Box<dyn Future<Output = Option<String>> + Send>>;
206
207    /// Attemp to resolve `host` into a base32-encoded destination hash.
208    fn resolve_base32(&self, host: &str) -> Option<String>;
209}
210
211pub trait Storage: Unpin + Send + Sync + 'static {
212    /// Save routers and their profiles to disk.
213    fn save_to_disk(&self, routers: Vec<(String, Option<Vec<u8>>, crate::Profile)>);
214}