summaryrefslogtreecommitdiffhomepage
path: root/test/test-rpc/src/lib.rs
blob: 2fd4411f494017ac05301421ecb9e479e8ea9c01 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
use serde::{Deserialize, Serialize};
use std::{
    collections::BTreeMap,
    net::{IpAddr, SocketAddr},
    path::PathBuf,
};

pub mod client;
pub mod logging;
pub mod meta;
pub mod mullvad_daemon;
pub mod net;
pub mod package;
pub mod transport;

#[derive(err_derive::Error, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum Error {
    #[error(display = "Test runner RPC failed")]
    Tarpc(#[error(source)] tarpc::client::RpcError),
    #[error(display = "Syscall failed")]
    Syscall,
    #[error(display = "Interface not found")]
    InterfaceNotFound,
    #[error(display = "HTTP request failed")]
    HttpRequest(String),
    #[error(display = "Failed to deserialize HTTP body")]
    DeserializeBody,
    #[error(display = "DNS resolution failed")]
    DnsResolution,
    #[error(display = "Test runner RPC timed out")]
    TestRunnerTimeout,
    #[error(display = "Package error")]
    Package(#[error(source)] package::Error),
    #[error(display = "Logger error")]
    Logger(#[error(source)] logging::Error),
    #[error(display = "Failed to send UDP datagram")]
    SendUdp,
    #[error(display = "Failed to send TCP segment")]
    SendTcp,
    #[error(display = "Failed to send ping")]
    Ping,
    #[error(display = "Failed to get or set registry value")]
    Registry(String),
    #[error(display = "Failed to change the service")]
    Service(String),
    #[error(display = "Could not read from or write to the file system")]
    FileSystem(String),
    #[error(display = "Could not serialize or deserialize file")]
    FileSerialization(String),
    #[error(display = "User must be logged in but is not")]
    UserNotLoggedIn(String),
    #[error(display = "Invalid URL")]
    InvalidUrl,
    #[error(display = "Timeout")]
    Timeout,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
pub enum Interface {
    Tunnel,
    NonTunnel,
}

/// Response from am.i.mullvad.net
#[derive(Debug, Serialize, Deserialize)]
pub struct AmIMullvad {
    pub ip: IpAddr,
    pub mullvad_exit_ip: bool,
    pub mullvad_exit_ip_hostname: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ExecResult {
    pub code: Option<i32>,
    pub stdout: Vec<u8>,
    pub stderr: Vec<u8>,
}

impl ExecResult {
    pub fn success(&self) -> bool {
        self.code == Some(0)
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub enum AppTrace {
    Path(PathBuf),
}

mod service {
    use std::collections::HashMap;

    pub use super::*;

    #[tarpc::service]
    pub trait Service {
        /// Install app package.
        async fn install_app(package_path: package::Package) -> Result<(), Error>;

        /// Remove app package.
        async fn uninstall_app(env: HashMap<String, String>) -> Result<(), Error>;

        /// Execute a program.
        async fn exec(
            path: String,
            args: Vec<String>,
            env: BTreeMap<String, String>,
        ) -> Result<ExecResult, Error>;

        /// Get the output of the runners stdout logs since the last time this function was called.
        /// Block if there is no output until some output is provided by the runner.
        async fn poll_output() -> Result<Vec<logging::Output>, Error>;

        /// Get the output of the runners stdout logs since the last time this function was called.
        /// Block if there is no output until some output is provided by the runner.
        async fn try_poll_output() -> Result<Vec<logging::Output>, Error>;

        async fn get_mullvad_app_logs() -> logging::LogOutput;

        /// Return the OS of the guest.
        async fn get_os() -> meta::Os;

        /// Return status of the system service.
        async fn mullvad_daemon_get_status() -> mullvad_daemon::ServiceStatus;

        /// Returns all Mullvad app files, directories, and other data found on the system.
        async fn find_mullvad_app_traces() -> Result<Vec<AppTrace>, Error>;

        /// Send TCP packet
        async fn send_tcp(
            interface: Option<Interface>,
            bind_addr: SocketAddr,
            destination: SocketAddr,
        ) -> Result<(), Error>;

        /// Send UDP packet
        async fn send_udp(
            interface: Option<Interface>,
            bind_addr: SocketAddr,
            destination: SocketAddr,
        ) -> Result<(), Error>;

        /// Send ICMP
        async fn send_ping(interface: Option<Interface>, destination: IpAddr) -> Result<(), Error>;

        /// Fetch the current location.
        async fn geoip_lookup(mullvad_host: String) -> Result<AmIMullvad, Error>;

        /// Returns the name of the given interface.
        async fn get_interface_name(interface: Interface) -> Result<String, Error>;

        /// Returns the IP of the given interface.
        async fn get_interface_ip(interface: Interface) -> Result<IpAddr, Error>;

        /// Perform DNS resolution.
        async fn resolve_hostname(hostname: String) -> Result<Vec<SocketAddr>, Error>;

        /// Sets the log level of the daemon service, the verbosity level represents the number of
        /// `-v`s passed on the command line. This will restart the daemon system service.
        async fn set_daemon_log_level(
            verbosity_level: mullvad_daemon::Verbosity,
        ) -> Result<(), Error>;

        /// Set environment variables for the daemon service. This will restart the daemon system service.
        async fn set_daemon_environment(env: HashMap<String, String>) -> Result<(), Error>;

        /// Copy a file from `src` to `dest` on the test runner.
        async fn copy_file(src: String, dest: String) -> Result<(), Error>;

        async fn reboot() -> Result<(), Error>;

        async fn set_mullvad_daemon_service_state(on: bool) -> Result<(), Error>;

        async fn make_device_json_old() -> Result<(), Error>;
    }
}

pub use client::ServiceClient;
pub use service::{Service, ServiceRequest, ServiceResponse};