author | unC0Rr |
Mon, 02 Oct 2023 21:36:13 +0200 | |
changeset 15979 | 1635ce22b214 |
parent 15939 | 4a8e6f9d5133 |
child 15989 | fb389df02e3e |
permissions | -rw-r--r-- |
15831 | 1 |
use bytes::{Buf, Bytes}; |
2 |
use log::*; |
|
3 |
use slab::Slab; |
|
15936 | 4 |
use std::io::Error; |
5 |
use std::pin::Pin; |
|
6 |
use std::task::{Context, Poll}; |
|
13414 | 7 |
use std::{ |
15831 | 8 |
iter::Iterator, |
15832 | 9 |
net::{IpAddr, SocketAddr}, |
15800 | 10 |
time::Duration, |
13414 | 11 |
}; |
15831 | 12 |
use tokio::{ |
15936 | 13 |
io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}, |
14457 | 14 |
net::{TcpListener, TcpStream}, |
15831 | 15 |
sync::mpsc::{channel, Receiver, Sender}, |
13414 | 16 |
}; |
15936 | 17 |
#[cfg(feature = "tls-connections")] |
18 |
use tokio_native_tls::{TlsAcceptor, TlsStream}; |
|
13119 | 19 |
|
13666 | 20 |
use crate::{ |
15939 | 21 |
core::types::ClientId, |
15074 | 22 |
handlers, |
15520 | 23 |
handlers::{IoResult, IoTask, ServerState}, |
15832 | 24 |
protocol::{self, ProtocolDecoder, ProtocolError}, |
13666 | 25 |
utils, |
13414 | 26 |
}; |
15831 | 27 |
use hedgewars_network_protocol::{ |
28 |
messages::HwServerMessage::Redirect, messages::*, parser::server_message, |
|
29 |
}; |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
30 |
|
15832 | 31 |
const PING_TIMEOUT: Duration = Duration::from_secs(15); |
32 |
||
15831 | 33 |
enum ClientUpdateData { |
34 |
Message(HwProtocolMessage), |
|
35 |
Error(String), |
|
36 |
} |
|
37 |
||
38 |
struct ClientUpdate { |
|
39 |
client_id: ClientId, |
|
40 |
data: ClientUpdateData, |
|
41 |
} |
|
13414 | 42 |
|
15831 | 43 |
struct ClientUpdateSender { |
44 |
client_id: ClientId, |
|
45 |
sender: Sender<ClientUpdate>, |
|
46 |
} |
|
13119 | 47 |
|
15831 | 48 |
impl ClientUpdateSender { |
49 |
async fn send(&mut self, data: ClientUpdateData) -> bool { |
|
50 |
self.sender |
|
51 |
.send(ClientUpdate { |
|
52 |
client_id: self.client_id, |
|
53 |
data, |
|
54 |
}) |
|
55 |
.await |
|
56 |
.is_ok() |
|
57 |
} |
|
58 |
} |
|
59 |
||
15936 | 60 |
enum ClientStream { |
61 |
Tcp(TcpStream), |
|
62 |
#[cfg(feature = "tls-connections")] |
|
63 |
Tls(TlsStream<TcpStream>), |
|
64 |
} |
|
65 |
||
66 |
impl Unpin for ClientStream {} |
|
67 |
||
68 |
impl AsyncRead for ClientStream { |
|
69 |
fn poll_read( |
|
70 |
self: Pin<&mut Self>, |
|
71 |
cx: &mut Context<'_>, |
|
72 |
buf: &mut ReadBuf<'_>, |
|
73 |
) -> Poll<std::io::Result<()>> { |
|
74 |
use ClientStream::*; |
|
75 |
match Pin::into_inner(self) { |
|
76 |
Tcp(stream) => Pin::new(stream).poll_read(cx, buf), |
|
77 |
#[cfg(feature = "tls-connections")] |
|
78 |
Tls(stream) => Pin::new(stream).poll_read(cx, buf), |
|
79 |
} |
|
80 |
} |
|
81 |
} |
|
82 |
||
83 |
impl AsyncWrite for ClientStream { |
|
84 |
fn poll_write( |
|
85 |
self: Pin<&mut Self>, |
|
86 |
cx: &mut Context<'_>, |
|
87 |
buf: &[u8], |
|
88 |
) -> Poll<Result<usize, Error>> { |
|
89 |
use ClientStream::*; |
|
90 |
match Pin::into_inner(self) { |
|
91 |
Tcp(stream) => Pin::new(stream).poll_write(cx, buf), |
|
92 |
#[cfg(feature = "tls-connections")] |
|
93 |
Tls(stream) => Pin::new(stream).poll_write(cx, buf), |
|
94 |
} |
|
95 |
} |
|
96 |
||
97 |
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> { |
|
98 |
use ClientStream::*; |
|
99 |
match Pin::into_inner(self) { |
|
100 |
Tcp(stream) => Pin::new(stream).poll_flush(cx), |
|
101 |
#[cfg(feature = "tls-connections")] |
|
102 |
Tls(stream) => Pin::new(stream).poll_flush(cx), |
|
103 |
} |
|
104 |
} |
|
105 |
||
106 |
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> { |
|
107 |
use ClientStream::*; |
|
108 |
match Pin::into_inner(self) { |
|
109 |
Tcp(stream) => Pin::new(stream).poll_shutdown(cx), |
|
110 |
#[cfg(feature = "tls-connections")] |
|
111 |
Tls(stream) => Pin::new(stream).poll_shutdown(cx), |
|
112 |
} |
|
113 |
} |
|
114 |
} |
|
115 |
||
15831 | 116 |
struct NetworkClient { |
117 |
id: ClientId, |
|
15936 | 118 |
stream: ClientStream, |
15831 | 119 |
receiver: Receiver<Bytes>, |
120 |
peer_addr: SocketAddr, |
|
121 |
decoder: ProtocolDecoder, |
|
13414 | 122 |
} |
123 |
||
15831 | 124 |
impl NetworkClient { |
125 |
fn new( |
|
126 |
id: ClientId, |
|
15936 | 127 |
stream: ClientStream, |
15831 | 128 |
peer_addr: SocketAddr, |
129 |
receiver: Receiver<Bytes>, |
|
130 |
) -> Self { |
|
131 |
Self { |
|
132 |
id, |
|
15936 | 133 |
stream, |
15831 | 134 |
peer_addr, |
135 |
receiver, |
|
15832 | 136 |
decoder: ProtocolDecoder::new(PING_TIMEOUT), |
15831 | 137 |
} |
138 |
} |
|
13119 | 139 |
|
15936 | 140 |
async fn read<T: AsyncRead + AsyncWrite + Unpin>( |
141 |
stream: &mut T, |
|
15832 | 142 |
decoder: &mut ProtocolDecoder, |
143 |
) -> protocol::Result<HwProtocolMessage> { |
|
15936 | 144 |
let result = decoder.read_from(stream).await; |
15832 | 145 |
if matches!(result, Err(ProtocolError::Timeout)) { |
15936 | 146 |
if Self::write(stream, Bytes::from(HwServerMessage::Ping.to_raw_protocol())).await { |
147 |
decoder.read_from(stream).await |
|
15832 | 148 |
} else { |
149 |
Err(ProtocolError::Eof) |
|
150 |
} |
|
151 |
} else { |
|
152 |
result |
|
153 |
} |
|
15831 | 154 |
} |
155 |
||
15936 | 156 |
async fn write<T: AsyncWrite + Unpin>(stream: &mut T, mut data: Bytes) -> bool { |
157 |
!data.has_remaining() || matches!(stream.write_buf(&mut data).await, Ok(n) if n > 0) |
|
15831 | 158 |
} |
13799 | 159 |
|
15831 | 160 |
async fn run(mut self, sender: Sender<ClientUpdate>) { |
161 |
use ClientUpdateData::*; |
|
162 |
let mut sender = ClientUpdateSender { |
|
163 |
client_id: self.id, |
|
164 |
sender, |
|
165 |
}; |
|
166 |
||
167 |
loop { |
|
168 |
tokio::select! { |
|
169 |
server_message = self.receiver.recv() => { |
|
170 |
match server_message { |
|
15936 | 171 |
Some(message) => if !Self::write(&mut self.stream, message).await { |
15831 | 172 |
sender.send(Error("Connection reset by peer".to_string())).await; |
173 |
break; |
|
174 |
} |
|
175 |
None => { |
|
176 |
break; |
|
177 |
} |
|
178 |
} |
|
179 |
} |
|
15936 | 180 |
client_message = Self::read(&mut self.stream, &mut self.decoder) => { |
15831 | 181 |
match client_message { |
15832 | 182 |
Ok(message) => { |
15831 | 183 |
if !sender.send(Message(message)).await { |
184 |
break; |
|
185 |
} |
|
186 |
} |
|
15832 | 187 |
Err(e) => { |
15938 | 188 |
todo!("send cmdline errors"); |
15832 | 189 |
sender.send(Error(format!("{}", e))).await; |
190 |
if matches!(e, ProtocolError::Timeout) { |
|
15936 | 191 |
Self::write(&mut self.stream, Bytes::from(HwServerMessage::Bye("Ping timeout".to_string()).to_raw_protocol())).await; |
15832 | 192 |
} |
15831 | 193 |
break; |
194 |
} |
|
195 |
} |
|
196 |
} |
|
197 |
} |
|
13799 | 198 |
} |
199 |
} |
|
200 |
} |
|
201 |
||
15936 | 202 |
#[cfg(feature = "tls-connections")] |
203 |
struct TlsListener { |
|
204 |
listener: TcpListener, |
|
205 |
acceptor: TlsAcceptor, |
|
206 |
} |
|
207 |
||
15831 | 208 |
pub struct NetworkLayer { |
209 |
listener: TcpListener, |
|
15936 | 210 |
#[cfg(feature = "tls-connections")] |
211 |
tls: TlsListener, |
|
15831 | 212 |
server_state: ServerState, |
213 |
clients: Slab<Sender<Bytes>>, |
|
13119 | 214 |
} |
215 |
||
15831 | 216 |
impl NetworkLayer { |
217 |
pub async fn run(&mut self) { |
|
218 |
let (update_tx, mut update_rx) = channel(128); |
|
13119 | 219 |
|
15936 | 220 |
async fn accept_plain_branch( |
221 |
layer: &mut NetworkLayer, |
|
222 |
value: (TcpStream, SocketAddr), |
|
223 |
update_tx: Sender<ClientUpdate>, |
|
224 |
) { |
|
225 |
let (stream, addr) = value; |
|
226 |
if let Some(client) = layer.create_client(ClientStream::Tcp(stream), addr).await { |
|
227 |
tokio::spawn(client.run(update_tx)); |
|
228 |
} |
|
229 |
} |
|
230 |
||
231 |
#[cfg(feature = "tls-connections")] |
|
232 |
async fn accept_tls_branch( |
|
233 |
layer: &mut NetworkLayer, |
|
234 |
value: (TcpStream, SocketAddr), |
|
235 |
update_tx: Sender<ClientUpdate>, |
|
236 |
) { |
|
237 |
let (stream, addr) = value; |
|
238 |
match layer.tls.acceptor.accept(stream).await { |
|
239 |
Ok(stream) => { |
|
240 |
if let Some(client) = layer.create_client(ClientStream::Tls(stream), addr).await |
|
241 |
{ |
|
15937 | 242 |
tokio::spawn(client.run(update_tx)); |
15831 | 243 |
} |
244 |
} |
|
15936 | 245 |
Err(e) => { |
246 |
warn!("Unable to establish TLS connection: {}", e); |
|
247 |
} |
|
248 |
} |
|
249 |
} |
|
250 |
||
251 |
async fn client_message_branch( |
|
252 |
layer: &mut NetworkLayer, |
|
253 |
client_message: Option<ClientUpdate>, |
|
254 |
) { |
|
255 |
use ClientUpdateData::*; |
|
256 |
match client_message { |
|
257 |
Some(ClientUpdate { |
|
258 |
client_id, |
|
259 |
data: Message(message), |
|
260 |
}) => { |
|
261 |
layer.handle_message(client_id, message).await; |
|
15831 | 262 |
} |
15936 | 263 |
Some(ClientUpdate { |
264 |
client_id, |
|
265 |
data: Error(e), |
|
266 |
}) => { |
|
267 |
let mut response = handlers::Response::new(client_id); |
|
268 |
info!("Client {} error: {:?}", client_id, e); |
|
269 |
response.remove_client(client_id); |
|
270 |
handlers::handle_client_loss(&mut layer.server_state, client_id, &mut response); |
|
271 |
layer.handle_response(response).await; |
|
272 |
} |
|
273 |
None => unreachable!(), |
|
274 |
} |
|
275 |
} |
|
276 |
||
15938 | 277 |
todo!("add the DB task"); |
278 |
todo!("add certfile watcher task"); |
|
15936 | 279 |
loop { |
280 |
#[cfg(not(feature = "tls-connections"))] |
|
281 |
tokio::select! { |
|
282 |
Ok(value) = self.listener.accept() => accept_plain_branch(self, value, update_tx.clone()).await, |
|
283 |
client_message = update_rx.recv(), if !self.clients.is_empty() => client_message_branch(self, client_message).await |
|
284 |
} |
|
285 |
||
286 |
#[cfg(feature = "tls-connections")] |
|
287 |
tokio::select! { |
|
288 |
Ok(value) = self.listener.accept() => accept_plain_branch(self, value, update_tx.clone()).await, |
|
289 |
Ok(value) = self.tls.listener.accept() => accept_tls_branch(self, value, update_tx.clone()).await, |
|
290 |
client_message = update_rx.recv(), if !self.clients.is_empty() => client_message_branch(self, client_message).await |
|
13802 | 291 |
} |
292 |
} |
|
293 |
} |
|
294 |
||
15831 | 295 |
async fn create_client( |
296 |
&mut self, |
|
15936 | 297 |
stream: ClientStream, |
15831 | 298 |
addr: SocketAddr, |
299 |
) -> Option<NetworkClient> { |
|
300 |
let entry = self.clients.vacant_entry(); |
|
301 |
let client_id = entry.key(); |
|
302 |
let (tx, rx) = channel(16); |
|
303 |
entry.insert(tx); |
|
304 |
||
305 |
let client = NetworkClient::new(client_id, stream, addr, rx); |
|
13414 | 306 |
|
15831 | 307 |
info!("client {} ({}) added", client.id, client.peer_addr); |
308 |
||
309 |
let mut response = handlers::Response::new(client_id); |
|
310 |
||
311 |
let added = if let IpAddr::V4(addr) = client.peer_addr.ip() { |
|
312 |
handlers::handle_client_accept( |
|
313 |
&mut self.server_state, |
|
314 |
client_id, |
|
315 |
&mut response, |
|
316 |
addr.octets(), |
|
317 |
addr.is_loopback(), |
|
318 |
) |
|
319 |
} else { |
|
320 |
todo!("implement something") |
|
15800 | 321 |
}; |
322 |
||
15831 | 323 |
self.handle_response(response).await; |
13414 | 324 |
|
15831 | 325 |
if added { |
326 |
Some(client) |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
327 |
} else { |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
328 |
None |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
329 |
} |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
330 |
} |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14697
diff
changeset
|
331 |
|
15831 | 332 |
async fn handle_message(&mut self, client_id: ClientId, message: HwProtocolMessage) { |
333 |
debug!("Handling message {:?} for client {}", message, client_id); |
|
334 |
let mut response = handlers::Response::new(client_id); |
|
335 |
handlers::handle(&mut self.server_state, client_id, &mut response, message); |
|
336 |
self.handle_response(response).await; |
|
13119 | 337 |
} |
338 |
||
15831 | 339 |
async fn handle_response(&mut self, mut response: handlers::Response) { |
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
340 |
if response.is_empty() { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
341 |
return; |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
342 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
343 |
|
14672
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14671
diff
changeset
|
344 |
debug!("{} pending server messages", response.len()); |
15520 | 345 |
let output = response.extract_messages(&mut self.server_state.server); |
14672
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14671
diff
changeset
|
346 |
for (clients, message) in output { |
13419 | 347 |
debug!("Message {:?} to {:?}", message, clients); |
15831 | 348 |
Self::send_message(&mut self.clients, message, clients.iter().cloned()).await; |
13414 | 349 |
} |
14696 | 350 |
|
351 |
for client_id in response.extract_removed_clients() { |
|
15831 | 352 |
if self.clients.contains(client_id) { |
353 |
self.clients.remove(client_id); |
|
14803 | 354 |
} |
15831 | 355 |
info!("Client {} removed", client_id); |
15517 | 356 |
} |
14835 | 357 |
} |
358 |
||
15831 | 359 |
async fn send_message<I>( |
360 |
clients: &mut Slab<Sender<Bytes>>, |
|
361 |
message: HwServerMessage, |
|
362 |
to_clients: I, |
|
363 |
) where |
|
364 |
I: Iterator<Item = ClientId>, |
|
365 |
{ |
|
366 |
let msg_string = message.to_raw_protocol(); |
|
367 |
let bytes = Bytes::copy_from_slice(msg_string.as_bytes()); |
|
368 |
for client_id in to_clients { |
|
369 |
if let Some(client) = clients.get_mut(client_id) { |
|
370 |
if !client.send(bytes.clone()).await.is_ok() { |
|
371 |
clients.remove(client_id); |
|
13414 | 372 |
} |
14457 | 373 |
} |
13119 | 374 |
} |
13414 | 375 |
} |
13119 | 376 |
} |
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
377 |
|
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
378 |
pub struct NetworkLayerBuilder { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
379 |
listener: Option<TcpListener>, |
15936 | 380 |
#[cfg(feature = "tls-connections")] |
381 |
tls_listener: Option<TcpListener>, |
|
382 |
#[cfg(feature = "tls-connections")] |
|
383 |
tls_acceptor: Option<TlsAcceptor>, |
|
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
384 |
clients_capacity: usize, |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
385 |
rooms_capacity: usize, |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
386 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
387 |
|
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
388 |
impl Default for NetworkLayerBuilder { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
389 |
fn default() -> Self { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
390 |
Self { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
391 |
clients_capacity: 1024, |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
392 |
rooms_capacity: 512, |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
393 |
listener: None, |
15936 | 394 |
#[cfg(feature = "tls-connections")] |
395 |
tls_listener: None, |
|
396 |
#[cfg(feature = "tls-connections")] |
|
397 |
tls_acceptor: None, |
|
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
398 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
399 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
400 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
401 |
|
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
402 |
impl NetworkLayerBuilder { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
403 |
pub fn with_listener(self, listener: TcpListener) -> Self { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
404 |
Self { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
405 |
listener: Some(listener), |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
406 |
..self |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
407 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
408 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
409 |
|
15936 | 410 |
#[cfg(feature = "tls-connections")] |
411 |
pub fn with_tls_acceptor(self, listener: TlsAcceptor) -> Self { |
|
412 |
Self { |
|
413 |
tls_acceptor: Option::from(listener), |
|
414 |
..self |
|
415 |
} |
|
416 |
} |
|
417 |
||
418 |
#[cfg(feature = "tls-connections")] |
|
419 |
pub fn with_tls_listener(self, listener: TlsAcceptor) -> Self { |
|
420 |
Self { |
|
421 |
tls_acceptor: Option::from(listener), |
|
422 |
..self |
|
423 |
} |
|
424 |
} |
|
425 |
||
15831 | 426 |
pub fn build(self) -> NetworkLayer { |
15520 | 427 |
let server_state = ServerState::new(self.clients_capacity, self.rooms_capacity); |
428 |
||
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
429 |
let clients = Slab::with_capacity(self.clients_capacity); |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
430 |
|
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
431 |
NetworkLayer { |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
432 |
listener: self.listener.expect("No listener provided"), |
15936 | 433 |
#[cfg(feature = "tls-connections")] |
434 |
tls: TlsListener { |
|
435 |
listener: self.tls_listener.expect("No TLS listener provided"), |
|
436 |
acceptor: self.tls_acceptor.expect("No TLS acceptor provided"), |
|
437 |
}, |
|
15520 | 438 |
server_state, |
14830
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
439 |
clients, |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
440 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
441 |
} |
8ddb5842fe0b
allow running plaintext and tls servers in parallel
alfadur
parents:
14807
diff
changeset
|
442 |
} |