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;