1use core::cmp::min;
2#[cfg(feature = "async")]
3use core::task::Waker;
4
5use crate::iface::Context;
6use crate::socket::PollAt;
7#[cfg(feature = "async")]
8use crate::socket::WakerRegistration;
9
10use crate::storage::Empty;
11use crate::wire::{IpProtocol, IpRepr, IpVersion};
12#[cfg(feature = "proto-ipv4")]
13use crate::wire::{Ipv4Packet, Ipv4Repr};
14#[cfg(feature = "proto-ipv6")]
15use crate::wire::{Ipv6Packet, Ipv6Repr};
16
17#[derive(Debug, PartialEq, Eq, Clone, Copy)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum BindError {
21 InvalidState,
22 Unaddressable,
23}
24
25impl core::fmt::Display for BindError {
26 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
27 match self {
28 BindError::InvalidState => write!(f, "invalid state"),
29 BindError::Unaddressable => write!(f, "unaddressable"),
30 }
31 }
32}
33
34#[cfg(feature = "std")]
35impl std::error::Error for BindError {}
36
37#[derive(Debug, PartialEq, Eq, Clone, Copy)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub enum SendError {
41 BufferFull,
42}
43
44impl core::fmt::Display for SendError {
45 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
46 match self {
47 SendError::BufferFull => write!(f, "buffer full"),
48 }
49 }
50}
51
52#[cfg(feature = "std")]
53impl std::error::Error for SendError {}
54
55#[derive(Debug, PartialEq, Eq, Clone, Copy)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58pub enum RecvError {
59 Exhausted,
60 Truncated,
61}
62
63impl core::fmt::Display for RecvError {
64 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
65 match self {
66 RecvError::Exhausted => write!(f, "exhausted"),
67 RecvError::Truncated => write!(f, "truncated"),
68 }
69 }
70}
71
72#[cfg(feature = "std")]
73impl std::error::Error for RecvError {}
74
75pub type PacketMetadata = crate::storage::PacketMetadata<()>;
77
78pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, ()>;
80
81#[derive(Debug)]
86pub struct Socket<'a> {
87 ip_version: IpVersion,
88 ip_protocol: IpProtocol,
89 rx_buffer: PacketBuffer<'a>,
90 tx_buffer: PacketBuffer<'a>,
91 #[cfg(feature = "async")]
92 rx_waker: WakerRegistration,
93 #[cfg(feature = "async")]
94 tx_waker: WakerRegistration,
95}
96
97impl<'a> Socket<'a> {
98 pub fn new(
101 ip_version: IpVersion,
102 ip_protocol: IpProtocol,
103 rx_buffer: PacketBuffer<'a>,
104 tx_buffer: PacketBuffer<'a>,
105 ) -> Socket<'a> {
106 Socket {
107 ip_version,
108 ip_protocol,
109 rx_buffer,
110 tx_buffer,
111 #[cfg(feature = "async")]
112 rx_waker: WakerRegistration::new(),
113 #[cfg(feature = "async")]
114 tx_waker: WakerRegistration::new(),
115 }
116 }
117
118 #[cfg(feature = "async")]
131 pub fn register_recv_waker(&mut self, waker: &Waker) {
132 self.rx_waker.register(waker)
133 }
134
135 #[cfg(feature = "async")]
149 pub fn register_send_waker(&mut self, waker: &Waker) {
150 self.tx_waker.register(waker)
151 }
152
153 #[inline]
155 pub fn ip_version(&self) -> IpVersion {
156 self.ip_version
157 }
158
159 #[inline]
161 pub fn ip_protocol(&self) -> IpProtocol {
162 self.ip_protocol
163 }
164
165 #[inline]
167 pub fn can_send(&self) -> bool {
168 !self.tx_buffer.is_full()
169 }
170
171 #[inline]
173 pub fn can_recv(&self) -> bool {
174 !self.rx_buffer.is_empty()
175 }
176
177 #[inline]
179 pub fn packet_recv_capacity(&self) -> usize {
180 self.rx_buffer.packet_capacity()
181 }
182
183 #[inline]
185 pub fn packet_send_capacity(&self) -> usize {
186 self.tx_buffer.packet_capacity()
187 }
188
189 #[inline]
191 pub fn payload_recv_capacity(&self) -> usize {
192 self.rx_buffer.payload_capacity()
193 }
194
195 #[inline]
197 pub fn payload_send_capacity(&self) -> usize {
198 self.tx_buffer.payload_capacity()
199 }
200
201 pub fn send(&mut self, size: usize) -> Result<&mut [u8], SendError> {
213 let packet_buf = self
214 .tx_buffer
215 .enqueue(size, ())
216 .map_err(|_| SendError::BufferFull)?;
217
218 net_trace!(
219 "raw:{}:{}: buffer to send {} octets",
220 self.ip_version,
221 self.ip_protocol,
222 packet_buf.len()
223 );
224 Ok(packet_buf)
225 }
226
227 pub fn send_with<F>(&mut self, max_size: usize, f: F) -> Result<usize, SendError>
232 where
233 F: FnOnce(&mut [u8]) -> usize,
234 {
235 let size = self
236 .tx_buffer
237 .enqueue_with_infallible(max_size, (), f)
238 .map_err(|_| SendError::BufferFull)?;
239
240 net_trace!(
241 "raw:{}:{}: buffer to send {} octets",
242 self.ip_version,
243 self.ip_protocol,
244 size
245 );
246
247 Ok(size)
248 }
249
250 pub fn send_slice(&mut self, data: &[u8]) -> Result<(), SendError> {
254 self.send(data.len())?.copy_from_slice(data);
255 Ok(())
256 }
257
258 pub fn recv(&mut self) -> Result<&[u8], RecvError> {
265 let ((), packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
266
267 net_trace!(
268 "raw:{}:{}: receive {} buffered octets",
269 self.ip_version,
270 self.ip_protocol,
271 packet_buf.len()
272 );
273 Ok(packet_buf)
274 }
275
276 pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError> {
283 let buffer = self.recv()?;
284 if data.len() < buffer.len() {
285 return Err(RecvError::Truncated);
286 }
287
288 let length = min(data.len(), buffer.len());
289 data[..length].copy_from_slice(&buffer[..length]);
290 Ok(length)
291 }
292
293 pub fn peek(&mut self) -> Result<&[u8], RecvError> {
299 let ((), packet_buf) = self.rx_buffer.peek().map_err(|_| RecvError::Exhausted)?;
300
301 net_trace!(
302 "raw:{}:{}: receive {} buffered octets",
303 self.ip_version,
304 self.ip_protocol,
305 packet_buf.len()
306 );
307
308 Ok(packet_buf)
309 }
310
311 pub fn peek_slice(&mut self, data: &mut [u8]) -> Result<usize, RecvError> {
320 let buffer = self.peek()?;
321 if data.len() < buffer.len() {
322 return Err(RecvError::Truncated);
323 }
324
325 let length = min(data.len(), buffer.len());
326 data[..length].copy_from_slice(&buffer[..length]);
327 Ok(length)
328 }
329
330 pub fn send_queue(&self) -> usize {
332 self.tx_buffer.payload_bytes_count()
333 }
334
335 pub fn recv_queue(&self) -> usize {
337 self.rx_buffer.payload_bytes_count()
338 }
339
340 pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool {
341 if ip_repr.version() != self.ip_version {
342 return false;
343 }
344 if ip_repr.next_header() != self.ip_protocol {
345 return false;
346 }
347
348 true
349 }
350
351 pub(crate) fn process(&mut self, cx: &mut Context, ip_repr: &IpRepr, payload: &[u8]) {
352 debug_assert!(self.accepts(ip_repr));
353
354 let header_len = ip_repr.header_len();
355 let total_len = header_len + payload.len();
356
357 net_trace!(
358 "raw:{}:{}: receiving {} octets",
359 self.ip_version,
360 self.ip_protocol,
361 total_len
362 );
363
364 match self.rx_buffer.enqueue(total_len, ()) {
365 Ok(buf) => {
366 ip_repr.emit(&mut buf[..header_len], &cx.checksum_caps());
367 buf[header_len..].copy_from_slice(payload);
368 }
369 Err(_) => net_trace!(
370 "raw:{}:{}: buffer full, dropped incoming packet",
371 self.ip_version,
372 self.ip_protocol
373 ),
374 }
375
376 #[cfg(feature = "async")]
377 self.rx_waker.wake();
378 }
379
380 pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
381 where
382 F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<(), E>,
383 {
384 let ip_protocol = self.ip_protocol;
385 let ip_version = self.ip_version;
386 let _checksum_caps = &cx.checksum_caps();
387 let res = self.tx_buffer.dequeue_with(|&mut (), buffer| {
388 match IpVersion::of_packet(buffer) {
389 #[cfg(feature = "proto-ipv4")]
390 Ok(IpVersion::Ipv4) => {
391 let mut packet = match Ipv4Packet::new_checked(buffer) {
392 Ok(x) => x,
393 Err(_) => {
394 net_trace!("raw: malformed ipv6 packet in queue, dropping.");
395 return Ok(());
396 }
397 };
398 if packet.next_header() != ip_protocol {
399 net_trace!("raw: sent packet with wrong ip protocol, dropping.");
400 return Ok(());
401 }
402 if _checksum_caps.ipv4.tx() {
403 packet.fill_checksum();
404 } else {
405 packet.set_checksum(0);
408 }
409
410 let packet = Ipv4Packet::new_unchecked(&*packet.into_inner());
411 let ipv4_repr = match Ipv4Repr::parse(&packet, _checksum_caps) {
412 Ok(x) => x,
413 Err(_) => {
414 net_trace!("raw: malformed ipv4 packet in queue, dropping.");
415 return Ok(());
416 }
417 };
418 net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
419 emit(cx, (IpRepr::Ipv4(ipv4_repr), packet.payload()))
420 }
421 #[cfg(feature = "proto-ipv6")]
422 Ok(IpVersion::Ipv6) => {
423 let packet = match Ipv6Packet::new_checked(buffer) {
424 Ok(x) => x,
425 Err(_) => {
426 net_trace!("raw: malformed ipv6 packet in queue, dropping.");
427 return Ok(());
428 }
429 };
430 if packet.next_header() != ip_protocol {
431 net_trace!("raw: sent ipv6 packet with wrong ip protocol, dropping.");
432 return Ok(());
433 }
434 let packet = Ipv6Packet::new_unchecked(&*packet.into_inner());
435 let ipv6_repr = match Ipv6Repr::parse(&packet) {
436 Ok(x) => x,
437 Err(_) => {
438 net_trace!("raw: malformed ipv6 packet in queue, dropping.");
439 return Ok(());
440 }
441 };
442
443 net_trace!("raw:{}:{}: sending", ip_version, ip_protocol);
444 emit(cx, (IpRepr::Ipv6(ipv6_repr), packet.payload()))
445 }
446 Err(_) => {
447 net_trace!("raw: sent packet with invalid IP version, dropping.");
448 Ok(())
449 }
450 }
451 });
452 match res {
453 Err(Empty) => Ok(()),
454 Ok(Err(e)) => Err(e),
455 Ok(Ok(())) => {
456 #[cfg(feature = "async")]
457 self.tx_waker.wake();
458 Ok(())
459 }
460 }
461 }
462
463 pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
464 if self.tx_buffer.is_empty() {
465 PollAt::Ingress
466 } else {
467 PollAt::Now
468 }
469 }
470}
471
472#[cfg(test)]
473mod test {
474 use crate::phy::Medium;
475 use crate::tests::setup;
476 use rstest::*;
477
478 use super::*;
479 use crate::wire::IpRepr;
480 #[cfg(feature = "proto-ipv4")]
481 use crate::wire::{Ipv4Address, Ipv4Repr};
482 #[cfg(feature = "proto-ipv6")]
483 use crate::wire::{Ipv6Address, Ipv6Repr};
484
485 fn buffer(packets: usize) -> PacketBuffer<'static> {
486 PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 48 * packets])
487 }
488
489 #[cfg(feature = "proto-ipv4")]
490 mod ipv4_locals {
491 use super::*;
492
493 pub fn socket(
494 rx_buffer: PacketBuffer<'static>,
495 tx_buffer: PacketBuffer<'static>,
496 ) -> Socket<'static> {
497 Socket::new(
498 IpVersion::Ipv4,
499 IpProtocol::Unknown(IP_PROTO),
500 rx_buffer,
501 tx_buffer,
502 )
503 }
504
505 pub const IP_PROTO: u8 = 63;
506 pub const HEADER_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
507 src_addr: Ipv4Address::new(10, 0, 0, 1),
508 dst_addr: Ipv4Address::new(10, 0, 0, 2),
509 next_header: IpProtocol::Unknown(IP_PROTO),
510 payload_len: 4,
511 hop_limit: 64,
512 });
513 pub const PACKET_BYTES: [u8; 24] = [
514 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x0a, 0x00,
515 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0xff,
516 ];
517 pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
518 }
519
520 #[cfg(feature = "proto-ipv6")]
521 mod ipv6_locals {
522 use super::*;
523
524 pub fn socket(
525 rx_buffer: PacketBuffer<'static>,
526 tx_buffer: PacketBuffer<'static>,
527 ) -> Socket<'static> {
528 Socket::new(
529 IpVersion::Ipv6,
530 IpProtocol::Unknown(IP_PROTO),
531 rx_buffer,
532 tx_buffer,
533 )
534 }
535
536 pub const IP_PROTO: u8 = 63;
537 pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
538 src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
539 dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
540 next_header: IpProtocol::Unknown(IP_PROTO),
541 payload_len: 4,
542 hop_limit: 64,
543 });
544
545 pub const PACKET_BYTES: [u8; 44] = [
546 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00,
549 0x00, 0xff,
550 ];
551
552 pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
553 }
554
555 macro_rules! reusable_ip_specific_tests {
556 ($module:ident, $socket:path, $hdr:path, $packet:path, $payload:path) => {
557 mod $module {
558 use super::*;
559
560 #[test]
561 fn test_send_truncated() {
562 let mut socket = $socket(buffer(0), buffer(1));
563 assert_eq!(socket.send_slice(&[0; 56][..]), Err(SendError::BufferFull));
564 }
565
566 #[rstest]
567 #[case::ip(Medium::Ip)]
568 #[cfg(feature = "medium-ip")]
569 #[case::ethernet(Medium::Ethernet)]
570 #[cfg(feature = "medium-ethernet")]
571 #[case::ieee802154(Medium::Ieee802154)]
572 #[cfg(feature = "medium-ieee802154")]
573 fn test_send_dispatch(#[case] medium: Medium) {
574 let (mut iface, _, _) = setup(medium);
575 let mut cx = iface.context();
576 let mut socket = $socket(buffer(0), buffer(1));
577
578 assert!(socket.can_send());
579 assert_eq!(
580 socket.dispatch(&mut cx, |_, _| unreachable!()),
581 Ok::<_, ()>(())
582 );
583
584 assert_eq!(socket.send_slice(&$packet[..]), Ok(()));
585 assert_eq!(socket.send_slice(b""), Err(SendError::BufferFull));
586 assert!(!socket.can_send());
587
588 assert_eq!(
589 socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
590 assert_eq!(ip_repr, $hdr);
591 assert_eq!(ip_payload, &$payload);
592 Err(())
593 }),
594 Err(())
595 );
596 assert!(!socket.can_send());
597
598 assert_eq!(
599 socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
600 assert_eq!(ip_repr, $hdr);
601 assert_eq!(ip_payload, &$payload);
602 Ok::<_, ()>(())
603 }),
604 Ok(())
605 );
606 assert!(socket.can_send());
607 }
608
609 #[rstest]
610 #[case::ip(Medium::Ip)]
611 #[cfg(feature = "medium-ip")]
612 #[case::ethernet(Medium::Ethernet)]
613 #[cfg(feature = "medium-ethernet")]
614 #[case::ieee802154(Medium::Ieee802154)]
615 #[cfg(feature = "medium-ieee802154")]
616 fn test_recv_truncated_slice(#[case] medium: Medium) {
617 let (mut iface, _, _) = setup(medium);
618 let mut cx = iface.context();
619 let mut socket = $socket(buffer(1), buffer(0));
620
621 assert!(socket.accepts(&$hdr));
622 socket.process(&mut cx, &$hdr, &$payload);
623
624 let mut slice = [0; 4];
625 assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated));
626 }
627
628 #[rstest]
629 #[case::ip(Medium::Ip)]
630 #[cfg(feature = "medium-ip")]
631 #[case::ethernet(Medium::Ethernet)]
632 #[cfg(feature = "medium-ethernet")]
633 #[case::ieee802154(Medium::Ieee802154)]
634 #[cfg(feature = "medium-ieee802154")]
635 fn test_recv_truncated_packet(#[case] medium: Medium) {
636 let (mut iface, _, _) = setup(medium);
637 let mut cx = iface.context();
638 let mut socket = $socket(buffer(1), buffer(0));
639
640 let mut buffer = vec![0; 128];
641 buffer[..$packet.len()].copy_from_slice(&$packet[..]);
642
643 assert!(socket.accepts(&$hdr));
644 socket.process(&mut cx, &$hdr, &buffer);
645 }
646
647 #[rstest]
648 #[case::ip(Medium::Ip)]
649 #[cfg(feature = "medium-ip")]
650 #[case::ethernet(Medium::Ethernet)]
651 #[cfg(feature = "medium-ethernet")]
652 #[case::ieee802154(Medium::Ieee802154)]
653 #[cfg(feature = "medium-ieee802154")]
654 fn test_peek_truncated_slice(#[case] medium: Medium) {
655 let (mut iface, _, _) = setup(medium);
656 let mut cx = iface.context();
657 let mut socket = $socket(buffer(1), buffer(0));
658
659 assert!(socket.accepts(&$hdr));
660 socket.process(&mut cx, &$hdr, &$payload);
661
662 let mut slice = [0; 4];
663 assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Truncated));
664 assert_eq!(socket.recv_slice(&mut slice[..]), Err(RecvError::Truncated));
665 assert_eq!(socket.peek_slice(&mut slice[..]), Err(RecvError::Exhausted));
666 }
667 }
668 };
669 }
670
671 #[cfg(feature = "proto-ipv4")]
672 reusable_ip_specific_tests!(
673 ipv4,
674 ipv4_locals::socket,
675 ipv4_locals::HEADER_REPR,
676 ipv4_locals::PACKET_BYTES,
677 ipv4_locals::PACKET_PAYLOAD
678 );
679
680 #[cfg(feature = "proto-ipv6")]
681 reusable_ip_specific_tests!(
682 ipv6,
683 ipv6_locals::socket,
684 ipv6_locals::HEADER_REPR,
685 ipv6_locals::PACKET_BYTES,
686 ipv6_locals::PACKET_PAYLOAD
687 );
688
689 #[rstest]
690 #[case::ip(Medium::Ip)]
691 #[case::ethernet(Medium::Ethernet)]
692 #[cfg(feature = "medium-ethernet")]
693 #[case::ieee802154(Medium::Ieee802154)]
694 #[cfg(feature = "medium-ieee802154")]
695 fn test_send_illegal(#[case] medium: Medium) {
696 #[cfg(feature = "proto-ipv4")]
697 {
698 let (mut iface, _, _) = setup(medium);
699 let cx = iface.context();
700 let mut socket = ipv4_locals::socket(buffer(0), buffer(2));
701
702 let mut wrong_version = ipv4_locals::PACKET_BYTES;
703 Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6);
704
705 assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
706 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
707
708 let mut wrong_protocol = ipv4_locals::PACKET_BYTES;
709 Ipv4Packet::new_unchecked(&mut wrong_protocol).set_next_header(IpProtocol::Tcp);
710
711 assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
712 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
713 }
714 #[cfg(feature = "proto-ipv6")]
715 {
716 let (mut iface, _, _) = setup(medium);
717 let cx = iface.context();
718 let mut socket = ipv6_locals::socket(buffer(0), buffer(2));
719
720 let mut wrong_version = ipv6_locals::PACKET_BYTES;
721 Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4);
722
723 assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
724 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
725
726 let mut wrong_protocol = ipv6_locals::PACKET_BYTES;
727 Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp);
728
729 assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
730 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
731 }
732 }
733
734 #[rstest]
735 #[case::ip(Medium::Ip)]
736 #[cfg(feature = "medium-ip")]
737 #[case::ethernet(Medium::Ethernet)]
738 #[cfg(feature = "medium-ethernet")]
739 #[case::ieee802154(Medium::Ieee802154)]
740 #[cfg(feature = "medium-ieee802154")]
741 fn test_recv_process(#[case] medium: Medium) {
742 #[cfg(feature = "proto-ipv4")]
743 {
744 let (mut iface, _, _) = setup(medium);
745 let cx = iface.context();
746 let mut socket = ipv4_locals::socket(buffer(1), buffer(0));
747 assert!(!socket.can_recv());
748
749 let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
750 Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
751
752 assert_eq!(socket.recv(), Err(RecvError::Exhausted));
753 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
754 socket.process(cx, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD);
755 assert!(socket.can_recv());
756
757 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
758 socket.process(cx, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD);
759 assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
760 assert!(!socket.can_recv());
761 }
762 #[cfg(feature = "proto-ipv6")]
763 {
764 let (mut iface, _, _) = setup(medium);
765 let cx = iface.context();
766 let mut socket = ipv6_locals::socket(buffer(1), buffer(0));
767 assert!(!socket.can_recv());
768
769 assert_eq!(socket.recv(), Err(RecvError::Exhausted));
770 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
771 socket.process(cx, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD);
772 assert!(socket.can_recv());
773
774 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
775 socket.process(cx, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD);
776 assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
777 assert!(!socket.can_recv());
778 }
779 }
780
781 #[rstest]
782 #[case::ip(Medium::Ip)]
783 #[case::ethernet(Medium::Ethernet)]
784 #[cfg(feature = "medium-ethernet")]
785 #[case::ieee802154(Medium::Ieee802154)]
786 #[cfg(feature = "medium-ieee802154")]
787 fn test_peek_process(#[case] medium: Medium) {
788 #[cfg(feature = "proto-ipv4")]
789 {
790 let (mut iface, _, _) = setup(medium);
791 let cx = iface.context();
792 let mut socket = ipv4_locals::socket(buffer(1), buffer(0));
793
794 let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
795 Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
796
797 assert_eq!(socket.peek(), Err(RecvError::Exhausted));
798 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
799 socket.process(cx, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD);
800
801 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
802 socket.process(cx, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD);
803 assert_eq!(socket.peek(), Ok(&cksumd_packet[..]));
804 assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
805 assert_eq!(socket.peek(), Err(RecvError::Exhausted));
806 }
807 #[cfg(feature = "proto-ipv6")]
808 {
809 let (mut iface, _, _) = setup(medium);
810 let cx = iface.context();
811 let mut socket = ipv6_locals::socket(buffer(1), buffer(0));
812
813 assert_eq!(socket.peek(), Err(RecvError::Exhausted));
814 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
815 socket.process(cx, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD);
816
817 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
818 socket.process(cx, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD);
819 assert_eq!(socket.peek(), Ok(&ipv6_locals::PACKET_BYTES[..]));
820 assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
821 assert_eq!(socket.peek(), Err(RecvError::Exhausted));
822 }
823 }
824
825 #[test]
826 fn test_doesnt_accept_wrong_proto() {
827 #[cfg(feature = "proto-ipv4")]
828 {
829 let socket = Socket::new(
830 IpVersion::Ipv4,
831 IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1),
832 buffer(1),
833 buffer(1),
834 );
835 assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
836 #[cfg(feature = "proto-ipv6")]
837 assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
838 }
839 #[cfg(feature = "proto-ipv6")]
840 {
841 let socket = Socket::new(
842 IpVersion::Ipv6,
843 IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1),
844 buffer(1),
845 buffer(1),
846 );
847 assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
848 #[cfg(feature = "proto-ipv4")]
849 assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
850 }
851 }
852}