iroh_docs/rpc/
proto.rs

1//! Protocol definitions for RPC.
2
3use std::path::PathBuf;
4
5use bytes::Bytes;
6use iroh::NodeAddr;
7use iroh_blobs::{export::ExportProgress, store::ExportMode, Hash};
8use nested_enum_utils::enum_conversions;
9use quic_rpc::pattern::try_server_streaming::StreamCreated;
10use quic_rpc_derive::rpc_requests;
11use serde::{Deserialize, Serialize};
12
13use super::{
14    client::docs::{ImportProgress, ShareMode},
15    AddrInfoOptions, RpcError, RpcResult,
16};
17use crate::{
18    actor::OpenState,
19    engine::LiveEvent,
20    store::{DownloadPolicy, Query},
21    Author, AuthorId, Capability, CapabilityKind, DocTicket, Entry, NamespaceId, PeerIdBytes,
22    SignedEntry,
23};
24
25/// The RPC service type for the docs protocol.
26#[derive(Debug, Clone)]
27pub struct RpcService;
28
29impl quic_rpc::Service for RpcService {
30    type Req = Request;
31    type Res = Response;
32}
33
34#[allow(missing_docs)]
35#[derive(strum::Display, Debug, Serialize, Deserialize)]
36#[enum_conversions]
37#[rpc_requests(RpcService)]
38pub enum Request {
39    #[rpc(response = RpcResult<OpenResponse>)]
40    Open(OpenRequest),
41    #[rpc(response = RpcResult<CloseResponse>)]
42    Close(CloseRequest),
43    #[rpc(response = RpcResult<StatusResponse>)]
44    Status(StatusRequest),
45    #[server_streaming(response = RpcResult<ListResponse>)]
46    List(DocListRequest),
47    #[rpc(response = RpcResult<CreateResponse>)]
48    Create(CreateRequest),
49    #[rpc(response = RpcResult<DropResponse>)]
50    Drop(DropRequest),
51    #[rpc(response = RpcResult<ImportResponse>)]
52    Import(ImportRequest),
53    #[rpc(response = RpcResult<SetResponse>)]
54    Set(SetRequest),
55    #[rpc(response = RpcResult<SetHashResponse>)]
56    SetHash(SetHashRequest),
57    #[server_streaming(response = RpcResult<GetManyResponse>)]
58    Get(GetManyRequest),
59    #[rpc(response = RpcResult<GetExactResponse>)]
60    GetExact(GetExactRequest),
61    #[server_streaming(response = ImportFileResponse)]
62    ImportFile(ImportFileRequest),
63    #[server_streaming(response = ExportFileResponse)]
64    ExportFile(ExportFileRequest),
65    #[rpc(response = RpcResult<DelResponse>)]
66    Del(DelRequest),
67    #[rpc(response = RpcResult<StartSyncResponse>)]
68    StartSync(StartSyncRequest),
69    #[rpc(response = RpcResult<LeaveResponse>)]
70    Leave(LeaveRequest),
71    #[rpc(response = RpcResult<ShareResponse>)]
72    Share(ShareRequest),
73    #[try_server_streaming(create_error = RpcError, item_error = RpcError, item = DocSubscribeResponse)]
74    Subscribe(DocSubscribeRequest),
75    #[rpc(response = RpcResult<GetDownloadPolicyResponse>)]
76    GetDownloadPolicy(GetDownloadPolicyRequest),
77    #[rpc(response = RpcResult<SetDownloadPolicyResponse>)]
78    SetDownloadPolicy(SetDownloadPolicyRequest),
79    #[rpc(response = RpcResult<GetSyncPeersResponse>)]
80    GetSyncPeers(GetSyncPeersRequest),
81    #[server_streaming(response = RpcResult<AuthorListResponse>)]
82    AuthorList(AuthorListRequest),
83    #[rpc(response = RpcResult<AuthorCreateResponse>)]
84    AuthorCreate(AuthorCreateRequest),
85    #[rpc(response = RpcResult<AuthorGetDefaultResponse>)]
86    AuthorGetDefault(AuthorGetDefaultRequest),
87    #[rpc(response = RpcResult<AuthorSetDefaultResponse>)]
88    AuthorSetDefault(AuthorSetDefaultRequest),
89    #[rpc(response = RpcResult<AuthorImportResponse>)]
90    AuthorImport(AuthorImportRequest),
91    #[rpc(response = RpcResult<AuthorExportResponse>)]
92    AuthorExport(AuthorExportRequest),
93    #[rpc(response = RpcResult<AuthorDeleteResponse>)]
94    AuthorDelete(AuthorDeleteRequest),
95}
96
97#[allow(missing_docs)]
98#[derive(strum::Display, Debug, Serialize, Deserialize)]
99#[enum_conversions]
100pub enum Response {
101    Open(RpcResult<OpenResponse>),
102    Close(RpcResult<CloseResponse>),
103    Status(RpcResult<StatusResponse>),
104    List(RpcResult<ListResponse>),
105    Create(RpcResult<CreateResponse>),
106    Drop(RpcResult<DropResponse>),
107    Import(RpcResult<ImportResponse>),
108    Set(RpcResult<SetResponse>),
109    SetHash(RpcResult<SetHashResponse>),
110    Get(RpcResult<GetManyResponse>),
111    GetExact(RpcResult<GetExactResponse>),
112    ImportFile(ImportFileResponse),
113    ExportFile(ExportFileResponse),
114    Del(RpcResult<DelResponse>),
115    Share(RpcResult<ShareResponse>),
116    StartSync(RpcResult<StartSyncResponse>),
117    Leave(RpcResult<LeaveResponse>),
118    Subscribe(RpcResult<DocSubscribeResponse>),
119    GetDownloadPolicy(RpcResult<GetDownloadPolicyResponse>),
120    SetDownloadPolicy(RpcResult<SetDownloadPolicyResponse>),
121    GetSyncPeers(RpcResult<GetSyncPeersResponse>),
122    StreamCreated(RpcResult<StreamCreated>),
123    AuthorList(RpcResult<AuthorListResponse>),
124    AuthorCreate(RpcResult<AuthorCreateResponse>),
125    AuthorGetDefault(RpcResult<AuthorGetDefaultResponse>),
126    AuthorSetDefault(RpcResult<AuthorSetDefaultResponse>),
127    AuthorImport(RpcResult<AuthorImportResponse>),
128    AuthorExport(RpcResult<AuthorExportResponse>),
129    AuthorDelete(RpcResult<AuthorDeleteResponse>),
130}
131
132/// Subscribe to events for a document.
133#[derive(Serialize, Deserialize, Debug)]
134pub struct DocSubscribeRequest {
135    /// The document id
136    pub doc_id: NamespaceId,
137}
138
139/// Response to [`DocSubscribeRequest`]
140#[derive(Serialize, Deserialize, Debug)]
141pub struct DocSubscribeResponse {
142    /// The event that occurred on the document
143    pub event: LiveEvent,
144}
145
146/// List all documents
147#[derive(Serialize, Deserialize, Debug)]
148pub struct DocListRequest {}
149
150/// Response to [`DocListRequest`]
151#[derive(Serialize, Deserialize, Debug)]
152pub struct ListResponse {
153    /// The document id
154    pub id: NamespaceId,
155    /// The capability over the document.
156    pub capability: CapabilityKind,
157}
158
159/// Create a new document
160#[derive(Serialize, Deserialize, Debug)]
161pub struct CreateRequest {}
162
163/// Response to [`CreateRequest`]
164#[derive(Serialize, Deserialize, Debug)]
165pub struct CreateResponse {
166    /// The document id
167    pub id: NamespaceId,
168}
169
170/// Import a document from a capability.
171#[derive(Serialize, Deserialize, Debug)]
172pub struct ImportRequest {
173    /// The namespace capability.
174    pub capability: Capability,
175}
176
177/// Response to [`ImportRequest`]
178#[derive(Serialize, Deserialize, Debug)]
179pub struct ImportResponse {
180    /// the document id
181    pub doc_id: NamespaceId,
182}
183
184/// Share a document with peers over a ticket.
185#[derive(Serialize, Deserialize, Debug)]
186pub struct ShareRequest {
187    /// The document id
188    pub doc_id: NamespaceId,
189    /// Whether to share read or write access to the document
190    pub mode: ShareMode,
191    /// Configuration of the addresses in the ticket.
192    pub addr_options: AddrInfoOptions,
193}
194
195/// The response to [`ShareRequest`]
196#[derive(Serialize, Deserialize, Debug)]
197pub struct ShareResponse(pub DocTicket);
198
199/// Get info on a document
200#[derive(Serialize, Deserialize, Debug)]
201pub struct StatusRequest {
202    /// The document id
203    pub doc_id: NamespaceId,
204}
205
206/// Response to [`StatusRequest`]
207// TODO: actually provide info
208#[derive(Serialize, Deserialize, Debug)]
209pub struct StatusResponse {
210    /// Live sync status
211    pub status: OpenState,
212}
213
214/// Open a document
215#[derive(Serialize, Deserialize, Debug)]
216pub struct OpenRequest {
217    /// The document id
218    pub doc_id: NamespaceId,
219}
220
221/// Response to [`OpenRequest`]
222#[derive(Serialize, Deserialize, Debug)]
223pub struct OpenResponse {}
224
225/// Open a document
226#[derive(Serialize, Deserialize, Debug)]
227pub struct CloseRequest {
228    /// The document id
229    pub doc_id: NamespaceId,
230}
231
232/// Response to [`CloseRequest`]
233#[derive(Serialize, Deserialize, Debug)]
234pub struct CloseResponse {}
235
236/// Start to sync a doc with peers.
237#[derive(Serialize, Deserialize, Debug)]
238pub struct StartSyncRequest {
239    /// The document id
240    pub doc_id: NamespaceId,
241    /// List of peers to join
242    pub peers: Vec<NodeAddr>,
243}
244
245/// Response to [`StartSyncRequest`]
246#[derive(Serialize, Deserialize, Debug)]
247pub struct StartSyncResponse {}
248
249/// Stop the live sync for a doc, and optionally delete the document.
250#[derive(Serialize, Deserialize, Debug)]
251pub struct LeaveRequest {
252    /// The document id
253    pub doc_id: NamespaceId,
254}
255
256/// Response to [`LeaveRequest`]
257#[derive(Serialize, Deserialize, Debug)]
258pub struct LeaveResponse {}
259
260/// Stop the live sync for a doc, and optionally delete the document.
261#[derive(Serialize, Deserialize, Debug)]
262pub struct DropRequest {
263    /// The document id
264    pub doc_id: NamespaceId,
265}
266
267/// Response to [`DropRequest`]
268#[derive(Serialize, Deserialize, Debug)]
269pub struct DropResponse {}
270
271/// Set an entry in a document
272#[derive(Serialize, Deserialize, Debug)]
273pub struct SetRequest {
274    /// The document id
275    pub doc_id: NamespaceId,
276    /// Author of this entry.
277    pub author_id: AuthorId,
278    /// Key of this entry.
279    pub key: Bytes,
280    /// Value of this entry.
281    // TODO: Allow to provide the hash directly
282    // TODO: Add a way to provide content as stream
283    pub value: Bytes,
284}
285
286/// Response to [`SetRequest`]
287#[derive(Serialize, Deserialize, Debug)]
288pub struct SetResponse {
289    /// The newly-created entry.
290    pub entry: SignedEntry,
291}
292
293/// A request to the node to add the data at the given filepath as an entry to the document
294///
295/// Will produce a stream of [`ImportProgress`] messages.
296#[derive(Debug, Serialize, Deserialize)]
297pub struct ImportFileRequest {
298    /// The document id
299    pub doc_id: NamespaceId,
300    /// Author of this entry.
301    pub author_id: AuthorId,
302    /// Key of this entry.
303    pub key: Bytes,
304    /// The filepath to the data
305    ///
306    /// This should be an absolute path valid for the file system on which
307    /// the node runs. Usually the cli will run on the same machine as the
308    /// node, so this should be an absolute path on the cli machine.
309    pub path: PathBuf,
310    /// True if the provider can assume that the data will not change, so it
311    /// can be shared in place.
312    pub in_place: bool,
313}
314
315/// Wrapper around [`ImportProgress`].
316#[derive(Debug, Serialize, Deserialize, derive_more::Into)]
317pub struct ImportFileResponse(pub ImportProgress);
318
319/// A request to the node to save the data of the entry to the given filepath
320///
321/// Will produce a stream of [`ExportFileResponse`] messages.
322#[derive(Debug, Serialize, Deserialize)]
323pub struct ExportFileRequest {
324    /// The entry you want to export
325    pub entry: Entry,
326    /// The filepath to where the data should be saved
327    ///
328    /// This should be an absolute path valid for the file system on which
329    /// the node runs. Usually the cli will run on the same machine as the
330    /// node, so this should be an absolute path on the cli machine.
331    pub path: PathBuf,
332    /// The mode of exporting. Setting to `ExportMode::TryReference` means attempting
333    /// to use references for keeping file
334    pub mode: ExportMode,
335}
336
337/// Progress messages for an doc export operation
338///
339/// An export operation involves reading the entry from the database ans saving the entry to the
340/// given `outpath`
341#[derive(Debug, Serialize, Deserialize, derive_more::Into)]
342pub struct ExportFileResponse(pub ExportProgress);
343
344/// Delete entries in a document
345#[derive(Serialize, Deserialize, Debug)]
346pub struct DelRequest {
347    /// The document id.
348    pub doc_id: NamespaceId,
349    /// Author of this entry.
350    pub author_id: AuthorId,
351    /// Prefix to delete.
352    pub prefix: Bytes,
353}
354
355/// Response to [`DelRequest`]
356#[derive(Serialize, Deserialize, Debug)]
357pub struct DelResponse {
358    /// The number of entries that were removed.
359    pub removed: usize,
360}
361
362/// Set an entry in a document via its hash
363#[derive(Serialize, Deserialize, Debug)]
364pub struct SetHashRequest {
365    /// The document id
366    pub doc_id: NamespaceId,
367    /// Author of this entry.
368    pub author_id: AuthorId,
369    /// Key of this entry.
370    pub key: Bytes,
371    /// Hash of this entry.
372    pub hash: Hash,
373    /// Size of this entry.
374    pub size: u64,
375}
376
377/// Response to [`SetHashRequest`]
378#[derive(Serialize, Deserialize, Debug)]
379pub struct SetHashResponse {}
380
381/// Get entries from a document
382#[derive(Serialize, Deserialize, Debug)]
383pub struct GetManyRequest {
384    /// The document id
385    pub doc_id: NamespaceId,
386    /// Query to run
387    pub query: Query,
388}
389
390/// Response to [`GetManyRequest`]
391#[derive(Serialize, Deserialize, Debug)]
392pub struct GetManyResponse {
393    /// The document entry
394    pub entry: SignedEntry,
395}
396
397/// Get entries from a document
398#[derive(Serialize, Deserialize, Debug)]
399pub struct GetExactRequest {
400    /// The document id
401    pub doc_id: NamespaceId,
402    /// Key matcher
403    pub key: Bytes,
404    /// Author matcher
405    pub author: AuthorId,
406    /// Whether to include empty entries (prefix deletion markers)
407    pub include_empty: bool,
408}
409
410/// Response to [`GetExactRequest`]
411#[derive(Serialize, Deserialize, Debug)]
412pub struct GetExactResponse {
413    /// The document entry
414    pub entry: Option<SignedEntry>,
415}
416
417/// Set a download policy
418#[derive(Serialize, Deserialize, Debug)]
419pub struct SetDownloadPolicyRequest {
420    /// The document id
421    pub doc_id: NamespaceId,
422    /// Download policy
423    pub policy: DownloadPolicy,
424}
425
426/// Response to [`SetDownloadPolicyRequest`]
427#[derive(Serialize, Deserialize, Debug)]
428pub struct SetDownloadPolicyResponse {}
429
430/// Get a download policy
431#[derive(Serialize, Deserialize, Debug)]
432pub struct GetDownloadPolicyRequest {
433    /// The document id
434    pub doc_id: NamespaceId,
435}
436
437/// Response to [`GetDownloadPolicyRequest`]
438#[derive(Serialize, Deserialize, Debug)]
439pub struct GetDownloadPolicyResponse {
440    /// The download policy
441    pub policy: DownloadPolicy,
442}
443
444/// Get peers for document
445#[derive(Serialize, Deserialize, Debug)]
446pub struct GetSyncPeersRequest {
447    /// The document id
448    pub doc_id: NamespaceId,
449}
450
451/// Response to [`GetSyncPeersRequest`]
452#[derive(Serialize, Deserialize, Debug)]
453pub struct GetSyncPeersResponse {
454    /// List of peers ids
455    pub peers: Option<Vec<PeerIdBytes>>,
456}
457
458/// List document authors for which we have a secret key.
459#[derive(Serialize, Deserialize, Debug)]
460pub struct AuthorListRequest {}
461
462/// Response for [`AuthorListRequest`]
463#[derive(Serialize, Deserialize, Debug)]
464pub struct AuthorListResponse {
465    /// The author id
466    pub author_id: AuthorId,
467}
468
469/// Create a new document author.
470#[derive(Serialize, Deserialize, Debug)]
471pub struct AuthorCreateRequest;
472
473/// Response for [`AuthorCreateRequest`]
474#[derive(Serialize, Deserialize, Debug)]
475pub struct AuthorCreateResponse {
476    /// The id of the created author
477    pub author_id: AuthorId,
478}
479
480/// Get the default author.
481#[derive(Serialize, Deserialize, Debug)]
482pub struct AuthorGetDefaultRequest;
483
484/// Response for [`AuthorGetDefaultRequest`]
485#[derive(Serialize, Deserialize, Debug)]
486pub struct AuthorGetDefaultResponse {
487    /// The id of the author
488    pub author_id: AuthorId,
489}
490
491/// Set the default author.
492#[derive(Serialize, Deserialize, Debug)]
493pub struct AuthorSetDefaultRequest {
494    /// The id of the author
495    pub author_id: AuthorId,
496}
497
498/// Response for [`AuthorSetDefaultRequest`]
499#[derive(Serialize, Deserialize, Debug)]
500pub struct AuthorSetDefaultResponse;
501
502/// Delete an author
503#[derive(Serialize, Deserialize, Debug)]
504pub struct AuthorDeleteRequest {
505    /// The id of the author to delete
506    pub author: AuthorId,
507}
508
509/// Response for [`AuthorDeleteRequest`]
510#[derive(Serialize, Deserialize, Debug)]
511pub struct AuthorDeleteResponse;
512
513/// Exports an author
514#[derive(Serialize, Deserialize, Debug)]
515pub struct AuthorExportRequest {
516    /// The id of the author to delete
517    pub author: AuthorId,
518}
519
520/// Response for [`AuthorExportRequest`]
521#[derive(Serialize, Deserialize, Debug)]
522pub struct AuthorExportResponse {
523    /// The author
524    pub author: Option<Author>,
525}
526
527/// Import author from secret key
528#[derive(Serialize, Deserialize, Debug)]
529pub struct AuthorImportRequest {
530    /// The author to import
531    pub author: Author,
532}
533
534/// Response to [`ImportRequest`]
535#[derive(Serialize, Deserialize, Debug)]
536pub struct AuthorImportResponse {
537    /// The author id of the imported author
538    pub author_id: AuthorId,
539}