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