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
180
181
182
183
184
185
|
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,
}
/// 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>;
async fn get_mullvad_app_cache_dir() -> Result<PathBuf, Error>;
/// Send TCP packet
async fn send_tcp(
interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error>;
/// Send UDP packet
async fn send_udp(
interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error>;
/// Send ICMP
async fn send_ping(interface: Option<String>, destination: IpAddr) -> Result<(), Error>;
/// Fetch the current location.
async fn geoip_lookup(mullvad_host: String) -> Result<AmIMullvad, Error>;
/// Returns the IP of the given interface.
async fn get_interface_ip(interface: String) -> Result<IpAddr, Error>;
/// Returns the name of the default interface.
async fn get_default_interface() -> Result<String, Error>;
/// Perform DNS resolution.
async fn resolve_hostname(hostname: String) -> Result<Vec<SocketAddr>, Error>;
/// Restart the Mullvad VPN application.
async fn restart_mullvad_daemon() -> Result<(), Error>;
/// Stop the Mullvad VPN application.
async fn stop_mullvad_daemon() -> Result<(), Error>;
/// Start the Mullvad VPN application.
async fn start_mullvad_daemon() -> Result<(), 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>;
/// Write arbitrary bytes to some file `dest` on the test runner.
async fn write_file(dest: PathBuf, bytes: Vec<u8>) -> Result<(), Error>;
async fn reboot() -> Result<(), Error>;
async fn make_device_json_old() -> Result<(), Error>;
}
}
pub use client::ServiceClient;
pub use service::{Service, ServiceRequest, ServiceResponse};
|