summaryrefslogtreecommitdiff
path: root/protocol/src/protocol.rs
blob: 4bcdbd2f5489c92508ffd4899b24973f271a97d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::path::PathBuf;

use crate::{
    context::ProtocolContext,
    member::Member,
    protocol::{
        error::{FetchLatestInfoFailed, ProtocolAuthorizeFailed, VaultOperationFailed},
        fetched_info::FetchedInfo,
        index_transfer::IndexesTransfer,
        operations::{VaultHostOperations, VaultOperations},
    },
};
use framework::space::{Space, SpaceRoot};
use vault_system::vault::Vault;
use workspace_system::workspace::Workspace;

pub mod error;
pub mod fetched_info;
pub mod index_transfer;
pub mod operations;

pub trait BasicProtocol {
    type User: SpaceRoot;
    type Server: SpaceRoot;

    /// Protocol name
    /// For example: return "jvcs" to accept protocols starting with "jvcs://"
    fn protocol_name() -> &'static str;

    /// Authentication
    ///
    /// authorizing is executed on the client side, and for some protocols also on the server side,
    /// ultimately outputting the authentication result
    /// - Ok(Member): indicates a successfully authenticated member
    /// - Err(ProtocolAuthorizeFailed): indicates the reason for failure
    fn authorizing(
        &self,
        ctx: &ProtocolContext<Self::User, Self::Server>,
    ) -> impl Future<Output = Result<Member, ProtocolAuthorizeFailed>> + Send;

    /// Host authentication
    ///
    /// Authenticate as a host (administrator) on the server side.
    /// Returns the authenticated host member if successful.
    fn authorizing_host(
        &self,
        ctx: &ProtocolContext<Self::User, Self::Server>,
    ) -> impl Future<Output = Result<Member, ProtocolAuthorizeFailed>> + Send;

    /// Build user space
    ///
    /// Build and return the user space based on the given current directory path.
    fn build_user_space(&self, current_dir: PathBuf) -> Space<Self::User>;

    /// Build server space
    ///
    /// Build and return the server space based on the given current directory path.
    fn build_server_space(&self, current_dir: PathBuf) -> Space<Self::Server>;

    /// Fetch the latest information from upstream
    ///
    /// - On the local side, workspace will be Some
    /// - On the remote side, vault will be Some
    ///
    /// # Result
    /// - The remote side returns Ok(Some(FetchedInfo)) to send data to the local side
    /// - The local side returns Ok(Some(FetchedInfo)) to get the latest information
    fn fetch_latest_info(
        &self,
        workspace: Option<Space<Workspace>>,
        vault: Option<Space<Vault>>,
    ) -> impl Future<Output = Result<Option<FetchedInfo>, FetchLatestInfoFailed>> + Send;

    /// Transfer indexes
    ///
    /// - `index_transfer` and `storage` represent the index file and
    ///   the corresponding block storage path, respectively.
    /// - If `vault` is Some, send block information from the Vault.
    /// - If `workspace` is Some, send block information from the Workspace.
    ///
    /// Each block transfer is atomic, but the overall transfer is not atomic.
    /// Blocks that have been successfully transferred are permanently retained on the upstream side.
    ///
    /// After the block information is correctly stored on the other side,
    /// transfer the `index_file` and register it to the corresponding IndexSource.
    ///
    /// If the IndexSource to be registered is a `local_id`, the server will issue a `remote_id`
    /// and write it into the local ID mapping.
    fn transfer_indexes(
        &self,
        index_transfer: IndexesTransfer,
        storage: PathBuf,
        workspace: Option<Space<Workspace>>,
        vault: Option<Space<Vault>>,
    ) -> impl Future<Output = Result<(), FetchLatestInfoFailed>> + Send;

    /// Handle operations
    ///
    /// Requests are sent from the client to the server,
    /// and the following requests are uniformly processed on the server side.
    fn handle_operation(
        &self,
        operation: VaultOperations,
        authorized_member: Member,
        vault: Space<Vault>,
    ) -> impl Future<Output = Result<(), VaultOperationFailed>> + Send;

    /// Handle host operations
    ///
    /// Requests are sent from the host (administrator) to the server,
    /// and the following requests are uniformly processed on the server side.
    fn handle_host_operation(
        &self,
        operation: VaultHostOperations,
        authorized_host: Member,
        vault: Space<Vault>,
    ) -> impl Future<Output = Result<(), VaultOperationFailed>> + Send;
}