xous_api_names/
api.rs

1mod rkyv_enum;
2pub use rkyv_enum::*;
3
4#[allow(dead_code)]
5pub const AUTHENTICATE_TIMEOUT: u32 = 10_000; // time in ms that a process has to respond to an authentication request
6
7#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive)]
8#[repr(C)]
9pub enum Opcode {
10    /// Create a new server with the given name and return its SID.
11    Register = 0,
12
13    /// Create a connection to the target server.
14    Lookup = 1,
15
16    /// Create an authenticated connection to the target server.
17    AuthenticatedLookup = 2,
18
19    /// unregister a server, given its cryptographically unique SID.
20    Unregister = 3,
21
22    /// disconnect, given a server name and a cryptographically unique, one-time use token
23    Disconnect = 4,
24
25    /// indicates if all inherently trusted slots have been occupied. Should not run untrusted code until
26    /// this is the case.
27    TrustedInitDone = 5,
28
29    /// Connect to a Server, blocking if the Server does not exist. When the Server is started,
30    /// return with either the CID or an AuthenticationRequest
31    ///
32    /// # Message Types
33    ///
34    ///     * MutableLend
35    ///
36    /// # Arguments
37    ///
38    /// The memory being pointed to should be a &str, and the length of the string should
39    /// be specified in the `valid` field.
40    ///
41    /// # Return Values
42    ///
43    /// Memory is overwritten to contain a return value.  This return value can be defined
44    /// as the following enum:
45    ///
46    /// ```rust
47    /// #[repr(C)]
48    /// #[non_exhaustive]
49    /// enum ConnectResult {
50    ///     Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */),
51    ///     Error(u32 /* error code */),
52    ///     Unhandled, /* Catchall for future Results */
53    /// }
54    /// ```
55    BlockingConnect = 6,
56
57    /// Connect to a Server, returning the connection ID or an authentication request if
58    /// it exists, and returning ServerNotFound if it does not exist.
59    ///
60    /// # Message Types
61    ///
62    ///     * MutableLend
63    ///
64    /// # Arguments
65    ///
66    /// The memory being pointed to should be a &str, and the length of the string should
67    /// be specified in the `valid` field.
68    ///
69    /// # Return Values
70    ///
71    /// Memory is overwritten to contain a return value.  This return value can be defined
72    /// as the following enum:
73    ///
74    /// ```rust
75    /// #[repr(C)]
76    /// #[non_exhaustive]
77    /// enum ConnectResult {
78    ///     Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */),
79    ///     Error(u32 /* error code */),
80    ///     Unhandled, /* Catchall for future Results */
81    /// }
82    /// ```
83    TryConnect = 7,
84}
85
86#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
87pub struct Registration {
88    pub name: String,
89    pub conn_limit: Option<u32>,
90}
91
92#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
93pub struct Disconnect {
94    pub name: String,
95    pub token: [u32; 4],
96}
97
98#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
99pub struct AuthenticatedLookup {
100    pub name: String,
101    pub pubkey_id: [u8; 20], // 160-bit pubkey ID encoded in network order (big endian)
102    pub response: [u32; 8],
103}
104
105#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
106#[repr(C)]
107pub struct AuthenticateRequest {
108    pub name: String,        // a copy of the originally requested lookup
109    pub pubkey_id: [u8; 20], // 160-bit pubkey ID encoded in network order (big endian)
110    pub challenge: [u32; 4],
111}
112
113//////////////////////////////////////////////////////////////////////////////////////////////
114// We keep XousServerName around because want to be able to index off the server name, without
115// burdening the Kernel String type with the Hash32 methods
116//////////////////////////////////////////////////////////////////////////////////////////////
117
118// --------------------- Taken from rkyv docs https://docs.rs/rkyv/0.3.0/rkyv/trait.Archive.html //
119#[derive(Debug, Copy, Clone)]
120pub struct XousServerName {
121    value: [u8; 64],
122    length: usize,
123}
124
125impl Default for XousServerName {
126    fn default() -> Self { XousServerName { value: [0u8; 64], length: 0 } }
127}
128
129#[allow(dead_code)]
130impl XousServerName {
131    pub fn to_str(&self) -> &str {
132        core::str::from_utf8(unsafe {
133            core::slice::from_raw_parts(self.value.as_ptr(), self.length as usize)
134        })
135        .unwrap()
136    }
137
138    pub fn new() -> XousServerName { XousServerName { value: [0; 64], length: 0 } }
139
140    pub fn from_str(src: &str) -> XousServerName {
141        let mut s = Self::new();
142        // Copy the string into our backing store.
143        for (&src_byte, dest_byte) in src.as_bytes().iter().zip(&mut s.value) {
144            *dest_byte = src_byte;
145        }
146        // Set the string length to the length of the passed-in String,
147        // or the maximum possible length. Which ever is smaller.
148        s.length = s.value.len().min(src.as_bytes().len());
149
150        // If the string is not valid, set its length to 0.
151        if s.as_str().is_err() {
152            s.length = 0;
153        }
154        assert!(s.length < s.value.len(), "incorrect length derivation!");
155
156        s
157    }
158
159    pub fn as_bytes(&self) -> [u8; 64] { self.value }
160
161    pub fn as_str(&self) -> core::result::Result<&str, core::str::Utf8Error> {
162        core::str::from_utf8(&self.value[0..self.length as usize])
163    }
164
165    pub fn len(&self) -> usize { self.length as usize }
166
167    pub fn is_empty(&self) -> bool { self.length == 0 }
168
169    /// Clear the contents and set the length to 0
170    pub fn clear(&mut self) {
171        self.length = 0;
172        self.value = [0; 64];
173    }
174}
175
176// Allow using the `write!()` macro to write into a `&XousServerName`
177impl core::fmt::Write for XousServerName {
178    fn write_str(&mut self, s: &str) -> core::result::Result<(), core::fmt::Error> {
179        self.length = 0;
180        let b = s.bytes();
181
182        // Ensure the length is acceptable
183        if b.len() > self.value.len() {
184            Err(core::fmt::Error)?;
185        }
186        self.length = b.len();
187        assert!(self.length < self.value.len(), "incorrect length derivation!");
188
189        // Copy the string into this variable
190        for (dest, src) in self.value.iter_mut().zip(s.bytes()) {
191            *dest = src;
192        }
193
194        // Attempt to convert the string to UTF-8 to validate it's correct UTF-8
195        core::str::from_utf8(unsafe {
196            core::slice::from_raw_parts(self.value.as_ptr(), self.length as usize)
197        })
198        .map_err(|_| core::fmt::Error)?;
199        Ok(())
200    }
201}
202
203impl std::hash::Hash for XousServerName {
204    fn hash<H>(&self, state: &mut H)
205    where
206        H: std::hash::Hasher,
207    {
208        assert!(self.length < self.value.len(), "incorret length on hash!");
209        std::hash::Hash::hash(&self.value[..self.length as usize], state);
210        std::hash::Hash::hash(&self.length, state)
211    }
212}
213
214impl PartialEq for XousServerName {
215    fn eq(&self, other: &Self) -> bool {
216        assert!(self.length < self.value.len(), "incorret length on Eq!");
217        assert!(other.length < other.value.len(), "incorrect length on Eq (other)!");
218        self.value[..self.length as usize] == other.value[..other.length as usize]
219            && self.length == other.length
220    }
221}
222
223impl Eq for XousServerName {}
224
225impl core::fmt::Display for XousServerName {
226    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.to_str()) }
227}