1 use core::cmp::min;
2 #[cfg(feature = "async")]
3 use core::task::Waker;
4 
5 use crate::iface::Context;
6 use crate::socket::PollAt;
7 #[cfg(feature = "async")]
8 use crate::socket::WakerRegistration;
9 
10 use crate::storage::Empty;
11 use crate::wire::{IpProtocol, IpRepr, IpVersion};
12 #[cfg(feature = "proto-ipv4")]
13 use crate::wire::{Ipv4Packet, Ipv4Repr};
14 #[cfg(feature = "proto-ipv6")]
15 use crate::wire::{Ipv6Packet, Ipv6Repr};
16 
17 /// Error returned by [`Socket::bind`]
18 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
19 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
20 pub enum BindError {
21     InvalidState,
22     Unaddressable,
23 }
24 
25 /// Error returned by [`Socket::send`]
26 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
27 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
28 pub enum SendError {
29     BufferFull,
30 }
31 
32 /// Error returned by [`Socket::recv`]
33 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
34 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
35 pub enum RecvError {
36     Exhausted,
37 }
38 
39 /// A UDP packet metadata.
40 pub type PacketMetadata = crate::storage::PacketMetadata<()>;
41 
42 /// A UDP packet ring buffer.
43 pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, ()>;
44 
45 /// A raw IP socket.
46 ///
47 /// A raw socket is bound to a specific IP protocol, and owns
48 /// transmit and receive packet buffers.
49 #[derive(Debug)]
50 pub struct Socket<'a> {
51     ip_version: IpVersion,
52     ip_protocol: IpProtocol,
53     rx_buffer: PacketBuffer<'a>,
54     tx_buffer: PacketBuffer<'a>,
55     #[cfg(feature = "async")]
56     rx_waker: WakerRegistration,
57     #[cfg(feature = "async")]
58     tx_waker: WakerRegistration,
59 }
60 
61 impl<'a> Socket<'a> {
62     /// Create a raw IP socket bound to the given IP version and datagram protocol,
63     /// with the given buffers.
new( ip_version: IpVersion, ip_protocol: IpProtocol, rx_buffer: PacketBuffer<'a>, tx_buffer: PacketBuffer<'a>, ) -> Socket<'a>64     pub fn new(
65         ip_version: IpVersion,
66         ip_protocol: IpProtocol,
67         rx_buffer: PacketBuffer<'a>,
68         tx_buffer: PacketBuffer<'a>,
69     ) -> Socket<'a> {
70         Socket {
71             ip_version,
72             ip_protocol,
73             rx_buffer,
74             tx_buffer,
75             #[cfg(feature = "async")]
76             rx_waker: WakerRegistration::new(),
77             #[cfg(feature = "async")]
78             tx_waker: WakerRegistration::new(),
79         }
80     }
81 
82     /// Register a waker for receive operations.
83     ///
84     /// The waker is woken on state changes that might affect the return value
85     /// of `recv` method calls, such as receiving data, or the socket closing.
86     ///
87     /// Notes:
88     ///
89     /// - Only one waker can be registered at a time. If another waker was previously registered,
90     ///   it is overwritten and will no longer be woken.
91     /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
92     /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has
93     ///   necessarily changed.
94     #[cfg(feature = "async")]
register_recv_waker(&mut self, waker: &Waker)95     pub fn register_recv_waker(&mut self, waker: &Waker) {
96         self.rx_waker.register(waker)
97     }
98 
99     /// Register a waker for send operations.
100     ///
101     /// The waker is woken on state changes that might affect the return value
102     /// of `send` method calls, such as space becoming available in the transmit
103     /// buffer, or the socket closing.
104     ///
105     /// Notes:
106     ///
107     /// - Only one waker can be registered at a time. If another waker was previously registered,
108     ///   it is overwritten and will no longer be woken.
109     /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
110     /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has
111     ///   necessarily changed.
112     #[cfg(feature = "async")]
register_send_waker(&mut self, waker: &Waker)113     pub fn register_send_waker(&mut self, waker: &Waker) {
114         self.tx_waker.register(waker)
115     }
116 
117     /// Return the IP version the socket is bound to.
118     #[inline]
ip_version(&self) -> IpVersion119     pub fn ip_version(&self) -> IpVersion {
120         self.ip_version
121     }
122 
123     /// Return the IP protocol the socket is bound to.
124     #[inline]
ip_protocol(&self) -> IpProtocol125     pub fn ip_protocol(&self) -> IpProtocol {
126         self.ip_protocol
127     }
128 
129     /// Check whether the transmit buffer is full.
130     #[inline]
can_send(&self) -> bool131     pub fn can_send(&self) -> bool {
132         !self.tx_buffer.is_full()
133     }
134 
135     /// Check whether the receive buffer is not empty.
136     #[inline]
can_recv(&self) -> bool137     pub fn can_recv(&self) -> bool {
138         !self.rx_buffer.is_empty()
139     }
140 
141     /// Return the maximum number packets the socket can receive.
142     #[inline]
packet_recv_capacity(&self) -> usize143     pub fn packet_recv_capacity(&self) -> usize {
144         self.rx_buffer.packet_capacity()
145     }
146 
147     /// Return the maximum number packets the socket can transmit.
148     #[inline]
packet_send_capacity(&self) -> usize149     pub fn packet_send_capacity(&self) -> usize {
150         self.tx_buffer.packet_capacity()
151     }
152 
153     /// Return the maximum number of bytes inside the recv buffer.
154     #[inline]
payload_recv_capacity(&self) -> usize155     pub fn payload_recv_capacity(&self) -> usize {
156         self.rx_buffer.payload_capacity()
157     }
158 
159     /// Return the maximum number of bytes inside the transmit buffer.
160     #[inline]
payload_send_capacity(&self) -> usize161     pub fn payload_send_capacity(&self) -> usize {
162         self.tx_buffer.payload_capacity()
163     }
164 
165     /// Enqueue a packet to send, and return a pointer to its payload.
166     ///
167     /// This function returns `Err(Error::Exhausted)` if the transmit buffer is full,
168     /// and `Err(Error::Truncated)` if there is not enough transmit buffer capacity
169     /// to ever send this packet.
170     ///
171     /// If the buffer is filled in a way that does not match the socket's
172     /// IP version or protocol, the packet will be silently dropped.
173     ///
174     /// **Note:** The IP header is parsed and re-serialized, and may not match
175     /// the header actually transmitted bit for bit.
send(&mut self, size: usize) -> Result<&mut [u8], SendError>176     pub fn send(&mut self, size: usize) -> Result<&mut [u8], SendError> {
177         let packet_buf = self
178             .tx_buffer
179             .enqueue(size, ())
180             .map_err(|_| SendError::BufferFull)?;
181 
182         net_trace!(
183             "raw:{}:{}: buffer to send {} octets",
184             self.ip_version,
185             self.ip_protocol,
186             packet_buf.len()
187         );
188         Ok(packet_buf)
189     }
190 
191     /// Enqueue a packet to be send and pass the buffer to the provided closure.
192     /// The closure then returns the size of the data written into the buffer.
193     ///
194     /// Also see [send](#method.send).
send_with<F>(&mut self, max_size: usize, f: F) -> Result<usize, SendError> where F: FnOnce(&mut [u8]) -> usize,195     pub fn send_with<F>(&mut self, max_size: usize, f: F) -> Result<usize, SendError>
196     where
197         F: FnOnce(&mut [u8]) -> usize,
198     {
199         let size = self
200             .tx_buffer
201             .enqueue_with_infallible(max_size, (), f)
202             .map_err(|_| SendError::BufferFull)?;
203 
204         net_trace!(
205             "raw:{}:{}: buffer to send {} octets",
206             self.ip_version,
207             self.ip_protocol,
208             size
209         );
210 
211         Ok(size)
212     }
213 
214     /// Enqueue a packet to send, and fill it from a slice.
215     ///
216     /// See also [send](#method.send).
send_slice(&mut self, data: &[u8]) -> Result<(), SendError>217     pub fn send_slice(&mut self, data: &[u8]) -> Result<(), SendError> {
218         self.send(data.len())?.copy_from_slice(data);
219         Ok(())
220     }
221 
222     /// Dequeue a packet, and return a pointer to the payload.
223     ///
224     /// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
225     ///
226     /// **Note:** The IP header is parsed and re-serialized, and may not match
227     /// the header actually received bit for bit.
recv(&mut self) -> Result<&[u8], RecvError>228     pub fn recv(&mut self) -> Result<&[u8], RecvError> {
229         let ((), packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
230 
231         net_trace!(
232             "raw:{}:{}: receive {} buffered octets",
233             self.ip_version,
234             self.ip_protocol,
235             packet_buf.len()
236         );
237         Ok(packet_buf)
238     }
239 
240     /// Dequeue a packet, and copy the payload into the given slice.
241     ///
242     /// See also [recv](#method.recv).
recv_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError>243     pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError> {
244         let buffer = self.recv()?;
245         let length = min(data.len(), buffer.len());
246         data[..length].copy_from_slice(&buffer[..length]);
247         Ok(length)
248     }
249 
250     /// Peek at a packet in the receive buffer and return a pointer to the
251     /// payload without removing the packet from the receive buffer.
252     /// This function otherwise behaves identically to [recv](#method.recv).
253     ///
254     /// It returns `Err(Error::Exhausted)` if the receive buffer is empty.
peek(&mut self) -> Result<&[u8], RecvError>255     pub fn peek(&mut self) -> Result<&[u8], RecvError> {
256         let ((), packet_buf) = self.rx_buffer.peek().map_err(|_| RecvError::Exhausted)?;
257 
258         net_trace!(
259             "raw:{}:{}: receive {} buffered octets",
260             self.ip_version,
261             self.ip_protocol,
262             packet_buf.len()
263         );
264 
265         Ok(packet_buf)
266     }
267 
268     /// Peek at a packet in the receive buffer, copy the payload into the given slice,
269     /// and return the amount of octets copied without removing the packet from the receive buffer.
270     /// This function otherwise behaves identically to [recv_slice](#method.recv_slice).
271     ///
272     /// See also [peek](#method.peek).
peek_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError>273     pub fn peek_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError> {
274         let buffer = self.peek()?;
275         let length = min(data.len(), buffer.len());
276         data[..length].copy_from_slice(&buffer[..length]);
277         Ok(length)
278     }
279 
accepts(&self, ip_repr: &IpRepr) -> bool280     pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool {
281         if ip_repr.version() != self.ip_version {
282             return false;
283         }
284         if ip_repr.next_header() != self.ip_protocol {
285             return false;
286         }
287 
288         true
289     }
290 
process(&mut self, cx: &mut Context, ip_repr: &IpRepr, payload: &[u8])291     pub(crate) fn process(&mut self, cx: &mut Context, ip_repr: &IpRepr, payload: &[u8]) {
292         debug_assert!(self.accepts(ip_repr));
293 
294         let header_len = ip_repr.header_len();
295         let total_len = header_len + payload.len();
296 
297         net_trace!(
298             "raw:{}:{}: receiving {} octets",
299             self.ip_version,
300             self.ip_protocol,
301             total_len
302         );
303 
304         match self.rx_buffer.enqueue(total_len, ()) {
305             Ok(buf) => {
306                 ip_repr.emit(&mut buf[..header_len], &cx.checksum_caps());
307                 buf[header_len..].copy_from_slice(payload);
308             }
309             Err(_) => net_trace!(
310                 "raw:{}:{}: buffer full, dropped incoming packet",
311                 self.ip_version,
312                 self.ip_protocol
313             ),
314         }
315 
316         #[cfg(feature = "async")]
317         self.rx_waker.wake();
318     }
319 
dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E> where F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<(), E>,320     pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
321     where
322         F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<(), E>,
323     {
324         let ip_protocol = self.ip_protocol;
325         let ip_version = self.ip_version;
326         let _checksum_caps = &cx.checksum_caps();
327         let res = self.tx_buffer.dequeue_with(|&mut (), buffer| {
328             match IpVersion::of_packet(buffer) {
329                 #[cfg(feature = "proto-ipv4")]
330                 Ok(IpVersion::Ipv4) => {
331                     let mut packet = match Ipv4Packet::new_checked(buffer) {
332                         Ok(x) => x,
333                         Err(_) => {
334                             net_trace!("raw: malformed ipv6 packet in queue, dropping.");
335                             return Ok(());
336                         }
337                     };
338                     if packet.next_header() != ip_protocol {
339                         net_trace!("raw: sent packet with wrong ip protocol, dropping.");
340                         return Ok(());
341                     }
342                     if _checksum_caps.ipv4.tx() {
343                         packet.fill_checksum();
344                     } else {
345                         // make sure we get a consistently zeroed checksum,
346                         // since implementations might rely on it
347                         packet.set_checksum(0);
348                     }
349 
350                     let packet = Ipv4Packet::new_unchecked(&*packet.into_inner());
351                     let ipv4_repr = match Ipv4Repr::parse(&packet, _checksum_caps) {
352                         Ok(x) => x,
353                         Err(_) => {
354                             net_trace!("raw: malformed ipv4 packet in queue, dropping.");
355                             return Ok(());
356                         }
357                     };
358                     net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
359                     emit(cx, (IpRepr::Ipv4(ipv4_repr), packet.payload()))
360                 }
361                 #[cfg(feature = "proto-ipv6")]
362                 Ok(IpVersion::Ipv6) => {
363                     let packet = match Ipv6Packet::new_checked(buffer) {
364                         Ok(x) => x,
365                         Err(_) => {
366                             net_trace!("raw: malformed ipv6 packet in queue, dropping.");
367                             return Ok(());
368                         }
369                     };
370                     if packet.next_header() != ip_protocol {
371                         net_trace!("raw: sent ipv6 packet with wrong ip protocol, dropping.");
372                         return Ok(());
373                     }
374                     let packet = Ipv6Packet::new_unchecked(&*packet.into_inner());
375                     let ipv6_repr = match Ipv6Repr::parse(&packet) {
376                         Ok(x) => x,
377                         Err(_) => {
378                             net_trace!("raw: malformed ipv6 packet in queue, dropping.");
379                             return Ok(());
380                         }
381                     };
382 
383                     net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
384                     emit(cx, (IpRepr::Ipv6(ipv6_repr), packet.payload()))
385                 }
386                 Err(_) => {
387                     net_trace!("raw: sent packet with invalid IP version, dropping.");
388                     Ok(())
389                 }
390             }
391         });
392         match res {
393             Err(Empty) => Ok(()),
394             Ok(Err(e)) => Err(e),
395             Ok(Ok(())) => {
396                 #[cfg(feature = "async")]
397                 self.tx_waker.wake();
398                 Ok(())
399             }
400         }
401     }
402 
poll_at(&self, _cx: &mut Context) -> PollAt403     pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
404         if self.tx_buffer.is_empty() {
405             PollAt::Ingress
406         } else {
407             PollAt::Now
408         }
409     }
410 }
411 
412 #[cfg(test)]
413 mod test {
414     use super::*;
415     use crate::wire::IpRepr;
416     #[cfg(feature = "proto-ipv4")]
417     use crate::wire::{Ipv4Address, Ipv4Repr};
418     #[cfg(feature = "proto-ipv6")]
419     use crate::wire::{Ipv6Address, Ipv6Repr};
420 
buffer(packets: usize) -> PacketBuffer<'static>421     fn buffer(packets: usize) -> PacketBuffer<'static> {
422         PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 48 * packets])
423     }
424 
425     #[cfg(feature = "proto-ipv4")]
426     mod ipv4_locals {
427         use super::*;
428 
socket( rx_buffer: PacketBuffer<'static>, tx_buffer: PacketBuffer<'static>, ) -> Socket<'static>429         pub fn socket(
430             rx_buffer: PacketBuffer<'static>,
431             tx_buffer: PacketBuffer<'static>,
432         ) -> Socket<'static> {
433             Socket::new(
434                 IpVersion::Ipv4,
435                 IpProtocol::Unknown(IP_PROTO),
436                 rx_buffer,
437                 tx_buffer,
438             )
439         }
440 
441         pub const IP_PROTO: u8 = 63;
442         pub const HEADER_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
443             src_addr: Ipv4Address([10, 0, 0, 1]),
444             dst_addr: Ipv4Address([10, 0, 0, 2]),
445             next_header: IpProtocol::Unknown(IP_PROTO),
446             payload_len: 4,
447             hop_limit: 64,
448         });
449         pub const PACKET_BYTES: [u8; 24] = [
450             0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x0a, 0x00,
451             0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0xff,
452         ];
453         pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
454     }
455 
456     #[cfg(feature = "proto-ipv6")]
457     mod ipv6_locals {
458         use super::*;
459 
socket( rx_buffer: PacketBuffer<'static>, tx_buffer: PacketBuffer<'static>, ) -> Socket<'static>460         pub fn socket(
461             rx_buffer: PacketBuffer<'static>,
462             tx_buffer: PacketBuffer<'static>,
463         ) -> Socket<'static> {
464             Socket::new(
465                 IpVersion::Ipv6,
466                 IpProtocol::Unknown(IP_PROTO),
467                 rx_buffer,
468                 tx_buffer,
469             )
470         }
471 
472         pub const IP_PROTO: u8 = 63;
473         pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
474             src_addr: Ipv6Address([
475                 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476                 0x00, 0x01,
477             ]),
478             dst_addr: Ipv6Address([
479                 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480                 0x00, 0x02,
481             ]),
482             next_header: IpProtocol::Unknown(IP_PROTO),
483             payload_len: 4,
484             hop_limit: 64,
485         });
486 
487         pub const PACKET_BYTES: [u8; 44] = [
488             0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
489             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00,
490             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00,
491             0x00, 0xff,
492         ];
493 
494         pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
495     }
496 
497     macro_rules! reusable_ip_specific_tests {
498         ($module:ident, $socket:path, $hdr:path, $packet:path, $payload:path) => {
499             mod $module {
500                 use super::*;
501 
502                 #[test]
503                 fn test_send_truncated() {
504                     let mut socket = $socket(buffer(0), buffer(1));
505                     assert_eq!(socket.send_slice(&[0; 56][..]), Err(SendError::BufferFull));
506                 }
507 
508                 #[test]
509                 fn test_send_dispatch() {
510                     let mut socket = $socket(buffer(0), buffer(1));
511                     let mut cx = Context::mock();
512 
513                     assert!(socket.can_send());
514                     assert_eq!(
515                         socket.dispatch(&mut cx, |_, _| unreachable!()),
516                         Ok::<_, ()>(())
517                     );
518 
519                     assert_eq!(socket.send_slice(&$packet[..]), Ok(()));
520                     assert_eq!(socket.send_slice(b""), Err(SendError::BufferFull));
521                     assert!(!socket.can_send());
522 
523                     assert_eq!(
524                         socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
525                             assert_eq!(ip_repr, $hdr);
526                             assert_eq!(ip_payload, &$payload);
527                             Err(())
528                         }),
529                         Err(())
530                     );
531                     assert!(!socket.can_send());
532 
533                     assert_eq!(
534                         socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
535                             assert_eq!(ip_repr, $hdr);
536                             assert_eq!(ip_payload, &$payload);
537                             Ok::<_, ()>(())
538                         }),
539                         Ok(())
540                     );
541                     assert!(socket.can_send());
542                 }
543 
544                 #[test]
545                 fn test_recv_truncated_slice() {
546                     let mut socket = $socket(buffer(1), buffer(0));
547                     let mut cx = Context::mock();
548 
549                     assert!(socket.accepts(&$hdr));
550                     socket.process(&mut cx, &$hdr, &$payload);
551 
552                     let mut slice = [0; 4];
553                     assert_eq!(socket.recv_slice(&mut slice[..]), Ok(4));
554                     assert_eq!(&slice, &$packet[..slice.len()]);
555                 }
556 
557                 #[test]
558                 fn test_recv_truncated_packet() {
559                     let mut socket = $socket(buffer(1), buffer(0));
560                     let mut cx = Context::mock();
561 
562                     let mut buffer = vec![0; 128];
563                     buffer[..$packet.len()].copy_from_slice(&$packet[..]);
564 
565                     assert!(socket.accepts(&$hdr));
566                     socket.process(&mut cx, &$hdr, &buffer);
567                 }
568 
569                 #[test]
570                 fn test_peek_truncated_slice() {
571                     let mut socket = $socket(buffer(1), buffer(0));
572                     let mut cx = Context::mock();
573 
574                     assert!(socket.accepts(&$hdr));
575                     socket.process(&mut cx, &$hdr, &$payload);
576 
577                     let mut slice = [0; 4];
578                     assert_eq!(socket.peek_slice(&mut slice[..]), Ok(4));
579                     assert_eq!(&slice, &$packet[..slice.len()]);
580                     assert_eq!(socket.recv_slice(&mut slice[..]), Ok(4));
581                     assert_eq!(&slice, &$packet[..slice.len()]);
582                     assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Exhausted));
583                 }
584             }
585         };
586     }
587 
588     #[cfg(feature = "proto-ipv4")]
589     reusable_ip_specific_tests!(
590         ipv4,
591         ipv4_locals::socket,
592         ipv4_locals::HEADER_REPR,
593         ipv4_locals::PACKET_BYTES,
594         ipv4_locals::PACKET_PAYLOAD
595     );
596 
597     #[cfg(feature = "proto-ipv6")]
598     reusable_ip_specific_tests!(
599         ipv6,
600         ipv6_locals::socket,
601         ipv6_locals::HEADER_REPR,
602         ipv6_locals::PACKET_BYTES,
603         ipv6_locals::PACKET_PAYLOAD
604     );
605 
606     #[test]
607     #[cfg(feature = "proto-ipv4")]
test_send_illegal()608     fn test_send_illegal() {
609         #[cfg(feature = "proto-ipv4")]
610         {
611             let mut socket = ipv4_locals::socket(buffer(0), buffer(2));
612             let mut cx = Context::mock();
613 
614             let mut wrong_version = ipv4_locals::PACKET_BYTES;
615             Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6);
616 
617             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
618             assert_eq!(
619                 socket.dispatch(&mut cx, |_, _| unreachable!()),
620                 Ok::<_, ()>(())
621             );
622 
623             let mut wrong_protocol = ipv4_locals::PACKET_BYTES;
624             Ipv4Packet::new_unchecked(&mut wrong_protocol).set_next_header(IpProtocol::Tcp);
625 
626             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
627             assert_eq!(
628                 socket.dispatch(&mut cx, |_, _| unreachable!()),
629                 Ok::<_, ()>(())
630             );
631         }
632         #[cfg(feature = "proto-ipv6")]
633         {
634             let mut socket = ipv6_locals::socket(buffer(0), buffer(2));
635             let mut cx = Context::mock();
636 
637             let mut wrong_version = ipv6_locals::PACKET_BYTES;
638             Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4);
639 
640             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
641             assert_eq!(
642                 socket.dispatch(&mut cx, |_, _| unreachable!()),
643                 Ok::<_, ()>(())
644             );
645 
646             let mut wrong_protocol = ipv6_locals::PACKET_BYTES;
647             Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp);
648 
649             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
650             assert_eq!(
651                 socket.dispatch(&mut cx, |_, _| unreachable!()),
652                 Ok::<_, ()>(())
653             );
654         }
655     }
656 
657     #[test]
test_recv_process()658     fn test_recv_process() {
659         #[cfg(feature = "proto-ipv4")]
660         {
661             let mut socket = ipv4_locals::socket(buffer(1), buffer(0));
662             assert!(!socket.can_recv());
663             let mut cx = Context::mock();
664 
665             let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
666             Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
667 
668             assert_eq!(socket.recv(), Err(RecvError::Exhausted));
669             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
670             socket.process(
671                 &mut cx,
672                 &ipv4_locals::HEADER_REPR,
673                 &ipv4_locals::PACKET_PAYLOAD,
674             );
675             assert!(socket.can_recv());
676 
677             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
678             socket.process(
679                 &mut cx,
680                 &ipv4_locals::HEADER_REPR,
681                 &ipv4_locals::PACKET_PAYLOAD,
682             );
683             assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
684             assert!(!socket.can_recv());
685         }
686         #[cfg(feature = "proto-ipv6")]
687         {
688             let mut socket = ipv6_locals::socket(buffer(1), buffer(0));
689             assert!(!socket.can_recv());
690             let mut cx = Context::mock();
691 
692             assert_eq!(socket.recv(), Err(RecvError::Exhausted));
693             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
694             socket.process(
695                 &mut cx,
696                 &ipv6_locals::HEADER_REPR,
697                 &ipv6_locals::PACKET_PAYLOAD,
698             );
699             assert!(socket.can_recv());
700 
701             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
702             socket.process(
703                 &mut cx,
704                 &ipv6_locals::HEADER_REPR,
705                 &ipv6_locals::PACKET_PAYLOAD,
706             );
707             assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
708             assert!(!socket.can_recv());
709         }
710     }
711 
712     #[test]
test_peek_process()713     fn test_peek_process() {
714         #[cfg(feature = "proto-ipv4")]
715         {
716             let mut socket = ipv4_locals::socket(buffer(1), buffer(0));
717             let mut cx = Context::mock();
718 
719             let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
720             Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
721 
722             assert_eq!(socket.peek(), Err(RecvError::Exhausted));
723             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
724             socket.process(
725                 &mut cx,
726                 &ipv4_locals::HEADER_REPR,
727                 &ipv4_locals::PACKET_PAYLOAD,
728             );
729 
730             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
731             socket.process(
732                 &mut cx,
733                 &ipv4_locals::HEADER_REPR,
734                 &ipv4_locals::PACKET_PAYLOAD,
735             );
736             assert_eq!(socket.peek(), Ok(&cksumd_packet[..]));
737             assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
738             assert_eq!(socket.peek(), Err(RecvError::Exhausted));
739         }
740         #[cfg(feature = "proto-ipv6")]
741         {
742             let mut socket = ipv6_locals::socket(buffer(1), buffer(0));
743             let mut cx = Context::mock();
744 
745             assert_eq!(socket.peek(), Err(RecvError::Exhausted));
746             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
747             socket.process(
748                 &mut cx,
749                 &ipv6_locals::HEADER_REPR,
750                 &ipv6_locals::PACKET_PAYLOAD,
751             );
752 
753             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
754             socket.process(
755                 &mut cx,
756                 &ipv6_locals::HEADER_REPR,
757                 &ipv6_locals::PACKET_PAYLOAD,
758             );
759             assert_eq!(socket.peek(), Ok(&ipv6_locals::PACKET_BYTES[..]));
760             assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
761             assert_eq!(socket.peek(), Err(RecvError::Exhausted));
762         }
763     }
764 
765     #[test]
test_doesnt_accept_wrong_proto()766     fn test_doesnt_accept_wrong_proto() {
767         #[cfg(feature = "proto-ipv4")]
768         {
769             let socket = Socket::new(
770                 IpVersion::Ipv4,
771                 IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1),
772                 buffer(1),
773                 buffer(1),
774             );
775             assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
776             #[cfg(feature = "proto-ipv6")]
777             assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
778         }
779         #[cfg(feature = "proto-ipv6")]
780         {
781             let socket = Socket::new(
782                 IpVersion::Ipv6,
783                 IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1),
784                 buffer(1),
785                 buffer(1),
786             );
787             assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
788             #[cfg(feature = "proto-ipv4")]
789             assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
790         }
791     }
792 }
793