1pub mod availability;
6pub mod bedrock;
7pub mod capability_source;
8pub mod component_instance;
9pub mod config;
10pub mod error;
11pub mod legacy_router;
12pub mod mapper;
13pub mod path;
14pub mod policy;
15pub mod resolving;
16pub mod rights;
17pub mod subdir;
18pub mod walk_state;
19
20use crate::bedrock::request_metadata::{
21 dictionary_metadata, directory_metadata, protocol_metadata, resolver_metadata, runner_metadata,
22 service_metadata,
23};
24use crate::capability_source::{
25 CapabilitySource, ComponentCapability, ComponentSource, InternalCapability, VoidSource,
26};
27use crate::component_instance::{
28 ComponentInstanceInterface, ResolvedInstanceInterface, WeakComponentInstanceInterface,
29};
30use crate::error::RoutingError;
31use crate::legacy_router::{
32 CapabilityVisitor, ErrorNotFoundFromParent, ErrorNotFoundInChild, ExposeVisitor, NoopVisitor,
33 OfferVisitor, RouteBundle, Sources,
34};
35use crate::mapper::DebugRouteMapper;
36use crate::rights::RightsWalker;
37use crate::walk_state::WalkState;
38use cm_rust::{
39 Availability, CapabilityTypeName, DebugProtocolRegistration, ExposeConfigurationDecl,
40 ExposeDecl, ExposeDeclCommon, ExposeDictionaryDecl, ExposeDirectoryDecl, ExposeProtocolDecl,
41 ExposeResolverDecl, ExposeRunnerDecl, ExposeServiceDecl, ExposeSource, ExposeTarget,
42 OfferConfigurationDecl, OfferDeclCommon, OfferDictionaryDecl, OfferDirectoryDecl,
43 OfferEventStreamDecl, OfferProtocolDecl, OfferResolverDecl, OfferRunnerDecl, OfferServiceDecl,
44 OfferSource, OfferStorageDecl, OfferTarget, RegistrationDeclCommon, RegistrationSource,
45 ResolverRegistration, RunnerRegistration, SourceName, StorageDecl, StorageDirectorySource,
46 UseConfigurationDecl, UseDecl, UseDeclCommon, UseDictionaryDecl, UseDirectoryDecl,
47 UseEventStreamDecl, UseProtocolDecl, UseRunnerDecl, UseServiceDecl, UseSource, UseStorageDecl,
48};
49use cm_types::{IterablePath, Name, RelativePath};
50use from_enum::FromEnum;
51use itertools::Itertools;
52use moniker::{ChildName, ExtendedMoniker, Moniker, MonikerError};
53use router_error::Explain;
54use sandbox::{
55 Capability, CapabilityBound, Connector, Data, Dict, DirConnector, Request, Routable, Router,
56 RouterResponse,
57};
58use std::fmt::Debug;
59use std::sync::Arc;
60use subdir::SubDir;
61use {fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_io as fio, zx_status as zx};
62
63pub use bedrock::dict_ext::{DictExt, GenericRouterResponse};
64pub use bedrock::lazy_get::LazyGet;
65pub use bedrock::weak_instance_token_ext::{WeakInstanceTokenExt, test_invalid_instance_token};
66pub use bedrock::with_porcelain::WithPorcelain;
67#[cfg(feature = "serde")]
68use serde::{Deserialize, Serialize};
69
70#[derive(Clone, Debug)]
72pub enum RouteRequest {
73 ExposeDirectory(ExposeDirectoryDecl),
75 ExposeProtocol(ExposeProtocolDecl),
76 ExposeService(RouteBundle<ExposeServiceDecl>),
77 ExposeRunner(ExposeRunnerDecl),
78 ExposeResolver(ExposeResolverDecl),
79 ExposeConfig(ExposeConfigurationDecl),
80 ExposeDictionary(ExposeDictionaryDecl),
81
82 Resolver(ResolverRegistration),
84
85 StorageBackingDirectory(StorageDecl),
87
88 UseDirectory(UseDirectoryDecl),
90 UseEventStream(UseEventStreamDecl),
91 UseProtocol(UseProtocolDecl),
92 UseService(UseServiceDecl),
93 UseStorage(UseStorageDecl),
94 UseRunner(UseRunnerDecl),
95 UseConfig(UseConfigurationDecl),
96 UseDictionary(UseDictionaryDecl),
97
98 OfferDirectory(OfferDirectoryDecl),
100 OfferEventStream(OfferEventStreamDecl),
101 OfferProtocol(OfferProtocolDecl),
102 OfferService(RouteBundle<OfferServiceDecl>),
103 OfferStorage(OfferStorageDecl),
104 OfferRunner(OfferRunnerDecl),
105 OfferResolver(OfferResolverDecl),
106 OfferConfig(OfferConfigurationDecl),
107 OfferDictionary(OfferDictionaryDecl),
108}
109
110impl From<UseDecl> for RouteRequest {
111 fn from(decl: UseDecl) -> Self {
112 match decl {
113 UseDecl::Directory(decl) => Self::UseDirectory(decl),
114 UseDecl::Protocol(decl) => Self::UseProtocol(decl),
115 UseDecl::Service(decl) => Self::UseService(decl),
116 UseDecl::Storage(decl) => Self::UseStorage(decl),
117 UseDecl::EventStream(decl) => Self::UseEventStream(decl),
118 UseDecl::Runner(decl) => Self::UseRunner(decl),
119 UseDecl::Config(decl) => Self::UseConfig(decl),
120 UseDecl::Dictionary(decl) => Self::UseDictionary(decl),
121 }
122 }
123}
124
125impl RouteRequest {
126 pub fn from_expose_decls(exposes: Vec<&ExposeDecl>) -> Result<Self, RoutingError> {
127 let first_expose = exposes.first().expect("invalid empty expose list");
128 let first_type_name = CapabilityTypeName::from(*first_expose);
129 assert!(
130 exposes.iter().all(|e| {
131 let type_name: CapabilityTypeName = CapabilityTypeName::from(*e);
132 first_type_name == type_name && first_expose.target_name() == e.target_name()
133 }),
134 "invalid expose input: {:?}",
135 exposes
136 );
137 match first_expose {
138 ExposeDecl::Protocol(e) => {
139 assert!(exposes.len() == 1, "multiple exposes: {:?}", exposes);
140 Ok(Self::ExposeProtocol(e.clone()))
141 }
142 ExposeDecl::Service(_) => {
143 let exposes: Vec<_> = exposes
146 .into_iter()
147 .filter_map(|e| match e {
148 cm_rust::ExposeDecl::Service(e) => Some(e.clone()),
149 _ => None,
150 })
151 .collect();
152 Ok(Self::ExposeService(RouteBundle::from_exposes(exposes)))
153 }
154 ExposeDecl::Directory(e) => {
155 assert!(exposes.len() == 1, "multiple exposes");
156 Ok(Self::ExposeDirectory(e.clone()))
157 }
158 ExposeDecl::Runner(e) => {
159 assert!(exposes.len() == 1, "multiple exposes");
160 Ok(Self::ExposeRunner(e.clone()))
161 }
162 ExposeDecl::Resolver(e) => {
163 assert!(exposes.len() == 1, "multiple exposes");
164 Ok(Self::ExposeResolver(e.clone()))
165 }
166 ExposeDecl::Config(e) => {
167 assert!(exposes.len() == 1, "multiple exposes");
168 Ok(Self::ExposeConfig(e.clone()))
169 }
170 ExposeDecl::Dictionary(e) => {
171 assert!(exposes.len() == 1, "multiple exposes");
172 Ok(Self::ExposeDictionary(e.clone()))
173 }
174 }
175 }
176
177 pub fn availability(&self) -> Option<Availability> {
179 use crate::RouteRequest::*;
180 match self {
181 UseDirectory(UseDirectoryDecl { availability, .. })
182 | UseEventStream(UseEventStreamDecl { availability, .. })
183 | UseProtocol(UseProtocolDecl { availability, .. })
184 | UseService(UseServiceDecl { availability, .. })
185 | UseConfig(UseConfigurationDecl { availability, .. })
186 | UseStorage(UseStorageDecl { availability, .. })
187 | UseDictionary(UseDictionaryDecl { availability, .. }) => Some(*availability),
188
189 ExposeDirectory(decl) => Some(*decl.availability()),
190 ExposeProtocol(decl) => Some(*decl.availability()),
191 ExposeService(decl) => Some(*decl.availability()),
192 ExposeRunner(decl) => Some(*decl.availability()),
193 ExposeResolver(decl) => Some(*decl.availability()),
194 ExposeConfig(decl) => Some(*decl.availability()),
195 ExposeDictionary(decl) => Some(*decl.availability()),
196
197 OfferRunner(decl) => Some(*decl.availability()),
198 OfferResolver(decl) => Some(*decl.availability()),
199 OfferDirectory(decl) => Some(*decl.availability()),
200 OfferEventStream(decl) => Some(*decl.availability()),
201 OfferProtocol(decl) => Some(*decl.availability()),
202 OfferConfig(decl) => Some(*decl.availability()),
203 OfferStorage(decl) => Some(*decl.availability()),
204 OfferDictionary(decl) => Some(*decl.availability()),
205
206 OfferService(_) | Resolver(_) | StorageBackingDirectory(_) | UseRunner(_) => None,
207 }
208 }
209}
210
211impl std::fmt::Display for RouteRequest {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 match self {
214 Self::ExposeDirectory(e) => {
215 write!(f, "directory `{}`", e.target_name)
216 }
217 Self::ExposeProtocol(e) => {
218 write!(f, "protocol `{}`", e.target_name)
219 }
220 Self::ExposeService(e) => {
221 write!(f, "service {:?}", e)
222 }
223 Self::ExposeRunner(e) => {
224 write!(f, "runner `{}`", e.target_name)
225 }
226 Self::ExposeResolver(e) => {
227 write!(f, "resolver `{}`", e.target_name)
228 }
229 Self::ExposeConfig(e) => {
230 write!(f, "config `{}`", e.target_name)
231 }
232 Self::ExposeDictionary(e) => {
233 write!(f, "dictionary `{}`", e.target_name)
234 }
235 Self::Resolver(r) => {
236 write!(f, "resolver `{}`", r.resolver)
237 }
238 Self::UseDirectory(u) => {
239 write!(f, "directory `{}`", u.source_name)
240 }
241 Self::UseProtocol(u) => {
242 write!(f, "protocol `{}`", u.source_name)
243 }
244 Self::UseService(u) => {
245 write!(f, "service `{}`", u.source_name)
246 }
247 Self::UseStorage(u) => {
248 write!(f, "storage `{}`", u.source_name)
249 }
250 Self::UseEventStream(u) => {
251 write!(f, "event stream `{}`", u.source_name)
252 }
253 Self::UseRunner(u) => {
254 write!(f, "runner `{}`", u.source_name)
255 }
256 Self::UseConfig(u) => {
257 write!(f, "config `{}`", u.source_name)
258 }
259 Self::UseDictionary(u) => {
260 write!(f, "dictionary `{}`", u.source_name)
261 }
262 Self::StorageBackingDirectory(u) => {
263 write!(f, "storage backing directory `{}`", u.backing_dir)
264 }
265 Self::OfferDirectory(o) => {
266 write!(f, "directory `{}`", o.target_name)
267 }
268 Self::OfferProtocol(o) => {
269 write!(f, "protocol `{}`", o.target_name)
270 }
271 Self::OfferService(o) => {
272 write!(f, "service {:?}", o)
273 }
274 Self::OfferEventStream(o) => {
275 write!(f, "event stream `{}`", o.target_name)
276 }
277 Self::OfferStorage(o) => {
278 write!(f, "storage `{}`", o.target_name)
279 }
280 Self::OfferResolver(o) => {
281 write!(f, "resolver `{}`", o.target_name)
282 }
283 Self::OfferRunner(o) => {
284 write!(f, "runner `{}`", o.target_name)
285 }
286 Self::OfferConfig(o) => {
287 write!(f, "config `{}`", o.target_name)
288 }
289 Self::OfferDictionary(o) => {
290 write!(f, "dictionary `{}`", o.target_name)
291 }
292 }
293 }
294}
295
296#[derive(Debug)]
298pub struct RouteSource {
299 pub source: CapabilitySource,
300 pub relative_path: RelativePath,
301}
302
303impl RouteSource {
304 pub fn new(source: CapabilitySource) -> Self {
305 Self { source, relative_path: Default::default() }
306 }
307
308 pub fn new_with_relative_path(source: CapabilitySource, relative_path: RelativePath) -> Self {
309 Self { source, relative_path }
310 }
311}
312
313pub async fn route_capability<C>(
327 request: RouteRequest,
328 target: &Arc<C>,
329 mapper: &mut dyn DebugRouteMapper,
330) -> Result<RouteSource, RoutingError>
331where
332 C: ComponentInstanceInterface + 'static,
333{
334 match request {
335 RouteRequest::ExposeDirectory(expose_dir_decl) => {
337 route_capability_inner::<DirConnector, _>(
338 &target.component_sandbox().await?.component_output.capabilities(),
339 &expose_dir_decl.target_name,
340 directory_metadata(
341 expose_dir_decl.availability,
342 expose_dir_decl.rights.and_then(|v| Some(v.into())),
343 Some(expose_dir_decl.subdir.into()),
344 ),
345 target,
346 )
347 .await
348 }
349 RouteRequest::ExposeProtocol(expose_protocol_decl) => {
350 let sandbox = target.component_sandbox().await?;
351 let dictionary = match &expose_protocol_decl.target {
352 ExposeTarget::Parent => sandbox.component_output.capabilities(),
353 ExposeTarget::Framework => sandbox.component_output.framework(),
354 };
355 route_capability_inner::<Connector, _>(
356 &dictionary,
357 &expose_protocol_decl.target_name,
358 protocol_metadata(expose_protocol_decl.availability),
359 target,
360 )
361 .await
362 }
363 RouteRequest::ExposeService(expose_bundle) => {
364 let first_expose = expose_bundle.iter().next().expect("can't route empty bundle");
365 route_capability_inner::<DirConnector, _>(
366 &target.component_sandbox().await?.component_output.capabilities(),
367 first_expose.target_name(),
368 service_metadata(*first_expose.availability()),
369 target,
370 )
371 .await
372 }
373 RouteRequest::ExposeRunner(expose_runner_decl) => {
374 let sandbox = target.component_sandbox().await?;
375 let dictionary = match &expose_runner_decl.target {
376 ExposeTarget::Parent => sandbox.component_output.capabilities(),
377 ExposeTarget::Framework => sandbox.component_output.framework(),
378 };
379 route_capability_inner::<Connector, _>(
380 &dictionary,
381 &expose_runner_decl.target_name,
382 runner_metadata(Availability::Required),
383 target,
384 )
385 .await
386 }
387 RouteRequest::ExposeResolver(expose_resolver_decl) => {
388 let sandbox = target.component_sandbox().await?;
389 let dictionary = match &expose_resolver_decl.target {
390 ExposeTarget::Parent => sandbox.component_output.capabilities(),
391 ExposeTarget::Framework => sandbox.component_output.framework(),
392 };
393 route_capability_inner::<Connector, _>(
394 &dictionary,
395 &expose_resolver_decl.target_name,
396 resolver_metadata(Availability::Required),
397 target,
398 )
399 .await
400 }
401 RouteRequest::ExposeDictionary(expose_dictionary_decl) => {
402 let sandbox = target.component_sandbox().await?;
403 let dictionary = match &expose_dictionary_decl.target {
404 ExposeTarget::Parent => sandbox.component_output.capabilities(),
405 ExposeTarget::Framework => sandbox.component_output.framework(),
406 };
407 route_capability_inner::<Dict, _>(
408 &dictionary,
409 &expose_dictionary_decl.target_name,
410 dictionary_metadata(expose_dictionary_decl.availability),
411 target,
412 )
413 .await
414 }
415 RouteRequest::ExposeConfig(expose_config_decl) => {
416 route_config_from_expose(expose_config_decl, target, mapper).await
417 }
418
419 RouteRequest::Resolver(resolver_registration) => {
421 let component_sandbox = target.component_sandbox().await?;
422 let source_dictionary = match &resolver_registration.source {
423 RegistrationSource::Parent => component_sandbox.component_input.capabilities(),
424 RegistrationSource::Self_ => component_sandbox.program_output_dict.clone(),
425 RegistrationSource::Child(static_name) => {
426 let child_name = ChildName::parse(static_name).expect(
427 "invalid child name, this should be prevented by manifest validation",
428 );
429 let child_component = target.lock_resolved_state().await?.get_child(&child_name).expect("resolver registration references nonexistent static child, this should be prevented by manifest validation");
430 let child_sandbox = child_component.component_sandbox().await?;
431 child_sandbox.component_output.capabilities().clone()
432 }
433 };
434 route_capability_inner::<Connector, _>(
435 &source_dictionary,
436 &resolver_registration.resolver,
437 resolver_metadata(Availability::Required),
438 target,
439 )
440 .await
441 }
442 RouteRequest::StorageBackingDirectory(storage_decl) => {
444 route_storage_backing_directory(storage_decl, target, mapper).await
445 }
446
447 RouteRequest::UseDirectory(use_directory_decl) => {
449 let subdir = match use_directory_decl.source {
450 UseSource::Self_ => None,
451 _ => Some(SubDir::from(use_directory_decl.subdir)),
452 };
453 route_capability_inner::<DirConnector, _>(
454 &target.component_sandbox().await?.program_input.namespace(),
455 &use_directory_decl.target_path,
456 directory_metadata(
457 use_directory_decl.availability,
458 Some(use_directory_decl.rights.into()),
459 subdir,
460 ),
461 target,
462 )
463 .await
464 }
465 RouteRequest::UseEventStream(use_event_stream_decl) => {
466 route_event_stream(use_event_stream_decl, target, mapper).await
467 }
468 RouteRequest::UseProtocol(use_protocol_decl) => {
469 if let Some(target_path) = use_protocol_decl.target_path.as_ref() {
470 route_capability_inner::<Connector, _>(
471 &target.component_sandbox().await?.program_input.namespace(),
472 target_path,
473 protocol_metadata(use_protocol_decl.availability),
474 target,
475 )
476 .await
477 } else {
478 let numbered_handle = use_protocol_decl
479 .numbered_handle
480 .expect("validation guarantees numbered_handle is set");
481 let numbered_handle = Name::from(numbered_handle);
482 route_capability_inner::<Connector, _>(
483 &target.component_sandbox().await?.program_input.numbered_handles(),
484 &numbered_handle,
485 protocol_metadata(use_protocol_decl.availability),
486 target,
487 )
488 .await
489 }
490 }
491 RouteRequest::UseService(use_service_decl) => {
492 route_capability_inner::<DirConnector, _>(
493 &target.component_sandbox().await?.program_input.namespace(),
494 &use_service_decl.target_path,
495 service_metadata(use_service_decl.availability),
496 target,
497 )
498 .await
499 }
500 RouteRequest::UseStorage(use_storage_decl) => {
501 route_storage(use_storage_decl, target, mapper).await
502 }
503 RouteRequest::UseRunner(_use_runner_decl) => {
504 let router =
505 target.component_sandbox().await?.program_input.runner().expect("we have a use declaration for a runner but the program input dictionary has no runner, this should be impossible");
506 perform_route::<Connector, _>(router, runner_metadata(Availability::Required), target)
507 .await
508 }
509 RouteRequest::UseConfig(use_config_decl) => {
510 route_config(use_config_decl, target, mapper).await
511 }
512 RouteRequest::UseDictionary(use_dictionary_decl) => {
513 route_capability_inner::<Dict, _>(
514 &target.component_sandbox().await?.program_input.namespace(),
515 &use_dictionary_decl.target_path,
516 dictionary_metadata(use_dictionary_decl.availability),
517 target,
518 )
519 .await
520 }
521
522 RouteRequest::OfferProtocol(offer_protocol_decl) => {
524 let target_dictionary =
525 get_dictionary_for_offer_target(target, &offer_protocol_decl).await?;
526 let metadata = protocol_metadata(offer_protocol_decl.availability);
527 metadata
528 .insert(
529 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
530 Capability::Data(Data::Uint64(1)),
531 )
532 .unwrap();
533 route_capability_inner::<Connector, _>(
534 &target_dictionary,
535 &offer_protocol_decl.target_name,
536 metadata,
537 target,
538 )
539 .await
540 }
541 RouteRequest::OfferDictionary(offer_dictionary_decl) => {
542 let target_dictionary =
543 get_dictionary_for_offer_target(target, &offer_dictionary_decl).await?;
544 let metadata = dictionary_metadata(offer_dictionary_decl.availability);
545 metadata
546 .insert(
547 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
548 Capability::Data(Data::Uint64(1)),
549 )
550 .unwrap();
551 route_capability_inner::<Dict, _>(
552 &target_dictionary,
553 &offer_dictionary_decl.target_name,
554 metadata,
555 target,
556 )
557 .await
558 }
559 RouteRequest::OfferDirectory(offer_directory_decl) => {
560 let target_dictionary =
561 get_dictionary_for_offer_target(target, &offer_directory_decl).await?;
562 let metadata = directory_metadata(
563 offer_directory_decl.availability,
564 offer_directory_decl.rights.and_then(|v| Some(v.into())),
565 Some(offer_directory_decl.subdir.into()),
566 );
567 metadata
568 .insert(
569 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
570 Capability::Data(Data::Uint64(1)),
571 )
572 .unwrap();
573 route_capability_inner::<DirConnector, _>(
574 &target_dictionary,
575 &offer_directory_decl.target_name,
576 metadata,
577 target,
578 )
579 .await
580 }
581 RouteRequest::OfferStorage(offer_storage_decl) => {
582 route_storage_from_offer(offer_storage_decl, target, mapper).await
583 }
584 RouteRequest::OfferService(offer_service_bundle) => {
585 let first_offer = offer_service_bundle.iter().next().expect("can't route empty bundle");
586 let target_dictionary = get_dictionary_for_offer_target(target, first_offer).await?;
587 let metadata = service_metadata(first_offer.availability);
588 metadata
589 .insert(
590 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
591 Capability::Data(Data::Uint64(1)),
592 )
593 .unwrap();
594 route_capability_inner::<DirConnector, _>(
595 &target_dictionary,
596 &first_offer.target_name,
597 metadata,
598 target,
599 )
600 .await
601 }
602 RouteRequest::OfferEventStream(offer_event_stream_decl) => {
603 route_event_stream_from_offer(offer_event_stream_decl, target, mapper).await
604 }
605 RouteRequest::OfferRunner(offer_runner_decl) => {
606 let target_dictionary =
607 get_dictionary_for_offer_target(target, &offer_runner_decl).await?;
608 let metadata = runner_metadata(Availability::Required);
609 metadata
610 .insert(
611 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
612 Capability::Data(Data::Uint64(1)),
613 )
614 .unwrap();
615 route_capability_inner::<Connector, _>(
616 &target_dictionary,
617 &offer_runner_decl.target_name,
618 metadata,
619 target,
620 )
621 .await
622 }
623 RouteRequest::OfferResolver(offer_resolver_decl) => {
624 let target_dictionary =
625 get_dictionary_for_offer_target(target, &offer_resolver_decl).await?;
626 let metadata = resolver_metadata(Availability::Required);
627 metadata
628 .insert(
629 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
630 Capability::Data(Data::Uint64(1)),
631 )
632 .unwrap();
633 route_capability_inner::<Connector, _>(
634 &target_dictionary,
635 &offer_resolver_decl.target_name,
636 metadata,
637 target,
638 )
639 .await
640 }
641 RouteRequest::OfferConfig(offer) => route_config_from_offer(offer, target, mapper).await,
642 }
643}
644
645pub enum Never {}
646
647async fn route_capability_inner<T, C>(
648 dictionary: &Dict,
649 path: &impl IterablePath,
650 metadata: Dict,
651 target: &Arc<C>,
652) -> Result<RouteSource, RoutingError>
653where
654 C: ComponentInstanceInterface + 'static,
655 T: CapabilityBound + Debug,
656 Router<T>: TryFrom<Capability>,
657{
658 let router = dictionary
659 .get_capability(path)
660 .and_then(|c| Router::<T>::try_from(c).ok())
661 .ok_or_else(|| RoutingError::BedrockNotPresentInDictionary {
662 moniker: target.moniker().clone().into(),
663 name: path.iter_segments().join("/"),
664 })?;
665 perform_route::<T, C>(router, metadata, target).await
666}
667
668async fn perform_route<T, C>(
669 router: impl Routable<T>,
670 metadata: Dict,
671 target: &Arc<C>,
672) -> Result<RouteSource, RoutingError>
673where
674 C: ComponentInstanceInterface + 'static,
675 T: CapabilityBound + Debug,
676 Router<T>: TryFrom<Capability>,
677{
678 let request = Request { target: WeakComponentInstanceInterface::new(target).into(), metadata };
679 let data = match router.route(Some(request), true).await? {
680 RouterResponse::<T>::Debug(d) => d,
681 d => panic!("Debug route did not return a debug response: {d:?}"),
682 };
683 Ok(RouteSource::new(data.try_into().unwrap()))
684}
685
686async fn get_dictionary_for_offer_target<C, O>(
687 target: &Arc<C>,
688 offer: &O,
689) -> Result<Dict, RoutingError>
690where
691 C: ComponentInstanceInterface + 'static,
692 O: OfferDeclCommon,
693{
694 match offer.target() {
695 OfferTarget::Child(child_ref) if child_ref.collection.is_none() => {
696 let child_input_name = Name::new(&child_ref.name)
698 .map_err(MonikerError::InvalidMonikerPart)
699 .expect("static child names must be short");
700 let target_sandbox = target.component_sandbox().await?;
701 let child_input = target_sandbox.child_inputs.get(&child_input_name).ok_or(
702 RoutingError::OfferFromChildInstanceNotFound {
703 child_moniker: child_ref.clone().into(),
704 moniker: target.moniker().clone(),
705 capability_id: offer.target_name().clone().to_string(),
706 },
707 )?;
708 Ok(child_input.capabilities())
709 }
710 OfferTarget::Child(child_ref) => {
711 let child = target
719 .lock_resolved_state()
720 .await?
721 .get_child(&ChildName::from(child_ref.clone()))
722 .ok_or(RoutingError::OfferFromChildInstanceNotFound {
723 child_moniker: child_ref.clone().into(),
724 moniker: target.moniker().clone(),
725 capability_id: offer.target_name().clone().to_string(),
726 })?;
727 Ok(child.component_sandbox().await?.component_input.capabilities())
728 }
729 OfferTarget::Collection(collection_name) => {
730 let target_sandbox = target.component_sandbox().await?;
733 let collection_input = target_sandbox.collection_inputs.get(collection_name).ok_or(
734 RoutingError::OfferFromCollectionNotFound {
735 collection: collection_name.to_string(),
736 moniker: target.moniker().clone(),
737 capability: offer.target_name().clone(),
738 },
739 )?;
740 Ok(collection_input.capabilities())
741 }
742 OfferTarget::Capability(dictionary_name) => {
743 let target_sandbox = target.component_sandbox().await?;
747 let capability =
748 target_sandbox.declared_dictionaries.get(dictionary_name).ok().flatten().ok_or(
749 RoutingError::BedrockNotPresentInDictionary {
750 name: dictionary_name.to_string(),
751 moniker: target.moniker().clone().into(),
752 },
753 )?;
754 match capability {
755 Capability::Dictionary(dictionary) => Ok(dictionary),
756 other_type => Err(RoutingError::BedrockWrongCapabilityType {
757 actual: other_type.debug_typename().to_string(),
758 expected: "Dictionary".to_string(),
759 moniker: target.moniker().clone().into(),
760 }),
761 }
762 }
763 }
764}
765
766async fn route_event_stream_from_offer<C>(
768 offer_decl: OfferEventStreamDecl,
769 target: &Arc<C>,
770 mapper: &mut dyn DebugRouteMapper,
771) -> Result<RouteSource, RoutingError>
772where
773 C: ComponentInstanceInterface + 'static,
774{
775 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
776
777 let mut availability_visitor = offer_decl.availability;
778 let source = legacy_router::route_from_offer(
779 RouteBundle::from_offer(offer_decl.into()),
780 target.clone(),
781 allowed_sources,
782 &mut availability_visitor,
783 mapper,
784 )
785 .await?;
786 Ok(RouteSource::new(source))
787}
788
789async fn route_storage_from_offer<C>(
790 offer_decl: OfferStorageDecl,
791 target: &Arc<C>,
792 mapper: &mut dyn DebugRouteMapper,
793) -> Result<RouteSource, RoutingError>
794where
795 C: ComponentInstanceInterface + 'static,
796{
797 let mut availability_visitor = offer_decl.availability;
798 let allowed_sources = Sources::new(CapabilityTypeName::Storage).component();
799 let source = legacy_router::route_from_offer(
800 RouteBundle::from_offer(offer_decl.into()),
801 target.clone(),
802 allowed_sources,
803 &mut availability_visitor,
804 mapper,
805 )
806 .await?;
807 Ok(RouteSource::new(source))
808}
809
810async fn route_config_from_offer<C>(
811 offer_decl: OfferConfigurationDecl,
812 target: &Arc<C>,
813 mapper: &mut dyn DebugRouteMapper,
814) -> Result<RouteSource, RoutingError>
815where
816 C: ComponentInstanceInterface + 'static,
817{
818 let allowed_sources = Sources::new(CapabilityTypeName::Config).builtin().component();
819 let source = legacy_router::route_from_offer(
820 RouteBundle::from_offer(offer_decl.into()),
821 target.clone(),
822 allowed_sources,
823 &mut NoopVisitor::new(),
824 mapper,
825 )
826 .await?;
827 Ok(RouteSource::new(source))
828}
829
830async fn route_config_from_expose<C>(
831 expose_decl: ExposeConfigurationDecl,
832 target: &Arc<C>,
833 mapper: &mut dyn DebugRouteMapper,
834) -> Result<RouteSource, RoutingError>
835where
836 C: ComponentInstanceInterface + 'static,
837{
838 let allowed_sources = Sources::new(CapabilityTypeName::Config).component().capability();
839 let source = legacy_router::route_from_expose(
840 RouteBundle::from_expose(expose_decl.into()),
841 target.clone(),
842 allowed_sources,
843 &mut NoopVisitor::new(),
844 mapper,
845 )
846 .await?;
847
848 target.policy_checker().can_route_capability(&source, target.moniker())?;
849 Ok(RouteSource::new(source))
850}
851
852#[derive(Clone, Debug)]
854pub struct DirectoryState {
855 rights: WalkState<RightsWalker>,
856 pub subdir: RelativePath,
857 availability_state: Availability,
858}
859
860impl DirectoryState {
861 fn new(rights: RightsWalker, subdir: RelativePath, availability: &Availability) -> Self {
862 DirectoryState {
863 rights: WalkState::at(rights),
864 subdir,
865 availability_state: availability.clone(),
866 }
867 }
868
869 fn advance_with_offer(
870 &mut self,
871 moniker: &ExtendedMoniker,
872 offer: &OfferDirectoryDecl,
873 ) -> Result<(), RoutingError> {
874 self.availability_state =
875 availability::advance_with_offer(moniker, self.availability_state, offer)?;
876 self.advance(moniker, offer.rights.clone(), offer.subdir.clone())
877 }
878
879 fn advance_with_expose(
880 &mut self,
881 moniker: &ExtendedMoniker,
882 expose: &ExposeDirectoryDecl,
883 ) -> Result<(), RoutingError> {
884 self.availability_state =
885 availability::advance_with_expose(moniker, self.availability_state, expose)?;
886 self.advance(moniker, expose.rights.clone(), expose.subdir.clone())
887 }
888
889 fn advance(
890 &mut self,
891 moniker: &ExtendedMoniker,
892 rights: Option<fio::Operations>,
893 mut subdir: RelativePath,
894 ) -> Result<(), RoutingError> {
895 self.rights = self.rights.advance(rights.map(|r| RightsWalker::new(r, moniker.clone())))?;
896 if !subdir.extend(self.subdir.clone()) {
897 return Err(RoutingError::PathTooLong {
898 moniker: moniker.clone(),
899 path: format!("{}/{}", subdir, self.subdir),
900 keyword: "subdir".into(),
901 });
902 }
903 self.subdir = subdir;
904 Ok(())
905 }
906
907 fn finalize(
908 &mut self,
909 moniker: &ExtendedMoniker,
910 rights: RightsWalker,
911 mut subdir: RelativePath,
912 ) -> Result<(), RoutingError> {
913 self.rights = self.rights.finalize(Some(rights))?;
914 if !subdir.extend(self.subdir.clone()) {
915 return Err(RoutingError::PathTooLong {
916 moniker: moniker.clone(),
917 path: format!("{}/{}", subdir, self.subdir),
918 keyword: "subdir".into(),
919 });
920 }
921 self.subdir = subdir;
922 Ok(())
923 }
924}
925
926impl OfferVisitor for DirectoryState {
927 fn visit(
928 &mut self,
929 moniker: &ExtendedMoniker,
930 offer: &cm_rust::OfferDecl,
931 ) -> Result<(), RoutingError> {
932 match offer {
933 cm_rust::OfferDecl::Directory(dir) => match dir.source {
934 OfferSource::Framework => self.finalize(
935 moniker,
936 RightsWalker::new(fio::RX_STAR_DIR, moniker.clone()),
937 dir.subdir.clone(),
938 ),
939 _ => self.advance_with_offer(moniker, dir),
940 },
941 _ => Ok(()),
942 }
943 }
944}
945
946impl ExposeVisitor for DirectoryState {
947 fn visit(
948 &mut self,
949 moniker: &ExtendedMoniker,
950 expose: &cm_rust::ExposeDecl,
951 ) -> Result<(), RoutingError> {
952 match expose {
953 cm_rust::ExposeDecl::Directory(dir) => match dir.source {
954 ExposeSource::Framework => self.finalize(
955 moniker,
956 RightsWalker::new(fio::RX_STAR_DIR, moniker.clone()),
957 dir.subdir.clone(),
958 ),
959 _ => self.advance_with_expose(moniker, dir),
960 },
961 _ => Ok(()),
962 }
963 }
964}
965
966impl CapabilityVisitor for DirectoryState {
967 fn visit(
968 &mut self,
969 moniker: &ExtendedMoniker,
970 capability: &cm_rust::CapabilityDecl,
971 ) -> Result<(), RoutingError> {
972 match capability {
973 cm_rust::CapabilityDecl::Directory(dir) => self.finalize(
974 moniker,
975 RightsWalker::new(dir.rights, moniker.clone()),
976 Default::default(),
977 ),
978 _ => Ok(()),
979 }
980 }
981}
982
983pub async fn verify_instance_in_component_id_index<C>(
987 source: &CapabilitySource,
988 instance: &Arc<C>,
989) -> Result<(), RoutingError>
990where
991 C: ComponentInstanceInterface + 'static,
992{
993 let (storage_decl, source_moniker) = match source {
994 CapabilitySource::Component(ComponentSource {
995 capability: ComponentCapability::Storage(storage_decl),
996 moniker,
997 }) => (storage_decl, moniker.clone()),
998 CapabilitySource::Void(VoidSource { .. }) => return Ok(()),
999 _ => unreachable!("unexpected storage source"),
1000 };
1001
1002 if storage_decl.storage_id == fdecl::StorageId::StaticInstanceId
1003 && instance.component_id_index().id_for_moniker(instance.moniker()).is_none()
1004 {
1005 return Err(RoutingError::ComponentNotInIdIndex {
1006 source_moniker,
1007 target_name: instance.moniker().leaf().map(Into::into),
1008 });
1009 }
1010 Ok(())
1011}
1012
1013pub async fn route_to_storage_decl<C>(
1016 use_decl: UseStorageDecl,
1017 target: &Arc<C>,
1018 mapper: &mut dyn DebugRouteMapper,
1019) -> Result<CapabilitySource, RoutingError>
1020where
1021 C: ComponentInstanceInterface + 'static,
1022{
1023 let mut availability_visitor = use_decl.availability;
1024 let allowed_sources = Sources::new(CapabilityTypeName::Storage).component();
1025 let source = legacy_router::route_from_use(
1026 use_decl.into(),
1027 target.clone(),
1028 allowed_sources,
1029 &mut availability_visitor,
1030 mapper,
1031 )
1032 .await?;
1033 Ok(source)
1034}
1035
1036async fn route_storage<C>(
1039 use_decl: UseStorageDecl,
1040 target: &Arc<C>,
1041 mapper: &mut dyn DebugRouteMapper,
1042) -> Result<RouteSource, RoutingError>
1043where
1044 C: ComponentInstanceInterface + 'static,
1045{
1046 let source = route_to_storage_decl(use_decl, &target, mapper).await?;
1047 verify_instance_in_component_id_index(&source, target).await?;
1048 target.policy_checker().can_route_capability(&source, target.moniker())?;
1049 Ok(RouteSource::new(source))
1050}
1051
1052async fn route_storage_backing_directory<C>(
1055 storage_decl: StorageDecl,
1056 target: &Arc<C>,
1057 mapper: &mut dyn DebugRouteMapper,
1058) -> Result<RouteSource, RoutingError>
1059where
1060 C: ComponentInstanceInterface + 'static,
1061{
1062 let mut state = DirectoryState::new(
1064 RightsWalker::new(fio::RW_STAR_DIR, target.moniker().clone()),
1065 Default::default(),
1066 &Availability::Required,
1067 );
1068 let allowed_sources = Sources::new(CapabilityTypeName::Directory).component().namespace();
1069 let source = legacy_router::route_from_registration(
1070 StorageDeclAsRegistration::from(storage_decl.clone()),
1071 target.clone(),
1072 allowed_sources,
1073 &mut state,
1074 mapper,
1075 )
1076 .await?;
1077
1078 target.policy_checker().can_route_capability(&source, target.moniker())?;
1079
1080 Ok(RouteSource::new_with_relative_path(source, state.subdir))
1081}
1082
1083async fn route_config<C>(
1085 use_decl: UseConfigurationDecl,
1086 target: &Arc<C>,
1087 mapper: &mut dyn DebugRouteMapper,
1088) -> Result<RouteSource, RoutingError>
1089where
1090 C: ComponentInstanceInterface + 'static,
1091{
1092 let allowed_sources = Sources::new(CapabilityTypeName::Config).component().capability();
1093 let mut availability_visitor = use_decl.availability().clone();
1094 let source = legacy_router::route_from_use(
1095 use_decl.clone().into(),
1096 target.clone(),
1097 allowed_sources,
1098 &mut availability_visitor,
1099 mapper,
1100 )
1101 .await;
1102 let source = match source {
1105 Ok(s) => s,
1106 Err(e) => {
1107 if *use_decl.availability() == Availability::Transitional
1108 && e.as_zx_status() == zx::Status::NOT_FOUND
1109 {
1110 CapabilitySource::Void(VoidSource {
1111 capability: InternalCapability::Config(use_decl.source_name),
1112 moniker: target.moniker().clone(),
1113 })
1114 } else {
1115 return Err(e);
1116 }
1117 }
1118 };
1119
1120 target.policy_checker().can_route_capability(&source, target.moniker())?;
1121 Ok(RouteSource::new(source))
1122}
1123
1124pub async fn route_event_stream<C>(
1129 use_decl: UseEventStreamDecl,
1130 target: &Arc<C>,
1131 mapper: &mut dyn DebugRouteMapper,
1132) -> Result<RouteSource, RoutingError>
1133where
1134 C: ComponentInstanceInterface + 'static,
1135{
1136 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
1137 let mut availability_visitor = use_decl.availability;
1138 let source = legacy_router::route_from_use(
1139 use_decl.into(),
1140 target.clone(),
1141 allowed_sources,
1142 &mut availability_visitor,
1143 mapper,
1144 )
1145 .await?;
1146 target.policy_checker().can_route_capability(&source, target.moniker())?;
1147 Ok(RouteSource::new(source))
1148}
1149
1150#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1153#[derive(Debug, Clone, PartialEq, Eq)]
1154pub struct StorageDeclAsRegistration {
1155 source: RegistrationSource,
1156 name: Name,
1157}
1158
1159impl From<StorageDecl> for StorageDeclAsRegistration {
1160 fn from(decl: StorageDecl) -> Self {
1161 Self {
1162 name: decl.backing_dir,
1163 source: match decl.source {
1164 StorageDirectorySource::Parent => RegistrationSource::Parent,
1165 StorageDirectorySource::Self_ => RegistrationSource::Self_,
1166 StorageDirectorySource::Child(child) => RegistrationSource::Child(child),
1167 },
1168 }
1169 }
1170}
1171
1172impl SourceName for StorageDeclAsRegistration {
1173 fn source_name(&self) -> &Name {
1174 &self.name
1175 }
1176}
1177
1178impl RegistrationDeclCommon for StorageDeclAsRegistration {
1179 const TYPE: &'static str = "storage";
1180
1181 fn source(&self) -> &RegistrationSource {
1182 &self.source
1183 }
1184}
1185
1186#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1189#[derive(FromEnum, Debug, Clone, PartialEq, Eq)]
1190pub enum RegistrationDecl {
1191 Resolver(ResolverRegistration),
1192 Runner(RunnerRegistration),
1193 Debug(DebugProtocolRegistration),
1194 Directory(StorageDeclAsRegistration),
1195}
1196
1197impl From<&RegistrationDecl> for cm_rust::CapabilityTypeName {
1198 fn from(registration: &RegistrationDecl) -> Self {
1199 match registration {
1200 RegistrationDecl::Directory(_) => Self::Directory,
1201 RegistrationDecl::Resolver(_) => Self::Resolver,
1202 RegistrationDecl::Runner(_) => Self::Runner,
1203 RegistrationDecl::Debug(_) => Self::Protocol,
1204 }
1205 }
1206}
1207
1208impl ErrorNotFoundFromParent for cm_rust::UseDecl {
1211 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1212 RoutingError::UseFromParentNotFound { moniker, capability_id: capability_name.into() }
1213 }
1214}
1215
1216impl ErrorNotFoundFromParent for cm_rust::DebugProtocolRegistration {
1217 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1218 RoutingError::EnvironmentFromParentNotFound {
1219 moniker,
1220 capability_name,
1221 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
1222 }
1223 }
1224}
1225
1226impl ErrorNotFoundInChild for cm_rust::DebugProtocolRegistration {
1227 fn error_not_found_in_child(
1228 moniker: Moniker,
1229 child_moniker: ChildName,
1230 capability_name: Name,
1231 ) -> RoutingError {
1232 RoutingError::EnvironmentFromChildExposeNotFound {
1233 moniker,
1234 child_moniker,
1235 capability_name,
1236 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
1237 }
1238 }
1239}
1240
1241impl ErrorNotFoundInChild for cm_rust::UseDecl {
1242 fn error_not_found_in_child(
1243 moniker: Moniker,
1244 child_moniker: ChildName,
1245 capability_name: Name,
1246 ) -> RoutingError {
1247 RoutingError::UseFromChildExposeNotFound {
1248 child_moniker,
1249 moniker,
1250 capability_id: capability_name.into(),
1251 }
1252 }
1253}
1254
1255impl ErrorNotFoundInChild for cm_rust::ExposeDecl {
1256 fn error_not_found_in_child(
1257 moniker: Moniker,
1258 child_moniker: ChildName,
1259 capability_name: Name,
1260 ) -> RoutingError {
1261 RoutingError::ExposeFromChildExposeNotFound {
1262 moniker,
1263 child_moniker,
1264 capability_id: capability_name.into(),
1265 }
1266 }
1267}
1268
1269impl ErrorNotFoundInChild for cm_rust::OfferDecl {
1270 fn error_not_found_in_child(
1271 moniker: Moniker,
1272 child_moniker: ChildName,
1273 capability_name: Name,
1274 ) -> RoutingError {
1275 RoutingError::OfferFromChildExposeNotFound {
1276 moniker,
1277 child_moniker,
1278 capability_id: capability_name.into(),
1279 }
1280 }
1281}
1282
1283impl ErrorNotFoundFromParent for cm_rust::OfferDecl {
1284 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1285 RoutingError::OfferFromParentNotFound { moniker, capability_id: capability_name.into() }
1286 }
1287}
1288
1289impl ErrorNotFoundInChild for StorageDeclAsRegistration {
1290 fn error_not_found_in_child(
1291 moniker: Moniker,
1292 child_moniker: ChildName,
1293 capability_name: Name,
1294 ) -> RoutingError {
1295 RoutingError::StorageFromChildExposeNotFound {
1296 moniker,
1297 child_moniker,
1298 capability_id: capability_name.into(),
1299 }
1300 }
1301}
1302
1303impl ErrorNotFoundFromParent for StorageDeclAsRegistration {
1304 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1305 RoutingError::StorageFromParentNotFound { moniker, capability_id: capability_name.into() }
1306 }
1307}
1308
1309impl ErrorNotFoundFromParent for RunnerRegistration {
1310 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1311 RoutingError::UseFromEnvironmentNotFound {
1312 moniker,
1313 capability_name,
1314 capability_type: "runner".to_string(),
1315 }
1316 }
1317}
1318
1319impl ErrorNotFoundInChild for RunnerRegistration {
1320 fn error_not_found_in_child(
1321 moniker: Moniker,
1322 child_moniker: ChildName,
1323 capability_name: Name,
1324 ) -> RoutingError {
1325 RoutingError::EnvironmentFromChildExposeNotFound {
1326 moniker,
1327 child_moniker,
1328 capability_name,
1329 capability_type: "runner".to_string(),
1330 }
1331 }
1332}
1333
1334impl ErrorNotFoundFromParent for ResolverRegistration {
1335 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1336 RoutingError::EnvironmentFromParentNotFound {
1337 moniker,
1338 capability_name,
1339 capability_type: "resolver".to_string(),
1340 }
1341 }
1342}
1343
1344impl ErrorNotFoundInChild for ResolverRegistration {
1345 fn error_not_found_in_child(
1346 moniker: Moniker,
1347 child_moniker: ChildName,
1348 capability_name: Name,
1349 ) -> RoutingError {
1350 RoutingError::EnvironmentFromChildExposeNotFound {
1351 moniker,
1352 child_moniker,
1353 capability_name,
1354 capability_type: "resolver".to_string(),
1355 }
1356 }
1357}