mesh_node/
resource.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Mesh resource definitions.
5//!
6//! Resources are things that can be sent across a mesh node boundary that
7//! cannot be serialized to a protobuf field type. This includes mesh ports,
8//! Unix file descriptors, and Windows file handles and sockets.
9
10use crate::local_node::Port;
11use thiserror::Error;
12
13#[derive(Debug)]
14pub enum OsResource {
15    #[cfg(unix)]
16    Fd(std::os::unix::io::OwnedFd),
17    #[cfg(windows)]
18    Handle(std::os::windows::io::OwnedHandle),
19    #[cfg(windows)]
20    Socket(std::os::windows::io::OwnedSocket),
21}
22
23/// A resource that can be sent via a port.
24#[derive(Debug)]
25pub enum Resource {
26    /// Another port.
27    Port(Port),
28    /// An OS resource (file descriptor, Windows handle, or socket).
29    Os(OsResource),
30}
31
32impl From<Port> for Resource {
33    fn from(port: Port) -> Self {
34        Self::Port(port)
35    }
36}
37
38#[derive(Debug, Error)]
39pub enum ResourceError {
40    #[error("wrong resource type")]
41    BadResourceType,
42    #[cfg(windows)]
43    #[error("failed to convert handle to socket")]
44    HandleToSocket(#[source] std::io::Error),
45}
46
47impl TryFrom<Resource> for Port {
48    type Error = ResourceError;
49
50    fn try_from(value: Resource) -> Result<Self, ResourceError> {
51        match value {
52            Resource::Port(port) => Ok(port),
53            _ => Err(ResourceError::BadResourceType),
54        }
55    }
56}
57
58#[cfg(unix)]
59impl From<std::os::unix::io::OwnedFd> for Resource {
60    fn from(fd: std::os::unix::io::OwnedFd) -> Self {
61        Self::Os(OsResource::Fd(fd))
62    }
63}
64
65#[cfg(unix)]
66impl TryFrom<Resource> for std::os::unix::io::OwnedFd {
67    type Error = ResourceError;
68
69    fn try_from(value: Resource) -> Result<Self, ResourceError> {
70        match value {
71            Resource::Os(OsResource::Fd(fd)) => Ok(fd),
72            _ => Err(ResourceError::BadResourceType),
73        }
74    }
75}
76
77#[cfg(windows)]
78impl From<std::os::windows::io::OwnedHandle> for Resource {
79    fn from(port: std::os::windows::io::OwnedHandle) -> Self {
80        Self::Os(OsResource::Handle(port))
81    }
82}
83
84#[cfg(windows)]
85impl TryFrom<Resource> for std::os::windows::io::OwnedHandle {
86    type Error = ResourceError;
87
88    fn try_from(value: Resource) -> Result<Self, ResourceError> {
89        match value {
90            Resource::Os(OsResource::Handle(handle)) => Ok(handle),
91            _ => Err(ResourceError::BadResourceType),
92        }
93    }
94}
95
96#[cfg(windows)]
97impl From<std::os::windows::io::OwnedSocket> for Resource {
98    fn from(port: std::os::windows::io::OwnedSocket) -> Self {
99        Self::Os(OsResource::Socket(port))
100    }
101}
102
103#[cfg(windows)]
104impl TryFrom<Resource> for std::os::windows::io::OwnedSocket {
105    type Error = ResourceError;
106
107    fn try_from(value: Resource) -> Result<Self, ResourceError> {
108        match value {
109            Resource::Os(OsResource::Socket(socket)) => Ok(socket),
110            Resource::Os(OsResource::Handle(handle)) => {
111                pal::windows::OwnedSocketExt::from_handle(handle)
112                    .map_err(ResourceError::HandleToSocket)
113            }
114            _ => Err(ResourceError::BadResourceType),
115        }
116    }
117}
118
119pub type SerializedMessage = mesh_protobuf::SerializedMessage<Resource>;