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