Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
39
vendor/mio/src/net/mod.rs
vendored
Normal file
39
vendor/mio/src/net/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//! Networking primitives.
|
||||
//!
|
||||
//! The types provided in this module are non-blocking by default and are
|
||||
//! designed to be portable across all supported Mio platforms. As long as the
|
||||
//! [portability guidelines] are followed, the behavior should be identical no
|
||||
//! matter the target platform.
|
||||
//!
|
||||
//! [portability guidelines]: ../struct.Poll.html#portability
|
||||
//!
|
||||
//! # Notes
|
||||
//!
|
||||
//! When using a datagram based socket, i.e. [`UdpSocket`] or [`UnixDatagram`],
|
||||
//! its only possible to receive a packet once. This means that if you provide a
|
||||
//! buffer that is too small you won't be able to receive the data anymore. How
|
||||
//! OSs deal with this situation is different for each OS:
|
||||
//! * Unixes, such as Linux, FreeBSD and macOS, will simply fill the buffer and
|
||||
//! return the amount of bytes written. This means that if the returned value
|
||||
//! is equal to the size of the buffer it may have only written a part of the
|
||||
//! packet (or the packet has the same size as the buffer).
|
||||
//! * Windows returns an `WSAEMSGSIZE` error.
|
||||
//!
|
||||
//! Mio does not change the value (either ok or error) returned by the OS, it's
|
||||
//! up to the user handle this. How to deal with these difference is still up
|
||||
//! for debate, specifically in
|
||||
//! <https://github.com/rust-lang/rust/issues/55794>. The best advice we can
|
||||
//! give is to always call receive with a large enough buffer.
|
||||
|
||||
mod tcp;
|
||||
pub use self::tcp::{TcpListener, TcpStream};
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
mod udp;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub use self::udp::UdpSocket;
|
||||
|
||||
#[cfg(unix)]
|
||||
mod uds;
|
||||
#[cfg(unix)]
|
||||
pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
|
||||
248
vendor/mio/src/net/tcp/listener.rs
vendored
Normal file
248
vendor/mio/src/net/tcp/listener.rs
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
use std::net::{self, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::net::TcpStream;
|
||||
#[cfg(unix)]
|
||||
use crate::sys::tcp::set_reuseaddr;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::sys::tcp::{bind, listen, new_for_addr};
|
||||
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.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
|
||||
let socket = new_for_addr(addr)?;
|
||||
#[cfg(unix)]
|
||||
let listener = unsafe { TcpListener::from_raw_fd(socket) };
|
||||
#[cfg(windows)]
|
||||
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };
|
||||
|
||||
// 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))]
|
||||
set_reuseaddr(&listener.inner, true)?;
|
||||
|
||||
bind(&listener.inner, addr)?;
|
||||
listen(&listener.inner, 1024)?;
|
||||
Ok(listener)
|
||||
}
|
||||
|
||||
/// 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))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl IntoRawFd for TcpListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl AsRawFd for TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
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))
|
||||
}
|
||||
}
|
||||
5
vendor/mio/src/net/tcp/mod.rs
vendored
Normal file
5
vendor/mio/src/net/tcp/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
mod listener;
|
||||
pub use self::listener::TcpListener;
|
||||
|
||||
mod stream;
|
||||
pub use self::stream::TcpStream;
|
||||
427
vendor/mio/src/net/tcp/stream.rs
vendored
Normal file
427
vendor/mio/src/net/tcp/stream.rs
vendored
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
use std::fmt;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
|
||||
use std::net::{self, Shutdown, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::sys::tcp::{connect, new_for_addr};
|
||||
use crate::{event, Interest, Registry, Token};
|
||||
|
||||
/// A non-blocking TCP stream between a local socket and a remote socket.
|
||||
///
|
||||
/// The socket will be closed when the value is dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(feature = "os-poll", doc = "```")]
|
||||
#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
|
||||
/// # use std::net::{TcpListener, SocketAddr};
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let address: SocketAddr = "127.0.0.1:0".parse()?;
|
||||
/// let listener = TcpListener::bind(address)?;
|
||||
/// use mio::{Events, Interest, Poll, Token};
|
||||
/// use mio::net::TcpStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let mut stream = TcpStream::connect(listener.local_addr()?)?;
|
||||
///
|
||||
/// let mut poll = Poll::new()?;
|
||||
/// let mut events = Events::with_capacity(128);
|
||||
///
|
||||
/// // Register the socket with `Poll`
|
||||
/// poll.registry().register(&mut stream, Token(0), Interest::WRITABLE)?;
|
||||
///
|
||||
/// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
|
||||
///
|
||||
/// // The socket might be ready at this point
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct TcpStream {
|
||||
inner: IoSource<net::TcpStream>,
|
||||
}
|
||||
|
||||
impl TcpStream {
|
||||
/// Create a new TCP stream and issue a non-blocking connect to the
|
||||
/// specified address.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The returned `TcpStream` may not be connected (and thus usable), unlike
|
||||
/// the API found in `std::net::TcpStream`. Because Mio issues a
|
||||
/// *non-blocking* connect it will not block the thread and instead return
|
||||
/// an unconnected `TcpStream`.
|
||||
///
|
||||
/// Ensuring the returned stream is connected is surprisingly complex when
|
||||
/// considering cross-platform support. Doing this properly should follow
|
||||
/// the steps below, an example implementation can be found
|
||||
/// [here](https://github.com/Thomasdezeeuw/heph/blob/0c4f1ab3eaf08bea1d65776528bfd6114c9f8374/src/net/tcp/stream.rs#L560-L622).
|
||||
///
|
||||
/// 1. Call `TcpStream::connect`
|
||||
/// 2. Register the returned stream with at least [write interest].
|
||||
/// 3. Wait for a (writable) event.
|
||||
/// 4. Check `TcpStream::peer_addr`. If it returns `libc::EINPROGRESS` or
|
||||
/// `ErrorKind::NotConnected` it means the stream is not yet connected,
|
||||
/// go back to step 3. If it returns an address it means the stream is
|
||||
/// connected, go to step 5. If another error is returned something
|
||||
/// whent wrong.
|
||||
/// 5. Now the stream can be used.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately, it usually means there are insufficient
|
||||
/// entries in the routing cache.
|
||||
///
|
||||
/// [write interest]: Interest::WRITABLE
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
|
||||
let socket = new_for_addr(addr)?;
|
||||
#[cfg(unix)]
|
||||
let stream = unsafe { TcpStream::from_raw_fd(socket) };
|
||||
#[cfg(windows)]
|
||||
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
|
||||
connect(&stream.inner, addr)?;
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
/// Creates a new `TcpStream` from a standard `net::TcpStream`.
|
||||
///
|
||||
/// This function is intended to be used to wrap a TCP stream from the
|
||||
/// standard library in the Mio equivalent. The conversion assumes nothing
|
||||
/// about the underlying stream; it is left up to the user to set it in
|
||||
/// non-blocking mode.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The TCP stream here will not have `connect` called on it, so it
|
||||
/// should already be connected via some other means (be it manually, or
|
||||
/// the standard library).
|
||||
pub fn from_std(stream: net::TcpStream) -> TcpStream {
|
||||
TcpStream {
|
||||
inner: IoSource::new(stream),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote peer of this TCP connection.
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.peer_addr()
|
||||
}
|
||||
|
||||
/// Returns the socket address of the local half of this TCP connection.
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.local_addr()
|
||||
}
|
||||
|
||||
/// Shuts down the read, write, or both halves of this connection.
|
||||
///
|
||||
/// This function will cause all pending and future I/O on the specified
|
||||
/// portions to return immediately with an appropriate value (see the
|
||||
/// documentation of `Shutdown`).
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.inner.shutdown(how)
|
||||
}
|
||||
|
||||
/// Sets the value of the `TCP_NODELAY` option on this socket.
|
||||
///
|
||||
/// If set, this option disables the Nagle algorithm. This means that
|
||||
/// segments are always sent as soon as possible, even if there is only a
|
||||
/// small amount of data. When not set, data is buffered until there is a
|
||||
/// sufficient amount to send out, thereby avoiding the frequent sending of
|
||||
/// small packets.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows make sure the stream is connected before calling this method,
|
||||
/// by receiving an (writable) event. Trying to set `nodelay` on an
|
||||
/// unconnected `TcpStream` is unspecified behavior.
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||
self.inner.set_nodelay(nodelay)
|
||||
}
|
||||
|
||||
/// Gets the value of the `TCP_NODELAY` option on this socket.
|
||||
///
|
||||
/// For more information about this option, see [`set_nodelay`][link].
|
||||
///
|
||||
/// [link]: #method.set_nodelay
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows make sure the stream is connected before calling this method,
|
||||
/// by receiving an (writable) event. Trying to get `nodelay` on an
|
||||
/// unconnected `TcpStream` is unspecified behavior.
|
||||
pub fn nodelay(&self) -> io::Result<bool> {
|
||||
self.inner.nodelay()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows make sure the stream is connected before calling this method,
|
||||
/// by receiving an (writable) event. Trying to set `ttl` on an
|
||||
/// unconnected `TcpStream` is unspecified behavior.
|
||||
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].
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows make sure the stream is connected before calling this method,
|
||||
/// by receiving an (writable) event. Trying to get `ttl` on an
|
||||
/// unconnected `TcpStream` is unspecified behavior.
|
||||
///
|
||||
/// [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()
|
||||
}
|
||||
|
||||
/// Receives data on the socket from the remote address to which it is
|
||||
/// connected, without removing that data from the queue. On success,
|
||||
/// returns the number of bytes peeked.
|
||||
///
|
||||
/// Successive calls return the same data. This is accomplished by passing
|
||||
/// `MSG_PEEK` as a flag to the underlying recv system call.
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.peek(buf)
|
||||
}
|
||||
|
||||
/// Execute an I/O operation ensuring that the socket receives more events
|
||||
/// if it hits a [`WouldBlock`] error.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method is required to be called for **all** I/O operations to
|
||||
/// ensure the user will receive events once the socket is ready again after
|
||||
/// returning a [`WouldBlock`] error.
|
||||
///
|
||||
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(unix, doc = "```no_run")]
|
||||
#[cfg_attr(windows, doc = "```ignore")]
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// #[cfg(windows)]
|
||||
/// use std::os::windows::io::AsRawSocket;
|
||||
/// use mio::net::TcpStream;
|
||||
///
|
||||
/// let address = "127.0.0.1:8080".parse().unwrap();
|
||||
/// let stream = TcpStream::connect(address)?;
|
||||
///
|
||||
/// // Wait until the stream is readable...
|
||||
///
|
||||
/// // Read from the stream using a direct libc call, of course the
|
||||
/// // `io::Read` implementation would be easier to use.
|
||||
/// let mut buf = [0; 512];
|
||||
/// let n = stream.try_io(|| {
|
||||
/// let buf_ptr = &mut buf as *mut _ as *mut _;
|
||||
/// #[cfg(unix)]
|
||||
/// let res = unsafe { libc::recv(stream.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// #[cfg(windows)]
|
||||
/// let res = unsafe { libc::recvfrom(stream.as_raw_socket() as usize, buf_ptr, buf.len() as i32, 0, std::ptr::null_mut(), std::ptr::null_mut()) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("read {} bytes", n);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
|
||||
where
|
||||
F: FnOnce() -> io::Result<T>,
|
||||
{
|
||||
self.inner.do_io(|_| f())
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for TcpStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a TcpStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for TcpStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for &'a TcpStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl event::Source for TcpStream {
|
||||
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 TcpStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl IntoRawFd for TcpStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsRawFd for TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl FromRawFd for TcpStream {
|
||||
/// Converts a `RawFd` to a `TcpStream`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
|
||||
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IntoRawSocket for TcpStream {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.inner.into_inner().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl AsRawSocket for TcpStream {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.inner.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl FromRawSocket for TcpStream {
|
||||
/// Converts a `RawSocket` to a `TcpStream`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_socket(socket: RawSocket) -> TcpStream {
|
||||
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl IntoRawFd for TcpStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl AsRawFd for TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl FromRawFd for TcpStream {
|
||||
/// Converts a `RawFd` to a `TcpStream`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
|
||||
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
697
vendor/mio/src/net/udp.rs
vendored
Normal file
697
vendor/mio/src/net/udp.rs
vendored
Normal file
|
|
@ -0,0 +1,697 @@
|
|||
//! Primitives for working with UDP.
|
||||
//!
|
||||
//! The types provided in this module are non-blocking by default and are
|
||||
//! designed to be portable across all supported Mio platforms. As long as the
|
||||
//! [portability guidelines] are followed, the behavior should be identical no
|
||||
//! matter the target platform.
|
||||
//!
|
||||
//! [portability guidelines]: ../struct.Poll.html#portability
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::net;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
|
||||
/// A User Datagram Protocol socket.
|
||||
///
|
||||
/// This is an implementation of a bound UDP socket. This supports both IPv4 and
|
||||
/// IPv6 addresses, and there is no corresponding notion of a server because UDP
|
||||
/// is a datagram protocol.
|
||||
///
|
||||
/// # 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>> {
|
||||
/// // An Echo program:
|
||||
/// // SENDER -> sends a message.
|
||||
/// // ECHOER -> listens and prints the message received.
|
||||
///
|
||||
/// use mio::net::UdpSocket;
|
||||
/// use mio::{Events, Interest, Poll, Token};
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// const SENDER: Token = Token(0);
|
||||
/// const ECHOER: Token = Token(1);
|
||||
///
|
||||
/// // This operation will fail if the address is in use, so we select different ports for each
|
||||
/// // socket.
|
||||
/// let mut sender_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
/// let mut echoer_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
///
|
||||
/// // If we do not use connect here, SENDER and ECHOER would need to call send_to and recv_from
|
||||
/// // respectively.
|
||||
/// sender_socket.connect(echoer_socket.local_addr()?)?;
|
||||
///
|
||||
/// // We need a Poll to check if SENDER is ready to be written into, and if ECHOER is ready to be
|
||||
/// // read from.
|
||||
/// let mut poll = Poll::new()?;
|
||||
///
|
||||
/// // We register our sockets here so that we can check if they are ready to be written/read.
|
||||
/// poll.registry().register(&mut sender_socket, SENDER, Interest::WRITABLE)?;
|
||||
/// poll.registry().register(&mut echoer_socket, ECHOER, Interest::READABLE)?;
|
||||
///
|
||||
/// let msg_to_send = [9; 9];
|
||||
/// let mut buffer = [0; 9];
|
||||
///
|
||||
/// let mut events = Events::with_capacity(128);
|
||||
/// loop {
|
||||
/// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
|
||||
/// for event in events.iter() {
|
||||
/// match event.token() {
|
||||
/// // Our SENDER is ready to be written into.
|
||||
/// SENDER => {
|
||||
/// let bytes_sent = sender_socket.send(&msg_to_send)?;
|
||||
/// assert_eq!(bytes_sent, 9);
|
||||
/// println!("sent {:?} -> {:?} bytes", msg_to_send, bytes_sent);
|
||||
/// },
|
||||
/// // Our ECHOER is ready to be read from.
|
||||
/// ECHOER => {
|
||||
/// let num_recv = echoer_socket.recv(&mut buffer)?;
|
||||
/// println!("echo {:?} -> {:?}", buffer, num_recv);
|
||||
/// buffer = [0; 9];
|
||||
/// # drop(buffer); // Silence unused assignment warning.
|
||||
/// # return Ok(());
|
||||
/// }
|
||||
/// _ => unreachable!()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct UdpSocket {
|
||||
inner: IoSource<net::UdpSocket>,
|
||||
}
|
||||
|
||||
impl UdpSocket {
|
||||
/// Creates a UDP socket from the given address.
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// // We must bind it to an open address.
|
||||
/// let socket = match UdpSocket::bind("127.0.0.1:0".parse()?) {
|
||||
/// Ok(new_socket) => new_socket,
|
||||
/// Err(fail) => {
|
||||
/// // We panic! here, but you could try to bind it again on another address.
|
||||
/// panic!("Failed to bind socket. {:?}", fail);
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// // Our socket was created, but we should not use it before checking it's readiness.
|
||||
/// # drop(socket); // Silence unused variable warning.
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
|
||||
sys::udp::bind(addr).map(UdpSocket::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UdpSocket` from a standard `net::UdpSocket`.
|
||||
///
|
||||
/// This function is intended to be used to wrap a UDP socket from the
|
||||
/// standard library in the Mio equivalent. The conversion assumes nothing
|
||||
/// about the underlying socket; it is left up to the user to set it in
|
||||
/// non-blocking mode.
|
||||
pub fn from_std(socket: net::UdpSocket) -> UdpSocket {
|
||||
UdpSocket {
|
||||
inner: IoSource::new(socket),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the socket address that this socket was created from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
// This assertion is almost, but not quite, universal. It fails on
|
||||
// shared-IP FreeBSD jails. It's hard for mio to know whether we're jailed,
|
||||
// so simply disable the test on FreeBSD.
|
||||
#[cfg_attr(all(feature = "os-poll", not(target_os = "freebsd")), doc = "```")]
|
||||
#[cfg_attr(
|
||||
any(not(feature = "os-poll"), target_os = "freebsd"),
|
||||
doc = "```ignore"
|
||||
)]
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use mio::net::UdpSocket;
|
||||
///
|
||||
/// let addr = "127.0.0.1:0".parse()?;
|
||||
/// let socket = UdpSocket::bind(addr)?;
|
||||
/// assert_eq!(socket.local_addr()?.ip(), addr.ip());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.local_addr()
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote peer this socket was connected to.
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// let addr = "127.0.0.1:0".parse()?;
|
||||
/// let peer_addr = "127.0.0.1:11100".parse()?;
|
||||
/// let socket = UdpSocket::bind(addr)?;
|
||||
/// socket.connect(peer_addr)?;
|
||||
/// assert_eq!(socket.peer_addr()?.ip(), peer_addr.ip());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.peer_addr()
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the given address. On success, returns the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// Address type can be any implementor of `ToSocketAddrs` trait. See its
|
||||
/// documentation for concrete examples.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use std::error::Error;
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use mio::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
///
|
||||
/// // We must check if the socket is writable before calling send_to,
|
||||
/// // or we could run into a WouldBlock error.
|
||||
///
|
||||
/// let bytes_sent = socket.send_to(&[9; 9], "127.0.0.1:11100".parse()?)?;
|
||||
/// assert_eq!(bytes_sent, 9);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.send_to(buf, target))
|
||||
}
|
||||
|
||||
/// Receives data from the socket. On success, returns the number of bytes
|
||||
/// read and the address from whence the data came.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows, if the data is larger than the buffer specified, the buffer
|
||||
/// is filled with the first part of the data, and recv_from returns the error
|
||||
/// WSAEMSGSIZE(10040). The excess data is lost.
|
||||
/// Make sure to always use a sufficiently large buffer to hold the
|
||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use mio::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
///
|
||||
/// // We must check if the socket is readable before calling recv_from,
|
||||
/// // or we could run into a WouldBlock error.
|
||||
///
|
||||
/// let mut buf = [0; 9];
|
||||
/// let (num_recv, from_addr) = socket.recv_from(&mut buf)?;
|
||||
/// println!("Received {:?} -> {:?} bytes from {:?}", buf, num_recv, from_addr);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.inner.do_io(|inner| inner.recv_from(buf))
|
||||
}
|
||||
|
||||
/// Receives data from the socket, without removing it from the input queue.
|
||||
/// On success, returns the number of bytes read and the address from whence
|
||||
/// the data came.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows, if the data is larger than the buffer specified, the buffer
|
||||
/// is filled with the first part of the data, and peek_from returns the error
|
||||
/// WSAEMSGSIZE(10040). The excess data is lost.
|
||||
/// Make sure to always use a sufficiently large buffer to hold the
|
||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use mio::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
///
|
||||
/// // We must check if the socket is readable before calling recv_from,
|
||||
/// // or we could run into a WouldBlock error.
|
||||
///
|
||||
/// let mut buf = [0; 9];
|
||||
/// let (num_recv, from_addr) = socket.peek_from(&mut buf)?;
|
||||
/// println!("Received {:?} -> {:?} bytes from {:?}", buf, num_recv, from_addr);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.inner.do_io(|inner| inner.peek_from(buf))
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the address previously bound via connect(). On success,
|
||||
/// returns the number of bytes written.
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.send(buf))
|
||||
}
|
||||
|
||||
/// Receives data from the socket previously bound with connect(). On success, returns
|
||||
/// the number of bytes read.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows, if the data is larger than the buffer specified, the buffer
|
||||
/// is filled with the first part of the data, and recv returns the error
|
||||
/// WSAEMSGSIZE(10040). The excess data is lost.
|
||||
/// Make sure to always use a sufficiently large buffer to hold the
|
||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.recv(buf))
|
||||
}
|
||||
|
||||
/// Receives data from the socket, without removing it from the input queue.
|
||||
/// On success, returns the number of bytes read.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// On Windows, if the data is larger than the buffer specified, the buffer
|
||||
/// is filled with the first part of the data, and peek returns the error
|
||||
/// WSAEMSGSIZE(10040). The excess data is lost.
|
||||
/// Make sure to always use a sufficiently large buffer to hold the
|
||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.peek(buf))
|
||||
}
|
||||
|
||||
/// Connects the UDP socket setting the default destination for `send()`
|
||||
/// and limiting packets that are read via `recv` from the address specified
|
||||
/// in `addr`.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately, it usually means there are insufficient
|
||||
/// entries in the routing cache.
|
||||
pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
|
||||
self.inner.connect(addr)
|
||||
}
|
||||
|
||||
/// Sets the value of the `SO_BROADCAST` option for this socket.
|
||||
///
|
||||
/// When enabled, this socket is allowed to send packets to a broadcast
|
||||
/// address.
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// let broadcast_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
/// if broadcast_socket.broadcast()? == false {
|
||||
/// broadcast_socket.set_broadcast(true)?;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(broadcast_socket.broadcast()?, true);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
|
||||
self.inner.set_broadcast(on)
|
||||
}
|
||||
|
||||
/// Gets the value of the `SO_BROADCAST` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`set_broadcast`][link].
|
||||
///
|
||||
/// [link]: #method.set_broadcast
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// let broadcast_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
/// assert_eq!(broadcast_socket.broadcast()?, false);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn broadcast(&self) -> io::Result<bool> {
|
||||
self.inner.broadcast()
|
||||
}
|
||||
|
||||
/// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
|
||||
///
|
||||
/// If enabled, multicast packets will be looped back to the local socket.
|
||||
/// Note that this may not have any affect on IPv6 sockets.
|
||||
pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
|
||||
self.inner.set_multicast_loop_v4(on)
|
||||
}
|
||||
|
||||
/// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`set_multicast_loop_v4`][link].
|
||||
///
|
||||
/// [link]: #method.set_multicast_loop_v4
|
||||
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
|
||||
self.inner.multicast_loop_v4()
|
||||
}
|
||||
|
||||
/// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
|
||||
///
|
||||
/// Indicates the time-to-live value of outgoing multicast packets for
|
||||
/// this socket. The default value is 1 which means that multicast packets
|
||||
/// don't leave the local network unless explicitly requested.
|
||||
///
|
||||
/// Note that this may not have any affect on IPv6 sockets.
|
||||
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
|
||||
self.inner.set_multicast_ttl_v4(ttl)
|
||||
}
|
||||
|
||||
/// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`set_multicast_ttl_v4`][link].
|
||||
///
|
||||
/// [link]: #method.set_multicast_ttl_v4
|
||||
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
|
||||
self.inner.multicast_ttl_v4()
|
||||
}
|
||||
|
||||
/// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
|
||||
///
|
||||
/// Controls whether this socket sees the multicast packets it sends itself.
|
||||
/// Note that this may not have any affect on IPv4 sockets.
|
||||
pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
|
||||
self.inner.set_multicast_loop_v6(on)
|
||||
}
|
||||
|
||||
/// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`set_multicast_loop_v6`][link].
|
||||
///
|
||||
/// [link]: #method.set_multicast_loop_v6
|
||||
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
|
||||
self.inner.multicast_loop_v6()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
/// if socket.ttl()? < 255 {
|
||||
/// socket.set_ttl(255)?;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(socket.ttl()?, 255);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
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
|
||||
///
|
||||
/// # 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::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
|
||||
/// socket.set_ttl(255)?;
|
||||
///
|
||||
/// assert_eq!(socket.ttl()?, 255);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
self.inner.ttl()
|
||||
}
|
||||
|
||||
/// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
|
||||
///
|
||||
/// This function specifies a new multicast group for this socket to join.
|
||||
/// The address must be a valid multicast address, and `interface` is the
|
||||
/// address of the local interface with which the system should join the
|
||||
/// multicast group. If it's equal to `INADDR_ANY` then an appropriate
|
||||
/// interface is chosen by the system.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
|
||||
self.inner.join_multicast_v4(multiaddr, interface)
|
||||
}
|
||||
|
||||
/// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
|
||||
///
|
||||
/// This function specifies a new multicast group for this socket to join.
|
||||
/// The address must be a valid multicast address, and `interface` is the
|
||||
/// index of the interface to join/leave (or 0 to indicate any interface).
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
|
||||
self.inner.join_multicast_v6(multiaddr, interface)
|
||||
}
|
||||
|
||||
/// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`join_multicast_v4`][link].
|
||||
///
|
||||
/// [link]: #method.join_multicast_v4
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
|
||||
self.inner.leave_multicast_v4(multiaddr, interface)
|
||||
}
|
||||
|
||||
/// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
|
||||
///
|
||||
/// For more information about this option, see
|
||||
/// [`join_multicast_v6`][link].
|
||||
///
|
||||
/// [link]: #method.join_multicast_v6
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
|
||||
self.inner.leave_multicast_v6(multiaddr, interface)
|
||||
}
|
||||
|
||||
/// Get the value of the `IPV6_V6ONLY` option on this socket.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn only_v6(&self) -> io::Result<bool> {
|
||||
sys::udp::only_v6(&self.inner)
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// Execute an I/O operation ensuring that the socket receives more events
|
||||
/// if it hits a [`WouldBlock`] error.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method is required to be called for **all** I/O operations to
|
||||
/// ensure the user will receive events once the socket is ready again after
|
||||
/// returning a [`WouldBlock`] error.
|
||||
///
|
||||
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(unix, doc = "```no_run")]
|
||||
#[cfg_attr(windows, doc = "```ignore")]
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// #[cfg(windows)]
|
||||
/// use std::os::windows::io::AsRawSocket;
|
||||
/// use mio::net::UdpSocket;
|
||||
///
|
||||
/// let address = "127.0.0.1:8080".parse().unwrap();
|
||||
/// let dgram = UdpSocket::bind(address)?;
|
||||
///
|
||||
/// // Wait until the dgram is readable...
|
||||
///
|
||||
/// // Read from the dgram using a direct libc call, of course the
|
||||
/// // `io::Read` implementation would be easier to use.
|
||||
/// let mut buf = [0; 512];
|
||||
/// let n = dgram.try_io(|| {
|
||||
/// let buf_ptr = &mut buf as *mut _ as *mut _;
|
||||
/// #[cfg(unix)]
|
||||
/// let res = unsafe { libc::recv(dgram.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// #[cfg(windows)]
|
||||
/// let res = unsafe { libc::recvfrom(dgram.as_raw_socket() as usize, buf_ptr, buf.len() as i32, 0, std::ptr::null_mut(), std::ptr::null_mut()) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("read {} bytes", n);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
|
||||
where
|
||||
F: FnOnce() -> io::Result<T>,
|
||||
{
|
||||
self.inner.do_io(|_| f())
|
||||
}
|
||||
}
|
||||
|
||||
impl event::Source for UdpSocket {
|
||||
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 UdpSocket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl IntoRawFd for UdpSocket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsRawFd for UdpSocket {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl FromRawFd for UdpSocket {
|
||||
/// Converts a `RawFd` to a `UdpSocket`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
|
||||
UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IntoRawSocket for UdpSocket {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.inner.into_inner().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl AsRawSocket for UdpSocket {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.inner.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl FromRawSocket for UdpSocket {
|
||||
/// Converts a `RawSocket` to a `UdpSocket`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket {
|
||||
UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
|
||||
}
|
||||
}
|
||||
236
vendor/mio/src/net/uds/datagram.rs
vendored
Normal file
236
vendor/mio/src/net/uds/datagram.rs
vendored
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::net::Shutdown;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// A Unix datagram socket.
|
||||
pub struct UnixDatagram {
|
||||
inner: IoSource<net::UnixDatagram>,
|
||||
}
|
||||
|
||||
impl UnixDatagram {
|
||||
/// Creates a Unix datagram socket bound to the given path.
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
|
||||
sys::uds::datagram::bind(path.as_ref()).map(UnixDatagram::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixDatagram` from a standard `net::UnixDatagram`.
|
||||
///
|
||||
/// This function is intended to be used to wrap a Unix datagram from the
|
||||
/// standard library in the Mio equivalent. The conversion assumes nothing
|
||||
/// about the underlying datagram; it is left up to the user to set it in
|
||||
/// non-blocking mode.
|
||||
pub fn from_std(socket: net::UnixDatagram) -> UnixDatagram {
|
||||
UnixDatagram {
|
||||
inner: IoSource::new(socket),
|
||||
}
|
||||
}
|
||||
|
||||
/// Connects the socket to the specified address.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately.
|
||||
pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
self.inner.connect(path)
|
||||
}
|
||||
|
||||
/// Creates a Unix Datagram socket which is not bound to any address.
|
||||
pub fn unbound() -> io::Result<UnixDatagram> {
|
||||
sys::uds::datagram::unbound().map(UnixDatagram::from_std)
|
||||
}
|
||||
|
||||
/// Create an unnamed pair of connected sockets.
|
||||
pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
|
||||
sys::uds::datagram::pair().map(|(socket1, socket2)| {
|
||||
(
|
||||
UnixDatagram::from_std(socket1),
|
||||
UnixDatagram::from_std(socket2),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the address of this socket.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::datagram::local_addr(&self.inner)
|
||||
}
|
||||
|
||||
/// Returns the address of this socket's peer.
|
||||
///
|
||||
/// The `connect` method will connect the socket to a peer.
|
||||
pub fn peer_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::datagram::peer_addr(&self.inner)
|
||||
}
|
||||
|
||||
/// Receives data from the socket.
|
||||
///
|
||||
/// On success, returns the number of bytes read and the address from
|
||||
/// whence the data came.
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, sys::SocketAddr)> {
|
||||
self.inner
|
||||
.do_io(|inner| sys::uds::datagram::recv_from(inner, buf))
|
||||
}
|
||||
|
||||
/// Receives data from the socket.
|
||||
///
|
||||
/// On success, returns the number of bytes read.
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.recv(buf))
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the specified address.
|
||||
///
|
||||
/// On success, returns the number of bytes written.
|
||||
pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.send_to(buf, path))
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the socket's peer.
|
||||
///
|
||||
/// The peer address may be set by the `connect` method, and this method
|
||||
/// will return an error if the socket has not already been connected.
|
||||
///
|
||||
/// On success, returns the number of bytes written.
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| inner.send(buf))
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.inner.take_error()
|
||||
}
|
||||
|
||||
/// Shut down the read, write, or both halves of this connection.
|
||||
///
|
||||
/// This function will cause all pending and future I/O calls on the
|
||||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of `Shutdown`).
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.inner.shutdown(how)
|
||||
}
|
||||
|
||||
/// Execute an I/O operation ensuring that the socket receives more events
|
||||
/// if it hits a [`WouldBlock`] error.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method is required to be called for **all** I/O operations to
|
||||
/// ensure the user will receive events once the socket is ready again after
|
||||
/// returning a [`WouldBlock`] error.
|
||||
///
|
||||
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use mio::net::UnixDatagram;
|
||||
///
|
||||
/// let (dgram1, dgram2) = UnixDatagram::pair()?;
|
||||
///
|
||||
/// // Wait until the dgram is writable...
|
||||
///
|
||||
/// // Write to the dgram using a direct libc call, of course the
|
||||
/// // `io::Write` implementation would be easier to use.
|
||||
/// let buf = b"hello";
|
||||
/// let n = dgram1.try_io(|| {
|
||||
/// let buf_ptr = &buf as *const _ as *const _;
|
||||
/// let res = unsafe { libc::send(dgram1.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::send, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("write {} bytes", n);
|
||||
///
|
||||
/// // Wait until the dgram is readable...
|
||||
///
|
||||
/// // Read from the dgram using a direct libc call, of course the
|
||||
/// // `io::Read` implementation would be easier to use.
|
||||
/// let mut buf = [0; 512];
|
||||
/// let n = dgram2.try_io(|| {
|
||||
/// let buf_ptr = &mut buf as *mut _ as *mut _;
|
||||
/// let res = unsafe { libc::recv(dgram2.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("read {} bytes", n);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
|
||||
where
|
||||
F: FnOnce() -> io::Result<T>,
|
||||
{
|
||||
self.inner.do_io(|_| f())
|
||||
}
|
||||
}
|
||||
|
||||
impl event::Source for UnixDatagram {
|
||||
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 UnixDatagram {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for UnixDatagram {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for UnixDatagram {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for UnixDatagram {
|
||||
/// Converts a `RawFd` to a `UnixDatagram`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
|
||||
UnixDatagram::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
104
vendor/mio/src/net/uds/listener.rs
vendored
Normal file
104
vendor/mio/src/net/uds/listener.rs
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
use crate::io_source::IoSource;
|
||||
use crate::net::{SocketAddr, UnixStream};
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// A non-blocking Unix domain socket server.
|
||||
pub struct UnixListener {
|
||||
inner: IoSource<net::UnixListener>,
|
||||
}
|
||||
|
||||
impl UnixListener {
|
||||
/// Creates a new `UnixListener` bound to the specified socket.
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
|
||||
sys::uds::listener::bind(path.as_ref()).map(UnixListener::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixListener` from a standard `net::UnixListener`.
|
||||
///
|
||||
/// This function is intended to be used to wrap a Unix 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::UnixListener) -> UnixListener {
|
||||
UnixListener {
|
||||
inner: IoSource::new(listener),
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts a new incoming connection to this listener.
|
||||
///
|
||||
/// The call is responsible for ensuring that the listening socket is in
|
||||
/// non-blocking mode.
|
||||
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
|
||||
sys::uds::listener::accept(&self.inner)
|
||||
}
|
||||
|
||||
/// Returns the local socket address of this listener.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::listener::local_addr(&self.inner)
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.inner.take_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl event::Source for UnixListener {
|
||||
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 UnixListener {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for UnixListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for UnixListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for UnixListener {
|
||||
/// Converts a `RawFd` to a `UnixListener`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
|
||||
UnixListener::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
10
vendor/mio/src/net/uds/mod.rs
vendored
Normal file
10
vendor/mio/src/net/uds/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
mod datagram;
|
||||
pub use self::datagram::UnixDatagram;
|
||||
|
||||
mod listener;
|
||||
pub use self::listener::UnixListener;
|
||||
|
||||
mod stream;
|
||||
pub use self::stream::UnixStream;
|
||||
|
||||
pub use crate::sys::SocketAddr;
|
||||
245
vendor/mio/src/net/uds/stream.rs
vendored
Normal file
245
vendor/mio/src/net/uds/stream.rs
vendored
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
|
||||
use std::net::Shutdown;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
|
||||
/// A non-blocking Unix stream socket.
|
||||
pub struct UnixStream {
|
||||
inner: IoSource<net::UnixStream>,
|
||||
}
|
||||
|
||||
impl UnixStream {
|
||||
/// Connects to the socket named by `path`.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately. Usually it means the backlog is full.
|
||||
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
|
||||
sys::uds::stream::connect(path.as_ref()).map(UnixStream::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixStream` from a standard `net::UnixStream`.
|
||||
///
|
||||
/// This function is intended to be used to wrap a Unix stream from the
|
||||
/// standard library in the Mio equivalent. The conversion assumes nothing
|
||||
/// about the underlying stream; it is left up to the user to set it in
|
||||
/// non-blocking mode.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The Unix stream here will not have `connect` called on it, so it
|
||||
/// should already be connected via some other means (be it manually, or
|
||||
/// the standard library).
|
||||
pub fn from_std(stream: net::UnixStream) -> UnixStream {
|
||||
UnixStream {
|
||||
inner: IoSource::new(stream),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an unnamed pair of connected sockets.
|
||||
///
|
||||
/// Returns two `UnixStream`s which are connected to each other.
|
||||
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
|
||||
sys::uds::stream::pair().map(|(stream1, stream2)| {
|
||||
(UnixStream::from_std(stream1), UnixStream::from_std(stream2))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the socket address of the local half of this connection.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::stream::local_addr(&self.inner)
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote half of this connection.
|
||||
pub fn peer_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::stream::peer_addr(&self.inner)
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.inner.take_error()
|
||||
}
|
||||
|
||||
/// Shuts down the read, write, or both halves of this connection.
|
||||
///
|
||||
/// This function will cause all pending and future I/O calls on the
|
||||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of `Shutdown`).
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.inner.shutdown(how)
|
||||
}
|
||||
|
||||
/// Execute an I/O operation ensuring that the socket receives more events
|
||||
/// if it hits a [`WouldBlock`] error.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This method is required to be called for **all** I/O operations to
|
||||
/// ensure the user will receive events once the socket is ready again after
|
||||
/// returning a [`WouldBlock`] error.
|
||||
///
|
||||
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use mio::net::UnixStream;
|
||||
///
|
||||
/// let (stream1, stream2) = UnixStream::pair()?;
|
||||
///
|
||||
/// // Wait until the stream is writable...
|
||||
///
|
||||
/// // Write to the stream using a direct libc call, of course the
|
||||
/// // `io::Write` implementation would be easier to use.
|
||||
/// let buf = b"hello";
|
||||
/// let n = stream1.try_io(|| {
|
||||
/// let buf_ptr = &buf as *const _ as *const _;
|
||||
/// let res = unsafe { libc::send(stream1.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::send, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("write {} bytes", n);
|
||||
///
|
||||
/// // Wait until the stream is readable...
|
||||
///
|
||||
/// // Read from the stream using a direct libc call, of course the
|
||||
/// // `io::Read` implementation would be easier to use.
|
||||
/// let mut buf = [0; 512];
|
||||
/// let n = stream2.try_io(|| {
|
||||
/// let buf_ptr = &mut buf as *mut _ as *mut _;
|
||||
/// let res = unsafe { libc::recv(stream2.as_raw_fd(), buf_ptr, buf.len(), 0) };
|
||||
/// if res != -1 {
|
||||
/// Ok(res as usize)
|
||||
/// } else {
|
||||
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
|
||||
/// // should return `WouldBlock` error.
|
||||
/// Err(io::Error::last_os_error())
|
||||
/// }
|
||||
/// })?;
|
||||
/// eprintln!("read {} bytes", n);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
|
||||
where
|
||||
F: FnOnce() -> io::Result<T>,
|
||||
{
|
||||
self.inner.do_io(|_| f())
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for &'a UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl event::Source for UnixStream {
|
||||
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 UnixStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for UnixStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for UnixStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for UnixStream {
|
||||
/// Converts a `RawFd` to a `UnixStream`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
|
||||
UnixStream::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue