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