Skip to main content

kcp_tokio/
transport.rs

1//! Abstract transport layer for KCP
2//!
3//! The [`Transport`] trait allows KCP to run over any async datagram transport,
4//! not just UDP. Enable the `tokio` feature (on by default) for the built-in
5//! [`UdpTransport`] implementation backed by `tokio::net::UdpSocket`.
6
7use std::fmt::{Debug, Display};
8use std::future::Future;
9use std::hash::Hash;
10use std::io;
11
12/// Marker trait for address types used by [`Transport`] implementations.
13///
14/// Any type satisfying the required bounds automatically implements `Addr`
15/// via the blanket impl. This keeps bound lists short elsewhere.
16pub trait Addr: Clone + Eq + Hash + Send + Sync + Debug + Display + 'static {}
17
18impl<T: Clone + Eq + Hash + Send + Sync + Debug + Display + 'static> Addr for T {}
19
20/// Async datagram transport used by [`KcpStream`](crate::stream::KcpStream)
21/// and [`KcpListener`](crate::listener::KcpListener).
22///
23/// Implementors provide send/receive operations addressed by an associated
24/// [`Addr`] type. The built-in [`UdpTransport`] uses `SocketAddr`.
25pub trait Transport: Send + Sync + 'static {
26    /// The address type used to identify endpoints.
27    type Addr: Addr;
28
29    /// Send `buf` to `target`, returning the number of bytes written.
30    fn send_to<'a>(
31        &'a self,
32        buf: &'a [u8],
33        target: &'a Self::Addr,
34    ) -> impl Future<Output = io::Result<usize>> + Send + 'a;
35
36    /// Receive a datagram into `buf`, returning `(bytes_read, source_address)`.
37    fn recv_from<'a>(
38        &'a self,
39        buf: &'a mut [u8],
40    ) -> impl Future<Output = io::Result<(usize, Self::Addr)>> + Send + 'a;
41
42    /// Return the local address this transport is bound to.
43    fn local_addr(&self) -> io::Result<Self::Addr>;
44}
45
46// ---------------------------------------------------------------------------
47// UdpTransport — default implementation backed by tokio::net::UdpSocket
48// ---------------------------------------------------------------------------
49
50#[cfg(feature = "tokio")]
51mod udp {
52    use super::*;
53    use std::net::SocketAddr;
54    use tokio::net::UdpSocket;
55
56    /// Default [`Transport`] implementation wrapping a `tokio::net::UdpSocket`.
57    pub struct UdpTransport {
58        socket: UdpSocket,
59    }
60
61    impl UdpTransport {
62        /// Bind a new UDP socket to `addr`.
63        pub async fn bind(addr: impl tokio::net::ToSocketAddrs) -> io::Result<Self> {
64            let socket = UdpSocket::bind(addr).await?;
65            Ok(Self { socket })
66        }
67
68        /// Wrap an existing `UdpSocket`.
69        pub fn new(socket: UdpSocket) -> Self {
70            Self { socket }
71        }
72    }
73
74    impl Transport for UdpTransport {
75        type Addr = SocketAddr;
76
77        async fn send_to(&self, buf: &[u8], target: &SocketAddr) -> io::Result<usize> {
78            self.socket.send_to(buf, target).await
79        }
80
81        async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
82            self.socket.recv_from(buf).await
83        }
84
85        fn local_addr(&self) -> io::Result<SocketAddr> {
86            self.socket.local_addr()
87        }
88    }
89}
90
91#[cfg(feature = "tokio")]
92pub use udp::UdpTransport;