1 /*! Communication between endpoints.
2 
3 The `socket` module deals with *network endpoints* and *buffering*.
4 It provides interfaces for accessing buffers of data, and protocol state machines
5 for filling and emptying these buffers.
6 
7 The programming interface implemented here differs greatly from the common Berkeley socket
8 interface. Specifically, in the Berkeley interface the buffering is implicit:
9 the operating system decides on the good size for a buffer and manages it.
10 The interface implemented by this module uses explicit buffering: you decide on the good
11 size for a buffer, allocate it, and let the networking stack use it.
12 */
13 
14 use crate::iface::Context;
15 use crate::time::Instant;
16 
17 #[cfg(feature = "socket-dhcpv4")]
18 pub mod dhcpv4;
19 #[cfg(feature = "socket-dns")]
20 pub mod dns;
21 #[cfg(feature = "socket-icmp")]
22 pub mod icmp;
23 #[cfg(feature = "socket-raw")]
24 pub mod raw;
25 #[cfg(feature = "socket-tcp")]
26 pub mod tcp;
27 #[cfg(feature = "socket-udp")]
28 pub mod udp;
29 
30 #[cfg(feature = "async")]
31 mod waker;
32 
33 #[cfg(feature = "async")]
34 pub(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))]
39 pub(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 pub enum Socket<'a> {
60     #[cfg(feature = "socket-raw")]
61     Raw(raw::Socket<'a>),
62     #[cfg(feature = "socket-icmp")]
63     Icmp(icmp::Socket<'a>),
64     #[cfg(feature = "socket-udp")]
65     Udp(udp::Socket<'a>),
66     #[cfg(feature = "socket-tcp")]
67     Tcp(tcp::Socket<'a>),
68     #[cfg(feature = "socket-dhcpv4")]
69     Dhcpv4(dhcpv4::Socket<'a>),
70     #[cfg(feature = "socket-dns")]
71     Dns(dns::Socket<'a>),
72 }
73 
74 impl<'a> Socket<'a> {
poll_at(&self, cx: &mut Context) -> PollAt75     pub(crate) fn poll_at(&self, cx: &mut Context) -> PollAt {
76         match self {
77             #[cfg(feature = "socket-raw")]
78             Socket::Raw(s) => s.poll_at(cx),
79             #[cfg(feature = "socket-icmp")]
80             Socket::Icmp(s) => s.poll_at(cx),
81             #[cfg(feature = "socket-udp")]
82             Socket::Udp(s) => s.poll_at(cx),
83             #[cfg(feature = "socket-tcp")]
84             Socket::Tcp(s) => s.poll_at(cx),
85             #[cfg(feature = "socket-dhcpv4")]
86             Socket::Dhcpv4(s) => s.poll_at(cx),
87             #[cfg(feature = "socket-dns")]
88             Socket::Dns(s) => s.poll_at(cx),
89         }
90     }
91 }
92 
93 /// A conversion trait for network sockets.
94 pub trait AnySocket<'a> {
upcast(self) -> Socket<'a>95     fn upcast(self) -> Socket<'a>;
downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self> where Self: Sized96     fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self>
97     where
98         Self: Sized;
downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self> where Self: Sized99     fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self>
100     where
101         Self: Sized;
102 }
103 
104 macro_rules! from_socket {
105     ($socket:ty, $variant:ident) => {
106         impl<'a> AnySocket<'a> for $socket {
107             fn upcast(self) -> Socket<'a> {
108                 Socket::$variant(self)
109             }
110 
111             fn downcast<'c>(socket: &'c Socket<'a>) -> Option<&'c Self> {
112                 #[allow(unreachable_patterns)]
113                 match socket {
114                     Socket::$variant(socket) => Some(socket),
115                     _ => None,
116                 }
117             }
118 
119             fn downcast_mut<'c>(socket: &'c mut Socket<'a>) -> Option<&'c mut Self> {
120                 #[allow(unreachable_patterns)]
121                 match socket {
122                     Socket::$variant(socket) => Some(socket),
123                     _ => None,
124                 }
125             }
126         }
127     };
128 }
129 
130 #[cfg(feature = "socket-raw")]
131 from_socket!(raw::Socket<'a>, Raw);
132 #[cfg(feature = "socket-icmp")]
133 from_socket!(icmp::Socket<'a>, Icmp);
134 #[cfg(feature = "socket-udp")]
135 from_socket!(udp::Socket<'a>, Udp);
136 #[cfg(feature = "socket-tcp")]
137 from_socket!(tcp::Socket<'a>, Tcp);
138 #[cfg(feature = "socket-dhcpv4")]
139 from_socket!(dhcpv4::Socket<'a>, Dhcpv4);
140 #[cfg(feature = "socket-dns")]
141 from_socket!(dns::Socket<'a>, Dns);
142