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