1use std::{future::Future, marker::PhantomData, sync::Arc, time::Duration};
2
3use log::{debug, error, info};
4
5use karyon_core::{
6 async_runtime::Executor,
7 async_util::{timeout, TaskGroup, TaskResult},
8 crypto::KeyPair,
9};
10use karyon_net::{
11 codec::Codec,
12 framed,
13 tcp::TcpListener,
14 tls::{ServerTlsConfig, TlsLayer},
15 ByteBuffer, ByteStream, Endpoint, FramedConn, ServerLayer,
16};
17
18use crate::{
19 access_control::{AccessControl, Action, Subject},
20 codec::PeerNetMsgCodec,
21 conn_queue::ConnQueue,
22 monitor::{ConnectionKind, Monitor},
23 peer::ConnDirection,
24 slots::ConnectionSlots,
25 tls_config::{peer_id_from_certs, tls_server_config},
26 Error, PeerID, Result,
27};
28
29enum StreamListener {
33 Tcp(TcpListener),
34 Tls(TcpListener, Box<TlsLayer>),
35}
36
37impl StreamListener {
38 async fn accept(&self) -> Result<Box<dyn ByteStream>> {
40 match self {
41 Self::Tcp(l) | Self::Tls(l, _) => Ok(l.accept().await?),
42 }
43 }
44
45 async fn handshake(
47 &self,
48 stream: Box<dyn ByteStream>,
49 handshake_timeout: Duration,
50 ) -> Result<Box<dyn ByteStream>> {
51 match self {
52 Self::Tcp(_) => Ok(stream),
53 Self::Tls(_, layer) => Ok(timeout(
54 handshake_timeout,
55 ServerLayer::handshake(layer.as_ref(), stream),
56 )
57 .await??),
58 }
59 }
60
61 fn local_endpoint(&self) -> Result<Endpoint> {
62 match self {
63 Self::Tcp(l) => Ok(l.local_endpoint()?),
64 Self::Tls(l, _) => {
67 let ep = l.local_endpoint()?;
68 Ok(Endpoint::Tls(ep.addr()?, ep.port()?))
69 }
70 }
71 }
72}
73
74#[cfg(feature = "quic")]
75use karyon_net::{quic, StreamMux};
76
77pub struct Listener<C: Codec<ByteBuffer> + Default + Clone> {
82 key_pair: KeyPair,
83 task_group: TaskGroup,
84 connection_slots: Arc<ConnectionSlots>,
85 conn_queue: Option<Arc<ConnQueue>>,
86 monitor: Arc<Monitor>,
87 handshake_timeout: Duration,
88 access_control: Arc<dyn AccessControl>,
89 _codec: PhantomData<C>,
90}
91
92impl<C> Listener<C>
93where
94 C: Codec<ByteBuffer, Error = karyon_net::Error> + Default + Clone + Send + Sync + 'static,
95{
96 pub fn new(
99 key_pair: &KeyPair,
100 connection_slots: Arc<ConnectionSlots>,
101 monitor: Arc<Monitor>,
102 handshake_timeout: u64,
103 access_control: Arc<dyn AccessControl>,
104 ex: Executor,
105 ) -> Arc<Self> {
106 Arc::new(Self {
107 key_pair: key_pair.clone(),
108 connection_slots,
109 conn_queue: None,
110 task_group: TaskGroup::with_executor(ex),
111 monitor,
112 handshake_timeout: Duration::from_secs(handshake_timeout),
113 access_control,
114 _codec: PhantomData,
115 })
116 }
117
118 pub async fn start_with_callback<Fut>(
120 self: &Arc<Self>,
121 endpoint: Endpoint,
122 callback: impl FnOnce(FramedConn<C>) -> Fut + Clone + Send + 'static,
123 ) -> Result<Endpoint>
124 where
125 Fut: Future<Output = Result<()>> + Send + 'static,
126 {
127 let listener = match self.listen(&endpoint).await {
128 Ok(l) => {
129 self.monitor
130 .notify(ConnectionKind::Listening(endpoint.clone()))
131 .await;
132 l
133 }
134 Err(err) => {
135 error!("Failed to listen on {endpoint}: {err}");
136 self.monitor
137 .notify(ConnectionKind::ListenFailed(endpoint))
138 .await;
139 return Err(err);
140 }
141 };
142
143 let resolved = listener.local_endpoint()?;
144 info!("Start listening on {resolved}");
145
146 self.task_group.spawn_then(
147 {
148 let this = self.clone();
149 async move {
150 this.listen_loop_callback(Arc::new(listener), callback)
151 .await
152 }
153 },
154 |res: TaskResult<()>| async move {
155 debug!("Listener callback loop ended: {res}");
156 },
157 );
158 Ok(resolved)
159 }
160
161 pub async fn shutdown(&self) {
162 self.task_group.cancel().await;
163 }
164
165 async fn upgrade(
168 &self,
169 listener: &StreamListener,
170 stream: Box<dyn ByteStream>,
171 ) -> Result<(FramedConn<C>, Option<PeerID>)> {
172 let stream = listener.handshake(stream, self.handshake_timeout).await?;
173 let vpid = stream
175 .peer_certificates()
176 .as_deref()
177 .and_then(peer_id_from_certs);
178 Ok((framed(stream, C::default()), vpid))
179 }
180
181 async fn listen_loop_callback<Fut>(
183 self: Arc<Self>,
184 listener: Arc<StreamListener>,
185 callback: impl FnOnce(FramedConn<C>) -> Fut + Clone + Send + 'static,
186 ) where
187 Fut: Future<Output = Result<()>> + Send + 'static,
188 {
189 loop {
190 self.connection_slots.wait_for_slot().await;
191
192 let stream = match listener.accept().await {
193 Ok(s) => s,
194 Err(err) => {
195 error!("Failed to accept connection: {err}");
196 self.monitor.notify(ConnectionKind::AcceptFailed).await;
197 continue;
198 }
199 };
200
201 let endpoint = match stream.peer_endpoint() {
202 Some(ep) => ep,
203 None => {
204 self.monitor.notify(ConnectionKind::AcceptFailed).await;
205 error!("Failed to get peer endpoint");
206 continue;
207 }
208 };
209
210 if !self.access_control.allow(
212 &Subject::Endpoint(&endpoint),
213 Action::Lookup(ConnDirection::Inbound),
214 ) {
215 debug!("Rejected inbound lookup connection from {endpoint}");
216 continue;
217 }
218
219 self.monitor
220 .notify(ConnectionKind::Accepted(endpoint.clone()))
221 .await;
222 self.connection_slots.add();
225
226 let on_disconnect = {
227 let this = self.clone();
228 |res| async move {
229 if let TaskResult::Completed(Err(err)) = res {
230 debug!("Inbound connection dropped: {err}");
231 }
232 this.monitor
233 .notify(ConnectionKind::Disconnected(endpoint))
234 .await;
235 this.connection_slots.remove().await;
236 }
237 };
238
239 let this = self.clone();
240 let listener = listener.clone();
241 let callback = callback.clone();
242 self.task_group.spawn_then(
243 async move {
244 let (conn, _) = this.upgrade(&listener, stream).await?;
245 callback(conn).await
246 },
247 on_disconnect,
248 );
249 }
250 }
251
252 async fn listen(&self, endpoint: &Endpoint) -> Result<StreamListener> {
254 match endpoint {
255 Endpoint::Tcp(..) => {
256 let listener = TcpListener::bind(endpoint, Default::default()).await?;
257 Ok(StreamListener::Tcp(listener))
258 }
259 Endpoint::Tls(..) => {
260 let tls_config = ServerTlsConfig {
261 server_config: tls_server_config(&self.key_pair)?,
262 };
263 let tcp_listener = TcpListener::bind(endpoint, Default::default()).await?;
264 Ok(StreamListener::Tls(
265 tcp_listener,
266 Box::new(TlsLayer::server(tls_config)),
267 ))
268 }
269 _ => Err(Error::UnsupportedEndpoint(endpoint.to_string())),
270 }
271 }
272}
273
274impl Listener<PeerNetMsgCodec> {
278 pub fn new_with_queue(
281 key_pair: &KeyPair,
282 connection_slots: Arc<ConnectionSlots>,
283 conn_queue: Arc<ConnQueue>,
284 monitor: Arc<Monitor>,
285 handshake_timeout: u64,
286 access_control: Arc<dyn AccessControl>,
287 ex: Executor,
288 ) -> Arc<Self> {
289 Arc::new(Self {
290 key_pair: key_pair.clone(),
291 connection_slots,
292 conn_queue: Some(conn_queue),
293 task_group: TaskGroup::with_executor(ex),
294 monitor,
295 handshake_timeout: Duration::from_secs(handshake_timeout),
296 access_control,
297 _codec: PhantomData,
298 })
299 }
300
301 pub async fn start(self: &Arc<Self>, endpoint: Endpoint) -> Result<Endpoint> {
303 #[cfg(feature = "quic")]
304 if endpoint.is_quic() {
305 return self.start_quic(endpoint).await;
306 }
307
308 let listener = match self.listen(&endpoint).await {
309 Ok(l) => {
310 self.monitor
311 .notify(ConnectionKind::Listening(endpoint.clone()))
312 .await;
313 l
314 }
315 Err(err) => {
316 error!("Failed to listen on {endpoint}: {err}");
317 self.monitor
318 .notify(ConnectionKind::ListenFailed(endpoint))
319 .await;
320 return Err(err);
321 }
322 };
323
324 let resolved = listener.local_endpoint()?;
325 info!("Start listening on {resolved}");
326
327 self.task_group.spawn({
328 let this = self.clone();
329 async move { this.listen_loop(Arc::new(listener)).await }
330 });
331 Ok(resolved)
332 }
333
334 async fn listen_loop(self: Arc<Self>, listener: Arc<StreamListener>) {
336 let conn_queue = self
337 .conn_queue
338 .as_ref()
339 .expect("listen_loop requires ConnQueue")
340 .clone();
341
342 loop {
343 self.connection_slots.wait_for_slot().await;
344
345 let stream = match listener.accept().await {
346 Ok(s) => s,
347 Err(err) => {
348 error!("Failed to accept connection: {err}");
349 self.monitor.notify(ConnectionKind::AcceptFailed).await;
350 continue;
351 }
352 };
353
354 let endpoint = match stream.peer_endpoint() {
355 Some(ep) => ep,
356 None => {
357 self.monitor.notify(ConnectionKind::AcceptFailed).await;
358 error!("Failed to get peer endpoint");
359 continue;
360 }
361 };
362
363 if !self.access_control.allow(
364 &Subject::Endpoint(&endpoint),
365 Action::Connect(ConnDirection::Inbound),
366 ) {
367 debug!("Rejected inbound connection from {endpoint}");
368 continue;
369 }
370
371 self.monitor
372 .notify(ConnectionKind::Accepted(endpoint.clone()))
373 .await;
374
375 self.connection_slots.add();
376
377 let on_disconnect = {
378 let this = self.clone();
379 |res: TaskResult<Result<()>>| async move {
380 if let TaskResult::Completed(Err(err)) = res {
381 debug!("Inbound connection dropped: {err}");
382 }
383 this.monitor
384 .notify(ConnectionKind::Disconnected(endpoint))
385 .await;
386 this.connection_slots.remove().await;
387 }
388 };
389
390 let cq = conn_queue.clone();
391 let this = self.clone();
392 let listener = listener.clone();
393 self.task_group.spawn_then(
394 async move {
395 let (conn, vpid) = this.upgrade(&listener, stream).await?;
396 cq.handle(conn, ConnDirection::Inbound, vpid).await?;
397 Ok(())
398 },
399 on_disconnect,
400 );
401 }
402 }
403
404 #[cfg(feature = "quic")]
406 async fn start_quic(self: &Arc<Self>, endpoint: Endpoint) -> Result<Endpoint> {
407 let rustls_config = tls_server_config(&self.key_pair)?;
408 let server_config = quic::ServerQuicConfig::from_rustls(rustls_config);
409
410 let quic_endpoint = match quic::QuicEndpoint::listen(&endpoint, server_config).await {
411 Ok(ep) => {
412 self.monitor
413 .notify(ConnectionKind::Listening(endpoint.clone()))
414 .await;
415 ep
416 }
417 Err(err) => {
418 error!("Failed to listen on {endpoint}: {err}");
419 self.monitor
420 .notify(ConnectionKind::ListenFailed(endpoint))
421 .await;
422 return Err(err.into());
423 }
424 };
425
426 let resolved: Endpoint = quic_endpoint.local_endpoint().map_err(Error::from)?;
427 info!("Start listening on {resolved}");
428
429 self.task_group.spawn_then(
430 {
431 let this = self.clone();
432 async move { this.listen_loop_quic(quic_endpoint).await }
433 },
434 |res: TaskResult<()>| async move {
435 debug!("QUIC listen loop ended: {res}");
436 },
437 );
438
439 Ok(resolved)
440 }
441
442 #[cfg(feature = "quic")]
444 async fn listen_loop_quic(self: Arc<Self>, quic_endpoint: quic::QuicEndpoint) {
445 loop {
446 self.connection_slots.wait_for_slot().await;
447
448 let incoming = match quic_endpoint.accept_incoming().await {
452 Ok(c) => c,
453 Err(err) => {
454 error!("Failed to accept QUIC conn: {err}");
455 self.monitor.notify(ConnectionKind::AcceptFailed).await;
456 continue;
457 }
458 };
459
460 let peer_ep = incoming.peer_endpoint();
461
462 if !self.access_control.allow(
463 &Subject::Endpoint(&peer_ep),
464 Action::Connect(ConnDirection::Inbound),
465 ) {
466 debug!("Rejected inbound QUIC connection from {peer_ep}");
467 continue;
468 }
469
470 self.monitor
471 .notify(ConnectionKind::Accepted(peer_ep.clone()))
472 .await;
473
474 self.connection_slots.add();
475
476 let on_disconnect = {
477 let this = self.clone();
478 |res: TaskResult<Result<()>>| async move {
479 if let TaskResult::Completed(Err(err)) = res {
480 debug!("Inbound QUIC conn dropped: {err}");
481 }
482 this.monitor
483 .notify(ConnectionKind::Disconnected(peer_ep))
484 .await;
485 this.connection_slots.remove().await;
486 }
487 };
488
489 let conn_queue = self
490 .conn_queue
491 .as_ref()
492 .expect("QUIC listener requires ConnQueue")
493 .clone();
494 let handshake_timeout = self.handshake_timeout;
495 self.task_group.spawn_then(
496 async move {
497 let quic_conn = timeout(handshake_timeout, incoming.handshake()).await??;
500 let vpid = quic_conn
501 .peer_certificates()
502 .as_deref()
503 .and_then(peer_id_from_certs);
504 let stream = timeout(handshake_timeout, quic_conn.accept_stream()).await??;
507 let conn: FramedConn<PeerNetMsgCodec> = framed(stream, PeerNetMsgCodec::new());
508 conn_queue
509 .handle_quic(conn, quic_conn, ConnDirection::Inbound, vpid)
510 .await?;
511 Ok(())
512 },
513 on_disconnect,
514 );
515 }
516 }
517}