Skip to main content

tokio_quiche/socket/
listener.rs

1// Copyright (C) 2025, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use std::fmt;
28use std::io;
29#[cfg(unix)]
30use std::os::fd::AsFd;
31#[cfg(unix)]
32use std::os::fd::AsRawFd;
33#[cfg(unix)]
34use std::os::fd::BorrowedFd;
35#[cfg(unix)]
36use std::os::fd::RawFd;
37use std::sync::Arc;
38use tokio::net::UdpSocket;
39
40use super::SocketCapabilities;
41use crate::quic::SimpleConnectionIdGenerator;
42use crate::ConnectionIdGenerator;
43
44/// Wrapper around a [`UdpSocket`] for server-side QUIC connections.
45///
46/// The wrapper carries socket-specific parameters, in contrast to the
47/// [`settings`](crate::settings) structs which apply to _all_ sockets
48/// for a given QUIC server.
49///
50/// To create a [`QuicListener`], you may either instantiate the struct yourself
51/// or use one of the `TryFrom` implementations.
52pub struct QuicListener {
53    /// The wrapped [tokio] socket.
54    pub socket: UdpSocket,
55    /// The [`ConnectionIdGenerator`] to use for connections arriving on this
56    /// socket. This can be one shared instance for all sockets, but
57    /// socket-specific ID generators are also possible.
58    pub cid_generator: Arc<dyn ConnectionIdGenerator<'static>>,
59    /// The [`SocketCapabilities`] to use for this socket.
60    ///
61    /// By default, [`QuicListener`]s are constructed with all capabilities
62    /// disabled. On Linux, you can use `apply_max_capabilities()` to (try
63    /// to) enable all supported capabilities.
64    pub capabilities: SocketCapabilities,
65}
66
67impl QuicListener {
68    /// Tries to enable all sockopts supported by the crate for this socket.
69    /// See `SocketCapabilities::apply_all_and_get_compatibility` for details.
70    #[cfg(target_os = "linux")]
71    pub fn apply_max_capabilities(&mut self) {
72        let capabilities =
73            SocketCapabilities::apply_all_and_get_compatibility(&self.socket);
74        self.capabilities = capabilities;
75    }
76}
77
78impl fmt::Debug for QuicListener {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        f.debug_struct("QuicListener")
81            .field("socket", &self.socket)
82            .field("cid_generator", &"dyn ConnectionIdGenerator")
83            .field("capabilities", &self.capabilities)
84            .finish()
85    }
86}
87
88impl TryFrom<UdpSocket> for QuicListener {
89    type Error = io::Error;
90
91    fn try_from(socket: UdpSocket) -> Result<Self, Self::Error> {
92        Ok(Self {
93            socket,
94            cid_generator: Arc::new(SimpleConnectionIdGenerator),
95            capabilities: SocketCapabilities::default(),
96        })
97    }
98}
99
100impl TryFrom<std::net::UdpSocket> for QuicListener {
101    type Error = io::Error;
102
103    fn try_from(socket: std::net::UdpSocket) -> Result<Self, Self::Error> {
104        socket.set_nonblocking(true)?;
105        let socket = UdpSocket::from_std(socket)?;
106        Self::try_from(socket)
107    }
108}
109
110#[cfg(unix)]
111impl AsFd for QuicListener {
112    fn as_fd(&self) -> BorrowedFd<'_> {
113        self.socket.as_fd()
114    }
115}
116
117#[cfg(unix)]
118impl AsRawFd for QuicListener {
119    fn as_raw_fd(&self) -> RawFd {
120        self.socket.as_raw_fd()
121    }
122}