Skip to main content

smoltcp/socket/
mod.rs

1/*! Communication between endpoints.
2
3The `socket` module deals with *network endpoints* and *buffering*.
4It provides interfaces for accessing buffers of data, and protocol state machines
5for filling and emptying these buffers.
6
7The programming interface implemented here differs greatly from the common Berkeley socket
8interface. Specifically, in the Berkeley interface the buffering is implicit:
9the operating system decides on the good size for a buffer and manages it.
10The interface implemented by this module uses explicit buffering: you decide on the good
11size for a buffer, allocate it, and let the networking stack use it.
12*/
13
14use crate::iface::Context;
15use crate::time::Instant;
16
17#[cfg(feature = "socket-dhcpv4")]
18pub mod dhcpv4;
19#[cfg(feature = "socket-dns")]
20pub mod dns;
21#[cfg(feature = "socket-icmp")]
22pub mod icmp;
23#[cfg(feature = "socket-raw")]
24pub mod raw;
25#[cfg(feature = "socket-tcp")]
26pub mod tcp;
27#[cfg(feature = "socket-udp")]
28pub mod udp;
29
30#[cfg(feature = "async")]
31mod waker;
32
33#[cfg(feature = "async")]
34pub(crate) use self::waker::WakerRegistration;
35
36/// Gives an indication on the next time the socket should be polled.
37#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39pub(crate) enum PollAt {
40    /// The socket needs to be polled immediately.
41    Now,
42    /// The socket needs to be polled at given [Instant][struct.Instant].
43    Time(Instant),
44    /// The socket does not need to be polled unless there are external changes.
45    Ingress,
46}
47
48/// A network socket.
49///
50/// This enumeration abstracts the various types of sockets based on the IP protocol.
51/// To downcast a `Socket` value to a concrete socket, use the [AnySocket] trait,
52/// e.g. to get `udp::Socket`, call `udp::Socket::downcast(socket)`.
53///
54/// It is usually more convenient to use [SocketSet::get] instead.
55///
56/// [AnySocket]: trait.AnySocket.html
57/// [SocketSet::get]: struct.SocketSet.html#method.get
58#[derive(Debug)]
59#[allow(clippy::large_enum_variant)]
60pub enum Socket<'a> {
61    #[cfg(feature = "socket-raw")]
62    Raw(raw::Socket<'a>),
63    #[cfg(feature = "socket-icmp")]
64    Icmp(icmp::Socket<'a>),
65    #[cfg(feature = "socket-udp")]
66    Udp(udp::Socket<'a>),
67    #[cfg(feature = "socket-tcp")]
68    Tcp(tcp::Socket<'a>),
69    #[cfg(feature = "socket-dhcpv4")]
70    Dhcpv4(dhcpv4::Socket<'a>),
71    #[cfg(feature = "socket-dns")]
72    Dns(dns::Socket<'a>),
73}
74
75impl<'a> Socket<'a> {
76    pub(crate) fn poll_at(&self, cx: &mut Context) -> PollAt {
77        match self {
78            #[cfg(feature = "socket-raw")]
79            Socket::Raw(s) => s.poll_at(cx),
80            #[cfg(feature = "socket-icmp")]
81            Socket::Icmp(s) => s.poll_at(cx),
82            #[cfg(feature = "socket-udp")]
83            Socket::Udp(s) => s.poll_at(cx),
84            #[cfg(feature = "socket-tcp")]
85            Socket::Tcp(s) => s.poll_at(cx),
86            #[cfg(feature = "socket-dhcpv4")]
87            Socket::Dhcpv4(s) => s.poll_at(cx),
88            #[cfg(feature = "socket-dns")]
89            Socket::Dns(s) => s.poll_at(cx),
90        }
91    }
92}
93
94/// A conversion trait for network sockets.
95pub trait AnySocket<'a> {
96    fn upcast(self) -> Socket<'a>;
97    fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self>
98    where
99        Self: Sized;
100    fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self>
101    where
102        Self: Sized;
103}
104
105impl<'a> AnySocket<'a> for Socket<'a> {
106    #[inline]
107    fn upcast(self) -> Socket<'a> {
108        self
109    }
110
111    #[inline]
112    fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self>
113    where
114        Self: Sized,
115    {
116        Some(socket)
117    }
118
119    #[inline]
120    fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self>
121    where
122        Self: Sized,
123    {
124        Some(socket)
125    }
126}
127
128macro_rules! from_socket {
129    ($socket:ty, $variant:ident) => {
130        impl<'a> AnySocket<'a> for $socket {
131            fn upcast(self) -> Socket<'a> {
132                Socket::$variant(self)
133            }
134
135            fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self> {
136                #[allow(unreachable_patterns)]
137                match socket {
138                    Socket::$variant(socket) => Some(socket),
139                    _ => None,
140                }
141            }
142
143            fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self> {
144                #[allow(unreachable_patterns)]
145                match socket {
146                    Socket::$variant(socket) => Some(socket),
147                    _ => None,
148                }
149            }
150        }
151    };
152}
153
154#[cfg(feature = "socket-raw")]
155from_socket!(raw::Socket<'a>, Raw);
156#[cfg(feature = "socket-icmp")]
157from_socket!(icmp::Socket<'a>, Icmp);
158#[cfg(feature = "socket-udp")]
159from_socket!(udp::Socket<'a>, Udp);
160#[cfg(feature = "socket-tcp")]
161from_socket!(tcp::Socket<'a>, Tcp);
162#[cfg(feature = "socket-dhcpv4")]
163from_socket!(dhcpv4::Socket<'a>, Dhcpv4);
164#[cfg(feature = "socket-dns")]
165from_socket!(dns::Socket<'a>, Dns);