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::io;
28#[cfg(unix)]
29use std::os::fd::AsFd;
30#[cfg(unix)]
31use std::os::fd::AsRawFd;
32#[cfg(unix)]
33use std::os::fd::BorrowedFd;
34#[cfg(unix)]
35use std::os::fd::RawFd;
36use tokio::net::UdpSocket;
37
38use super::SocketCapabilities;
39
40/// Wrapper around a [`UdpSocket`] for server-side QUIC connections.
41///
42/// The wrapper carries socket-specific parameters, in contrast to the
43/// [`settings`](crate::settings) structs which apply to _all_ sockets
44/// for a given QUIC server.
45///
46/// To create a [`QuicListener`], you may either instantiate the struct yourself
47/// or use one of the `TryFrom` implementations.
48#[derive(Debug)]
49pub struct QuicListener {
50 /// The wrapped [tokio] socket.
51 pub socket: UdpSocket,
52 /// An opaque value that is later passed to the
53 /// [`ConnectionIdGenerator`](crate::ConnectionIdGenerator).
54 pub socket_cookie: u64,
55 /// The [`SocketCapabilities`] to use for this socket.
56 ///
57 /// By default, [`QuicListener`]s are constructed with all capabilities
58 /// disabled. On Linux, you can use `apply_max_capabilities()` to (try
59 /// to) enable all supported capabilities.
60 pub capabilities: SocketCapabilities,
61}
62
63impl QuicListener {
64 /// Tries to enable all sockopts supported by the crate for this socket.
65 /// See `SocketCapabilities::apply_all_and_get_compatibility` for details.
66 #[cfg(target_os = "linux")]
67 pub fn apply_max_capabilities(&mut self) {
68 let capabilities =
69 SocketCapabilities::apply_all_and_get_compatibility(&self.socket);
70 self.capabilities = capabilities;
71 }
72}
73
74impl TryFrom<UdpSocket> for QuicListener {
75 type Error = io::Error;
76
77 fn try_from(socket: UdpSocket) -> Result<Self, Self::Error> {
78 Ok(Self {
79 socket,
80 socket_cookie: 0,
81 capabilities: SocketCapabilities::default(),
82 })
83 }
84}
85
86impl TryFrom<std::net::UdpSocket> for QuicListener {
87 type Error = io::Error;
88
89 fn try_from(socket: std::net::UdpSocket) -> Result<Self, Self::Error> {
90 socket.set_nonblocking(true)?;
91 let socket = UdpSocket::from_std(socket)?;
92 Self::try_from(socket)
93 }
94}
95
96#[cfg(unix)]
97impl AsFd for QuicListener {
98 fn as_fd(&self) -> BorrowedFd<'_> {
99 self.socket.as_fd()
100 }
101}
102
103#[cfg(unix)]
104impl AsRawFd for QuicListener {
105 fn as_raw_fd(&self) -> RawFd {
106 self.socket.as_raw_fd()
107 }
108}