1 use std::net::{self, SocketAddr}; 2 #[cfg(unix)] 3 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 4 #[cfg(windows)] 5 use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; 6 use std::{fmt, io}; 7 8 use super::{TcpSocket, TcpStream}; 9 use crate::io_source::IoSource; 10 use crate::{event, sys, Interest, Registry, Token}; 11 12 /// A structure representing a socket server 13 /// 14 /// # Examples 15 /// 16 #[cfg_attr(feature = "os-poll", doc = "```")] 17 #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")] 18 /// # use std::error::Error; 19 /// # fn main() -> Result<(), Box<dyn Error>> { 20 /// use mio::{Events, Interest, Poll, Token}; 21 /// use mio::net::TcpListener; 22 /// use std::time::Duration; 23 /// 24 /// let mut listener = TcpListener::bind("127.0.0.1:34255".parse()?)?; 25 /// 26 /// let mut poll = Poll::new()?; 27 /// let mut events = Events::with_capacity(128); 28 /// 29 /// // Register the socket with `Poll` 30 /// poll.registry().register(&mut listener, Token(0), Interest::READABLE)?; 31 /// 32 /// poll.poll(&mut events, Some(Duration::from_millis(100)))?; 33 /// 34 /// // There may be a socket ready to be accepted 35 /// # Ok(()) 36 /// # } 37 /// ``` 38 pub struct TcpListener { 39 inner: IoSource<net::TcpListener>, 40 } 41 42 impl TcpListener { 43 /// Convenience method to bind a new TCP listener to the specified address 44 /// to receive new connections. 45 /// 46 /// This function will take the following steps: 47 /// 48 /// 1. Create a new TCP socket. 49 /// 2. Set the `SO_REUSEADDR` option on the socket on Unix. 50 /// 3. Bind the socket to the specified address. 51 /// 4. Calls `listen` on the socket to prepare it to receive new connections. bind(addr: SocketAddr) -> io::Result<TcpListener>52 pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> { 53 let socket = TcpSocket::new_for_addr(addr)?; 54 55 // On platforms with Berkeley-derived sockets, this allows to quickly 56 // rebind a socket, without needing to wait for the OS to clean up the 57 // previous one. 58 // 59 // On Windows, this allows rebinding sockets which are actively in use, 60 // which allows “socket hijacking”, so we explicitly don't set it here. 61 // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse 62 #[cfg(not(windows))] 63 socket.set_reuseaddr(true)?; 64 65 socket.bind(addr)?; 66 socket.listen(1024) 67 } 68 69 /// Creates a new `TcpListener` from a standard `net::TcpListener`. 70 /// 71 /// This function is intended to be used to wrap a TCP listener from the 72 /// standard library in the Mio equivalent. The conversion assumes nothing 73 /// about the underlying listener; ; it is left up to the user to set it 74 /// in non-blocking mode. from_std(listener: net::TcpListener) -> TcpListener75 pub fn from_std(listener: net::TcpListener) -> TcpListener { 76 TcpListener { 77 inner: IoSource::new(listener), 78 } 79 } 80 81 /// Accepts a new `TcpStream`. 82 /// 83 /// This may return an `Err(e)` where `e.kind()` is 84 /// `io::ErrorKind::WouldBlock`. This means a stream may be ready at a later 85 /// point and one should wait for an event before calling `accept` again. 86 /// 87 /// If an accepted stream is returned, the remote address of the peer is 88 /// returned along with it. accept(&self) -> io::Result<(TcpStream, SocketAddr)>89 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { 90 self.inner.do_io(|inner| { 91 sys::tcp::accept(inner).map(|(stream, addr)| (TcpStream::from_std(stream), addr)) 92 }) 93 } 94 95 /// Returns the local socket address of this listener. local_addr(&self) -> io::Result<SocketAddr>96 pub fn local_addr(&self) -> io::Result<SocketAddr> { 97 self.inner.local_addr() 98 } 99 100 /// Sets the value for the `IP_TTL` option on this socket. 101 /// 102 /// This value sets the time-to-live field that is used in every packet sent 103 /// from this socket. set_ttl(&self, ttl: u32) -> io::Result<()>104 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { 105 self.inner.set_ttl(ttl) 106 } 107 108 /// Gets the value of the `IP_TTL` option for this socket. 109 /// 110 /// For more information about this option, see [`set_ttl`][link]. 111 /// 112 /// [link]: #method.set_ttl ttl(&self) -> io::Result<u32>113 pub fn ttl(&self) -> io::Result<u32> { 114 self.inner.ttl() 115 } 116 117 /// Get the value of the `SO_ERROR` option on this socket. 118 /// 119 /// This will retrieve the stored error in the underlying socket, clearing 120 /// the field in the process. This can be useful for checking errors between 121 /// calls. take_error(&self) -> io::Result<Option<io::Error>>122 pub fn take_error(&self) -> io::Result<Option<io::Error>> { 123 self.inner.take_error() 124 } 125 } 126 127 impl event::Source for TcpListener { register( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>128 fn register( 129 &mut self, 130 registry: &Registry, 131 token: Token, 132 interests: Interest, 133 ) -> io::Result<()> { 134 self.inner.register(registry, token, interests) 135 } 136 reregister( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>137 fn reregister( 138 &mut self, 139 registry: &Registry, 140 token: Token, 141 interests: Interest, 142 ) -> io::Result<()> { 143 self.inner.reregister(registry, token, interests) 144 } 145 deregister(&mut self, registry: &Registry) -> io::Result<()>146 fn deregister(&mut self, registry: &Registry) -> io::Result<()> { 147 self.inner.deregister(registry) 148 } 149 } 150 151 impl fmt::Debug for TcpListener { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 153 self.inner.fmt(f) 154 } 155 } 156 157 #[cfg(unix)] 158 impl IntoRawFd for TcpListener { into_raw_fd(self) -> RawFd159 fn into_raw_fd(self) -> RawFd { 160 self.inner.into_inner().into_raw_fd() 161 } 162 } 163 164 #[cfg(unix)] 165 impl AsRawFd for TcpListener { as_raw_fd(&self) -> RawFd166 fn as_raw_fd(&self) -> RawFd { 167 self.inner.as_raw_fd() 168 } 169 } 170 171 #[cfg(unix)] 172 impl FromRawFd for TcpListener { 173 /// Converts a `RawFd` to a `TcpListener`. 174 /// 175 /// # Notes 176 /// 177 /// The caller is responsible for ensuring that the socket is in 178 /// non-blocking mode. from_raw_fd(fd: RawFd) -> TcpListener179 unsafe fn from_raw_fd(fd: RawFd) -> TcpListener { 180 TcpListener::from_std(FromRawFd::from_raw_fd(fd)) 181 } 182 } 183 184 #[cfg(windows)] 185 impl IntoRawSocket for TcpListener { into_raw_socket(self) -> RawSocket186 fn into_raw_socket(self) -> RawSocket { 187 self.inner.into_inner().into_raw_socket() 188 } 189 } 190 191 #[cfg(windows)] 192 impl AsRawSocket for TcpListener { as_raw_socket(&self) -> RawSocket193 fn as_raw_socket(&self) -> RawSocket { 194 self.inner.as_raw_socket() 195 } 196 } 197 198 #[cfg(windows)] 199 impl FromRawSocket for TcpListener { 200 /// Converts a `RawSocket` to a `TcpListener`. 201 /// 202 /// # Notes 203 /// 204 /// The caller is responsible for ensuring that the socket is in 205 /// non-blocking mode. from_raw_socket(socket: RawSocket) -> TcpListener206 unsafe fn from_raw_socket(socket: RawSocket) -> TcpListener { 207 TcpListener::from_std(FromRawSocket::from_raw_socket(socket)) 208 } 209 } 210