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