iroh_docs/api/
protocol.rs

1//! Protocol definitions for irpc-based RPC.
2
3use std::path::PathBuf;
4
5use bytes::Bytes;
6use iroh::NodeAddr;
7use iroh_blobs::{api::blobs::ExportMode, Hash};
8use irpc::{
9    channel::{mpsc, oneshot},
10    rpc_requests,
11};
12use serde::{Deserialize, Serialize};
13
14use super::RpcResult;
15use crate::{
16    actor::OpenState,
17    engine::LiveEvent,
18    store::{DownloadPolicy, Query},
19    Author, AuthorId, Capability, CapabilityKind, DocTicket, Entry, NamespaceId, PeerIdBytes,
20    SignedEntry,
21};
22
23/// Progress during import operations
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub enum ImportProgress {
26    /// Found the blob
27    Found { size: u64 },
28    /// Progress
29    Progress { offset: u64 },
30    /// Done
31    Done { hash: Hash },
32    /// All done
33    AllDone,
34}
35
36/// Mode for sharing documents
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub enum ShareMode {
39    /// Share with read access
40    Read,
41    /// Share with write access
42    Write,
43}
44
45// Request types
46#[derive(Debug, Serialize, Deserialize, Clone)]
47pub struct OpenRequest {
48    pub doc_id: NamespaceId,
49}
50
51#[derive(Debug, Serialize, Deserialize, Clone)]
52pub struct OpenResponse;
53
54#[derive(Debug, Serialize, Deserialize, Clone)]
55pub struct CloseRequest {
56    pub doc_id: NamespaceId,
57}
58
59#[derive(Debug, Serialize, Deserialize, Clone)]
60pub struct CloseResponse;
61
62#[derive(Debug, Serialize, Deserialize, Clone)]
63pub struct StatusRequest {
64    pub doc_id: NamespaceId,
65}
66
67#[derive(Debug, Serialize, Deserialize, Clone)]
68pub struct StatusResponse {
69    pub status: OpenState,
70}
71
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct ListRequest;
74
75#[derive(Debug, Serialize, Deserialize, Clone)]
76pub struct ListResponse {
77    pub id: NamespaceId,
78    pub capability: CapabilityKind,
79}
80
81#[derive(Debug, Serialize, Deserialize, Clone)]
82pub struct CreateRequest;
83
84#[derive(Debug, Serialize, Deserialize, Clone)]
85pub struct CreateResponse {
86    pub id: NamespaceId,
87}
88
89#[derive(Debug, Serialize, Deserialize, Clone)]
90pub struct DropRequest {
91    pub doc_id: NamespaceId,
92}
93
94#[derive(Debug, Serialize, Deserialize, Clone)]
95pub struct DropResponse;
96
97#[derive(Debug, Serialize, Deserialize, Clone)]
98pub struct ImportRequest {
99    pub capability: Capability,
100}
101
102#[derive(Debug, Serialize, Deserialize, Clone)]
103pub struct ImportResponse {
104    pub doc_id: NamespaceId,
105}
106
107#[derive(Debug, Serialize, Deserialize, Clone)]
108pub struct SetRequest {
109    pub doc_id: NamespaceId,
110    pub author_id: AuthorId,
111    pub key: Bytes,
112    pub value: Bytes,
113}
114
115#[derive(Debug, Serialize, Deserialize, Clone)]
116pub struct SetResponse {
117    pub entry: SignedEntry,
118}
119
120#[derive(Debug, Serialize, Deserialize, Clone)]
121pub struct SetHashRequest {
122    pub doc_id: NamespaceId,
123    pub author_id: AuthorId,
124    pub key: Bytes,
125    pub hash: Hash,
126    pub size: u64,
127}
128
129#[derive(Debug, Serialize, Deserialize, Clone)]
130pub struct SetHashResponse;
131
132#[derive(Debug, Serialize, Deserialize, Clone)]
133pub struct GetManyRequest {
134    pub doc_id: NamespaceId,
135    pub query: Query,
136}
137
138#[derive(Debug, Serialize, Deserialize, Clone)]
139pub struct GetExactRequest {
140    pub doc_id: NamespaceId,
141    pub key: Bytes,
142    pub author: AuthorId,
143    pub include_empty: bool,
144}
145
146#[derive(Debug, Serialize, Deserialize, Clone)]
147pub struct GetExactResponse {
148    pub entry: Option<SignedEntry>,
149}
150
151#[derive(Debug, Serialize, Deserialize, Clone)]
152pub struct ImportFileRequest {
153    pub doc_id: NamespaceId,
154    pub author_id: AuthorId,
155    pub key: Bytes,
156    pub path: PathBuf,
157    pub in_place: bool,
158}
159
160#[derive(Debug, Serialize, Deserialize, Clone)]
161pub struct ExportFileRequest {
162    pub entry: Entry,
163    pub path: PathBuf,
164    pub mode: ExportMode,
165}
166
167#[derive(Debug, Serialize, Deserialize, Clone)]
168pub struct DelRequest {
169    pub doc_id: NamespaceId,
170    pub author_id: AuthorId,
171    pub prefix: Bytes,
172}
173
174#[derive(Debug, Serialize, Deserialize, Clone)]
175pub struct DelResponse {
176    pub removed: usize,
177}
178
179#[derive(Debug, Serialize, Deserialize, Clone)]
180pub struct StartSyncRequest {
181    pub doc_id: NamespaceId,
182    pub peers: Vec<NodeAddr>,
183}
184
185#[derive(Debug, Serialize, Deserialize, Clone)]
186pub struct StartSyncResponse;
187
188#[derive(Debug, Serialize, Deserialize, Clone)]
189pub struct LeaveRequest {
190    pub doc_id: NamespaceId,
191}
192
193#[derive(Debug, Serialize, Deserialize, Clone)]
194pub struct LeaveResponse;
195
196#[derive(Debug, Serialize, Deserialize, Clone)]
197pub struct ShareRequest {
198    pub doc_id: NamespaceId,
199    pub mode: ShareMode,
200    pub addr_options: AddrInfoOptions,
201}
202
203#[derive(Debug, Serialize, Deserialize, Clone)]
204pub struct ShareResponse(pub DocTicket);
205
206#[derive(Debug, Serialize, Deserialize, Clone)]
207pub struct SubscribeRequest {
208    pub doc_id: NamespaceId,
209}
210
211#[derive(Debug, Serialize, Deserialize, Clone)]
212pub struct SubscribeResponse {
213    pub event: LiveEvent,
214}
215
216#[derive(Debug, Serialize, Deserialize, Clone)]
217pub struct GetDownloadPolicyRequest {
218    pub doc_id: NamespaceId,
219}
220
221#[derive(Debug, Serialize, Deserialize, Clone)]
222pub struct GetDownloadPolicyResponse {
223    pub policy: DownloadPolicy,
224}
225
226#[derive(Debug, Serialize, Deserialize, Clone)]
227pub struct SetDownloadPolicyRequest {
228    pub doc_id: NamespaceId,
229    pub policy: DownloadPolicy,
230}
231
232#[derive(Debug, Serialize, Deserialize, Clone)]
233pub struct SetDownloadPolicyResponse;
234
235#[derive(Debug, Serialize, Deserialize, Clone)]
236pub struct GetSyncPeersRequest {
237    pub doc_id: NamespaceId,
238}
239
240#[derive(Debug, Serialize, Deserialize, Clone)]
241pub struct GetSyncPeersResponse {
242    pub peers: Option<Vec<PeerIdBytes>>,
243}
244
245#[derive(Debug, Serialize, Deserialize, Clone)]
246pub struct AuthorListRequest;
247
248#[derive(Debug, Serialize, Deserialize, Clone)]
249pub struct AuthorListResponse {
250    pub author_id: AuthorId,
251}
252
253#[derive(Debug, Serialize, Deserialize, Clone)]
254pub struct AuthorCreateRequest;
255
256#[derive(Debug, Serialize, Deserialize, Clone)]
257pub struct AuthorCreateResponse {
258    pub author_id: AuthorId,
259}
260
261#[derive(Debug, Serialize, Deserialize, Clone)]
262pub struct AuthorGetDefaultRequest;
263
264#[derive(Debug, Serialize, Deserialize, Clone)]
265pub struct AuthorGetDefaultResponse {
266    pub author_id: AuthorId,
267}
268
269#[derive(Debug, Serialize, Deserialize, Clone)]
270pub struct AuthorSetDefaultRequest {
271    pub author_id: AuthorId,
272}
273
274#[derive(Debug, Serialize, Deserialize, Clone)]
275pub struct AuthorSetDefaultResponse;
276
277#[derive(Debug, Serialize, Deserialize, Clone)]
278pub struct AuthorImportRequest {
279    pub author: Author,
280}
281
282#[derive(Debug, Serialize, Deserialize, Clone)]
283pub struct AuthorImportResponse {
284    pub author_id: AuthorId,
285}
286
287#[derive(Debug, Serialize, Deserialize, Clone)]
288pub struct AuthorExportRequest {
289    pub author: AuthorId,
290}
291
292#[derive(Debug, Serialize, Deserialize, Clone)]
293pub struct AuthorExportResponse {
294    pub author: Option<Author>,
295}
296
297#[derive(Debug, Serialize, Deserialize, Clone)]
298pub struct AuthorDeleteRequest {
299    pub author: AuthorId,
300}
301
302#[derive(Debug, Serialize, Deserialize, Clone)]
303pub struct AuthorDeleteResponse;
304
305// Use the macro to generate both the DocsProtocol and DocsMessage enums
306// plus implement Channels for each type
307#[rpc_requests(message = DocsMessage)]
308#[derive(Serialize, Deserialize, Debug)]
309pub enum DocsProtocol {
310    #[rpc(tx = oneshot::Sender<RpcResult<OpenResponse>>)]
311    Open(OpenRequest),
312    #[rpc(tx = oneshot::Sender<RpcResult<CloseResponse>>)]
313    Close(CloseRequest),
314    #[rpc(tx = oneshot::Sender<RpcResult<StatusResponse>>)]
315    Status(StatusRequest),
316    #[rpc(tx = mpsc::Sender<RpcResult<ListResponse>>)]
317    List(ListRequest),
318    #[rpc(tx = oneshot::Sender<RpcResult<CreateResponse>>)]
319    Create(CreateRequest),
320    #[rpc(tx = oneshot::Sender<RpcResult<DropResponse>>)]
321    Drop(DropRequest),
322    #[rpc(tx = oneshot::Sender<RpcResult<ImportResponse>>)]
323    Import(ImportRequest),
324    #[rpc(tx = oneshot::Sender<RpcResult<SetResponse>>)]
325    Set(SetRequest),
326    #[rpc(tx = oneshot::Sender<RpcResult<SetHashResponse>>)]
327    SetHash(SetHashRequest),
328    #[rpc(tx = mpsc::Sender<RpcResult<SignedEntry>>)]
329    Get(GetManyRequest),
330    #[rpc(tx = oneshot::Sender<RpcResult<GetExactResponse>>)]
331    GetExact(GetExactRequest),
332    // #[rpc(tx = mpsc::Sender<ImportProgress>)]
333    // ImportFile(ImportFileRequest),
334    // #[rpc(tx = mpsc::Sender<ExportProgress>)]
335    // ExportFile(ExportFileRequest),
336    #[rpc(tx = oneshot::Sender<RpcResult<DelResponse>>)]
337    Del(DelRequest),
338    #[rpc(tx = oneshot::Sender<RpcResult<StartSyncResponse>>)]
339    StartSync(StartSyncRequest),
340    #[rpc(tx = oneshot::Sender<RpcResult<LeaveResponse>>)]
341    Leave(LeaveRequest),
342    #[rpc(tx = oneshot::Sender<RpcResult<ShareResponse>>)]
343    Share(ShareRequest),
344    #[rpc(tx = mpsc::Sender<RpcResult<SubscribeResponse>>)]
345    Subscribe(SubscribeRequest),
346    #[rpc(tx = oneshot::Sender<RpcResult<GetDownloadPolicyResponse>>)]
347    GetDownloadPolicy(GetDownloadPolicyRequest),
348    #[rpc(tx = oneshot::Sender<RpcResult<SetDownloadPolicyResponse>>)]
349    SetDownloadPolicy(SetDownloadPolicyRequest),
350    #[rpc(tx = oneshot::Sender<RpcResult<GetSyncPeersResponse>>)]
351    GetSyncPeers(GetSyncPeersRequest),
352    #[rpc(tx = mpsc::Sender<RpcResult<AuthorListResponse>>)]
353    AuthorList(AuthorListRequest),
354    #[rpc(tx = oneshot::Sender<RpcResult<AuthorCreateResponse>>)]
355    AuthorCreate(AuthorCreateRequest),
356    #[rpc(tx = oneshot::Sender<RpcResult<AuthorGetDefaultResponse>>)]
357    AuthorGetDefault(AuthorGetDefaultRequest),
358    #[rpc(tx = oneshot::Sender<RpcResult<AuthorSetDefaultResponse>>)]
359    AuthorSetDefault(AuthorSetDefaultRequest),
360    #[rpc(tx = oneshot::Sender<RpcResult<AuthorImportResponse>>)]
361    AuthorImport(AuthorImportRequest),
362    #[rpc(tx = oneshot::Sender<RpcResult<AuthorExportResponse>>)]
363    AuthorExport(AuthorExportRequest),
364    #[rpc(tx = oneshot::Sender<RpcResult<AuthorDeleteResponse>>)]
365    AuthorDelete(AuthorDeleteRequest),
366}
367
368/// Options to configure what is included in a [`iroh::NodeAddr`].
369#[derive(
370    Copy,
371    Clone,
372    PartialEq,
373    Eq,
374    Default,
375    Debug,
376    derive_more::Display,
377    derive_more::FromStr,
378    Serialize,
379    Deserialize,
380)]
381pub enum AddrInfoOptions {
382    /// Only the Node ID is added.
383    ///
384    /// This usually means that iroh-dns discovery is used to find address information.
385    #[default]
386    Id,
387    /// Includes the Node ID and both the relay URL, and the direct addresses.
388    RelayAndAddresses,
389    /// Includes the Node ID and the relay URL.
390    Relay,
391    /// Includes the Node ID and the direct addresses.
392    Addresses,
393}
394
395impl AddrInfoOptions {
396    /// Apply the options to the given address.
397    pub fn apply(
398        &self,
399        iroh::NodeAddr {
400            node_id,
401            relay_url,
402            direct_addresses,
403        }: &iroh::NodeAddr,
404    ) -> iroh::NodeAddr {
405        match self {
406            Self::Id => iroh::NodeAddr {
407                node_id: *node_id,
408                relay_url: None,
409                direct_addresses: Default::default(),
410            },
411            Self::Relay => iroh::NodeAddr {
412                node_id: *node_id,
413                relay_url: relay_url.clone(),
414                direct_addresses: Default::default(),
415            },
416            Self::Addresses => iroh::NodeAddr {
417                node_id: *node_id,
418                relay_url: None,
419                direct_addresses: direct_addresses.clone(),
420            },
421            Self::RelayAndAddresses => iroh::NodeAddr {
422                node_id: *node_id,
423                relay_url: relay_url.clone(),
424                direct_addresses: direct_addresses.clone(),
425            },
426        }
427    }
428}