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}