async_coap/datagram/
async_socket.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use super::*;
17use futures::prelude::*;
18use futures::task::Context;
19use futures::Poll;
20use std::pin::Pin;
21
22/// A trait for asynchronous datagram sockets.
23///
24/// This is an empty convenience trait that requires several additional traits to be implemented:
25/// [`DatagramSocketTypes`], [`AsyncSendTo`], [`AsyncRecvFrom`], [`MulticastSocket`],
26/// and [`Send`]+[`Sync`].
27///
28/// Implementations of this trait can be used with [`DatagramLocalEndpoint`].
29pub trait AsyncDatagramSocket:
30    DatagramSocketTypes + AsyncSendTo + AsyncRecvFrom + MulticastSocket + Send + Sync
31{
32}
33
34/// Trait implemented by a "socket" that describes the underlying `SocketAddr` and socket error
35/// types as associated types.
36pub trait DatagramSocketTypes: Unpin {
37    /// The "`SocketAddr`" type used by this "socket".  Typically [`std::net::SocketAddr`].
38    type SocketAddr: SocketAddrExt
39        + core::fmt::Display
40        + core::fmt::Debug
41        + std::string::ToString
42        + ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::Error>
43        + Send
44        + Unpin
45        + Copy;
46
47    /// The error type for errors emitted from this socket. Typically [`std::io::Error`].
48    type Error: std::fmt::Display + std::fmt::Debug;
49
50    /// Returns the local `SocketAddr` of this "socket".
51    fn local_addr(&self) -> Result<Self::SocketAddr, Self::Error>;
52
53    /// Performs a blocking hostname lookup.
54    fn lookup_host(
55        host: &str,
56        port: u16,
57    ) -> Result<std::vec::IntoIter<Self::SocketAddr>, Self::Error>
58    where
59        Self: Sized;
60}
61
62/// Trait for providing `sent_to` functionality for asynchronous, datagram-based sockets.
63pub trait AsyncSendTo: DatagramSocketTypes {
64    /// A non-blocking[^1], `poll_*` version of `std::net::UdpSocket::send_to`.
65    ///
66    /// [^1]: Note that while the spirit of this method intends for it to be non-blocking,
67    ///       [`AllowStdUdpSocket`] can block execution depending on the implementation details
68    ///       of the underlying [`std::net::UdpSocket`].
69    fn poll_send_to<B>(
70        self: Pin<&Self>,
71        cx: &mut Context<'_>,
72        buf: &[u8],
73        addr: B,
74    ) -> Poll<Result<usize, Self::Error>>
75    where
76        B: super::ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::Error>;
77
78    /// Returns a future that uses [`AsyncSendTo::poll_send_to`].
79    fn next_send_to<'a, 'b, B>(&'a self, buf: &'b [u8], addr: B) -> NextSendToFuture<'a, 'b, Self>
80    where
81        B: super::ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::Error>,
82    {
83        let addr = addr.to_socket_addrs().unwrap().next().unwrap();
84        NextSendToFuture {
85            socket: self,
86            buffer: buf,
87            addr: addr,
88        }
89    }
90
91    /// A *synchronous* version of [`AsyncSendTo::poll_send_to`]. If this isn't overridden by the
92    /// trait's implementation, the default version will call `poll_send_to()` and panics if it
93    /// returns `Poll::Pending`.
94    fn send_to<B>(&self, buf: &[u8], addr: B) -> Result<usize, Self::Error>
95    where
96        B: super::ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::Error>,
97    {
98        self.next_send_to(buf, addr)
99            .now_or_never()
100            .expect("send_to blocked")
101    }
102}
103
104/// Future returned from [`AsyncSendTo::next_send_to`].
105#[derive(Debug)]
106pub struct NextSendToFuture<'a, 'b, T>
107where
108    T: DatagramSocketTypes + AsyncSendTo + ?Sized,
109{
110    socket: &'a T,
111    buffer: &'b [u8],
112    addr: T::SocketAddr,
113}
114
115impl<'a, 'b, T> NextSendToFuture<'a, 'b, T>
116where
117    T: DatagramSocketTypes + AsyncSendTo + ?Sized,
118{
119    fn poll_unpin(
120        self: &mut Self,
121        cx: &mut futures::task::Context<'_>,
122    ) -> futures::task::Poll<Result<usize, T::Error>> {
123        Pin::new(self.socket).poll_send_to(cx, self.buffer, self.addr.clone())
124    }
125}
126
127impl<'a, 'b, T> Future for NextSendToFuture<'a, 'b, T>
128where
129    T: DatagramSocketTypes + AsyncSendTo + ?Sized,
130{
131    type Output = Result<usize, T::Error>;
132
133    fn poll(
134        self: Pin<&mut Self>,
135        cx: &mut futures::task::Context<'_>,
136    ) -> futures::task::Poll<Self::Output> {
137        self.get_mut().poll_unpin(cx)
138    }
139}
140
141/// Future returned from [`AsyncRecvFrom::next_recv_from`].
142#[derive(Debug)]
143pub struct NextRecvFromFuture<'a, 'b, T: AsyncRecvFrom + ?Sized> {
144    socket: &'a T,
145    buffer: &'b mut [u8],
146}
147
148impl<'a, 'b, T: AsyncRecvFrom + ?Sized + Unpin> NextRecvFromFuture<'a, 'b, T> {
149    fn poll_unpin(
150        self: &mut Self,
151        cx: &mut futures::task::Context<'_>,
152    ) -> futures::task::Poll<Result<(usize, T::SocketAddr, Option<T::SocketAddr>), T::Error>> {
153        Pin::new(self.socket).poll_recv_from(cx, self.buffer)
154    }
155}
156
157impl<'a, 'b, T: AsyncRecvFrom + ?Sized> Future for NextRecvFromFuture<'a, 'b, T> {
158    type Output = Result<(usize, T::SocketAddr, Option<T::SocketAddr>), T::Error>;
159
160    fn poll(
161        self: Pin<&mut Self>,
162        cx: &mut futures::task::Context<'_>,
163    ) -> futures::task::Poll<Self::Output> {
164        self.get_mut().poll_unpin(cx)
165    }
166}
167
168/// Trait for providing `recv_from` functionality for asynchronous, datagram-based sockets.
169///
170/// The value returned on success is a tuple of the following:
171///
172/// ```
173/// # use std::net::SocketAddr;
174/// # fn ignore_this_line
175/// #
176/// (bytes_written: usize,
177///  remote_socket_addr: SocketAddr,
178///  local_socket_addr: Option<SocketAddr>)
179/// #
180/// # {} // ignore this line
181/// ```
182///
183/// `local_socket_addr` indicates the local address that the packet was sent to, and may not be
184/// supported. If this isn't supported, `local_socket_addr` will be set to `None`.
185pub trait AsyncRecvFrom: DatagramSocketTypes {
186    /// A non-blocking[^1], `poll_*` version of [`std::net::UdpSocket::recv_from`] that can
187    /// optionally provide the destination (local) `SocketAddr`.
188    ///
189    /// If you need to receive a packet from within an async block, see
190    /// [`AsyncRecvFrom::next_recv_from`], which returns a [`Future`][std::future::Future].
191    ///
192    /// [^1]: Note that while the spirit of this method intends for it to be non-blocking,
193    ///       [`AllowStdUdpSocket`] can in fact block execution depending on the state of the
194    ///       underlying [`std::net::UdpSocket`].
195    fn poll_recv_from(
196        self: Pin<&Self>,
197        cx: &mut Context<'_>,
198        buf: &mut [u8],
199    ) -> Poll<Result<(usize, Self::SocketAddr, Option<Self::SocketAddr>), Self::Error>>;
200
201    /// Returns a future that uses [`poll_recv_from`][AsyncRecvFrom::poll_recv_from].
202    fn next_recv_from<'a, 'b>(&'a self, buf: &'b mut [u8]) -> NextRecvFromFuture<'a, 'b, Self> {
203        NextRecvFromFuture {
204            socket: self,
205            buffer: buf,
206        }
207    }
208}
209
210/// Trait that provides methods for joining/leaving multicast groups.
211pub trait MulticastSocket: DatagramSocketTypes {
212    /// The "address" type for this socket.
213    ///
214    /// Note that this is different than a `SocketAddr`, which also includes a port number.
215    /// This is just the address.
216    type IpAddr;
217
218    /// Attempts to join the given multicast group.
219    fn join_multicast<A>(&self, addr: A) -> Result<(), Self::Error>
220    where
221        A: std::convert::Into<Self::IpAddr>;
222
223    /// Attempts to leave the given multicast group.
224    fn leave_multicast<A>(&self, addr: A) -> Result<(), Self::Error>
225    where
226        A: std::convert::Into<Self::IpAddr>;
227}