1use alloc::collections::BTreeMap;
7use alloc::string::String;
8use alloc::sync::{Arc, Weak};
9use alloc::vec::Vec;
10use spin::{Mutex, RwLock};
11
12use crate::early_println;
13use crate::network::Ipv4Address;
14use crate::network::protocol_stack::get_network_manager;
15use crate::network::protocol_stack::{LayerContext, NetworkLayer, NetworkLayerStats, SocketConfig};
16use crate::network::socket::{
17 Inet4SocketAddress, SocketAddress, SocketControl, SocketError, SocketObject, SocketProtocol,
18 SocketState, SocketType,
19};
20use crate::object::capability::selectable::Selectable;
21
22fn get_local_ip_bytes() -> [u8; 4] {
24 let manager = get_network_manager();
25 if let Some(default_iface) = manager.get_default_interface() {
26 if let Some(ip_layer) = manager.get_layer("ip") {
27 if let Some(ipv4_layer) = ip_layer
28 .as_any()
29 .downcast_ref::<crate::network::ipv4::Ipv4Layer>()
30 {
31 if let Some(addr) = ipv4_layer.get_primary_ip(default_iface.name()) {
32 return addr.as_bytes();
33 }
34 }
35 }
36 }
37 [0u8; 4]
38}
39
40#[derive(Debug, Clone, Copy)]
42#[repr(C, packed)]
43pub struct UdpHeader {
44 pub src_port: u16,
46 pub dst_port: u16,
48 pub length: u16,
50 pub checksum: u16,
52}
53
54impl UdpHeader {
55 pub fn new(src_port: u16, dst_port: u16, length: u16) -> Self {
57 Self {
58 src_port,
59 dst_port,
60 length,
61 checksum: 0,
62 }
63 }
64
65 pub fn calculate_checksum(&self, src_ip: [u8; 4], dst_ip: [u8; 4], data: &[u8]) -> u16 {
67 let mut sum: u32 = 0;
68
69 sum += u16::from_be_bytes([src_ip[0], src_ip[1]]) as u32;
71 sum = (sum & 0xFFFF) + (sum >> 16);
72 sum += u16::from_be_bytes([src_ip[2], src_ip[3]]) as u32;
73 sum = (sum & 0xFFFF) + (sum >> 16);
74 sum += u16::from_be_bytes([dst_ip[0], dst_ip[1]]) as u32;
75 sum = (sum & 0xFFFF) + (sum >> 16);
76 sum += u16::from_be_bytes([dst_ip[2], dst_ip[3]]) as u32;
77 sum = (sum & 0xFFFF) + (sum >> 16);
78 sum += 17u32; sum = (sum & 0xFFFF) + (sum >> 16);
80 sum += self.length as u32;
81 sum = (sum & 0xFFFF) + (sum >> 16);
82
83 sum += self.src_port as u32;
85 sum = (sum & 0xFFFF) + (sum >> 16);
86 sum += self.dst_port as u32;
87 sum = (sum & 0xFFFF) + (sum >> 16);
88 sum += self.length as u32;
89 sum = (sum & 0xFFFF) + (sum >> 16);
90
91 for chunk in data.chunks(2) {
93 if chunk.len() == 2 {
94 sum += u16::from_be_bytes([chunk[0], chunk[1]]) as u32;
95 sum = (sum & 0xFFFF) + (sum >> 16);
96 } else if chunk.len() == 1 {
97 sum += (chunk[0] as u32) << 8;
98 sum = (sum & 0xFFFF) + (sum >> 16);
99 }
100 }
101
102 while sum >> 16 != 0 {
104 sum = (sum & 0xFFFF) + (sum >> 16);
105 }
106
107 !sum as u16
108 }
109
110 pub fn to_bytes(&self) -> [u8; 8] {
112 let mut bytes = [0u8; 8];
113 bytes[0..2].copy_from_slice(&self.src_port.to_be_bytes());
114 bytes[2..4].copy_from_slice(&self.dst_port.to_be_bytes());
115 bytes[4..6].copy_from_slice(&self.length.to_be_bytes());
116 bytes[6..8].copy_from_slice(&self.checksum.to_be_bytes());
117 bytes
118 }
119
120 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
122 if bytes.len() < 8 {
123 return None;
124 }
125
126 Some(Self {
127 src_port: u16::from_be_bytes([bytes[0], bytes[1]]),
128 dst_port: u16::from_be_bytes([bytes[2], bytes[3]]),
129 length: u16::from_be_bytes([bytes[4], bytes[5]]),
130 checksum: u16::from_be_bytes([bytes[6], bytes[7]]),
131 })
132 }
133}
134
135pub struct UdpSocket {
139 local_addr: RwLock<Option<SocketAddress>>,
141 remote_addr: RwLock<Option<SocketAddress>>,
143 send_buffer: Mutex<Vec<Vec<u8>>>,
145 recv_buffer: Mutex<Vec<Vec<u8>>>,
147 state: RwLock<SocketState>,
149 udp_layer: Arc<UdpLayer>,
151 self_weak: Weak<UdpSocket>,
153 recv_waker: Mutex<Option<alloc::sync::Arc<crate::sync::Waker>>>,
155 send_waker: Mutex<Option<alloc::sync::Arc<crate::sync::Waker>>>,
157 blocking_mode: spin::Mutex<bool>,
159}
160
161impl UdpSocket {
162 pub fn new(udp_layer: Arc<UdpLayer>) -> Arc<Self> {
164 Arc::new_cyclic(|weak| Self {
165 local_addr: RwLock::new(None),
166 remote_addr: RwLock::new(None),
167 send_buffer: Mutex::new(Vec::new()),
168 recv_buffer: Mutex::new(Vec::new()),
169 state: RwLock::new(SocketState::Unconnected),
170 udp_layer,
171 self_weak: weak.clone(),
172 recv_waker: Mutex::new(None),
173 send_waker: Mutex::new(None),
174 blocking_mode: spin::Mutex::new(true),
175 })
176 }
177
178 pub fn deliver_datagram(&self, data: Vec<u8>) {
180 self.recv_buffer.lock().push(data);
181 if let Some(waker) = self.recv_waker.lock().as_ref() {
183 waker.wake_one();
184 }
185 }
186}
187
188impl SocketObject for UdpSocket {
189 fn socket_type(&self) -> SocketType {
190 SocketType::Datagram
191 }
192
193 fn socket_domain(&self) -> crate::network::socket::SocketDomain {
194 crate::network::socket::SocketDomain::Inet4
195 }
196
197 fn socket_protocol(&self) -> SocketProtocol {
198 SocketProtocol::Udp
199 }
200
201 fn as_any(&self) -> &dyn core::any::Any {
202 self
203 }
204
205 fn sendto(
206 &self,
207 data: &[u8],
208 address: &SocketAddress,
209 _flags: u32,
210 ) -> Result<usize, SocketError> {
211 match address {
212 SocketAddress::Inet(inet) => {
213 let addr = inet.addr;
214 let port = inet.port;
215 let mut buffer = self.send_buffer.lock();
217 let datagram = data.to_vec();
218 buffer.push(datagram.clone());
219
220 *self.remote_addr.write() = Some(address.clone());
222 *self.state.write() = SocketState::Connected;
223
224 self.udp_layer.send_datagram(self, addr, port, datagram)?;
226
227 Ok(data.len())
228 }
229 _ => Err(SocketError::InvalidAddress),
230 }
231 }
232
233 fn recvfrom(
234 &self,
235 buffer: &mut [u8],
236 _flags: u32,
237 ) -> Result<(usize, SocketAddress), SocketError> {
238 if !self.is_nonblocking() {
240 let interest = crate::object::capability::selectable::ReadyInterest {
241 read: true,
242 write: false,
243 except: false,
244 };
245 let task = crate::task::mytask();
246 if let Some(t) = task {
247 let trapframe = t.get_trapframe();
248 Selectable::wait_until_ready(self, interest, trapframe, None);
249 }
250 }
251
252 let mut recv_buf = self.recv_buffer.lock();
253
254 if recv_buf.is_empty() {
255 return Err(SocketError::WouldBlock);
256 }
257
258 let datagram = recv_buf.remove(0);
259 let len = buffer.len().min(datagram.len());
260 buffer[..len].copy_from_slice(&datagram[..len]);
261
262 Ok((
263 len,
264 self.remote_addr
265 .read()
266 .clone()
267 .unwrap_or(SocketAddress::Unspecified),
268 ))
269 }
270}
271
272impl SocketControl for UdpSocket {
273 fn bind(&self, address: &SocketAddress) -> Result<(), SocketError> {
274 match address {
275 SocketAddress::Inet(inet) => {
276 let addr = inet.addr;
277 let port = inet.port;
278 let mut config = SocketConfig::new();
279 config.set("udp_local_port", &port.to_be_bytes());
280 config.set("ip_local", &addr);
281
282 self.udp_layer
284 .configure_socket(self.self_weak.clone(), &config)?;
285
286 *self.local_addr.write() = Some(address.clone());
287 *self.state.write() = SocketState::Bound;
288 Ok(())
289 }
290 _ => Err(SocketError::InvalidAddress),
291 }
292 }
293
294 fn connect(&self, address: &SocketAddress) -> Result<(), SocketError> {
295 match address {
296 SocketAddress::Inet(_) => {
297 *self.remote_addr.write() = Some(address.clone());
298 *self.state.write() = SocketState::Connected;
299 Ok(())
300 }
301 _ => Err(SocketError::InvalidAddress),
302 }
303 }
304
305 fn listen(&self, _backlog: usize) -> Result<(), SocketError> {
306 Err(SocketError::NotSupported)
307 }
308
309 fn accept(&self) -> Result<Arc<dyn SocketObject>, SocketError> {
310 Err(SocketError::NotSupported)
311 }
312
313 fn getpeername(&self) -> Result<SocketAddress, SocketError> {
314 self.remote_addr
315 .read()
316 .clone()
317 .ok_or(SocketError::NotConnected)
318 }
319
320 fn getsockname(&self) -> Result<SocketAddress, SocketError> {
321 self.local_addr
322 .read()
323 .clone()
324 .ok_or(SocketError::InvalidAddress)
325 }
326
327 fn shutdown(&self, _how: crate::network::socket::ShutdownHow) -> Result<(), SocketError> {
328 *self.state.write() = SocketState::Closed;
329 Ok(())
330 }
331
332 fn is_connected(&self) -> bool {
333 *self.state.read() == SocketState::Connected
334 }
335
336 fn state(&self) -> SocketState {
337 *self.state.read()
338 }
339}
340
341impl crate::ipc::StreamIpcOps for UdpSocket {
342 fn is_connected(&self) -> bool {
343 SocketControl::is_connected(self)
344 }
345
346 fn peer_count(&self) -> usize {
347 if SocketControl::is_connected(self) {
348 1
349 } else {
350 0
351 }
352 }
353
354 fn description(&self) -> String {
355 alloc::format!("UDP socket")
356 }
357}
358
359impl crate::object::capability::StreamOps for UdpSocket {
360 fn read(&self, buffer: &mut [u8]) -> Result<usize, crate::object::capability::StreamError> {
361 use crate::object::capability::selectable::Selectable;
362
363 if !Selectable::is_nonblocking(self) {
364 let task = crate::task::mytask();
366 if let Some(t) = task {
367 let trapframe = t.get_trapframe();
368 let interest = crate::object::capability::selectable::ReadyInterest {
369 read: true,
370 write: false,
371 except: false,
372 };
373 Selectable::wait_until_ready(self, interest, trapframe, None);
374 }
375 }
376
377 let (len, _) = self.recvfrom(buffer, 0).map_err(|e| match e {
378 SocketError::WouldBlock => crate::object::capability::StreamError::WouldBlock,
379 _ => crate::object::capability::StreamError::Other("udp recv error".into()),
380 })?;
381 Ok(len)
382 }
383
384 fn write(&self, data: &[u8]) -> Result<usize, crate::object::capability::StreamError> {
385 let remote_addr = self
386 .remote_addr
387 .read()
388 .clone()
389 .unwrap_or(SocketAddress::Unspecified);
390 self.sendto(data, &remote_addr, 0)
391 .map_err(|_| crate::object::capability::StreamError::Other("udp send error".into()))?;
392 Ok(data.len())
393 }
394}
395
396impl crate::object::capability::CloneOps for UdpSocket {
397 fn custom_clone(&self) -> crate::object::KernelObject {
398 crate::object::KernelObject::Socket(UdpSocket::new(self.udp_layer.clone()))
399 }
400}
401
402impl crate::object::capability::Selectable for UdpSocket {
403 fn current_ready(
404 &self,
405 interest: crate::object::capability::selectable::ReadyInterest,
406 ) -> crate::object::capability::selectable::ReadySet {
407 let mut ready = crate::object::capability::selectable::ReadySet::none();
408
409 if interest.read {
410 let recv_buf = self.recv_buffer.lock();
411 ready.read = !recv_buf.is_empty();
412 }
413
414 if interest.write {
415 ready.write = true;
417 }
418
419 ready
420 }
421
422 fn wait_until_ready(
423 &self,
424 interest: crate::object::capability::selectable::ReadyInterest,
425 trapframe: &mut crate::arch::Trapframe,
426 timeout_ticks: Option<u64>,
427 ) -> crate::object::capability::selectable::SelectWaitOutcome {
428 let current = self.current_ready(interest);
429 if (interest.read && current.read) || (interest.write && current.write) {
430 return crate::object::capability::selectable::SelectWaitOutcome::Ready;
431 }
432
433 let task_id = {
434 use crate::arch::get_cpu;
435 use crate::sched::scheduler::get_scheduler;
436 let cpu_id = get_cpu().get_cpuid();
437 get_scheduler().get_current_task_id(cpu_id).unwrap_or(0)
438 };
439
440 let woke = if interest.read {
441 let waker = {
442 let mut waker_lock = self.recv_waker.lock();
443 waker_lock
444 .get_or_insert_with(|| {
445 alloc::sync::Arc::new(crate::sync::Waker::new_interruptible("udp_recv"))
446 })
447 .clone()
448 };
449 waker.wait_with_timeout(task_id, trapframe, timeout_ticks)
450 } else {
451 true
452 };
453
454 if timeout_ticks.is_some() && !woke {
455 let after = self.current_ready(interest);
456 if (interest.read && !after.read) && (interest.write && !after.write) {
457 return crate::object::capability::selectable::SelectWaitOutcome::TimedOut;
458 }
459 }
460
461 crate::object::capability::selectable::SelectWaitOutcome::Ready
462 }
463
464 fn set_nonblocking(&self, enabled: bool) {
465 *self.blocking_mode.lock() = !enabled;
466 }
467
468 fn is_nonblocking(&self) -> bool {
469 !*self.blocking_mode.lock()
470 }
471}
472
473pub struct UdpLayer {
477 port_map: RwLock<BTreeMap<u16, alloc::sync::Weak<UdpSocket>>>,
479 next_ephemeral_port: Mutex<u16>,
481 stats: RwLock<NetworkLayerStats>,
483 self_weak: Weak<UdpLayer>,
484}
485
486impl UdpLayer {
487 pub fn new() -> Arc<Self> {
489 Arc::new_cyclic(|weak| Self {
490 port_map: RwLock::new(BTreeMap::new()),
491 next_ephemeral_port: Mutex::new(49152),
492 stats: RwLock::new(NetworkLayerStats::default()),
493 self_weak: weak.clone(),
494 })
495 }
496
497 pub fn init(network_manager: &crate::network::NetworkManager) {
506 let layer = Self::new();
507 network_manager.register_layer("udp", layer.clone());
508
509 let ipv4 = network_manager
511 .get_layer("ip")
512 .expect("Ipv4Layer must be initialized before UdpLayer");
513 ipv4.register_protocol(crate::network::ipv4::protocol::UDP as u16, layer);
514 }
515
516 pub fn create_socket(&self) -> Arc<UdpSocket> {
518 let layer = self
519 .self_weak
520 .upgrade()
521 .expect("udp layer is not initialized");
522 UdpSocket::new(layer)
523 }
524
525 pub fn allocate_port(&self) -> u16 {
527 let mut next_port = self.next_ephemeral_port.lock();
528 let port = *next_port;
529
530 *next_port = if port == 65535 { 49152 } else { port + 1 };
531
532 port
533 }
534
535 pub fn register_port(&self, port: u16, socket: alloc::sync::Weak<UdpSocket>) {
537 self.port_map.write().insert(port, socket);
538 }
539
540 pub fn unregister_socket(&self, port: u16, socket: &alloc::sync::Weak<UdpSocket>) {
544 let mut map = self.port_map.write();
545 if let Some(existing) = map.get(&port) {
546 if existing.ptr_eq(socket) {
547 map.remove(&port);
548 }
549 }
550 }
551
552 pub fn find_socket(&self, port: u16) -> Option<Arc<UdpSocket>> {
554 self.port_map
555 .read()
556 .get(&port)
557 .and_then(|weak| weak.upgrade())
558 }
559
560 pub fn configure_socket(
562 &self,
563 socket: Weak<UdpSocket>,
564 config: &SocketConfig,
565 ) -> Result<(), SocketError> {
566 let port = config
567 .get_u16("udp_local_port")
568 .ok_or(SocketError::InvalidAddress)?;
569
570 self.register_port(port, socket);
572
573 Ok(())
575 }
576
577 pub fn send_datagram(
579 &self,
580 socket: &UdpSocket,
581 dest_ip: [u8; 4],
582 dest_port: u16,
583 data: Vec<u8>,
584 ) -> Result<(), SocketError> {
585 let (src_ip_bytes, src_port) = match socket.local_addr.read().clone() {
586 Some(SocketAddress::Inet(inet)) => {
587 if inet.addr == [0, 0, 0, 0] {
588 let ip = get_local_ip_bytes();
589 (ip, inet.port)
590 } else {
591 (inet.addr, inet.port)
592 }
593 }
594 _ => {
595 let ip = get_local_ip_bytes();
597 let port = self.allocate_port();
599 self.register_port(port, socket.self_weak.clone());
600 (ip, port)
601 }
602 };
603
604 let total_length = (8 + data.len()) as u16;
605
606 let mut header = UdpHeader::new(src_port, dest_port, total_length);
607
608 header.checksum = header.calculate_checksum(src_ip_bytes, dest_ip, &data);
609
610 let mut udp_packet = Vec::with_capacity(8 + data.len());
611 udp_packet.extend_from_slice(&header.to_bytes());
612 udp_packet.extend_from_slice(&data);
613
614 let mut ip_context = LayerContext::new();
615 ip_context.set("ip_src", &src_ip_bytes);
616 ip_context.set("ip_dst", &dest_ip);
617 ip_context.set("ip_protocol", &[17]);
618
619 early_println!(
620 "[UDP] Send: {} bytes (src port: {}, dst: {}.{}.{}.{})",
621 udp_packet.len(),
622 src_port,
623 dest_ip[0],
624 dest_ip[1],
625 dest_ip[2],
626 dest_ip[3]
627 );
628
629 if let Some(ip_layer) = get_network_manager().get_layer("ip") {
630 ip_layer.send(&udp_packet, &ip_context, &[])?;
631 }
632
633 let mut stats = self.stats.write();
634 stats.packets_sent += 1;
635 stats.bytes_sent += udp_packet.len() as u64;
636
637 Ok(())
638 }
639
640 pub fn receive_datagram(
642 &self,
643 src_ip: Ipv4Address,
644 src_port: u16,
645 dst_port: u16,
646 data: Vec<u8>,
647 ) {
648 let mut stats = self.stats.write();
649 stats.packets_received += 1;
650 stats.bytes_received += (8 + data.len()) as u64;
651
652 if let Some(socket) = self.find_socket(dst_port) {
653 socket.deliver_datagram(data);
654 let mut remote_lock = socket.remote_addr.write();
655 if remote_lock.is_none() {
656 *remote_lock = Some(SocketAddress::Inet(Inet4SocketAddress::new(
657 src_ip.0, src_port,
658 )));
659 }
660 }
661 }
662}
663
664impl NetworkLayer for UdpLayer {
665 fn register_protocol(&self, _proto_num: u16, _handler: Arc<dyn NetworkLayer>) {
666 }
668
669 fn send(
670 &self,
671 _packet: &[u8],
672 _context: &LayerContext,
673 _next_layers: &[Arc<dyn NetworkLayer>],
674 ) -> Result<(), SocketError> {
675 Ok(())
677 }
678
679 fn receive(&self, packet: &[u8], context: Option<&LayerContext>) -> Result<(), SocketError> {
680 let mut src_ip = Ipv4Address::new(0, 0, 0, 0);
681 let mut dst_ip = Ipv4Address::new(0, 0, 0, 0);
682 if let Some(ctx) = context {
683 if let Some(raw) = ctx.get("ip_src") {
684 if raw.len() >= 4 {
685 src_ip = Ipv4Address::new(raw[0], raw[1], raw[2], raw[3]);
686 }
687 }
688 if let Some(raw) = ctx.get("ip_dst") {
689 if raw.len() >= 4 {
690 dst_ip = Ipv4Address::new(raw[0], raw[1], raw[2], raw[3]);
691 }
692 }
693 }
694 self.receive_packet(src_ip, dst_ip, packet)
695 }
696
697 fn name(&self) -> &'static str {
698 "UDP"
699 }
700
701 fn stats(&self) -> NetworkLayerStats {
702 self.stats.read().clone()
703 }
704
705 fn as_any(&self) -> &dyn core::any::Any {
706 self
707 }
708}
709
710impl UdpLayer {
711 pub fn receive_packet(
713 &self,
714 src_ip: Ipv4Address,
715 _dst_ip: Ipv4Address,
716 packet: &[u8],
717 ) -> Result<(), SocketError> {
718 if packet.len() < 8 {
719 return Err(SocketError::InvalidPacket);
720 }
721
722 let header = UdpHeader::from_bytes(&packet[..8]).ok_or(SocketError::InvalidPacket)?;
724
725 let data_offset = header.length as usize;
726 if data_offset < 8 || data_offset > packet.len() {
727 return Err(SocketError::InvalidPacket);
728 }
729
730 let data = &packet[8..data_offset];
731
732 self.receive_datagram(src_ip, header.src_port, header.dst_port, data.to_vec());
734
735 Ok(())
736 }
737}
738
739#[cfg(test)]
740mod tests {
741 use super::*;
742
743 #[test_case]
744 fn test_udp_header_creation() {
745 let header = UdpHeader::new(1234, 5678, 100);
746
747 let src_port = unsafe { core::ptr::addr_of!(header.src_port).read_unaligned() };
748 let dst_port = unsafe { core::ptr::addr_of!(header.dst_port).read_unaligned() };
749 let length = unsafe { core::ptr::addr_of!(header.length).read_unaligned() };
750 assert_eq!(src_port, 1234);
751 assert_eq!(dst_port, 5678);
752 assert_eq!(length, 100);
753 }
754
755 #[test_case]
756 fn test_udp_header_serialization() {
757 let header = UdpHeader::new(1234, 5678, 100);
758 let bytes = header.to_bytes();
759
760 assert_eq!(bytes.len(), 8);
761 assert_eq!(u16::from_be_bytes([bytes[0], bytes[1]]), 1234);
762 assert_eq!(u16::from_be_bytes([bytes[2], bytes[3]]), 5678);
763 assert_eq!(u16::from_be_bytes([bytes[4], bytes[5]]), 100);
764 }
765
766 #[test_case]
767 fn test_udp_header_parsing() {
768 let mut bytes = [0u8; 8];
769 bytes[0..2].copy_from_slice(&1234u16.to_be_bytes());
770 bytes[2..4].copy_from_slice(&5678u16.to_be_bytes());
771 bytes[4..6].copy_from_slice(&100u16.to_be_bytes());
772 bytes[6..8].copy_from_slice(&0xABCDu16.to_be_bytes());
773
774 let header = UdpHeader::from_bytes(&bytes).unwrap();
775
776 let src_port = unsafe { core::ptr::addr_of!(header.src_port).read_unaligned() };
777 let dst_port = unsafe { core::ptr::addr_of!(header.dst_port).read_unaligned() };
778 let length = unsafe { core::ptr::addr_of!(header.length).read_unaligned() };
779 let checksum = unsafe { core::ptr::addr_of!(header.checksum).read_unaligned() };
780 assert_eq!(src_port, 1234);
781 assert_eq!(dst_port, 5678);
782 assert_eq!(length, 100);
783 assert_eq!(checksum, 0xABCD);
784 }
785
786 #[test_case]
787 fn test_udp_checksum() {
788 let src_ip = [192, 168, 1, 100];
789 let dst_ip = [192, 168, 1, 1];
790 let data = b"test";
791
792 let mut header = UdpHeader::new(1234, 5678, (8 + data.len()) as u16);
793 header.checksum = header.calculate_checksum(src_ip, dst_ip, data);
794
795 let checksum = unsafe { core::ptr::addr_of!(header.checksum).read_unaligned() };
797 assert_ne!(checksum, 0);
798 }
799
800 #[test_case]
801 fn test_udp_layer_creation() {
802 let udp_layer = UdpLayer::new();
803
804 let port1 = udp_layer.allocate_port();
806 let port2 = udp_layer.allocate_port();
807
808 assert!(port1 >= 49152 && port1 <= 65535);
809 assert!(port2 >= 49152 && port2 <= 65535);
810 assert_ne!(port1, port2);
811 }
812}