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}