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 config_metadata, dictionary_metadata, directory_metadata, protocol_metadata, resolver_metadata,
22 runner_metadata, 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, OfferVisitor,
31 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 let sandbox = target.component_sandbox().await?;
415 let dictionary = match &expose_config_decl.target {
416 ExposeTarget::Parent => sandbox.component_output.capabilities(),
417 ExposeTarget::Framework => sandbox.component_output.framework(),
418 };
419 let source = route_capability_inner::<Data, _>(
420 &dictionary,
421 &expose_config_decl.target_name,
422 config_metadata(expose_config_decl.availability),
423 target,
424 )
425 .await;
426 let source = match source {
429 Ok(s) => s,
430 Err(e) => {
431 if *expose_config_decl.availability() == Availability::Transitional
432 && e.as_zx_status() == zx::Status::NOT_FOUND
433 {
434 RouteSource::new(CapabilitySource::Void(VoidSource {
435 capability: InternalCapability::Config(expose_config_decl.source_name),
436 moniker: target.moniker().clone(),
437 }))
438 } else {
439 return Err(e);
440 }
441 }
442 };
443 Ok(source)
444 }
445
446 RouteRequest::Resolver(resolver_registration) => {
448 let component_sandbox = target.component_sandbox().await?;
449 let source_dictionary = match &resolver_registration.source {
450 RegistrationSource::Parent => component_sandbox.component_input.capabilities(),
451 RegistrationSource::Self_ => component_sandbox.program_output_dict.clone(),
452 RegistrationSource::Child(static_name) => {
453 let child_name = ChildName::parse(static_name).expect(
454 "invalid child name, this should be prevented by manifest validation",
455 );
456 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");
457 let child_sandbox = child_component.component_sandbox().await?;
458 child_sandbox.component_output.capabilities().clone()
459 }
460 };
461 route_capability_inner::<Connector, _>(
462 &source_dictionary,
463 &resolver_registration.resolver,
464 resolver_metadata(Availability::Required),
465 target,
466 )
467 .await
468 }
469 RouteRequest::StorageBackingDirectory(storage_decl) => {
471 route_storage_backing_directory(storage_decl, target, mapper).await
472 }
473
474 RouteRequest::UseDirectory(use_directory_decl) => {
476 let subdir = match use_directory_decl.source {
477 UseSource::Self_ => None,
478 _ => Some(SubDir::from(use_directory_decl.subdir)),
479 };
480 route_capability_inner::<DirConnector, _>(
481 &target.component_sandbox().await?.program_input.namespace(),
482 &use_directory_decl.target_path,
483 directory_metadata(
484 use_directory_decl.availability,
485 Some(use_directory_decl.rights.into()),
486 subdir,
487 ),
488 target,
489 )
490 .await
491 }
492 RouteRequest::UseEventStream(use_event_stream_decl) => {
493 route_event_stream(use_event_stream_decl, target, mapper).await
494 }
495 RouteRequest::UseProtocol(use_protocol_decl) => {
496 if let Some(target_path) = use_protocol_decl.target_path.as_ref() {
497 route_capability_inner::<Connector, _>(
498 &target.component_sandbox().await?.program_input.namespace(),
499 target_path,
500 protocol_metadata(use_protocol_decl.availability),
501 target,
502 )
503 .await
504 } else {
505 let numbered_handle = use_protocol_decl
506 .numbered_handle
507 .expect("validation guarantees numbered_handle is set");
508 let numbered_handle = Name::from(numbered_handle);
509 route_capability_inner::<Connector, _>(
510 &target.component_sandbox().await?.program_input.numbered_handles(),
511 &numbered_handle,
512 protocol_metadata(use_protocol_decl.availability),
513 target,
514 )
515 .await
516 }
517 }
518 RouteRequest::UseService(use_service_decl) => {
519 route_capability_inner::<DirConnector, _>(
520 &target.component_sandbox().await?.program_input.namespace(),
521 &use_service_decl.target_path,
522 service_metadata(use_service_decl.availability),
523 target,
524 )
525 .await
526 }
527 RouteRequest::UseStorage(use_storage_decl) => {
528 route_storage(use_storage_decl, target, mapper).await
529 }
530 RouteRequest::UseRunner(_use_runner_decl) => {
531 let router =
532 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");
533 perform_route::<Connector, _>(router, runner_metadata(Availability::Required), target)
534 .await
535 }
536 RouteRequest::UseConfig(use_config_decl) => {
537 let source = route_capability_inner::<Data, _>(
538 &target.component_sandbox().await?.program_input.config(),
539 &use_config_decl.target_name,
540 config_metadata(use_config_decl.availability),
541 target,
542 )
543 .await;
544 let source = match source {
547 Ok(s) => s,
548 Err(e) => {
549 if *use_config_decl.availability() == Availability::Transitional
550 && e.as_zx_status() == zx::Status::NOT_FOUND
551 {
552 RouteSource::new(CapabilitySource::Void(VoidSource {
553 capability: InternalCapability::Config(use_config_decl.source_name),
554 moniker: target.moniker().clone(),
555 }))
556 } else {
557 return Err(e);
558 }
559 }
560 };
561 Ok(source)
562 }
563 RouteRequest::UseDictionary(use_dictionary_decl) => {
564 route_capability_inner::<Dict, _>(
565 &target.component_sandbox().await?.program_input.namespace(),
566 &use_dictionary_decl.target_path,
567 dictionary_metadata(use_dictionary_decl.availability),
568 target,
569 )
570 .await
571 }
572
573 RouteRequest::OfferProtocol(offer_protocol_decl) => {
575 let target_dictionary =
576 get_dictionary_for_offer_target(target, &offer_protocol_decl).await?;
577 let metadata = protocol_metadata(offer_protocol_decl.availability);
578 metadata
579 .insert(
580 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
581 Capability::Data(Data::Uint64(1)),
582 )
583 .unwrap();
584 route_capability_inner::<Connector, _>(
585 &target_dictionary,
586 &offer_protocol_decl.target_name,
587 metadata,
588 target,
589 )
590 .await
591 }
592 RouteRequest::OfferDictionary(offer_dictionary_decl) => {
593 let target_dictionary =
594 get_dictionary_for_offer_target(target, &offer_dictionary_decl).await?;
595 let metadata = dictionary_metadata(offer_dictionary_decl.availability);
596 metadata
597 .insert(
598 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
599 Capability::Data(Data::Uint64(1)),
600 )
601 .unwrap();
602 route_capability_inner::<Dict, _>(
603 &target_dictionary,
604 &offer_dictionary_decl.target_name,
605 metadata,
606 target,
607 )
608 .await
609 }
610 RouteRequest::OfferDirectory(offer_directory_decl) => {
611 let target_dictionary =
612 get_dictionary_for_offer_target(target, &offer_directory_decl).await?;
613 let metadata = directory_metadata(
614 offer_directory_decl.availability,
615 offer_directory_decl.rights.and_then(|v| Some(v.into())),
616 Some(offer_directory_decl.subdir.into()),
617 );
618 metadata
619 .insert(
620 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
621 Capability::Data(Data::Uint64(1)),
622 )
623 .unwrap();
624 route_capability_inner::<DirConnector, _>(
625 &target_dictionary,
626 &offer_directory_decl.target_name,
627 metadata,
628 target,
629 )
630 .await
631 }
632 RouteRequest::OfferStorage(offer_storage_decl) => {
633 route_storage_from_offer(offer_storage_decl, target, mapper).await
634 }
635 RouteRequest::OfferService(offer_service_bundle) => {
636 let first_offer = offer_service_bundle.iter().next().expect("can't route empty bundle");
637 let target_dictionary = get_dictionary_for_offer_target(target, first_offer).await?;
638 let metadata = service_metadata(first_offer.availability);
639 metadata
640 .insert(
641 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
642 Capability::Data(Data::Uint64(1)),
643 )
644 .unwrap();
645 route_capability_inner::<DirConnector, _>(
646 &target_dictionary,
647 &first_offer.target_name,
648 metadata,
649 target,
650 )
651 .await
652 }
653 RouteRequest::OfferEventStream(offer_event_stream_decl) => {
654 route_event_stream_from_offer(offer_event_stream_decl, target, mapper).await
655 }
656 RouteRequest::OfferRunner(offer_runner_decl) => {
657 let target_dictionary =
658 get_dictionary_for_offer_target(target, &offer_runner_decl).await?;
659 let metadata = runner_metadata(Availability::Required);
660 metadata
661 .insert(
662 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
663 Capability::Data(Data::Uint64(1)),
664 )
665 .unwrap();
666 route_capability_inner::<Connector, _>(
667 &target_dictionary,
668 &offer_runner_decl.target_name,
669 metadata,
670 target,
671 )
672 .await
673 }
674 RouteRequest::OfferResolver(offer_resolver_decl) => {
675 let target_dictionary =
676 get_dictionary_for_offer_target(target, &offer_resolver_decl).await?;
677 let metadata = resolver_metadata(Availability::Required);
678 metadata
679 .insert(
680 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
681 Capability::Data(Data::Uint64(1)),
682 )
683 .unwrap();
684 route_capability_inner::<Connector, _>(
685 &target_dictionary,
686 &offer_resolver_decl.target_name,
687 metadata,
688 target,
689 )
690 .await
691 }
692 RouteRequest::OfferConfig(offer) => {
693 let target_dictionary = get_dictionary_for_offer_target(target, &offer).await?;
694 let metadata = config_metadata(offer.availability);
695 metadata
696 .insert(
697 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
698 Capability::Data(Data::Uint64(1)),
699 )
700 .unwrap();
701 route_capability_inner::<Data, _>(
702 &target_dictionary,
703 &offer.target_name,
704 metadata,
705 target,
706 )
707 .await
708 }
709 }
710}
711
712pub enum Never {}
713
714async fn route_capability_inner<T, C>(
715 dictionary: &Dict,
716 path: &impl IterablePath,
717 metadata: Dict,
718 target: &Arc<C>,
719) -> Result<RouteSource, RoutingError>
720where
721 C: ComponentInstanceInterface + 'static,
722 T: CapabilityBound + Debug,
723 Router<T>: TryFrom<Capability>,
724{
725 let router = dictionary.get_router_or_not_found(
726 path,
727 RoutingError::BedrockNotPresentInDictionary {
728 moniker: target.moniker().clone().into(),
729 name: path.iter_segments().join("/"),
730 },
731 );
732 perform_route::<T, C>(router, metadata, target).await
733}
734
735async fn perform_route<T, C>(
736 router: impl Routable<T>,
737 metadata: Dict,
738 target: &Arc<C>,
739) -> Result<RouteSource, RoutingError>
740where
741 C: ComponentInstanceInterface + 'static,
742 T: CapabilityBound + Debug,
743 Router<T>: TryFrom<Capability>,
744{
745 let request = Request { metadata };
746 let data = match router.route(Some(request), true, target.as_weak().into()).await? {
747 RouterResponse::<T>::Debug(d) => d,
748 d => panic!("Debug route did not return a debug response: {d:?}"),
749 };
750 Ok(RouteSource::new(data.try_into().unwrap()))
751}
752
753async fn get_dictionary_for_offer_target<C, O>(
754 target: &Arc<C>,
755 offer: &O,
756) -> Result<Dict, RoutingError>
757where
758 C: ComponentInstanceInterface + 'static,
759 O: OfferDeclCommon,
760{
761 match offer.target() {
762 OfferTarget::Child(child_ref) if child_ref.collection.is_none() => {
763 let child_input_name = Name::new(&child_ref.name)
765 .map_err(MonikerError::InvalidMonikerPart)
766 .expect("static child names must be short");
767 let target_sandbox = target.component_sandbox().await?;
768 let child_input = target_sandbox.child_inputs.get(&child_input_name).ok_or(
769 RoutingError::OfferFromChildInstanceNotFound {
770 child_moniker: child_ref.clone().into(),
771 moniker: target.moniker().clone(),
772 capability_id: offer.target_name().clone().to_string(),
773 },
774 )?;
775 Ok(child_input.capabilities())
776 }
777 OfferTarget::Child(child_ref) => {
778 let child = target
786 .lock_resolved_state()
787 .await?
788 .get_child(&ChildName::from(child_ref.clone()))
789 .ok_or(RoutingError::OfferFromChildInstanceNotFound {
790 child_moniker: child_ref.clone().into(),
791 moniker: target.moniker().clone(),
792 capability_id: offer.target_name().clone().to_string(),
793 })?;
794 Ok(child.component_sandbox().await?.component_input.capabilities())
795 }
796 OfferTarget::Collection(collection_name) => {
797 let target_sandbox = target.component_sandbox().await?;
800 let collection_input = target_sandbox.collection_inputs.get(collection_name).ok_or(
801 RoutingError::OfferFromCollectionNotFound {
802 collection: collection_name.to_string(),
803 moniker: target.moniker().clone(),
804 capability: offer.target_name().clone(),
805 },
806 )?;
807 Ok(collection_input.capabilities())
808 }
809 OfferTarget::Capability(dictionary_name) => {
810 let target_sandbox = target.component_sandbox().await?;
814 let capability =
815 target_sandbox.declared_dictionaries.get(dictionary_name).ok().flatten().ok_or(
816 RoutingError::BedrockNotPresentInDictionary {
817 name: dictionary_name.to_string(),
818 moniker: target.moniker().clone().into(),
819 },
820 )?;
821 match capability {
822 Capability::Dictionary(dictionary) => Ok(dictionary),
823 other_type => Err(RoutingError::BedrockWrongCapabilityType {
824 actual: other_type.debug_typename().to_string(),
825 expected: "Dictionary".to_string(),
826 moniker: target.moniker().clone().into(),
827 }),
828 }
829 }
830 }
831}
832
833async fn route_event_stream_from_offer<C>(
835 offer_decl: OfferEventStreamDecl,
836 target: &Arc<C>,
837 mapper: &mut dyn DebugRouteMapper,
838) -> Result<RouteSource, RoutingError>
839where
840 C: ComponentInstanceInterface + 'static,
841{
842 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
843
844 let mut availability_visitor = offer_decl.availability;
845 let source = legacy_router::route_from_offer(
846 RouteBundle::from_offer(offer_decl.into()),
847 target.clone(),
848 allowed_sources,
849 &mut availability_visitor,
850 mapper,
851 )
852 .await?;
853 Ok(RouteSource::new(source))
854}
855
856async fn route_storage_from_offer<C>(
857 offer_decl: OfferStorageDecl,
858 target: &Arc<C>,
859 mapper: &mut dyn DebugRouteMapper,
860) -> Result<RouteSource, RoutingError>
861where
862 C: ComponentInstanceInterface + 'static,
863{
864 let mut availability_visitor = offer_decl.availability;
865 let allowed_sources = Sources::new(CapabilityTypeName::Storage).component();
866 let source = legacy_router::route_from_offer(
867 RouteBundle::from_offer(offer_decl.into()),
868 target.clone(),
869 allowed_sources,
870 &mut availability_visitor,
871 mapper,
872 )
873 .await?;
874 Ok(RouteSource::new(source))
875}
876
877#[derive(Clone, Debug)]
879pub struct DirectoryState {
880 rights: WalkState<RightsWalker>,
881 pub subdir: RelativePath,
882 availability_state: Availability,
883}
884
885impl DirectoryState {
886 fn new(rights: RightsWalker, subdir: RelativePath, availability: &Availability) -> Self {
887 DirectoryState {
888 rights: WalkState::at(rights),
889 subdir,
890 availability_state: availability.clone(),
891 }
892 }
893
894 fn advance_with_offer(
895 &mut self,
896 moniker: &ExtendedMoniker,
897 offer: &OfferDirectoryDecl,
898 ) -> Result<(), RoutingError> {
899 self.availability_state =
900 availability::advance_with_offer(moniker, self.availability_state, offer)?;
901 self.advance(moniker, offer.rights.clone(), offer.subdir.clone())
902 }
903
904 fn advance_with_expose(
905 &mut self,
906 moniker: &ExtendedMoniker,
907 expose: &ExposeDirectoryDecl,
908 ) -> Result<(), RoutingError> {
909 self.availability_state =
910 availability::advance_with_expose(moniker, self.availability_state, expose)?;
911 self.advance(moniker, expose.rights.clone(), expose.subdir.clone())
912 }
913
914 fn advance(
915 &mut self,
916 moniker: &ExtendedMoniker,
917 rights: Option<fio::Operations>,
918 mut subdir: RelativePath,
919 ) -> Result<(), RoutingError> {
920 self.rights = self.rights.advance(rights.map(|r| RightsWalker::new(r, moniker.clone())))?;
921 if !subdir.extend(self.subdir.clone()) {
922 return Err(RoutingError::PathTooLong {
923 moniker: moniker.clone(),
924 path: format!("{}/{}", subdir, self.subdir),
925 keyword: "subdir".into(),
926 });
927 }
928 self.subdir = subdir;
929 Ok(())
930 }
931
932 fn finalize(
933 &mut self,
934 moniker: &ExtendedMoniker,
935 rights: RightsWalker,
936 mut subdir: RelativePath,
937 ) -> Result<(), RoutingError> {
938 self.rights = self.rights.finalize(Some(rights))?;
939 if !subdir.extend(self.subdir.clone()) {
940 return Err(RoutingError::PathTooLong {
941 moniker: moniker.clone(),
942 path: format!("{}/{}", subdir, self.subdir),
943 keyword: "subdir".into(),
944 });
945 }
946 self.subdir = subdir;
947 Ok(())
948 }
949}
950
951impl OfferVisitor for DirectoryState {
952 fn visit(
953 &mut self,
954 moniker: &ExtendedMoniker,
955 offer: &cm_rust::OfferDecl,
956 ) -> Result<(), RoutingError> {
957 match offer {
958 cm_rust::OfferDecl::Directory(dir) => match dir.source {
959 OfferSource::Framework => self.finalize(
960 moniker,
961 RightsWalker::new(fio::RX_STAR_DIR, moniker.clone()),
962 dir.subdir.clone(),
963 ),
964 _ => self.advance_with_offer(moniker, dir),
965 },
966 _ => Ok(()),
967 }
968 }
969}
970
971impl ExposeVisitor for DirectoryState {
972 fn visit(
973 &mut self,
974 moniker: &ExtendedMoniker,
975 expose: &cm_rust::ExposeDecl,
976 ) -> Result<(), RoutingError> {
977 match expose {
978 cm_rust::ExposeDecl::Directory(dir) => match dir.source {
979 ExposeSource::Framework => self.finalize(
980 moniker,
981 RightsWalker::new(fio::RX_STAR_DIR, moniker.clone()),
982 dir.subdir.clone(),
983 ),
984 _ => self.advance_with_expose(moniker, dir),
985 },
986 _ => Ok(()),
987 }
988 }
989}
990
991impl CapabilityVisitor for DirectoryState {
992 fn visit(
993 &mut self,
994 moniker: &ExtendedMoniker,
995 capability: &cm_rust::CapabilityDecl,
996 ) -> Result<(), RoutingError> {
997 match capability {
998 cm_rust::CapabilityDecl::Directory(dir) => self.finalize(
999 moniker,
1000 RightsWalker::new(dir.rights, moniker.clone()),
1001 Default::default(),
1002 ),
1003 _ => Ok(()),
1004 }
1005 }
1006}
1007
1008pub async fn verify_instance_in_component_id_index<C>(
1012 source: &CapabilitySource,
1013 instance: &Arc<C>,
1014) -> Result<(), RoutingError>
1015where
1016 C: ComponentInstanceInterface + 'static,
1017{
1018 let (storage_decl, source_moniker) = match source {
1019 CapabilitySource::Component(ComponentSource {
1020 capability: ComponentCapability::Storage(storage_decl),
1021 moniker,
1022 }) => (storage_decl, moniker.clone()),
1023 CapabilitySource::Void(VoidSource { .. }) => return Ok(()),
1024 _ => unreachable!("unexpected storage source"),
1025 };
1026
1027 if storage_decl.storage_id == fdecl::StorageId::StaticInstanceId
1028 && instance.component_id_index().id_for_moniker(instance.moniker()).is_none()
1029 {
1030 return Err(RoutingError::ComponentNotInIdIndex {
1031 source_moniker,
1032 target_name: instance.moniker().leaf().map(Into::into),
1033 });
1034 }
1035 Ok(())
1036}
1037
1038pub async fn route_to_storage_decl<C>(
1041 use_decl: UseStorageDecl,
1042 target: &Arc<C>,
1043 mapper: &mut dyn DebugRouteMapper,
1044) -> Result<CapabilitySource, RoutingError>
1045where
1046 C: ComponentInstanceInterface + 'static,
1047{
1048 let mut availability_visitor = use_decl.availability;
1049 let allowed_sources = Sources::new(CapabilityTypeName::Storage).component();
1050 let source = legacy_router::route_from_use(
1051 use_decl.into(),
1052 target.clone(),
1053 allowed_sources,
1054 &mut availability_visitor,
1055 mapper,
1056 )
1057 .await?;
1058 Ok(source)
1059}
1060
1061async fn route_storage<C>(
1064 use_decl: UseStorageDecl,
1065 target: &Arc<C>,
1066 mapper: &mut dyn DebugRouteMapper,
1067) -> Result<RouteSource, RoutingError>
1068where
1069 C: ComponentInstanceInterface + 'static,
1070{
1071 let source = route_to_storage_decl(use_decl, &target, mapper).await?;
1072 verify_instance_in_component_id_index(&source, target).await?;
1073 target.policy_checker().can_route_capability(&source, target.moniker())?;
1074 Ok(RouteSource::new(source))
1075}
1076
1077async fn route_storage_backing_directory<C>(
1080 storage_decl: StorageDecl,
1081 target: &Arc<C>,
1082 mapper: &mut dyn DebugRouteMapper,
1083) -> Result<RouteSource, RoutingError>
1084where
1085 C: ComponentInstanceInterface + 'static,
1086{
1087 let mut state = DirectoryState::new(
1089 RightsWalker::new(fio::RW_STAR_DIR, target.moniker().clone()),
1090 Default::default(),
1091 &Availability::Required,
1092 );
1093 let allowed_sources = Sources::new(CapabilityTypeName::Directory).component().namespace();
1094 let source = legacy_router::route_from_registration(
1095 StorageDeclAsRegistration::from(storage_decl.clone()),
1096 target.clone(),
1097 allowed_sources,
1098 &mut state,
1099 mapper,
1100 )
1101 .await?;
1102
1103 target.policy_checker().can_route_capability(&source, target.moniker())?;
1104
1105 Ok(RouteSource::new_with_relative_path(source, state.subdir))
1106}
1107
1108pub async fn route_event_stream<C>(
1113 use_decl: UseEventStreamDecl,
1114 target: &Arc<C>,
1115 mapper: &mut dyn DebugRouteMapper,
1116) -> Result<RouteSource, RoutingError>
1117where
1118 C: ComponentInstanceInterface + 'static,
1119{
1120 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
1121 let mut availability_visitor = use_decl.availability;
1122 let source = legacy_router::route_from_use(
1123 use_decl.into(),
1124 target.clone(),
1125 allowed_sources,
1126 &mut availability_visitor,
1127 mapper,
1128 )
1129 .await?;
1130 target.policy_checker().can_route_capability(&source, target.moniker())?;
1131 Ok(RouteSource::new(source))
1132}
1133
1134#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1137#[derive(Debug, Clone, PartialEq, Eq)]
1138pub struct StorageDeclAsRegistration {
1139 source: RegistrationSource,
1140 name: Name,
1141}
1142
1143impl From<StorageDecl> for StorageDeclAsRegistration {
1144 fn from(decl: StorageDecl) -> Self {
1145 Self {
1146 name: decl.backing_dir,
1147 source: match decl.source {
1148 StorageDirectorySource::Parent => RegistrationSource::Parent,
1149 StorageDirectorySource::Self_ => RegistrationSource::Self_,
1150 StorageDirectorySource::Child(child) => RegistrationSource::Child(child),
1151 },
1152 }
1153 }
1154}
1155
1156impl SourceName for StorageDeclAsRegistration {
1157 fn source_name(&self) -> &Name {
1158 &self.name
1159 }
1160}
1161
1162impl RegistrationDeclCommon for StorageDeclAsRegistration {
1163 const TYPE: &'static str = "storage";
1164
1165 fn source(&self) -> &RegistrationSource {
1166 &self.source
1167 }
1168}
1169
1170#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1173#[derive(FromEnum, Debug, Clone, PartialEq, Eq)]
1174pub enum RegistrationDecl {
1175 Resolver(ResolverRegistration),
1176 Runner(RunnerRegistration),
1177 Debug(DebugProtocolRegistration),
1178 Directory(StorageDeclAsRegistration),
1179}
1180
1181impl From<&RegistrationDecl> for cm_rust::CapabilityTypeName {
1182 fn from(registration: &RegistrationDecl) -> Self {
1183 match registration {
1184 RegistrationDecl::Directory(_) => Self::Directory,
1185 RegistrationDecl::Resolver(_) => Self::Resolver,
1186 RegistrationDecl::Runner(_) => Self::Runner,
1187 RegistrationDecl::Debug(_) => Self::Protocol,
1188 }
1189 }
1190}
1191
1192impl ErrorNotFoundFromParent for cm_rust::UseDecl {
1195 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1196 RoutingError::UseFromParentNotFound { moniker, capability_id: capability_name.into() }
1197 }
1198}
1199
1200impl ErrorNotFoundFromParent for cm_rust::DebugProtocolRegistration {
1201 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1202 RoutingError::EnvironmentFromParentNotFound {
1203 moniker,
1204 capability_name,
1205 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
1206 }
1207 }
1208}
1209
1210impl ErrorNotFoundInChild for cm_rust::DebugProtocolRegistration {
1211 fn error_not_found_in_child(
1212 moniker: Moniker,
1213 child_moniker: ChildName,
1214 capability_name: Name,
1215 ) -> RoutingError {
1216 RoutingError::EnvironmentFromChildExposeNotFound {
1217 moniker,
1218 child_moniker,
1219 capability_name,
1220 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
1221 }
1222 }
1223}
1224
1225impl ErrorNotFoundInChild for cm_rust::UseDecl {
1226 fn error_not_found_in_child(
1227 moniker: Moniker,
1228 child_moniker: ChildName,
1229 capability_name: Name,
1230 ) -> RoutingError {
1231 RoutingError::UseFromChildExposeNotFound {
1232 child_moniker,
1233 moniker,
1234 capability_id: capability_name.into(),
1235 }
1236 }
1237}
1238
1239impl ErrorNotFoundInChild for cm_rust::ExposeDecl {
1240 fn error_not_found_in_child(
1241 moniker: Moniker,
1242 child_moniker: ChildName,
1243 capability_name: Name,
1244 ) -> RoutingError {
1245 RoutingError::ExposeFromChildExposeNotFound {
1246 moniker,
1247 child_moniker,
1248 capability_id: capability_name.into(),
1249 }
1250 }
1251}
1252
1253impl ErrorNotFoundInChild for cm_rust::OfferDecl {
1254 fn error_not_found_in_child(
1255 moniker: Moniker,
1256 child_moniker: ChildName,
1257 capability_name: Name,
1258 ) -> RoutingError {
1259 RoutingError::OfferFromChildExposeNotFound {
1260 moniker,
1261 child_moniker,
1262 capability_id: capability_name.into(),
1263 }
1264 }
1265}
1266
1267impl ErrorNotFoundFromParent for cm_rust::OfferDecl {
1268 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1269 RoutingError::OfferFromParentNotFound { moniker, capability_id: capability_name.into() }
1270 }
1271}
1272
1273impl ErrorNotFoundInChild for StorageDeclAsRegistration {
1274 fn error_not_found_in_child(
1275 moniker: Moniker,
1276 child_moniker: ChildName,
1277 capability_name: Name,
1278 ) -> RoutingError {
1279 RoutingError::StorageFromChildExposeNotFound {
1280 moniker,
1281 child_moniker,
1282 capability_id: capability_name.into(),
1283 }
1284 }
1285}
1286
1287impl ErrorNotFoundFromParent for StorageDeclAsRegistration {
1288 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1289 RoutingError::StorageFromParentNotFound { moniker, capability_id: capability_name.into() }
1290 }
1291}
1292
1293impl ErrorNotFoundFromParent for RunnerRegistration {
1294 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1295 RoutingError::UseFromEnvironmentNotFound {
1296 moniker,
1297 capability_name,
1298 capability_type: "runner".to_string(),
1299 }
1300 }
1301}
1302
1303impl ErrorNotFoundInChild for RunnerRegistration {
1304 fn error_not_found_in_child(
1305 moniker: Moniker,
1306 child_moniker: ChildName,
1307 capability_name: Name,
1308 ) -> RoutingError {
1309 RoutingError::EnvironmentFromChildExposeNotFound {
1310 moniker,
1311 child_moniker,
1312 capability_name,
1313 capability_type: "runner".to_string(),
1314 }
1315 }
1316}
1317
1318impl ErrorNotFoundFromParent for ResolverRegistration {
1319 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1320 RoutingError::EnvironmentFromParentNotFound {
1321 moniker,
1322 capability_name,
1323 capability_type: "resolver".to_string(),
1324 }
1325 }
1326}
1327
1328impl ErrorNotFoundInChild for ResolverRegistration {
1329 fn error_not_found_in_child(
1330 moniker: Moniker,
1331 child_moniker: ChildName,
1332 capability_name: Name,
1333 ) -> RoutingError {
1334 RoutingError::EnvironmentFromChildExposeNotFound {
1335 moniker,
1336 child_moniker,
1337 capability_name,
1338 capability_type: "resolver".to_string(),
1339 }
1340 }
1341}