      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209

    use std::net::{self, SocketAddr};
    #[cfg(unix)]
    use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
    #[cfg(windows)]
    use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
    use std::{fmt, io};

    use super::{TcpSocket, TcpStream};
    use crate::io_source::IoSource;
    use crate::{event, sys, Interest, Registry, Token};

    /// A structure representing a socket server
    ///
    /// # Examples
    ///
    #[cfg_attr(feature = "os-poll", doc = "```")]
    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
    /// # use std::error::Error;
    /// # fn main() -> Result<(), Box<dyn Error>> {
    /// use mio::{Events, Interest, Poll, Token};
    /// use mio::net::TcpListener;
    /// use std::time::Duration;
    ///
    /// let mut listener = TcpListener::bind("127.0.0.1:34255".parse()?)?;
    ///
    /// let mut poll = Poll::new()?;
    /// let mut events = Events::with_capacity(128);
    ///
    /// // Register the socket with `Poll`
    /// poll.registry().register(&mut listener, Token(0), Interest::READABLE)?;
    ///
    /// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
    ///
    /// // There may be a socket ready to be accepted
    /// #     Ok(())
    /// # }
    /// ```
    pub struct TcpListener {
        inner: IoSource<net::TcpListener>,
    }

    impl TcpListener {
        /// Convenience method to bind a new TCP listener to the specified address
        /// to receive new connections.
        ///
        /// This function will take the following steps:
        ///
        /// 1. Create a new TCP socket.
        /// 2. Set the `SO_REUSEADDR` option on the socket on Unix.
        /// 3. Bind the socket to the specified address.
        /// 4. Calls `listen` on the socket to prepare it to receive new connections.
        pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
            let socket = TcpSocket::new_for_addr(addr)?;

            // On platforms with Berkeley-derived sockets, this allows to quickly
            // rebind a socket, without needing to wait for the OS to clean up the
            // previous one.
            //
            // On Windows, this allows rebinding sockets which are actively in use,
            // which allows “socket hijacking”, so we explicitly don't set it here.
            // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
            #[cfg(not(windows))]
            socket.set_reuseaddr(true)?;

            socket.bind(addr)?;
            socket.listen(1024)
        }

        /// Creates a new `TcpListener` from a standard `net::TcpListener`.
        ///
        /// This function is intended to be used to wrap a TCP listener from the
        /// standard library in the Mio equivalent. The conversion assumes nothing
        /// about the underlying listener; ; it is left up to the user to set it
        /// in non-blocking mode.
        pub fn from_std(listener: net::TcpListener) -> TcpListener {
            TcpListener {
                inner: IoSource::new(listener),
            }
        }

        /// Accepts a new `TcpStream`.
        ///
        /// This may return an `Err(e)` where `e.kind()` is
        /// `io::ErrorKind::WouldBlock`. This means a stream may be ready at a later
        /// point and one should wait for an event before calling `accept` again.
        ///
        /// If an accepted stream is returned, the remote address of the peer is
        /// returned along with it.
        pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
            self.inner.do_io(|inner| {
                sys::tcp::accept(inner).map(|(stream, addr)| (TcpStream::from_std(stream), addr))
            })
        }

        /// Returns the local socket address of this listener.
        pub fn local_addr(&self) -> io::Result<SocketAddr> {
            self.inner.local_addr()
        }

        /// Sets the value for the `IP_TTL` option on this socket.
        ///
        /// This value sets the time-to-live field that is used in every packet sent
        /// from this socket.
        pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
            self.inner.set_ttl(ttl)
        }

        /// Gets the value of the `IP_TTL` option for this socket.
        ///
        /// For more information about this option, see [`set_ttl`][link].
        ///
        /// [link]: #method.set_ttl
        pub fn ttl(&self) -> io::Result<u32> {
            self.inner.ttl()
        }

        /// Get the value of the `SO_ERROR` option on this socket.
        ///
        /// This will retrieve the stored error in the underlying socket, clearing
        /// the field in the process. This can be useful for checking errors between
        /// calls.
        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            self.inner.take_error()
        }
    }

    impl event::Source for TcpListener {
        fn register(
            &mut self,
            registry: &Registry,
            token: Token,
            interests: Interest,
        ) -> io::Result<()> {
            self.inner.register(registry, token, interests)
        }

        fn reregister(
            &mut self,
            registry: &Registry,
            token: Token,
            interests: Interest,
        ) -> io::Result<()> {
            self.inner.reregister(registry, token, interests)
        }

        fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
            self.inner.deregister(registry)
        }
    }

    impl fmt::Debug for TcpListener {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            self.inner.fmt(f)
        }
    }

    #[cfg(unix)]
    impl IntoRawFd for TcpListener {
        fn into_raw_fd(self) -> RawFd {
            self.inner.into_inner().into_raw_fd()
        }
    }

    #[cfg(unix)]
    impl AsRawFd for TcpListener {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_raw_fd()
        }
    }

    #[cfg(unix)]
    impl FromRawFd for TcpListener {
        /// Converts a `RawFd` to a `TcpListener`.
        ///
        /// # Notes
        ///
        /// The caller is responsible for ensuring that the socket is in
        /// non-blocking mode.
        unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
            TcpListener::from_std(FromRawFd::from_raw_fd(fd))
        }
    }

    #[cfg(windows)]
    impl IntoRawSocket for TcpListener {
        fn into_raw_socket(self) -> RawSocket {
            self.inner.into_inner().into_raw_socket()
        }
    }

    #[cfg(windows)]
    impl AsRawSocket for TcpListener {
        fn as_raw_socket(&self) -> RawSocket {
            self.inner.as_raw_socket()
        }
    }

    #[cfg(windows)]
    impl FromRawSocket for TcpListener {
        /// Converts a `RawSocket` to a `TcpListener`.
        ///
        /// # Notes
        ///
        /// The caller is responsible for ensuring that the socket is in
        /// non-blocking mode.
        unsafe fn from_raw_socket(socket: RawSocket) -> TcpListener {
            TcpListener::from_std(FromRawSocket::from_raw_socket(socket))
        }
    }