aranya_daemon_api/
service.rs1#![allow(clippy::disallowed_macros)] use core::{fmt, hash::Hash, net::SocketAddr, time::Duration};
4
5use aranya_base58::ToBase58;
6use aranya_crypto::{
7 afc::{BidiChannelId, UniChannelId},
8 custom_id,
9 default::DefaultCipherSuite,
10 Id,
11};
12use aranya_fast_channels::{Label, NodeId};
13use aranya_util::Addr;
14use serde::{Deserialize, Serialize};
15use tracing::error;
16
17pub type CS = DefaultCipherSuite;
19
20#[derive(Serialize, Deserialize, Debug)]
23pub struct Error(String);
24
25impl From<anyhow::Error> for Error {
26 fn from(err: anyhow::Error) -> Self {
27 error!(?err);
28 Self(format!("{err:?}"))
29 }
30}
31
32impl From<aranya_crypto::id::IdError> for Error {
33 fn from(err: aranya_crypto::id::IdError) -> Self {
34 error!(%err);
35 Self(err.to_string())
36 }
37}
38
39impl fmt::Display for Error {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 self.0.fmt(f)
42 }
43}
44
45impl core::error::Error for Error {}
46
47pub type Result<T, E = Error> = core::result::Result<T, E>;
48
49custom_id! {
50 pub struct DeviceId;
52}
53
54custom_id! {
55 pub struct TeamId;
57}
58
59#[derive(Clone, Debug, Serialize, Deserialize)]
61pub struct KeyBundle {
62 pub identity: Vec<u8>,
63 pub signing: Vec<u8>,
64 pub encoding: Vec<u8>,
65}
66
67#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
69pub enum Role {
70 Owner,
71 Admin,
72 Operator,
73 Member,
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize, Eq, Ord, PartialEq, PartialOrd)]
78pub struct NetIdentifier(pub String);
79
80impl AsRef<str> for NetIdentifier {
81 fn as_ref(&self) -> &str {
82 &self.0
83 }
84}
85
86impl fmt::Display for NetIdentifier {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 self.0.fmt(f)
89 }
90}
91
92#[repr(transparent)]
97#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
98pub struct AfcId([u8; 16]);
99
100impl fmt::Display for AfcId {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "{}", self.0.to_base58())
103 }
104}
105
106fn truncate<const BIG: usize, const SMALL: usize>(arr: &[u8; BIG]) -> &[u8; SMALL] {
107 const { assert!(BIG >= SMALL) };
108 arr[..SMALL].try_into().expect("array must fit")
109}
110
111impl From<BidiChannelId> for AfcId {
113 fn from(value: BidiChannelId) -> Self {
114 Self(*truncate(value.as_array()))
115 }
116}
117
118impl From<UniChannelId> for AfcId {
120 fn from(value: UniChannelId) -> Self {
121 Self(*truncate(value.as_array()))
122 }
123}
124
125impl From<Id> for AfcId {
127 fn from(value: Id) -> Self {
128 Self(*truncate(value.as_array()))
129 }
130}
131
132pub type AfcCtrl = Vec<Box<[u8]>>;
134
135#[tarpc::service]
136pub trait DaemonApi {
137 async fn aranya_local_addr() -> Result<SocketAddr>;
139
140 async fn get_key_bundle() -> Result<KeyBundle>;
142
143 async fn get_device_id() -> Result<DeviceId>;
145
146 async fn add_sync_peer(addr: Addr, team: TeamId, interval: Duration) -> Result<()>;
148
149 async fn remove_sync_peer(addr: Addr, team: TeamId) -> Result<()>;
151
152 async fn add_team(team: TeamId) -> Result<()>;
154
155 async fn remove_team(team: TeamId) -> Result<()>;
157
158 async fn create_team() -> Result<TeamId>;
160 async fn close_team(team: TeamId) -> Result<()>;
162
163 async fn add_device_to_team(team: TeamId, keys: KeyBundle) -> Result<()>;
165 async fn remove_device_from_team(team: TeamId, device: DeviceId) -> Result<()>;
167
168 async fn assign_role(team: TeamId, device: DeviceId, role: Role) -> Result<()>;
170 async fn revoke_role(team: TeamId, device: DeviceId, role: Role) -> Result<()>;
172
173 async fn assign_net_identifier(
175 team: TeamId,
176 device: DeviceId,
177 name: NetIdentifier,
178 ) -> Result<()>;
179 async fn remove_net_identifier(
181 team: TeamId,
182 device: DeviceId,
183 name: NetIdentifier,
184 ) -> Result<()>;
185
186 async fn create_label(team: TeamId, label: Label) -> Result<()>;
188 async fn delete_label(team: TeamId, label: Label) -> Result<()>;
190
191 async fn assign_label(team: TeamId, device: DeviceId, label: Label) -> Result<()>;
193 async fn revoke_label(team: TeamId, device: DeviceId, label: Label) -> Result<()>;
195 async fn create_bidi_channel(
197 team: TeamId,
198 peer: NetIdentifier,
199 node_id: NodeId,
200 label: Label,
201 ) -> Result<(AfcId, AfcCtrl)>;
202 async fn delete_channel(chan: AfcId) -> Result<AfcCtrl>;
204 async fn receive_afc_ctrl(
206 team: TeamId,
207 node_id: NodeId,
208 ctrl: AfcCtrl,
209 ) -> Result<(AfcId, NetIdentifier, Label)>;
210}