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, storage_metadata,
23};
24use crate::capability_source::{CapabilitySource, InternalCapability, VoidSource};
25use crate::component_instance::{ComponentInstanceInterface, ResolvedInstanceInterface};
26use crate::error::RoutingError;
27use crate::legacy_router::{ErrorNotFoundFromParent, ErrorNotFoundInChild, RouteBundle, Sources};
28use crate::mapper::DebugRouteMapper;
29use cm_rust::{
30 Availability, CapabilityTypeName, DebugProtocolRegistration, ExposeConfigurationDecl,
31 ExposeDecl, ExposeDeclCommon, ExposeDictionaryDecl, ExposeDirectoryDecl, ExposeProtocolDecl,
32 ExposeResolverDecl, ExposeRunnerDecl, ExposeServiceDecl, ExposeTarget, OfferConfigurationDecl,
33 OfferDeclCommon, OfferDictionaryDecl, OfferDirectoryDecl, OfferEventStreamDecl,
34 OfferProtocolDecl, OfferResolverDecl, OfferRunnerDecl, OfferServiceDecl, OfferStorageDecl,
35 OfferTarget, RegistrationDeclCommon, RegistrationSource, ResolverRegistration,
36 RunnerRegistration, SourceName, StorageDecl, StorageDirectorySource, UseConfigurationDecl,
37 UseDecl, UseDeclCommon, UseDictionaryDecl, UseDirectoryDecl, UseEventStreamDecl,
38 UseProtocolDecl, UseRunnerDecl, UseServiceDecl, UseSource, UseStorageDecl,
39};
40use cm_types::{IterablePath, Name, RelativePath};
41use fidl_fuchsia_io::RW_STAR_DIR;
42use from_enum::FromEnum;
43use itertools::Itertools;
44use moniker::{ChildName, Moniker, MonikerError};
45use router_error::Explain;
46use sandbox::{
47 Capability, CapabilityBound, Connector, Data, Dict, DirConnector, Request, Routable, Router,
48 RouterResponse,
49};
50use std::fmt::Debug;
51use std::sync::Arc;
52use subdir::SubDir;
53use zx_status as zx;
54
55pub use bedrock::dict_ext::{DictExt, GenericRouterResponse};
56pub use bedrock::lazy_get::LazyGet;
57pub use bedrock::weak_instance_token_ext::{WeakInstanceTokenExt, test_invalid_instance_token};
58pub use bedrock::with_porcelain::WithPorcelain;
59#[cfg(feature = "serde")]
60use serde::{Deserialize, Serialize};
61
62#[derive(Clone, Debug)]
64pub enum RouteRequest {
65 ExposeDirectory(ExposeDirectoryDecl),
67 ExposeProtocol(ExposeProtocolDecl),
68 ExposeService(RouteBundle<ExposeServiceDecl>),
69 ExposeRunner(ExposeRunnerDecl),
70 ExposeResolver(ExposeResolverDecl),
71 ExposeConfig(ExposeConfigurationDecl),
72 ExposeDictionary(ExposeDictionaryDecl),
73
74 Resolver(ResolverRegistration),
76
77 StorageBackingDirectory(StorageDecl),
79
80 UseDirectory(UseDirectoryDecl),
82 UseEventStream(UseEventStreamDecl),
83 UseProtocol(UseProtocolDecl),
84 UseService(UseServiceDecl),
85 UseStorage(UseStorageDecl),
86 UseRunner(UseRunnerDecl),
87 UseConfig(UseConfigurationDecl),
88 UseDictionary(UseDictionaryDecl),
89
90 OfferDirectory(OfferDirectoryDecl),
92 OfferEventStream(OfferEventStreamDecl),
93 OfferProtocol(OfferProtocolDecl),
94 OfferService(RouteBundle<OfferServiceDecl>),
95 OfferStorage(OfferStorageDecl),
96 OfferRunner(OfferRunnerDecl),
97 OfferResolver(OfferResolverDecl),
98 OfferConfig(OfferConfigurationDecl),
99 OfferDictionary(OfferDictionaryDecl),
100}
101
102impl From<UseDecl> for RouteRequest {
103 fn from(decl: UseDecl) -> Self {
104 match decl {
105 UseDecl::Directory(decl) => Self::UseDirectory(decl),
106 UseDecl::Protocol(decl) => Self::UseProtocol(decl),
107 UseDecl::Service(decl) => Self::UseService(decl),
108 UseDecl::Storage(decl) => Self::UseStorage(decl),
109 UseDecl::EventStream(decl) => Self::UseEventStream(decl),
110 UseDecl::Runner(decl) => Self::UseRunner(decl),
111 UseDecl::Config(decl) => Self::UseConfig(decl),
112 UseDecl::Dictionary(decl) => Self::UseDictionary(decl),
113 }
114 }
115}
116
117impl RouteRequest {
118 pub fn from_expose_decls(exposes: Vec<&ExposeDecl>) -> Result<Self, RoutingError> {
119 let first_expose = exposes.first().expect("invalid empty expose list");
120 let first_type_name = CapabilityTypeName::from(*first_expose);
121 assert!(
122 exposes.iter().all(|e| {
123 let type_name: CapabilityTypeName = CapabilityTypeName::from(*e);
124 first_type_name == type_name && first_expose.target_name() == e.target_name()
125 }),
126 "invalid expose input: {:?}",
127 exposes
128 );
129 match first_expose {
130 ExposeDecl::Protocol(e) => {
131 assert!(exposes.len() == 1, "multiple exposes: {:?}", exposes);
132 Ok(Self::ExposeProtocol(e.clone()))
133 }
134 ExposeDecl::Service(_) => {
135 let exposes: Vec<_> = exposes
138 .into_iter()
139 .filter_map(|e| match e {
140 cm_rust::ExposeDecl::Service(e) => Some(e.clone()),
141 _ => None,
142 })
143 .collect();
144 Ok(Self::ExposeService(RouteBundle::from_exposes(exposes)))
145 }
146 ExposeDecl::Directory(e) => {
147 assert!(exposes.len() == 1, "multiple exposes");
148 Ok(Self::ExposeDirectory(e.clone()))
149 }
150 ExposeDecl::Runner(e) => {
151 assert!(exposes.len() == 1, "multiple exposes");
152 Ok(Self::ExposeRunner(e.clone()))
153 }
154 ExposeDecl::Resolver(e) => {
155 assert!(exposes.len() == 1, "multiple exposes");
156 Ok(Self::ExposeResolver(e.clone()))
157 }
158 ExposeDecl::Config(e) => {
159 assert!(exposes.len() == 1, "multiple exposes");
160 Ok(Self::ExposeConfig(e.clone()))
161 }
162 ExposeDecl::Dictionary(e) => {
163 assert!(exposes.len() == 1, "multiple exposes");
164 Ok(Self::ExposeDictionary(e.clone()))
165 }
166 }
167 }
168
169 pub fn availability(&self) -> Option<Availability> {
171 use crate::RouteRequest::*;
172 match self {
173 UseDirectory(UseDirectoryDecl { availability, .. })
174 | UseEventStream(UseEventStreamDecl { availability, .. })
175 | UseProtocol(UseProtocolDecl { availability, .. })
176 | UseService(UseServiceDecl { availability, .. })
177 | UseConfig(UseConfigurationDecl { availability, .. })
178 | UseStorage(UseStorageDecl { availability, .. })
179 | UseDictionary(UseDictionaryDecl { availability, .. }) => Some(*availability),
180
181 ExposeDirectory(decl) => Some(*decl.availability()),
182 ExposeProtocol(decl) => Some(*decl.availability()),
183 ExposeService(decl) => Some(*decl.availability()),
184 ExposeRunner(decl) => Some(*decl.availability()),
185 ExposeResolver(decl) => Some(*decl.availability()),
186 ExposeConfig(decl) => Some(*decl.availability()),
187 ExposeDictionary(decl) => Some(*decl.availability()),
188
189 OfferRunner(decl) => Some(*decl.availability()),
190 OfferResolver(decl) => Some(*decl.availability()),
191 OfferDirectory(decl) => Some(*decl.availability()),
192 OfferEventStream(decl) => Some(*decl.availability()),
193 OfferProtocol(decl) => Some(*decl.availability()),
194 OfferConfig(decl) => Some(*decl.availability()),
195 OfferStorage(decl) => Some(*decl.availability()),
196 OfferDictionary(decl) => Some(*decl.availability()),
197
198 OfferService(_) | Resolver(_) | StorageBackingDirectory(_) | UseRunner(_) => None,
199 }
200 }
201}
202
203impl std::fmt::Display for RouteRequest {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 match self {
206 Self::ExposeDirectory(e) => {
207 write!(f, "directory `{}`", e.target_name)
208 }
209 Self::ExposeProtocol(e) => {
210 write!(f, "protocol `{}`", e.target_name)
211 }
212 Self::ExposeService(e) => {
213 write!(f, "service {:?}", e)
214 }
215 Self::ExposeRunner(e) => {
216 write!(f, "runner `{}`", e.target_name)
217 }
218 Self::ExposeResolver(e) => {
219 write!(f, "resolver `{}`", e.target_name)
220 }
221 Self::ExposeConfig(e) => {
222 write!(f, "config `{}`", e.target_name)
223 }
224 Self::ExposeDictionary(e) => {
225 write!(f, "dictionary `{}`", e.target_name)
226 }
227 Self::Resolver(r) => {
228 write!(f, "resolver `{}`", r.resolver)
229 }
230 Self::UseDirectory(u) => {
231 write!(f, "directory `{}`", u.source_name)
232 }
233 Self::UseProtocol(u) => {
234 write!(f, "protocol `{}`", u.source_name)
235 }
236 Self::UseService(u) => {
237 write!(f, "service `{}`", u.source_name)
238 }
239 Self::UseStorage(u) => {
240 write!(f, "storage `{}`", u.source_name)
241 }
242 Self::UseEventStream(u) => {
243 write!(f, "event stream `{}`", u.source_name)
244 }
245 Self::UseRunner(u) => {
246 write!(f, "runner `{}`", u.source_name)
247 }
248 Self::UseConfig(u) => {
249 write!(f, "config `{}`", u.source_name)
250 }
251 Self::UseDictionary(u) => {
252 write!(f, "dictionary `{}`", u.source_name)
253 }
254 Self::StorageBackingDirectory(u) => {
255 write!(f, "storage backing directory `{}`", u.backing_dir)
256 }
257 Self::OfferDirectory(o) => {
258 write!(f, "directory `{}`", o.target_name)
259 }
260 Self::OfferProtocol(o) => {
261 write!(f, "protocol `{}`", o.target_name)
262 }
263 Self::OfferService(o) => {
264 write!(f, "service {:?}", o)
265 }
266 Self::OfferEventStream(o) => {
267 write!(f, "event stream `{}`", o.target_name)
268 }
269 Self::OfferStorage(o) => {
270 write!(f, "storage `{}`", o.target_name)
271 }
272 Self::OfferResolver(o) => {
273 write!(f, "resolver `{}`", o.target_name)
274 }
275 Self::OfferRunner(o) => {
276 write!(f, "runner `{}`", o.target_name)
277 }
278 Self::OfferConfig(o) => {
279 write!(f, "config `{}`", o.target_name)
280 }
281 Self::OfferDictionary(o) => {
282 write!(f, "dictionary `{}`", o.target_name)
283 }
284 }
285 }
286}
287
288#[derive(Debug)]
290pub struct RouteSource {
291 pub source: CapabilitySource,
292 pub relative_path: RelativePath,
293}
294
295impl RouteSource {
296 pub fn new(source: CapabilitySource) -> Self {
297 Self { source, relative_path: Default::default() }
298 }
299
300 pub fn new_with_relative_path(source: CapabilitySource, relative_path: RelativePath) -> Self {
301 Self { source, relative_path }
302 }
303}
304
305pub async fn route_capability<C>(
319 request: RouteRequest,
320 target: &Arc<C>,
321 mapper: &mut dyn DebugRouteMapper,
322) -> Result<RouteSource, RoutingError>
323where
324 C: ComponentInstanceInterface + 'static,
325{
326 match request {
327 RouteRequest::ExposeDirectory(expose_dir_decl) => {
329 route_capability_inner::<DirConnector, _>(
330 &target.component_sandbox().await?.component_output.capabilities(),
331 &expose_dir_decl.target_name,
332 directory_metadata(
333 expose_dir_decl.availability,
334 expose_dir_decl.rights.and_then(|v| Some(v.into())),
335 Some(expose_dir_decl.subdir.into()),
336 ),
337 target,
338 )
339 .await
340 }
341 RouteRequest::ExposeProtocol(expose_protocol_decl) => {
342 let sandbox = target.component_sandbox().await?;
343 let dictionary = match &expose_protocol_decl.target {
344 ExposeTarget::Parent => sandbox.component_output.capabilities(),
345 ExposeTarget::Framework => sandbox.component_output.framework(),
346 };
347 route_capability_inner::<Connector, _>(
348 &dictionary,
349 &expose_protocol_decl.target_name,
350 protocol_metadata(expose_protocol_decl.availability),
351 target,
352 )
353 .await
354 }
355 RouteRequest::ExposeService(expose_bundle) => {
356 let first_expose = expose_bundle.iter().next().expect("can't route empty bundle");
357 route_capability_inner::<DirConnector, _>(
358 &target.component_sandbox().await?.component_output.capabilities(),
359 first_expose.target_name(),
360 service_metadata(*first_expose.availability()),
361 target,
362 )
363 .await
364 }
365 RouteRequest::ExposeRunner(expose_runner_decl) => {
366 let sandbox = target.component_sandbox().await?;
367 let dictionary = match &expose_runner_decl.target {
368 ExposeTarget::Parent => sandbox.component_output.capabilities(),
369 ExposeTarget::Framework => sandbox.component_output.framework(),
370 };
371 route_capability_inner::<Connector, _>(
372 &dictionary,
373 &expose_runner_decl.target_name,
374 runner_metadata(Availability::Required),
375 target,
376 )
377 .await
378 }
379 RouteRequest::ExposeResolver(expose_resolver_decl) => {
380 let sandbox = target.component_sandbox().await?;
381 let dictionary = match &expose_resolver_decl.target {
382 ExposeTarget::Parent => sandbox.component_output.capabilities(),
383 ExposeTarget::Framework => sandbox.component_output.framework(),
384 };
385 route_capability_inner::<Connector, _>(
386 &dictionary,
387 &expose_resolver_decl.target_name,
388 resolver_metadata(Availability::Required),
389 target,
390 )
391 .await
392 }
393 RouteRequest::ExposeDictionary(expose_dictionary_decl) => {
394 let sandbox = target.component_sandbox().await?;
395 let dictionary = match &expose_dictionary_decl.target {
396 ExposeTarget::Parent => sandbox.component_output.capabilities(),
397 ExposeTarget::Framework => sandbox.component_output.framework(),
398 };
399 route_capability_inner::<Dict, _>(
400 &dictionary,
401 &expose_dictionary_decl.target_name,
402 dictionary_metadata(expose_dictionary_decl.availability),
403 target,
404 )
405 .await
406 }
407 RouteRequest::ExposeConfig(expose_config_decl) => {
408 let sandbox = target.component_sandbox().await?;
409 let dictionary = match &expose_config_decl.target {
410 ExposeTarget::Parent => sandbox.component_output.capabilities(),
411 ExposeTarget::Framework => sandbox.component_output.framework(),
412 };
413 let source = route_capability_inner::<Data, _>(
414 &dictionary,
415 &expose_config_decl.target_name,
416 config_metadata(expose_config_decl.availability),
417 target,
418 )
419 .await;
420 let source = match source {
423 Ok(s) => s,
424 Err(e) => {
425 if *expose_config_decl.availability() == Availability::Transitional
426 && e.as_zx_status() == zx::Status::NOT_FOUND
427 {
428 RouteSource::new(CapabilitySource::Void(VoidSource {
429 capability: InternalCapability::Config(expose_config_decl.source_name),
430 moniker: target.moniker().clone(),
431 }))
432 } else {
433 return Err(e);
434 }
435 }
436 };
437 Ok(source)
438 }
439
440 RouteRequest::Resolver(resolver_registration) => {
442 let component_sandbox = target.component_sandbox().await?;
443 let source_dictionary = match &resolver_registration.source {
444 RegistrationSource::Parent => component_sandbox.component_input.capabilities(),
445 RegistrationSource::Self_ => component_sandbox.program_output_dict.clone(),
446 RegistrationSource::Child(static_name) => {
447 let child_name = ChildName::parse(static_name).expect(
448 "invalid child name, this should be prevented by manifest validation",
449 );
450 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");
451 let child_sandbox = child_component.component_sandbox().await?;
452 child_sandbox.component_output.capabilities().clone()
453 }
454 };
455 route_capability_inner::<Connector, _>(
456 &source_dictionary,
457 &resolver_registration.resolver,
458 resolver_metadata(Availability::Required),
459 target,
460 )
461 .await
462 }
463 RouteRequest::StorageBackingDirectory(storage_decl) => {
465 let component_sandbox = target.component_sandbox().await?;
466 let registration = StorageDeclAsRegistration::from(storage_decl.clone());
467 let source_dictionary = match registration.source {
468 RegistrationSource::Parent => component_sandbox.component_input.capabilities(),
469 RegistrationSource::Self_ => component_sandbox.program_output_dict.clone(),
470 RegistrationSource::Child(static_name) => {
471 let child_name = ChildName::parse(static_name).expect(
472 "invalid child name, this should be prevented by manifest validation",
473 );
474 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");
475 let child_sandbox = child_component.component_sandbox().await?;
476 child_sandbox.component_output.capabilities().clone()
477 }
478 };
479 route_capability_inner::<DirConnector, _>(
480 &source_dictionary,
481 &storage_decl.backing_dir,
482 directory_metadata(Availability::Required, Some(RW_STAR_DIR.into()), None),
483 target,
484 )
485 .await
486 }
487
488 RouteRequest::UseDirectory(use_directory_decl) => {
490 let subdir = match use_directory_decl.source {
491 UseSource::Self_ => None,
492 _ => Some(SubDir::from(use_directory_decl.subdir)),
493 };
494 route_capability_inner::<DirConnector, _>(
495 &target.component_sandbox().await?.program_input.namespace(),
496 &use_directory_decl.target_path,
497 directory_metadata(
498 use_directory_decl.availability,
499 Some(use_directory_decl.rights.into()),
500 subdir,
501 ),
502 target,
503 )
504 .await
505 }
506 RouteRequest::UseEventStream(use_event_stream_decl) => {
507 route_event_stream(use_event_stream_decl, target, mapper).await
508 }
509 RouteRequest::UseProtocol(use_protocol_decl) => {
510 if let Some(target_path) = use_protocol_decl.target_path.as_ref() {
511 route_capability_inner::<Connector, _>(
512 &target.component_sandbox().await?.program_input.namespace(),
513 target_path,
514 protocol_metadata(use_protocol_decl.availability),
515 target,
516 )
517 .await
518 } else {
519 let numbered_handle = use_protocol_decl
520 .numbered_handle
521 .expect("validation guarantees numbered_handle is set");
522 let numbered_handle = Name::from(numbered_handle);
523 route_capability_inner::<Connector, _>(
524 &target.component_sandbox().await?.program_input.numbered_handles(),
525 &numbered_handle,
526 protocol_metadata(use_protocol_decl.availability),
527 target,
528 )
529 .await
530 }
531 }
532 RouteRequest::UseService(use_service_decl) => {
533 route_capability_inner::<DirConnector, _>(
534 &target.component_sandbox().await?.program_input.namespace(),
535 &use_service_decl.target_path,
536 service_metadata(use_service_decl.availability),
537 target,
538 )
539 .await
540 }
541 RouteRequest::UseStorage(use_storage_decl) => {
542 route_capability_inner::<DirConnector, _>(
543 &target.component_sandbox().await?.program_input.namespace(),
544 &use_storage_decl.target_path,
545 storage_metadata(use_storage_decl.availability),
546 target,
547 )
548 .await
549 }
550 RouteRequest::UseRunner(_use_runner_decl) => {
551 let router =
552 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");
553 perform_route::<Connector, _>(router, runner_metadata(Availability::Required), target)
554 .await
555 }
556 RouteRequest::UseConfig(use_config_decl) => {
557 let source = route_capability_inner::<Data, _>(
558 &target.component_sandbox().await?.program_input.config(),
559 &use_config_decl.target_name,
560 config_metadata(use_config_decl.availability),
561 target,
562 )
563 .await;
564 let source = match source {
567 Ok(s) => s,
568 Err(e) => {
569 if *use_config_decl.availability() == Availability::Transitional
570 && e.as_zx_status() == zx::Status::NOT_FOUND
571 {
572 RouteSource::new(CapabilitySource::Void(VoidSource {
573 capability: InternalCapability::Config(use_config_decl.source_name),
574 moniker: target.moniker().clone(),
575 }))
576 } else {
577 return Err(e);
578 }
579 }
580 };
581 Ok(source)
582 }
583 RouteRequest::UseDictionary(use_dictionary_decl) => {
584 route_capability_inner::<Dict, _>(
585 &target.component_sandbox().await?.program_input.namespace(),
586 &use_dictionary_decl.target_path,
587 dictionary_metadata(use_dictionary_decl.availability),
588 target,
589 )
590 .await
591 }
592
593 RouteRequest::OfferProtocol(offer_protocol_decl) => {
595 let target_dictionary =
596 get_dictionary_for_offer_target(target, &offer_protocol_decl).await?;
597 let metadata = protocol_metadata(offer_protocol_decl.availability);
598 metadata
599 .insert(
600 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
601 Capability::Data(Data::Uint64(1)),
602 )
603 .unwrap();
604 route_capability_inner::<Connector, _>(
605 &target_dictionary,
606 &offer_protocol_decl.target_name,
607 metadata,
608 target,
609 )
610 .await
611 }
612 RouteRequest::OfferDictionary(offer_dictionary_decl) => {
613 let target_dictionary =
614 get_dictionary_for_offer_target(target, &offer_dictionary_decl).await?;
615 let metadata = dictionary_metadata(offer_dictionary_decl.availability);
616 metadata
617 .insert(
618 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
619 Capability::Data(Data::Uint64(1)),
620 )
621 .unwrap();
622 route_capability_inner::<Dict, _>(
623 &target_dictionary,
624 &offer_dictionary_decl.target_name,
625 metadata,
626 target,
627 )
628 .await
629 }
630 RouteRequest::OfferDirectory(offer_directory_decl) => {
631 let target_dictionary =
632 get_dictionary_for_offer_target(target, &offer_directory_decl).await?;
633 let metadata = directory_metadata(
634 offer_directory_decl.availability,
635 offer_directory_decl.rights.and_then(|v| Some(v.into())),
636 Some(offer_directory_decl.subdir.into()),
637 );
638 metadata
639 .insert(
640 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
641 Capability::Data(Data::Uint64(1)),
642 )
643 .unwrap();
644 route_capability_inner::<DirConnector, _>(
645 &target_dictionary,
646 &offer_directory_decl.target_name,
647 metadata,
648 target,
649 )
650 .await
651 }
652 RouteRequest::OfferStorage(offer_storage_decl) => {
653 let target_dictionary =
654 get_dictionary_for_offer_target(target, &offer_storage_decl).await?;
655 let metadata = storage_metadata(offer_storage_decl.availability);
656 metadata
657 .insert(
658 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
659 Capability::Data(Data::Uint64(1)),
660 )
661 .unwrap();
662 route_capability_inner::<DirConnector, _>(
663 &target_dictionary,
664 &offer_storage_decl.target_name,
665 metadata,
666 target,
667 )
668 .await
669 }
670 RouteRequest::OfferService(offer_service_bundle) => {
671 let first_offer = offer_service_bundle.iter().next().expect("can't route empty bundle");
672 let target_dictionary = get_dictionary_for_offer_target(target, first_offer).await?;
673 let metadata = service_metadata(first_offer.availability);
674 metadata
675 .insert(
676 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
677 Capability::Data(Data::Uint64(1)),
678 )
679 .unwrap();
680 route_capability_inner::<DirConnector, _>(
681 &target_dictionary,
682 &first_offer.target_name,
683 metadata,
684 target,
685 )
686 .await
687 }
688 RouteRequest::OfferEventStream(offer_event_stream_decl) => {
689 route_event_stream_from_offer(offer_event_stream_decl, target, mapper).await
690 }
691 RouteRequest::OfferRunner(offer_runner_decl) => {
692 let target_dictionary =
693 get_dictionary_for_offer_target(target, &offer_runner_decl).await?;
694 let metadata = runner_metadata(Availability::Required);
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::<Connector, _>(
702 &target_dictionary,
703 &offer_runner_decl.target_name,
704 metadata,
705 target,
706 )
707 .await
708 }
709 RouteRequest::OfferResolver(offer_resolver_decl) => {
710 let target_dictionary =
711 get_dictionary_for_offer_target(target, &offer_resolver_decl).await?;
712 let metadata = resolver_metadata(Availability::Required);
713 metadata
714 .insert(
715 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
716 Capability::Data(Data::Uint64(1)),
717 )
718 .unwrap();
719 route_capability_inner::<Connector, _>(
720 &target_dictionary,
721 &offer_resolver_decl.target_name,
722 metadata,
723 target,
724 )
725 .await
726 }
727 RouteRequest::OfferConfig(offer) => {
728 let target_dictionary = get_dictionary_for_offer_target(target, &offer).await?;
729 let metadata = config_metadata(offer.availability);
730 metadata
731 .insert(
732 Name::new(crate::bedrock::with_policy_check::SKIP_POLICY_CHECKS).unwrap(),
733 Capability::Data(Data::Uint64(1)),
734 )
735 .unwrap();
736 route_capability_inner::<Data, _>(
737 &target_dictionary,
738 &offer.target_name,
739 metadata,
740 target,
741 )
742 .await
743 }
744 }
745}
746
747pub enum Never {}
748
749async fn route_capability_inner<T, C>(
750 dictionary: &Dict,
751 path: &impl IterablePath,
752 metadata: Dict,
753 target: &Arc<C>,
754) -> Result<RouteSource, RoutingError>
755where
756 C: ComponentInstanceInterface + 'static,
757 T: CapabilityBound + Debug,
758 Router<T>: TryFrom<Capability>,
759{
760 let router = dictionary.get_router_or_not_found(
761 path,
762 RoutingError::BedrockNotPresentInDictionary {
763 moniker: target.moniker().clone().into(),
764 name: path.iter_segments().join("/"),
765 },
766 );
767 perform_route::<T, C>(router, metadata, target).await
768}
769
770async fn perform_route<T, C>(
771 router: impl Routable<T>,
772 metadata: Dict,
773 target: &Arc<C>,
774) -> Result<RouteSource, RoutingError>
775where
776 C: ComponentInstanceInterface + 'static,
777 T: CapabilityBound + Debug,
778 Router<T>: TryFrom<Capability>,
779{
780 let request = Request { metadata };
781 let data = match router.route(Some(request), true, target.as_weak().into()).await? {
782 RouterResponse::<T>::Debug(d) => d,
783 d => panic!("Debug route did not return a debug response: {d:?}"),
784 };
785 Ok(RouteSource::new(data.try_into().unwrap()))
786}
787
788async fn get_dictionary_for_offer_target<C, O>(
789 target: &Arc<C>,
790 offer: &O,
791) -> Result<Dict, RoutingError>
792where
793 C: ComponentInstanceInterface + 'static,
794 O: OfferDeclCommon,
795{
796 match offer.target() {
797 OfferTarget::Child(child_ref) if child_ref.collection.is_none() => {
798 let child_input_name = Name::new(&child_ref.name)
800 .map_err(MonikerError::InvalidMonikerPart)
801 .expect("static child names must be short");
802 let target_sandbox = target.component_sandbox().await?;
803 let child_input = target_sandbox.child_inputs.get(&child_input_name).ok_or(
804 RoutingError::OfferFromChildInstanceNotFound {
805 child_moniker: child_ref.clone().into(),
806 moniker: target.moniker().clone(),
807 capability_id: offer.target_name().clone().to_string(),
808 },
809 )?;
810 Ok(child_input.capabilities())
811 }
812 OfferTarget::Child(child_ref) => {
813 let child = target
821 .lock_resolved_state()
822 .await?
823 .get_child(&ChildName::from(child_ref.clone()))
824 .ok_or(RoutingError::OfferFromChildInstanceNotFound {
825 child_moniker: child_ref.clone().into(),
826 moniker: target.moniker().clone(),
827 capability_id: offer.target_name().clone().to_string(),
828 })?;
829 Ok(child.component_sandbox().await?.component_input.capabilities())
830 }
831 OfferTarget::Collection(collection_name) => {
832 let target_sandbox = target.component_sandbox().await?;
835 let collection_input = target_sandbox.collection_inputs.get(collection_name).ok_or(
836 RoutingError::OfferFromCollectionNotFound {
837 collection: collection_name.to_string(),
838 moniker: target.moniker().clone(),
839 capability: offer.target_name().clone(),
840 },
841 )?;
842 Ok(collection_input.capabilities())
843 }
844 OfferTarget::Capability(dictionary_name) => {
845 let target_sandbox = target.component_sandbox().await?;
849 let capability =
850 target_sandbox.declared_dictionaries.get(dictionary_name).ok().flatten().ok_or(
851 RoutingError::BedrockNotPresentInDictionary {
852 name: dictionary_name.to_string(),
853 moniker: target.moniker().clone().into(),
854 },
855 )?;
856 match capability {
857 Capability::Dictionary(dictionary) => Ok(dictionary),
858 other_type => Err(RoutingError::BedrockWrongCapabilityType {
859 actual: other_type.debug_typename().to_string(),
860 expected: "Dictionary".to_string(),
861 moniker: target.moniker().clone().into(),
862 }),
863 }
864 }
865 }
866}
867
868async fn route_event_stream_from_offer<C>(
870 offer_decl: OfferEventStreamDecl,
871 target: &Arc<C>,
872 mapper: &mut dyn DebugRouteMapper,
873) -> Result<RouteSource, RoutingError>
874where
875 C: ComponentInstanceInterface + 'static,
876{
877 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
878
879 let mut availability_visitor = offer_decl.availability;
880 let source = legacy_router::route_from_offer(
881 RouteBundle::from_offer(offer_decl.into()),
882 target.clone(),
883 allowed_sources,
884 &mut availability_visitor,
885 mapper,
886 )
887 .await?;
888 Ok(RouteSource::new(source))
889}
890
891pub async fn route_event_stream<C>(
896 use_decl: UseEventStreamDecl,
897 target: &Arc<C>,
898 mapper: &mut dyn DebugRouteMapper,
899) -> Result<RouteSource, RoutingError>
900where
901 C: ComponentInstanceInterface + 'static,
902{
903 let allowed_sources = Sources::new(CapabilityTypeName::EventStream).builtin();
904 let mut availability_visitor = use_decl.availability;
905 let source = legacy_router::route_from_use(
906 use_decl.into(),
907 target.clone(),
908 allowed_sources,
909 &mut availability_visitor,
910 mapper,
911 )
912 .await?;
913 target.policy_checker().can_route_capability(&source, target.moniker())?;
914 Ok(RouteSource::new(source))
915}
916
917#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
920#[derive(Debug, Clone, PartialEq, Eq)]
921pub struct StorageDeclAsRegistration {
922 source: RegistrationSource,
923 name: Name,
924}
925
926impl From<StorageDecl> for StorageDeclAsRegistration {
927 fn from(decl: StorageDecl) -> Self {
928 Self {
929 name: decl.backing_dir,
930 source: match decl.source {
931 StorageDirectorySource::Parent => RegistrationSource::Parent,
932 StorageDirectorySource::Self_ => RegistrationSource::Self_,
933 StorageDirectorySource::Child(child) => RegistrationSource::Child(child),
934 },
935 }
936 }
937}
938
939impl SourceName for StorageDeclAsRegistration {
940 fn source_name(&self) -> &Name {
941 &self.name
942 }
943}
944
945impl RegistrationDeclCommon for StorageDeclAsRegistration {
946 const TYPE: &'static str = "storage";
947
948 fn source(&self) -> &RegistrationSource {
949 &self.source
950 }
951}
952
953#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
956#[derive(FromEnum, Debug, Clone, PartialEq, Eq)]
957pub enum RegistrationDecl {
958 Resolver(ResolverRegistration),
959 Runner(RunnerRegistration),
960 Debug(DebugProtocolRegistration),
961 Directory(StorageDeclAsRegistration),
962}
963
964impl From<&RegistrationDecl> for cm_rust::CapabilityTypeName {
965 fn from(registration: &RegistrationDecl) -> Self {
966 match registration {
967 RegistrationDecl::Directory(_) => Self::Directory,
968 RegistrationDecl::Resolver(_) => Self::Resolver,
969 RegistrationDecl::Runner(_) => Self::Runner,
970 RegistrationDecl::Debug(_) => Self::Protocol,
971 }
972 }
973}
974
975impl ErrorNotFoundFromParent for cm_rust::UseDecl {
978 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
979 RoutingError::UseFromParentNotFound { moniker, capability_id: capability_name.into() }
980 }
981}
982
983impl ErrorNotFoundFromParent for cm_rust::DebugProtocolRegistration {
984 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
985 RoutingError::EnvironmentFromParentNotFound {
986 moniker,
987 capability_name,
988 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
989 }
990 }
991}
992
993impl ErrorNotFoundInChild for cm_rust::DebugProtocolRegistration {
994 fn error_not_found_in_child(
995 moniker: Moniker,
996 child_moniker: ChildName,
997 capability_name: Name,
998 ) -> RoutingError {
999 RoutingError::EnvironmentFromChildExposeNotFound {
1000 moniker,
1001 child_moniker,
1002 capability_name,
1003 capability_type: cm_rust::CapabilityTypeName::Protocol.to_string(),
1004 }
1005 }
1006}
1007
1008impl ErrorNotFoundInChild for cm_rust::UseDecl {
1009 fn error_not_found_in_child(
1010 moniker: Moniker,
1011 child_moniker: ChildName,
1012 capability_name: Name,
1013 ) -> RoutingError {
1014 RoutingError::UseFromChildExposeNotFound {
1015 child_moniker,
1016 moniker,
1017 capability_id: capability_name.into(),
1018 }
1019 }
1020}
1021
1022impl ErrorNotFoundInChild for cm_rust::ExposeDecl {
1023 fn error_not_found_in_child(
1024 moniker: Moniker,
1025 child_moniker: ChildName,
1026 capability_name: Name,
1027 ) -> RoutingError {
1028 RoutingError::ExposeFromChildExposeNotFound {
1029 moniker,
1030 child_moniker,
1031 capability_id: capability_name.into(),
1032 }
1033 }
1034}
1035
1036impl ErrorNotFoundInChild for cm_rust::OfferDecl {
1037 fn error_not_found_in_child(
1038 moniker: Moniker,
1039 child_moniker: ChildName,
1040 capability_name: Name,
1041 ) -> RoutingError {
1042 RoutingError::OfferFromChildExposeNotFound {
1043 moniker,
1044 child_moniker,
1045 capability_id: capability_name.into(),
1046 }
1047 }
1048}
1049
1050impl ErrorNotFoundFromParent for cm_rust::OfferDecl {
1051 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1052 RoutingError::OfferFromParentNotFound { moniker, capability_id: capability_name.into() }
1053 }
1054}
1055
1056impl ErrorNotFoundInChild for StorageDeclAsRegistration {
1057 fn error_not_found_in_child(
1058 moniker: Moniker,
1059 child_moniker: ChildName,
1060 capability_name: Name,
1061 ) -> RoutingError {
1062 RoutingError::StorageFromChildExposeNotFound {
1063 moniker,
1064 child_moniker,
1065 capability_id: capability_name.into(),
1066 }
1067 }
1068}
1069
1070impl ErrorNotFoundFromParent for StorageDeclAsRegistration {
1071 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1072 RoutingError::StorageFromParentNotFound { moniker, capability_id: capability_name.into() }
1073 }
1074}
1075
1076impl ErrorNotFoundFromParent for RunnerRegistration {
1077 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1078 RoutingError::UseFromEnvironmentNotFound {
1079 moniker,
1080 capability_name,
1081 capability_type: "runner".to_string(),
1082 }
1083 }
1084}
1085
1086impl ErrorNotFoundInChild for RunnerRegistration {
1087 fn error_not_found_in_child(
1088 moniker: Moniker,
1089 child_moniker: ChildName,
1090 capability_name: Name,
1091 ) -> RoutingError {
1092 RoutingError::EnvironmentFromChildExposeNotFound {
1093 moniker,
1094 child_moniker,
1095 capability_name,
1096 capability_type: "runner".to_string(),
1097 }
1098 }
1099}
1100
1101impl ErrorNotFoundFromParent for ResolverRegistration {
1102 fn error_not_found_from_parent(moniker: Moniker, capability_name: Name) -> RoutingError {
1103 RoutingError::EnvironmentFromParentNotFound {
1104 moniker,
1105 capability_name,
1106 capability_type: "resolver".to_string(),
1107 }
1108 }
1109}
1110
1111impl ErrorNotFoundInChild for ResolverRegistration {
1112 fn error_not_found_in_child(
1113 moniker: Moniker,
1114 child_moniker: ChildName,
1115 capability_name: Name,
1116 ) -> RoutingError {
1117 RoutingError::EnvironmentFromChildExposeNotFound {
1118 moniker,
1119 child_moniker,
1120 capability_name,
1121 capability_type: "resolver".to_string(),
1122 }
1123 }
1124}