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