1use super::*;
2
3impl LinkManager {
4 pub(super) fn handle_request(
6 &mut self,
7 link_id: &LinkId,
8 plaintext: &[u8],
9 request_id: [u8; 16],
10 rng: &mut dyn Rng,
11 ) -> Vec<LinkManagerAction> {
12 use rns_core::msgpack::{self, Value};
13
14 let arr = match msgpack::unpack_exact(plaintext) {
16 Ok(Value::Array(arr)) if arr.len() >= 3 => arr,
17 _ => return Vec::new(),
18 };
19
20 let path_hash_bytes = match &arr[1] {
21 Value::Bin(b) if b.len() == 16 => b,
22 _ => return Vec::new(),
23 };
24 let mut path_hash = [0u8; 16];
25 path_hash.copy_from_slice(path_hash_bytes);
26
27 let request_data = msgpack::pack(&arr[2]);
29
30 if self.management_paths.contains(&path_hash) {
32 let remote_identity = self.links.get(link_id).and_then(|l| l.remote_identity);
33 return vec![LinkManagerAction::ManagementRequest {
34 link_id: *link_id,
35 path_hash,
36 data: request_data,
37 request_id,
38 remote_identity,
39 }];
40 }
41
42 if let Some(handler) = self
43 .deferred_request_handlers
44 .iter()
45 .find(|handler| handler.path_hash == path_hash)
46 {
47 let remote_identity = self
48 .links
49 .get(link_id)
50 .and_then(|link| link.remote_identity.as_ref());
51 if let Some(allowed) = &handler.allowed_list {
52 let Some((identity_hash, _)) = remote_identity else {
53 log::debug!("Deferred request denied: peer not identified");
54 return Vec::new();
55 };
56 if !allowed.contains(identity_hash) {
57 log::debug!("Deferred request denied: identity not in allowed list");
58 return Vec::new();
59 }
60 }
61 (handler.handler)(
62 *link_id,
63 &handler.path,
64 request_id,
65 &request_data,
66 remote_identity,
67 );
68 return Vec::new();
69 }
70
71 let handler_idx = self
73 .request_handlers
74 .iter()
75 .position(|h| h.path_hash == path_hash);
76 let handler_idx = match handler_idx {
77 Some(i) => i,
78 None => return Vec::new(),
79 };
80
81 let remote_identity = self
83 .links
84 .get(link_id)
85 .and_then(|l| l.remote_identity.as_ref());
86 let handler = &self.request_handlers[handler_idx];
87 if let Some(ref allowed) = handler.allowed_list {
88 match remote_identity {
89 Some((identity_hash, _)) => {
90 if !allowed.contains(identity_hash) {
91 log::debug!("Request denied: identity not in allowed list");
92 return Vec::new();
93 }
94 }
95 None => {
96 log::debug!("Request denied: peer not identified");
97 return Vec::new();
98 }
99 }
100 }
101
102 let path = handler.path.clone();
104 let response = (handler.handler)(*link_id, &path, &request_data, remote_identity);
105
106 let mut actions = Vec::new();
107 if let Some(response) = response {
108 match response {
109 RequestResponse::Bytes(response_data) => {
110 let mut response_actions =
111 self.build_response_packet(link_id, &request_id, &response_data, rng);
112 if response_actions.is_empty() {
113 response_actions.extend(self.send_response_resource(
114 link_id,
115 &request_id,
116 &response_data,
117 None,
118 true,
119 rng,
120 ));
121 }
122 actions.extend(response_actions);
123 }
124 RequestResponse::Resource {
125 data,
126 metadata,
127 auto_compress,
128 } => {
129 actions.extend(self.send_response_resource(
130 link_id,
131 &request_id,
132 &data,
133 metadata.as_deref(),
134 auto_compress,
135 rng,
136 ));
137 }
138 }
139 }
140
141 actions
142 }
143
144 fn build_response_packet(
147 &self,
148 link_id: &LinkId,
149 request_id: &[u8; 16],
150 response_data: &[u8],
151 rng: &mut dyn Rng,
152 ) -> Vec<LinkManagerAction> {
153 use rns_core::msgpack::{self, Value};
154
155 let response_value = msgpack::unpack_exact(response_data)
156 .unwrap_or_else(|_| Value::Bin(response_data.to_vec()));
157
158 let response_array = Value::Array(vec![Value::Bin(request_id.to_vec()), response_value]);
159 let response_plaintext = msgpack::pack(&response_array);
160
161 let mut actions = Vec::new();
162 if let Some(link) = self.links.get(link_id) {
163 if let Ok(encrypted) = link.engine.encrypt(&response_plaintext, rng) {
164 let flags = PacketFlags {
165 header_type: constants::HEADER_1,
166 context_flag: constants::FLAG_UNSET,
167 transport_type: constants::TRANSPORT_BROADCAST,
168 destination_type: constants::DESTINATION_LINK,
169 packet_type: constants::PACKET_TYPE_DATA,
170 };
171 let max_mtu = link.engine.mtu() as usize;
172 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash_with_max_mtu(
173 flags,
174 0,
175 link_id,
176 None,
177 constants::CONTEXT_RESPONSE,
178 &encrypted,
179 max_mtu,
180 ) {
181 actions.push(LinkManagerAction::SendPacket {
182 raw,
183 dest_type: constants::DESTINATION_LINK,
184 attached_interface: None,
185 });
186 }
187 }
188 }
189 actions
190 }
191
192 pub(super) fn send_response_resource(
193 &mut self,
194 link_id: &LinkId,
195 request_id: &[u8; 16],
196 response_data: &[u8],
197 metadata: Option<&[u8]>,
198 auto_compress: bool,
199 rng: &mut dyn Rng,
200 ) -> Vec<LinkManagerAction> {
201 use rns_core::msgpack::{self, Value};
202
203 let link = match self.links.get_mut(link_id) {
204 Some(l) => l,
205 None => return Vec::new(),
206 };
207
208 if link.engine.state() != LinkState::Active {
209 return Vec::new();
210 }
211
212 let now = time::now();
213
214 let response_value = msgpack::unpack_exact(response_data)
218 .unwrap_or_else(|_| Value::Bin(response_data.to_vec()));
219 let response_array = Value::Array(vec![Value::Bin(request_id.to_vec()), response_value]);
220 let resource_payload = msgpack::pack(&response_array);
221
222 let senders = match Self::build_resource_senders(
223 link,
224 ResourceSendParams {
225 data: &resource_payload,
226 metadata,
227 auto_compress,
228 is_response: true,
229 request_id: Some(request_id.to_vec()),
230 rng,
231 now,
232 },
233 ) {
234 Ok(s) => s,
235 Err(e) => {
236 log::debug!("Failed to create response ResourceSender: {}", e);
237 return Vec::new();
238 }
239 };
240
241 let adv_actions = Self::start_resource_senders(link, senders, now);
242
243 let _ = link;
244 self.process_resource_actions(link_id, adv_actions, rng)
245 }
246
247 pub fn send_deferred_response(
249 &mut self,
250 link_id: &LinkId,
251 request_id: &[u8; 16],
252 response_data: &[u8],
253 rng: &mut dyn Rng,
254 ) -> Vec<LinkManagerAction> {
255 let packet_actions = self.build_response_packet(link_id, request_id, response_data, rng);
256 if !packet_actions.is_empty() {
257 packet_actions
258 } else {
259 self.send_response_resource(link_id, request_id, response_data, None, true, rng)
260 }
261 }
262
263 pub fn send_management_response(
266 &mut self,
267 link_id: &LinkId,
268 request_id: &[u8; 16],
269 response_data: &[u8],
270 rng: &mut dyn Rng,
271 ) -> Vec<LinkManagerAction> {
272 let mut actions = self.build_response_packet(link_id, request_id, response_data, rng);
273 if actions.is_empty() {
274 actions.extend(self.send_response_resource(
275 link_id,
276 request_id,
277 response_data,
278 None,
279 true,
280 rng,
281 ));
282 }
283 actions
284 }
285
286 pub fn send_request(
294 &mut self,
295 link_id: &LinkId,
296 path: &str,
297 data: &[u8],
298 rng: &mut dyn Rng,
299 ) -> Vec<LinkManagerAction> {
300 self.send_request_with_max_response_size(link_id, path, data, None, rng)
301 }
302
303 pub fn send_request_with_max_response_size(
305 &mut self,
306 link_id: &LinkId,
307 path: &str,
308 data: &[u8],
309 max_response_size: Option<usize>,
310 rng: &mut dyn Rng,
311 ) -> Vec<LinkManagerAction> {
312 use rns_core::msgpack::{self, Value};
313
314 let link = match self.links.get_mut(link_id) {
315 Some(l) => l,
316 None => return Vec::new(),
317 };
318
319 if link.engine.state() != LinkState::Active {
320 return Vec::new();
321 }
322
323 let path_hash = compute_path_hash(path);
324
325 let data_value = msgpack::unpack_exact(data).unwrap_or_else(|_| Value::Bin(data.to_vec()));
327
328 let request_array = Value::Array(vec![
330 Value::Float(time::now()),
331 Value::Bin(path_hash.to_vec()),
332 data_value,
333 ]);
334 let plaintext = msgpack::pack(&request_array);
335
336 if plaintext.len() > link.engine.mdu() {
337 let request_id = rns_core::hash::truncated_hash(&plaintext);
338 let now = time::now();
339 let senders = match Self::build_resource_senders(
340 link,
341 ResourceSendParams {
342 data: &plaintext,
343 metadata: None,
344 auto_compress: true,
345 is_response: false,
346 request_id: Some(request_id.to_vec()),
347 rng,
348 now,
349 },
350 ) {
351 Ok(senders) => senders,
352 Err(e) => {
353 log::debug!("Failed to create request ResourceSender: {}", e);
354 return Vec::new();
355 }
356 };
357 link.pending_requests.insert(
360 request_id,
361 PendingRequest {
362 deadline: None,
363 max_response_size,
364 },
365 );
366 let adv_actions = Self::start_resource_senders(link, senders, now);
367 let _ = link;
368 return self.process_resource_actions(link_id, adv_actions, rng);
369 }
370
371 let encrypted = match link.engine.encrypt(&plaintext, rng) {
372 Ok(e) => e,
373 Err(_) => return Vec::new(),
374 };
375
376 let flags = PacketFlags {
377 header_type: constants::HEADER_1,
378 context_flag: constants::FLAG_UNSET,
379 transport_type: constants::TRANSPORT_BROADCAST,
380 destination_type: constants::DESTINATION_LINK,
381 packet_type: constants::PACKET_TYPE_DATA,
382 };
383
384 let mut actions = Vec::new();
385 let max_mtu = link.engine.mtu() as usize;
386 if let Ok((raw, packet_hash)) = RawPacket::pack_raw_with_hash_with_max_mtu(
387 flags,
388 0,
389 link_id,
390 None,
391 constants::CONTEXT_REQUEST,
392 &encrypted,
393 max_mtu,
394 ) {
395 let mut request_id = [0u8; 16];
396 request_id.copy_from_slice(&packet_hash[..16]);
397 let deadline = Self::request_response_deadline(link, time::now());
398 link.pending_requests.insert(
399 request_id,
400 PendingRequest {
401 deadline: Some(deadline),
402 max_response_size,
403 },
404 );
405 actions.push(LinkManagerAction::SendPacket {
406 raw,
407 dest_type: constants::DESTINATION_LINK,
408 attached_interface: None,
409 });
410 }
411 actions
412 }
413
414 pub(super) fn handle_response(
417 &mut self,
418 link_id: &LinkId,
419 plaintext: &[u8],
420 metadata: Option<Vec<u8>>,
421 resource_request_id: Option<[u8; 16]>,
422 ) -> Vec<LinkManagerAction> {
423 use rns_core::msgpack;
424
425 let packet_response = msgpack::unpack_exact(plaintext).ok().and_then(|value| {
427 let msgpack::Value::Array(arr) = value else {
428 return None;
429 };
430 if arr.len() < 2 {
431 return None;
432 }
433 let msgpack::Value::Bin(request_id_bytes) = &arr[0] else {
434 return None;
435 };
436 if request_id_bytes.len() != 16 {
437 return None;
438 }
439 let mut request_id = [0u8; 16];
440 request_id.copy_from_slice(request_id_bytes);
441 Some((request_id, msgpack::pack(&arr[1])))
442 });
443
444 let (request_id, response_data, check_size) = match packet_response {
445 Some((request_id, response_data)) => (request_id, response_data, true),
446 None => {
447 let Some(request_id) = resource_request_id else {
448 return Vec::new();
449 };
450 (
451 request_id,
452 msgpack::pack(&msgpack::Value::Bin(plaintext.to_vec())),
453 false,
454 )
455 }
456 };
457
458 let Some(link) = self.links.get_mut(link_id) else {
459 return Vec::new();
460 };
461 let Some(pending) = link.pending_requests.get(&request_id) else {
462 return Vec::new();
463 };
464 if check_size {
465 let response_size = response_data.len().saturating_sub(2) as u64;
469 if let Some(maximum) = pending.max_response_size {
470 if response_size > maximum as u64 {
471 link.pending_requests.remove(&request_id);
472 log::debug!(
473 "rejected response with excessive size {} bytes on link {:02x?}",
474 response_size,
475 &link_id[..4]
476 );
477 return vec![LinkManagerAction::RequestFailed {
478 link_id: *link_id,
479 request_id,
480 reason: RequestFailure::ResponseTooLarge {
481 size: response_size,
482 maximum,
483 },
484 }];
485 }
486 }
487 }
488 link.pending_requests.remove(&request_id);
489
490 vec![LinkManagerAction::ResponseReceived {
491 link_id: *link_id,
492 request_id,
493 data: response_data,
494 metadata,
495 }]
496 }
497
498 pub(super) fn response_request_id(request_id: &Option<Vec<u8>>) -> Option<[u8; 16]> {
499 let bytes = request_id.as_deref()?;
500 if bytes.len() != 16 {
501 return None;
502 }
503 let mut out = [0u8; 16];
504 out.copy_from_slice(bytes);
505 Some(out)
506 }
507}