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