1use crate::policy::PolicyError;
6use crate::rights::Rights;
7use async_trait::async_trait;
8use clonable_error::ClonableError;
9use cm_rust::offer::OfferDeclCommon;
10use cm_rust::{CapabilityTypeName, ExposeDeclCommon, SourceName, UseDeclCommon};
11use cm_types::{Availability, Name};
12use fidl_fuchsia_component as fcomponent;
13use itertools::Itertools;
14use moniker::{ChildName, ExtendedMoniker, Moniker};
15use router_error::{Explain, RouterError};
16use std::sync::Arc;
17use thiserror::Error;
18use zx_status as zx;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
25#[derive(Debug, Error, Clone)]
26pub enum ComponentInstanceError {
27 #[error("could not find `{moniker}`")]
28 InstanceNotFound { moniker: Moniker },
29 #[error("component is not executable `{moniker}`")]
30 InstanceNotExecutable { moniker: Moniker },
31 #[error("component manager instance unavailable")]
32 ComponentManagerInstanceUnavailable {},
33 #[error("expected a component instance, but got component manager's instance")]
34 ComponentManagerInstanceUnexpected {},
35 #[error("malformed url `{url}` for `{moniker}`")]
36 MalformedUrl { url: String, moniker: Moniker },
37 #[error("url `{url}` for `{moniker}` does not resolve to an absolute url")]
38 NoAbsoluteUrl { url: String, moniker: Moniker },
39 #[cfg_attr(feature = "serde", serde(skip))]
42 #[error("failed to resolve `{moniker}`:\n\t{err}")]
43 ResolveFailed {
44 moniker: Moniker,
45 #[source]
46 err: ClonableError,
47 },
48 #[cfg_attr(feature = "serde", serde(skip))]
51 #[error("failed to start `{moniker}`:\n\t{err_msg}")]
52 StartFailed {
53 moniker: Moniker,
54 err_msg: String,
58 err_as_zx: zx::Status,
59 },
60 #[error("failed to create storage for `{moniker}`:\n\t{err_msg}")]
61 FailedToCreateStorage { moniker: Moniker, err_msg: String },
62}
63
64impl ComponentInstanceError {
65 pub fn as_zx_status(&self) -> zx::Status {
66 match self {
67 ComponentInstanceError::ResolveFailed { .. }
68 | ComponentInstanceError::InstanceNotFound { .. }
69 | ComponentInstanceError::ComponentManagerInstanceUnavailable {}
70 | ComponentInstanceError::InstanceNotExecutable { .. }
71 | ComponentInstanceError::NoAbsoluteUrl { .. }
72 | ComponentInstanceError::FailedToCreateStorage { .. } => zx::Status::NOT_FOUND,
73 ComponentInstanceError::StartFailed { err_as_zx, .. } => *err_as_zx,
74 ComponentInstanceError::MalformedUrl { .. }
75 | ComponentInstanceError::ComponentManagerInstanceUnexpected { .. } => {
76 zx::Status::INTERNAL
77 }
78 }
79 }
80
81 pub fn instance_not_found(moniker: Moniker) -> ComponentInstanceError {
82 ComponentInstanceError::InstanceNotFound { moniker }
83 }
84
85 pub fn cm_instance_unavailable() -> ComponentInstanceError {
86 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
87 }
88
89 pub fn resolve_failed(moniker: Moniker, err: impl Into<anyhow::Error>) -> Self {
90 Self::ResolveFailed { moniker, err: err.into().into() }
91 }
92}
93
94impl Explain for ComponentInstanceError {
95 fn as_zx_status(&self) -> zx::Status {
96 self.as_zx_status()
97 }
98}
99
100impl From<ComponentInstanceError> for ExtendedMoniker {
101 fn from(err: ComponentInstanceError) -> ExtendedMoniker {
102 match err {
103 ComponentInstanceError::InstanceNotFound { moniker }
104 | ComponentInstanceError::MalformedUrl { moniker, .. }
105 | ComponentInstanceError::NoAbsoluteUrl { moniker, .. }
106 | ComponentInstanceError::InstanceNotExecutable { moniker }
107 | ComponentInstanceError::ResolveFailed { moniker, .. }
108 | ComponentInstanceError::StartFailed { moniker, .. }
109 | ComponentInstanceError::FailedToCreateStorage { moniker, .. } => {
110 ExtendedMoniker::ComponentInstance(moniker)
111 }
112 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
113 | ComponentInstanceError::ComponentManagerInstanceUnexpected {} => {
114 ExtendedMoniker::ComponentManager
115 }
116 }
117 }
118}
119
120impl PartialEq for ComponentInstanceError {
123 fn eq(&self, other: &Self) -> bool {
124 match (self, other) {
125 (
126 Self::InstanceNotFound { moniker: self_moniker },
127 Self::InstanceNotFound { moniker: other_moniker },
128 ) => self_moniker.eq(other_moniker),
129 (
130 Self::ComponentManagerInstanceUnavailable {},
131 Self::ComponentManagerInstanceUnavailable {},
132 ) => true,
133 (Self::ResolveFailed { .. }, Self::ResolveFailed { .. }) => false,
134 _ => false,
135 }
136 }
137}
138
139#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
141#[derive(Debug, Error, Clone, PartialEq)]
142pub enum RoutingError {
143 #[error(
144 "backing directory `{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`"
145 )]
146 StorageFromChildExposeNotFound {
147 child_moniker: ChildName,
148 moniker: Moniker,
149 capability_id: String,
150 },
151
152 #[error(
153 "`{target_name:?}` tried to use a storage capability from `{source_moniker}` but it is \
154 not in the component id index. https://fuchsia.dev/go/components/instance-id"
155 )]
156 ComponentNotInIdIndex { source_moniker: Moniker, target_name: Option<ChildName> },
157
158 #[error("`{capability_id}` is not a built-in capability")]
159 UseFromComponentManagerNotFound { capability_id: String },
160
161 #[error("`{capability_id}` is not a built-in capability")]
162 RegisterFromComponentManagerNotFound { capability_id: String },
163
164 #[error("`{capability_id}` is not a built-in capability")]
165 OfferFromComponentManagerNotFound { capability_id: String },
166
167 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
168 UseFromParentNotFound { moniker: Moniker, capability_id: String },
169
170 #[error("`{capability_id}` was not declared as a capability by `{moniker}`")]
171 UseFromSelfNotFound { moniker: Moniker, capability_id: String },
172
173 #[error("`{moniker}` does not have child `#{child_moniker}`")]
174 UseFromChildInstanceNotFound {
175 child_moniker: ChildName,
176 moniker: Moniker,
177 capability_id: String,
178 },
179
180 #[error(
181 "{capability_type} `{capability_name}` was not registered in environment of `{moniker}`"
182 )]
183 UseFromEnvironmentNotFound { moniker: Moniker, capability_type: String, capability_name: Name },
184
185 #[error(
186 "`{moniker}` tried to use {capability_type} `{capability_name}` from the root environment"
187 )]
188 UseFromRootEnvironmentNotAllowed {
189 moniker: Moniker,
190 capability_type: String,
191 capability_name: Name,
192 },
193
194 #[error("{capability_type} `{capability_name}` was not offered to `{moniker}` by parent")]
195 EnvironmentFromParentNotFound {
196 moniker: Moniker,
197 capability_type: String,
198 capability_name: Name,
199 },
200
201 #[error("`{capability_name}` was not exposed to `{moniker}` from `#{child_moniker}`")]
202 EnvironmentFromChildExposeNotFound {
203 child_moniker: ChildName,
204 moniker: Moniker,
205 capability_type: String,
206 capability_name: Name,
207 },
208
209 #[error("`{moniker}` does not have child `#{child_moniker}`")]
210 EnvironmentFromChildInstanceNotFound {
211 child_moniker: ChildName,
212 moniker: Moniker,
213 capability_name: Name,
214 capability_type: String,
215 },
216
217 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
218 OfferFromParentNotFound { moniker: Moniker, capability_id: String },
219
220 #[error(
221 "cannot offer `{capability_id}` because was not declared as a capability by `{moniker}`"
222 )]
223 OfferFromSelfNotFound { moniker: Moniker, capability_id: String },
224
225 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
226 StorageFromParentNotFound { moniker: Moniker, capability_id: String },
227
228 #[error("`{moniker}` does not have child `#{child_moniker}`")]
229 OfferFromChildInstanceNotFound {
230 child_moniker: ChildName,
231 moniker: Moniker,
232 capability_id: String,
233 },
234
235 #[error("`{moniker}` does not have collection `#{collection}`")]
236 OfferFromCollectionNotFound { collection: String, moniker: Moniker, capability: Name },
237
238 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
239 OfferFromChildExposeNotFound {
240 child_moniker: ChildName,
241 moniker: Moniker,
242 capability_id: String,
243 },
244
245 #[error("`{capability_id}` is not a framework capability (at component `{moniker}`)")]
247 CapabilityFromFrameworkNotFound { moniker: Moniker, capability_id: String },
248
249 #[error(
250 "A capability was sourced to a base capability `{capability_id}` from `{moniker}`, but this is unsupported"
251 )]
252 CapabilityFromCapabilityNotFound { moniker: Moniker, capability_id: String },
253
254 #[error("`{capability_id}` is not a framework capability")]
256 CapabilityFromComponentManagerNotFound { capability_id: String },
257
258 #[error(
259 "unable to expose `{capability_id}` because it was not declared as a capability by `{moniker}`"
260 )]
261 ExposeFromSelfNotFound { moniker: Moniker, capability_id: String },
262
263 #[error("`{moniker}` does not have child `#{child_moniker}`")]
264 ExposeFromChildInstanceNotFound {
265 child_moniker: ChildName,
266 moniker: Moniker,
267 capability_id: String,
268 },
269
270 #[error("`{moniker}` does not have collection `#{collection}`")]
271 ExposeFromCollectionNotFound { collection: String, moniker: Moniker, capability: Name },
272
273 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
274 ExposeFromChildExposeNotFound {
275 child_moniker: ChildName,
276 moniker: Moniker,
277 capability_id: String,
278 },
279
280 #[error(
281 "`{moniker}` tried to expose `{capability_id}` from the framework, but no such framework capability was found"
282 )]
283 ExposeFromFrameworkNotFound { moniker: Moniker, capability_id: String },
284
285 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
286 UseFromChildExposeNotFound { child_moniker: ChildName, moniker: Moniker, capability_id: String },
287
288 #[error("`{capability_id}` was not exposed from `/`")]
289 UseFromRootExposeNotFound { capability_id: String },
290
291 #[error("routing a capability from an unsupported source type `{source_type}` at `{moniker}`")]
292 UnsupportedRouteSource { source_type: String, moniker: ExtendedMoniker },
293
294 #[error("routing a capability of an unsupported type `{type_name}` at `{moniker}`")]
295 UnsupportedCapabilityType { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
296
297 #[error(
298 "dictionaries are not yet supported for {cap_type} capabilities at component `{moniker}`"
299 )]
300 DictionariesNotSupported { moniker: Moniker, cap_type: CapabilityTypeName },
301
302 #[error("dynamic dictionaries are not allowed at component `{moniker}`")]
303 DynamicDictionariesNotAllowed { moniker: Moniker },
304
305 #[error("the capability does not support member access at `{moniker}`")]
306 BedrockMemberAccessUnsupported { moniker: ExtendedMoniker },
307
308 #[error("item `{name}` is not present in dictionary at component `{moniker}`")]
309 BedrockNotPresentInDictionary { name: String, moniker: ExtendedMoniker },
310
311 #[error(
312 "routed capability was the wrong type at component `{moniker}`. Was: {actual}, expected: {expected}"
313 )]
314 BedrockWrongCapabilityType { actual: String, expected: String, moniker: ExtendedMoniker },
315
316 #[error(
317 "expected type {type_name} for routed capability at component `{moniker}`, but type was missing"
318 )]
319 BedrockMissingCapabilityType { type_name: String, moniker: ExtendedMoniker },
320
321 #[error("there was an error remoting a capability at component `{moniker}`")]
322 BedrockRemoteCapability { moniker: Moniker },
323
324 #[error("source dictionary was not found in child's exposes at component `{moniker}`")]
325 BedrockSourceDictionaryExposeNotFound { moniker: Moniker },
326
327 #[error("Some capability in the routing chain could not be cloned at `{moniker}`.")]
328 BedrockNotCloneable { moniker: ExtendedMoniker },
329
330 #[error(
331 "a capability in a dictionary extended from a source dictionary collides with \
332 a capability in the source dictionary that has the same key at `{moniker}`"
333 )]
334 BedrockSourceDictionaryCollision { moniker: ExtendedMoniker },
335
336 #[error("failed to send message for capability `{capability_id}` from component `{moniker}`")]
337 BedrockFailedToSend { moniker: ExtendedMoniker, capability_id: String },
338
339 #[error(
340 "failed to route capability because the route source has been shutdown and possibly destroyed"
341 )]
342 RouteSourceShutdown { moniker: Moniker },
343
344 #[error(transparent)]
345 ComponentInstanceError(#[from] ComponentInstanceError),
346
347 #[error(transparent)]
348 EventsRoutingError(#[from] EventsRoutingError),
349
350 #[error(transparent)]
351 RightsRoutingError(#[from] RightsRoutingError),
352
353 #[error(transparent)]
354 AvailabilityRoutingError(#[from] AvailabilityRoutingError),
355
356 #[error(transparent)]
357 PolicyError(#[from] PolicyError),
358
359 #[error(
360 "source capability at component {moniker} is void. \
361 If the offer/expose declaration has `source_availability` set to `unknown`, \
362 the source component instance likely isn't defined in the component declaration"
363 )]
364 SourceCapabilityIsVoid { moniker: Moniker },
365
366 #[error(
367 "routes that do not set the `debug` flag are unsupported in the current configuration (at `{moniker}`)."
368 )]
369 NonDebugRoutesUnsupported { moniker: ExtendedMoniker },
370
371 #[error("debug routes are unsupported for external routers (at `{moniker}`).")]
372 DebugRoutesUnsupported { moniker: ExtendedMoniker },
373
374 #[error("{type_name} router unexpectedly returned debug info for target {moniker}")]
375 RouteUnexpectedDebug { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
376
377 #[error("{type_name} router unexpectedly returned unavailable for target {moniker}")]
378 RouteUnexpectedUnavailable { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
379
380 #[error("{name} at {moniker} is missing porcelain type metadata.")]
381 MissingPorcelainType { name: Name, moniker: Moniker },
382
383 #[error("path at `{moniker}` was too long for `{keyword}`: {path}")]
384 PathTooLong { moniker: ExtendedMoniker, path: String, keyword: String },
385
386 #[error(
387 "conflicting dictionary entries detected component `{moniker}`: {}",
388 conflicting_names.iter().map(|n| format!("{}", n)).join(", ")
389 )]
390 ConflictingDictionaryEntries { moniker: ExtendedMoniker, conflicting_names: Vec<Name> },
391
392 #[error("FIDL error encountered while talking to a router implemented by component {moniker}")]
393 RemoteFIDLError { moniker: Moniker },
394
395 #[error("error returned by a router implemented by component {moniker}")]
397 RemoteRouterError { moniker: Moniker, error_code: i32 },
398
399 #[error("unexpected error received")]
400 UnexpectedError,
401}
402
403impl Explain for RoutingError {
404 fn as_zx_status(&self) -> zx::Status {
406 match self {
407 RoutingError::UseFromRootEnvironmentNotAllowed { .. }
408 | RoutingError::DynamicDictionariesNotAllowed { .. } => zx::Status::ACCESS_DENIED,
409 RoutingError::StorageFromChildExposeNotFound { .. }
410 | RoutingError::ComponentNotInIdIndex { .. }
411 | RoutingError::UseFromComponentManagerNotFound { .. }
412 | RoutingError::RegisterFromComponentManagerNotFound { .. }
413 | RoutingError::OfferFromComponentManagerNotFound { .. }
414 | RoutingError::UseFromParentNotFound { .. }
415 | RoutingError::UseFromSelfNotFound { .. }
416 | RoutingError::UseFromChildInstanceNotFound { .. }
417 | RoutingError::UseFromEnvironmentNotFound { .. }
418 | RoutingError::EnvironmentFromParentNotFound { .. }
419 | RoutingError::EnvironmentFromChildExposeNotFound { .. }
420 | RoutingError::EnvironmentFromChildInstanceNotFound { .. }
421 | RoutingError::OfferFromParentNotFound { .. }
422 | RoutingError::OfferFromSelfNotFound { .. }
423 | RoutingError::StorageFromParentNotFound { .. }
424 | RoutingError::OfferFromChildInstanceNotFound { .. }
425 | RoutingError::OfferFromCollectionNotFound { .. }
426 | RoutingError::OfferFromChildExposeNotFound { .. }
427 | RoutingError::CapabilityFromFrameworkNotFound { .. }
428 | RoutingError::CapabilityFromCapabilityNotFound { .. }
429 | RoutingError::CapabilityFromComponentManagerNotFound { .. }
430 | RoutingError::ConflictingDictionaryEntries { .. }
431 | RoutingError::ExposeFromSelfNotFound { .. }
432 | RoutingError::ExposeFromChildInstanceNotFound { .. }
433 | RoutingError::ExposeFromCollectionNotFound { .. }
434 | RoutingError::ExposeFromChildExposeNotFound { .. }
435 | RoutingError::ExposeFromFrameworkNotFound { .. }
436 | RoutingError::UseFromChildExposeNotFound { .. }
437 | RoutingError::UseFromRootExposeNotFound { .. }
438 | RoutingError::UnsupportedRouteSource { .. }
439 | RoutingError::UnsupportedCapabilityType { .. }
440 | RoutingError::EventsRoutingError(_)
441 | RoutingError::BedrockNotPresentInDictionary { .. }
442 | RoutingError::BedrockSourceDictionaryExposeNotFound { .. }
443 | RoutingError::BedrockSourceDictionaryCollision { .. }
444 | RoutingError::BedrockFailedToSend { .. }
445 | RoutingError::RouteSourceShutdown { .. }
446 | RoutingError::BedrockMissingCapabilityType { .. }
447 | RoutingError::BedrockWrongCapabilityType { .. }
448 | RoutingError::BedrockRemoteCapability { .. }
449 | RoutingError::BedrockNotCloneable { .. }
450 | RoutingError::AvailabilityRoutingError(_)
451 | RoutingError::PathTooLong { .. } => zx::Status::NOT_FOUND,
452 RoutingError::BedrockMemberAccessUnsupported { .. }
453 | RoutingError::NonDebugRoutesUnsupported { .. }
454 | RoutingError::DebugRoutesUnsupported { .. }
455 | RoutingError::DictionariesNotSupported { .. } => zx::Status::NOT_SUPPORTED,
456 RoutingError::ComponentInstanceError(err) => err.as_zx_status(),
457 RoutingError::RightsRoutingError(err) => err.as_zx_status(),
458 RoutingError::PolicyError(err) => err.as_zx_status(),
459 RoutingError::SourceCapabilityIsVoid { .. } => zx::Status::NOT_FOUND,
460 RoutingError::RouteUnexpectedDebug { .. }
461 | RoutingError::RouteUnexpectedUnavailable { .. }
462 | RoutingError::MissingPorcelainType { .. }
463 | RoutingError::UnexpectedError => zx::Status::INTERNAL,
464 RoutingError::RemoteFIDLError { .. } => zx::Status::PEER_CLOSED,
465 RoutingError::RemoteRouterError { error_code, .. } => zx::Status::from_raw(*error_code),
466 }
467 }
468}
469
470impl From<RoutingError> for ExtendedMoniker {
471 fn from(err: RoutingError) -> ExtendedMoniker {
472 match err {
473 RoutingError::BedrockRemoteCapability { moniker, .. }
474 | RoutingError::BedrockSourceDictionaryExposeNotFound { moniker, .. }
475 | RoutingError::CapabilityFromCapabilityNotFound { moniker, .. }
476 | RoutingError::CapabilityFromFrameworkNotFound { moniker, .. }
477 | RoutingError::ComponentNotInIdIndex { source_moniker: moniker, .. }
478 | RoutingError::DictionariesNotSupported { moniker, .. }
479 | RoutingError::EnvironmentFromChildExposeNotFound { moniker, .. }
480 | RoutingError::EnvironmentFromChildInstanceNotFound { moniker, .. }
481 | RoutingError::EnvironmentFromParentNotFound { moniker, .. }
482 | RoutingError::ExposeFromChildExposeNotFound { moniker, .. }
483 | RoutingError::ExposeFromChildInstanceNotFound { moniker, .. }
484 | RoutingError::ExposeFromCollectionNotFound { moniker, .. }
485 | RoutingError::ExposeFromFrameworkNotFound { moniker, .. }
486 | RoutingError::ExposeFromSelfNotFound { moniker, .. }
487 | RoutingError::OfferFromChildExposeNotFound { moniker, .. }
488 | RoutingError::OfferFromChildInstanceNotFound { moniker, .. }
489 | RoutingError::OfferFromCollectionNotFound { moniker, .. }
490 | RoutingError::OfferFromParentNotFound { moniker, .. }
491 | RoutingError::OfferFromSelfNotFound { moniker, .. }
492 | RoutingError::SourceCapabilityIsVoid { moniker, .. }
493 | RoutingError::StorageFromChildExposeNotFound { moniker, .. }
494 | RoutingError::StorageFromParentNotFound { moniker, .. }
495 | RoutingError::UseFromChildExposeNotFound { moniker, .. }
496 | RoutingError::UseFromChildInstanceNotFound { moniker, .. }
497 | RoutingError::UseFromEnvironmentNotFound { moniker, .. }
498 | RoutingError::UseFromParentNotFound { moniker, .. }
499 | RoutingError::UseFromRootEnvironmentNotAllowed { moniker, .. }
500 | RoutingError::DynamicDictionariesNotAllowed { moniker, .. }
501 | RoutingError::RouteSourceShutdown { moniker }
502 | RoutingError::UseFromSelfNotFound { moniker, .. }
503 | RoutingError::MissingPorcelainType { moniker, .. }
504 | RoutingError::RemoteFIDLError { moniker }
505 | RoutingError::RemoteRouterError { moniker, .. } => moniker.into(),
506 RoutingError::PathTooLong { moniker, .. } => moniker,
507
508 RoutingError::BedrockMemberAccessUnsupported { moniker }
509 | RoutingError::BedrockNotPresentInDictionary { moniker, .. }
510 | RoutingError::BedrockNotCloneable { moniker }
511 | RoutingError::BedrockSourceDictionaryCollision { moniker }
512 | RoutingError::BedrockFailedToSend { moniker, .. }
513 | RoutingError::BedrockMissingCapabilityType { moniker, .. }
514 | RoutingError::BedrockWrongCapabilityType { moniker, .. }
515 | RoutingError::ConflictingDictionaryEntries { moniker, .. }
516 | RoutingError::NonDebugRoutesUnsupported { moniker }
517 | RoutingError::DebugRoutesUnsupported { moniker }
518 | RoutingError::RouteUnexpectedDebug { moniker, .. }
519 | RoutingError::RouteUnexpectedUnavailable { moniker, .. }
520 | RoutingError::UnsupportedCapabilityType { moniker, .. }
521 | RoutingError::UnsupportedRouteSource { moniker, .. } => moniker,
522 RoutingError::AvailabilityRoutingError(err) => err.into(),
523 RoutingError::ComponentInstanceError(err) => err.into(),
524 RoutingError::EventsRoutingError(err) => err.into(),
525 RoutingError::PolicyError(err) => err.into(),
526 RoutingError::RightsRoutingError(err) => err.into(),
527
528 RoutingError::CapabilityFromComponentManagerNotFound { .. }
529 | RoutingError::OfferFromComponentManagerNotFound { .. }
530 | RoutingError::RegisterFromComponentManagerNotFound { .. }
531 | RoutingError::UseFromComponentManagerNotFound { .. }
532 | RoutingError::UseFromRootExposeNotFound { .. }
533 | RoutingError::UnexpectedError => ExtendedMoniker::ComponentManager,
534 }
535 }
536}
537
538impl From<RoutingError> for RouterError {
539 fn from(value: RoutingError) -> Self {
540 Self::NotFound(Arc::new(value))
541 }
542}
543
544impl TryFrom<RouterError> for RoutingError {
545 type Error = RouterError;
546
547 fn try_from(value: RouterError) -> Result<Self, Self::Error> {
548 match value {
549 RouterError::NotFound(arc_dyn_explain) => {
550 match arc_dyn_explain.as_any().downcast_ref::<Self>() {
551 Some(routing_error) => Ok(routing_error.clone()),
552 None => Err(RouterError::NotFound(arc_dyn_explain)),
553 }
554 }
555 err => Err(err),
556 }
557 }
558}
559
560impl RoutingError {
561 pub fn as_fidl_error(&self) -> fcomponent::Error {
563 fcomponent::Error::ResourceUnavailable
564 }
565
566 pub fn storage_from_child_expose_not_found(
567 child_moniker: &ChildName,
568 moniker: &Moniker,
569 capability_id: impl Into<String>,
570 ) -> Self {
571 Self::StorageFromChildExposeNotFound {
572 child_moniker: child_moniker.clone(),
573 moniker: moniker.clone(),
574 capability_id: capability_id.into(),
575 }
576 }
577
578 pub fn use_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
579 Self::UseFromComponentManagerNotFound { capability_id: capability_id.into() }
580 }
581
582 pub fn register_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
583 Self::RegisterFromComponentManagerNotFound { capability_id: capability_id.into() }
584 }
585
586 pub fn offer_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
587 Self::OfferFromComponentManagerNotFound { capability_id: capability_id.into() }
588 }
589
590 pub fn use_from_parent_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
591 Self::UseFromParentNotFound {
592 moniker: moniker.clone(),
593 capability_id: capability_id.into(),
594 }
595 }
596
597 pub fn use_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
598 Self::UseFromSelfNotFound { moniker: moniker.clone(), capability_id: capability_id.into() }
599 }
600
601 pub fn use_from_child_instance_not_found(
602 child_moniker: &ChildName,
603 moniker: &Moniker,
604 capability_id: impl Into<String>,
605 ) -> Self {
606 Self::UseFromChildInstanceNotFound {
607 child_moniker: child_moniker.clone(),
608 moniker: moniker.clone(),
609 capability_id: capability_id.into(),
610 }
611 }
612
613 pub fn use_from_environment_not_found(
614 moniker: &Moniker,
615 capability_type: impl Into<String>,
616 capability_name: &Name,
617 ) -> Self {
618 Self::UseFromEnvironmentNotFound {
619 moniker: moniker.clone(),
620 capability_type: capability_type.into(),
621 capability_name: capability_name.clone(),
622 }
623 }
624
625 pub fn offer_from_parent_not_found(
626 moniker: &Moniker,
627 capability_id: impl Into<String>,
628 ) -> Self {
629 Self::OfferFromParentNotFound {
630 moniker: moniker.clone(),
631 capability_id: capability_id.into(),
632 }
633 }
634
635 pub fn offer_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
636 Self::OfferFromSelfNotFound {
637 moniker: moniker.clone(),
638 capability_id: capability_id.into(),
639 }
640 }
641
642 pub fn storage_from_parent_not_found(
643 moniker: &Moniker,
644 capability_id: impl Into<String>,
645 ) -> Self {
646 Self::StorageFromParentNotFound {
647 moniker: moniker.clone(),
648 capability_id: capability_id.into(),
649 }
650 }
651
652 pub fn offer_from_child_instance_not_found(
653 child_moniker: &ChildName,
654 moniker: &Moniker,
655 capability_id: impl Into<String>,
656 ) -> Self {
657 Self::OfferFromChildInstanceNotFound {
658 child_moniker: child_moniker.clone(),
659 moniker: moniker.clone(),
660 capability_id: capability_id.into(),
661 }
662 }
663
664 pub fn offer_from_child_expose_not_found(
665 child_moniker: &ChildName,
666 moniker: &Moniker,
667 capability_id: impl Into<String>,
668 ) -> Self {
669 Self::OfferFromChildExposeNotFound {
670 child_moniker: child_moniker.clone(),
671 moniker: moniker.clone(),
672 capability_id: capability_id.into(),
673 }
674 }
675
676 pub fn use_from_child_expose_not_found(
677 child_moniker: &ChildName,
678 moniker: &Moniker,
679 capability_id: impl Into<String>,
680 ) -> Self {
681 Self::UseFromChildExposeNotFound {
682 child_moniker: child_moniker.clone(),
683 moniker: moniker.clone(),
684 capability_id: capability_id.into(),
685 }
686 }
687
688 pub fn expose_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
689 Self::ExposeFromSelfNotFound {
690 moniker: moniker.clone(),
691 capability_id: capability_id.into(),
692 }
693 }
694
695 pub fn expose_from_child_instance_not_found(
696 child_moniker: &ChildName,
697 moniker: &Moniker,
698 capability_id: impl Into<String>,
699 ) -> Self {
700 Self::ExposeFromChildInstanceNotFound {
701 child_moniker: child_moniker.clone(),
702 moniker: moniker.clone(),
703 capability_id: capability_id.into(),
704 }
705 }
706
707 pub fn expose_from_child_expose_not_found(
708 child_moniker: &ChildName,
709 moniker: &Moniker,
710 capability_id: impl Into<String>,
711 ) -> Self {
712 Self::ExposeFromChildExposeNotFound {
713 child_moniker: child_moniker.clone(),
714 moniker: moniker.clone(),
715 capability_id: capability_id.into(),
716 }
717 }
718
719 pub fn capability_from_framework_not_found(
720 moniker: &Moniker,
721 capability_id: impl Into<String>,
722 ) -> Self {
723 Self::CapabilityFromFrameworkNotFound {
724 moniker: moniker.clone(),
725 capability_id: capability_id.into(),
726 }
727 }
728
729 pub fn capability_from_capability_not_found(
730 moniker: &Moniker,
731 capability_id: impl Into<String>,
732 ) -> Self {
733 Self::CapabilityFromCapabilityNotFound {
734 moniker: moniker.clone(),
735 capability_id: capability_id.into(),
736 }
737 }
738
739 pub fn capability_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
740 Self::CapabilityFromComponentManagerNotFound { capability_id: capability_id.into() }
741 }
742
743 pub fn expose_from_framework_not_found(
744 moniker: &Moniker,
745 capability_id: impl Into<String>,
746 ) -> Self {
747 Self::ExposeFromFrameworkNotFound {
748 moniker: moniker.clone(),
749 capability_id: capability_id.into(),
750 }
751 }
752
753 pub fn unsupported_route_source(
754 moniker: impl Into<ExtendedMoniker>,
755 source: impl Into<String>,
756 ) -> Self {
757 Self::UnsupportedRouteSource { source_type: source.into(), moniker: moniker.into() }
758 }
759
760 pub fn unsupported_capability_type(
761 moniker: impl Into<ExtendedMoniker>,
762 type_name: impl Into<CapabilityTypeName>,
763 ) -> Self {
764 Self::UnsupportedCapabilityType { type_name: type_name.into(), moniker: moniker.into() }
765 }
766}
767
768#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
770#[derive(Error, Debug, Clone, PartialEq)]
771pub enum EventsRoutingError {
772 #[error("filter is not a subset at `{moniker}`")]
773 InvalidFilter { moniker: ExtendedMoniker },
774
775 #[error("event routes must end at source with a filter declaration at `{moniker}`")]
776 MissingFilter { moniker: ExtendedMoniker },
777}
778
779impl From<EventsRoutingError> for ExtendedMoniker {
780 fn from(err: EventsRoutingError) -> ExtendedMoniker {
781 match err {
782 EventsRoutingError::InvalidFilter { moniker }
783 | EventsRoutingError::MissingFilter { moniker } => moniker,
784 }
785 }
786}
787
788#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
789#[derive(Debug, Error, Clone, PartialEq)]
790pub enum RightsRoutingError {
791 #[error(
792 "requested rights ({requested}) greater than provided rights ({provided}) at \"{moniker}\""
793 )]
794 Invalid { moniker: ExtendedMoniker, requested: Rights, provided: Rights },
795
796 #[error(
797 "directory routes must end at source with a rights declaration, it's missing at \"{moniker}\""
798 )]
799 MissingRightsSource { moniker: ExtendedMoniker },
800}
801
802impl RightsRoutingError {
803 pub fn as_zx_status(&self) -> zx::Status {
805 match self {
806 RightsRoutingError::Invalid { .. } => zx::Status::ACCESS_DENIED,
807 RightsRoutingError::MissingRightsSource { .. } => zx::Status::NOT_FOUND,
808 }
809 }
810}
811
812impl From<RightsRoutingError> for ExtendedMoniker {
813 fn from(err: RightsRoutingError) -> ExtendedMoniker {
814 match err {
815 RightsRoutingError::Invalid { moniker, .. }
816 | RightsRoutingError::MissingRightsSource { moniker } => moniker,
817 }
818 }
819}
820
821#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
822#[derive(Debug, Error, Clone, PartialEq)]
823pub enum AvailabilityRoutingError {
824 #[error(
825 "availability requested by the target has stronger guarantees than what \
826 is being provided at the source at `{moniker}`"
827 )]
828 TargetHasStrongerAvailability { moniker: ExtendedMoniker },
829
830 #[error("offer uses void source, but target requires the capability at `{moniker}`")]
831 OfferFromVoidToRequiredTarget { moniker: ExtendedMoniker },
832
833 #[error("expose uses void source, but target requires the capability at `{moniker}`")]
834 ExposeFromVoidToRequiredTarget { moniker: ExtendedMoniker },
835}
836
837impl From<availability::TargetHasStrongerAvailability> for AvailabilityRoutingError {
838 fn from(value: availability::TargetHasStrongerAvailability) -> Self {
839 let availability::TargetHasStrongerAvailability { moniker } = value;
840 AvailabilityRoutingError::TargetHasStrongerAvailability { moniker }
841 }
842}
843
844impl From<AvailabilityRoutingError> for ExtendedMoniker {
845 fn from(err: AvailabilityRoutingError) -> ExtendedMoniker {
846 match err {
847 AvailabilityRoutingError::ExposeFromVoidToRequiredTarget { moniker }
848 | AvailabilityRoutingError::OfferFromVoidToRequiredTarget { moniker }
849 | AvailabilityRoutingError::TargetHasStrongerAvailability { moniker } => moniker,
850 }
851 }
852}
853
854#[async_trait]
857pub trait ErrorReporter: Clone + Send + Sync + 'static {
858 async fn report(
859 &self,
860 request: &RouteRequestErrorInfo,
861 err: &RouterError,
862 route_target: sandbox::WeakInstanceToken,
863 );
864}
865
866pub struct RouteRequestErrorInfo {
868 capability_type: cm_rust::CapabilityTypeName,
869 name: cm_types::Name,
870 availability: cm_rust::Availability,
871}
872
873impl RouteRequestErrorInfo {
874 pub fn availability(&self) -> cm_rust::Availability {
875 self.availability
876 }
877
878 pub fn for_builtin(capability_type: CapabilityTypeName, name: &Name) -> Self {
879 Self { capability_type, name: name.clone(), availability: Availability::Required }
880 }
881}
882
883impl From<&cm_rust::UseDecl> for RouteRequestErrorInfo {
884 fn from(value: &cm_rust::UseDecl) -> Self {
885 RouteRequestErrorInfo {
886 capability_type: value.into(),
887 name: value.source_name().clone(),
888 availability: value.availability().clone(),
889 }
890 }
891}
892
893impl From<&cm_rust::UseConfigurationDecl> for RouteRequestErrorInfo {
894 fn from(value: &cm_rust::UseConfigurationDecl) -> Self {
895 RouteRequestErrorInfo {
896 capability_type: CapabilityTypeName::Config,
897 name: value.source_name().clone(),
898 availability: value.availability().clone(),
899 }
900 }
901}
902
903impl From<&cm_rust::UseEventStreamDecl> for RouteRequestErrorInfo {
904 fn from(value: &cm_rust::UseEventStreamDecl) -> Self {
905 RouteRequestErrorInfo {
906 capability_type: CapabilityTypeName::EventStream,
907 name: value.source_name.clone(),
908 availability: value.availability,
909 }
910 }
911}
912
913impl From<&cm_rust::ExposeDecl> for RouteRequestErrorInfo {
914 fn from(value: &cm_rust::ExposeDecl) -> Self {
915 RouteRequestErrorInfo {
916 capability_type: value.into(),
917 name: value.target_name().clone(),
918 availability: value.availability().clone(),
919 }
920 }
921}
922
923impl From<&cm_rust::offer::OfferDecl> for RouteRequestErrorInfo {
924 fn from(value: &cm_rust::offer::OfferDecl) -> Self {
925 RouteRequestErrorInfo {
926 capability_type: value.into(),
927 name: value.target_name().clone(),
928 availability: value.availability().clone(),
929 }
930 }
931}
932
933impl From<&cm_rust::ResolverRegistration> for RouteRequestErrorInfo {
934 fn from(value: &cm_rust::ResolverRegistration) -> Self {
935 RouteRequestErrorInfo {
936 capability_type: CapabilityTypeName::Resolver,
937 name: value.source_name().clone(),
938 availability: Availability::Required,
939 }
940 }
941}
942
943impl From<&cm_rust::RunnerRegistration> for RouteRequestErrorInfo {
944 fn from(value: &cm_rust::RunnerRegistration) -> Self {
945 RouteRequestErrorInfo {
946 capability_type: CapabilityTypeName::Runner,
947 name: value.source_name().clone(),
948 availability: Availability::Required,
949 }
950 }
951}
952
953impl From<&cm_rust::DebugRegistration> for RouteRequestErrorInfo {
954 fn from(value: &cm_rust::DebugRegistration) -> Self {
955 RouteRequestErrorInfo {
956 capability_type: CapabilityTypeName::Protocol,
957 name: value.source_name().clone(),
958 availability: Availability::Required,
959 }
960 }
961}
962
963impl From<&cm_rust::CapabilityDecl> for RouteRequestErrorInfo {
964 fn from(value: &cm_rust::CapabilityDecl) -> Self {
965 RouteRequestErrorInfo {
966 capability_type: value.into(),
967 name: value.name().clone(),
968 availability: Availability::Required,
969 }
970 }
971}
972
973impl std::fmt::Display for RouteRequestErrorInfo {
974 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
975 write!(f, "{} `{}`", self.capability_type, self.name)
976 }
977}