s2n_quic_platform/message/
simple.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::message::Message as MessageTrait;
5use core::alloc::Layout;
6use s2n_quic_core::{
7    inet::{datagram, SocketAddress},
8    io::tx,
9    path,
10};
11
12/// A simple message type that holds an address and payload
13///
14/// All other fields are not supported by the platform.
15#[derive(Clone, Copy, Debug)]
16pub struct Message {
17    address: SocketAddress,
18    payload_ptr: *mut u8,
19    payload_len: usize,
20}
21
22impl Message {
23    #[inline]
24    pub fn remote_address(&self) -> &SocketAddress {
25        &self.address
26    }
27
28    #[inline]
29    pub fn set_remote_address(&mut self, remote_address: &SocketAddress) {
30        let remote_address = *remote_address;
31
32        self.address = remote_address;
33    }
34}
35
36pub type Handle = path::Tuple;
37
38impl MessageTrait for Message {
39    type Handle = Handle;
40
41    const SUPPORTS_GSO: bool = false;
42    const SUPPORTS_ECN: bool = false;
43    const SUPPORTS_FLOW_LABELS: bool = false;
44
45    #[inline]
46    fn alloc(entries: u32, payload_len: u32, offset: usize) -> super::Storage {
47        unsafe { alloc(entries, payload_len, offset) }
48    }
49
50    #[inline]
51    fn payload_len(&self) -> usize {
52        self.payload_len
53    }
54
55    #[inline]
56    unsafe fn set_payload_len(&mut self, len: usize) {
57        self.payload_len = len;
58    }
59
60    #[inline]
61    unsafe fn reset(&mut self, mtu: usize) {
62        self.set_payload_len(mtu)
63    }
64
65    #[inline]
66    fn payload_ptr_mut(&mut self) -> *mut u8 {
67        self.payload_ptr
68    }
69
70    #[inline]
71    fn validate_replication(source: &Self, dest: &Self) {
72        assert_eq!(source.payload_ptr, dest.payload_ptr);
73    }
74
75    #[inline]
76    fn rx_read(
77        &mut self,
78        local_address: &path::LocalAddress,
79    ) -> Option<super::RxMessage<'_, Self::Handle>> {
80        let path = path::Tuple {
81            remote_address: self.address.into(),
82            local_address: *local_address,
83        };
84        let header = datagram::Header {
85            path,
86            ecn: Default::default(),
87        };
88        let payload = self.payload_mut();
89
90        let message = super::RxMessage {
91            header,
92            segment_size: payload.len(),
93            payload,
94        };
95
96        Some(message)
97    }
98
99    #[inline]
100    fn tx_write<M: tx::Message<Handle = Self::Handle>>(
101        &mut self,
102        mut message: M,
103    ) -> Result<usize, tx::Error> {
104        let payload = self.payload_mut();
105
106        let len = message.write_payload(tx::PayloadBuffer::new(payload), 0)?;
107
108        unsafe {
109            debug_assert!(len <= payload.len());
110            let len = len.min(payload.len());
111            self.set_payload_len(len);
112        }
113
114        let remote_address = message.path_handle().remote_address;
115        self.address = remote_address.0;
116
117        Ok(len)
118    }
119}
120
121#[inline]
122unsafe fn alloc(entries: u32, payload_len: u32, offset: usize) -> super::Storage {
123    let (layout, entry_offset, payload_offset) = layout(entries, payload_len, offset);
124
125    let storage = super::Storage::new(layout);
126
127    {
128        let ptr = storage.as_ptr();
129
130        let mut entry_ptr = ptr.add(entry_offset) as *mut Message;
131        let mut payload_ptr = ptr.add(payload_offset);
132        for _ in 0..entries {
133            let entry = &mut *entry_ptr;
134            entry.payload_ptr = payload_ptr;
135            entry.payload_len = payload_len as _;
136
137            entry_ptr = entry_ptr.add(1);
138            payload_ptr = payload_ptr.add(payload_len as _);
139            storage.check_bounds(entry_ptr);
140            storage.check_bounds(payload_ptr);
141        }
142
143        let primary = ptr.add(entry_offset) as *mut Message;
144        let secondary = primary.add(entries as _);
145        storage.check_bounds(secondary.add(entries as _));
146        core::ptr::copy_nonoverlapping(primary, secondary, entries as _);
147    }
148
149    storage
150}
151
152fn layout(entries: u32, payload_len: u32, offset: usize) -> (Layout, usize, usize) {
153    let cursor = Layout::array::<u8>(offset).unwrap();
154    let payloads = Layout::array::<u8>(entries as usize * payload_len as usize).unwrap();
155    let entries = Layout::array::<Message>((entries * 2) as usize).unwrap();
156    let (layout, entry_offset) = cursor.extend(entries).unwrap();
157    let (layout, payload_offset) = layout.extend(payloads).unwrap();
158    (layout, entry_offset, payload_offset)
159}