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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
use crate::{general::Metrics, handshake, metrics};
use log::{error, info};
use rand::Rng;
use std::collections::BTreeMap;
use std::sync::Arc;
use tokio::net::TcpListener;
mod forwarder;
use forwarder::{Client, ClientManager};
mod ports;
mod user;
use forwarder::Forwarder;
pub use ports::Strategy;
/// Holds all information needed to creating and running
/// a single Tunneler-Server
#[derive(Debug, PartialEq)]
pub struct Server<M> {
listen_port: u32,
port_strategy: Strategy,
key: Vec<u8>,
metrics: Arc<M>,
}
impl Server<metrics::Empty> {
/// Creates a new Server-Instance from the given Data
///
/// Params:
/// * listen_port: The Port clients will connect to
/// * port_strategy: The Strategy to determine if a port a client wants to use is valid
/// * key: The Key/Password clients need to connect to the server
pub fn new(listen_port: u32, port_strategy: Strategy, key: Vec<u8>) -> Self {
Self::new_metrics(listen_port, port_strategy, key, metrics::Empty::new())
}
}
impl<M> Server<M>
where
M: Metrics,
{
/// Creates a new Server-Instance from the given Data
///
/// Params:
/// * listen_port: The Port clients will connect to
/// * port_strategy: The Strategy to determine if a port a client wants to use is valid
/// * key: The Key/Password clients need to connect to the server
/// * p_metrics: The Metrics-Collector to use
pub fn new_metrics(
listen_port: u32,
port_strategy: Strategy,
key: Vec<u8>,
p_metrics: M,
) -> Self {
Self {
listen_port,
port_strategy,
key,
metrics: Arc::new(p_metrics),
}
}
/// Starts the actual server itself along with all the needed tasks
///
/// This is a blocking call and is not expected to return
pub async fn start(self) -> ! {
info!("Starting...");
let listen_bind_addr = format!("0.0.0.0:{}", self.listen_port);
let client_listener = match TcpListener::bind(&listen_bind_addr).await {
Ok(l) => l,
Err(e) => {
log::error!("Binding to Address('{}'): {:?}", listen_bind_addr, e);
panic!();
}
};
info!("Listening for Clients on: {}", listen_bind_addr);
let mut ports: BTreeMap<u16, Arc<ClientManager>> = BTreeMap::new();
// Accept new Clients
loop {
// Get Client
let mut client_socket = match client_listener.accept().await {
Ok((socket, _)) => socket,
Err(e) => {
error!("Accepting client-connection: {}", e);
continue;
}
};
let port = match handshake::server::perform(&mut client_socket, &self.key, |port| {
self.port_strategy.contains_port(port)
})
.await
{
Ok(p) => p,
Err(e) => {
error!("Validating Client-Connection: {:?}", e);
continue;
}
};
let clients = match ports.get(&port) {
Some(c) => c.clone(),
None => {
// Create new Client-List for the Port and start a Forwarder for
// the Port as well
let tmp = Arc::new(ClientManager::new());
let fwd = match Forwarder::new(port, tmp.clone()).await {
Ok(f) => f,
Err(e) => {
log::error!("Binding Forwader: {:?}", e);
continue;
}
};
tokio::task::spawn(fwd.start());
ports.insert(port, tmp.clone());
tmp
}
};
let c_id: u32 = rand::thread_rng().gen();
info!("Accepted client: {}", c_id);
let (rx, tx) = client_socket.into_split();
let (queue_tx, queue_rx) = tokio::sync::mpsc::unbounded_channel();
let client = Client::new(c_id, clients.clone(), queue_tx);
tokio::task::spawn(Client::sender(c_id, tx, queue_rx, clients.clone()));
tokio::task::spawn(Client::receiver(
c_id,
rx,
client.get_user_cons(),
clients.clone(),
));
clients.add(client);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_server() {
assert_eq!(
Server {
listen_port: 8080,
port_strategy: Strategy::Single(12),
key: vec![2, 3, 1],
metrics: Arc::new(metrics::Empty::new()),
},
Server::new(8080, Strategy::Single(12), vec![2, 3, 1])
);
}
}