Skip to main content

iroh_services/
protocol.rs

1use std::collections::BTreeMap;
2
3use anyhow::Result;
4use irpc::{channel::oneshot, rpc_requests};
5use rcan::Rcan;
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::{caps::Caps, net_diagnostics::DiagnosticsReport};
10
11/// The main ALPN for connecting from the client to the cloud node.
12pub const ALPN: &[u8] = b"/iroh/n0des/1";
13
14pub type IrohServicesClient = irpc::Client<IrohServicesProtocol>;
15
16#[rpc_requests(message = ServicesMessage)]
17#[derive(Debug, Serialize, Deserialize)]
18#[allow(clippy::large_enum_variant)]
19pub enum IrohServicesProtocol {
20    #[rpc(tx=oneshot::Sender<()>)]
21    Auth(Auth),
22    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
23    PutMetrics(PutMetrics),
24    #[rpc(tx=oneshot::Sender<Pong>)]
25    Ping(Ping),
26
27    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
28    PutNetworkDiagnostics(PutNetworkDiagnostics),
29
30    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
31    GrantCap(GrantCap),
32
33    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
34    NameEndpoint(NameEndpoint),
35
36    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
37    SetGroup(SetGroup),
38
39    #[rpc(tx=oneshot::Sender<RemoteResult<()>>)]
40    SetAttributes(SetAttributes),
41}
42
43/// Dedicated protocol for cloud-to-endpoint net diagnostics connections.
44#[rpc_requests(message = NetDiagnosticsMessage)]
45#[derive(Debug, Serialize, Deserialize)]
46#[allow(clippy::large_enum_variant)]
47pub enum ClientHostProtocol {
48    #[rpc(tx=oneshot::Sender<()>)]
49    Auth(Auth),
50    #[rpc(tx=oneshot::Sender<RemoteResult<DiagnosticsReport>>)]
51    RunNetworkDiagnostics(RunNetworkDiagnostics),
52}
53
54pub type RemoteResult<T> = Result<T, RemoteError>;
55
56#[derive(Clone, Serialize, Deserialize, thiserror::Error, Debug)]
57pub enum RemoteError {
58    #[error("Missing capability: {}", _0.to_strings().join(", "))]
59    MissingCapability(Caps),
60    #[error("Unauthorized: {}", _0)]
61    AuthError(String),
62    #[error("Internal server error")]
63    InternalServerError,
64}
65
66/// Authentication on first request
67#[derive(Debug, Serialize, Deserialize)]
68pub struct Auth {
69    pub caps: Rcan<Caps>,
70}
71
72/// Request to store the given metrics data
73#[derive(Debug, Serialize, Deserialize)]
74pub struct PutMetrics {
75    pub session_id: Uuid,
76    pub update: iroh_metrics::encoding::Update,
77}
78
79/// Simple ping requests
80#[derive(Debug, Serialize, Deserialize)]
81pub struct Ping {
82    pub req_id: [u8; 16],
83}
84
85/// Simple ping response
86#[derive(Debug, Serialize, Deserialize)]
87pub struct Pong {
88    pub req_id: [u8; 16],
89}
90
91/// Publishing network diagnostics
92#[derive(Debug, Serialize, Deserialize)]
93pub struct PutNetworkDiagnostics {
94    pub report: crate::net_diagnostics::DiagnosticsReport,
95}
96
97/// ask this node to run diagnostics & return the result.
98/// present even without the net_diagnostics feature flag because the request
99/// struct is empty in both cases
100#[derive(Debug, Serialize, Deserialize)]
101pub struct RunNetworkDiagnostics;
102
103/// Grant a capability token to the remote endpoint. The remote should store
104/// the RCAN and use it when dialing back to authorize its requests.
105#[derive(Debug, Serialize, Deserialize)]
106pub struct GrantCap {
107    pub cap: Rcan<Caps>,
108}
109
110/// Label the client endpoint cloud-side with a string identifier.
111#[derive(Debug, Serialize, Deserialize)]
112pub struct NameEndpoint {
113    pub name: String,
114}
115
116/// Attach the client endpoint to a single named group cloud-side.
117#[derive(Debug, Serialize, Deserialize)]
118pub struct SetGroup {
119    pub group: String,
120}
121
122/// Replace the arbitrary key-value attributes on the client endpoint cloud-side.
123#[derive(Debug, Serialize, Deserialize)]
124pub struct SetAttributes {
125    pub attributes: BTreeMap<String, String>,
126}