summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--mullvad-daemon/src/main.rs13
-rw-r--r--mullvad-daemon/src/management_interface.rs8
-rw-r--r--mullvad-rpc/Cargo.toml1
-rw-r--r--mullvad-rpc/src/lib.rs17
-rw-r--r--mullvad-types/src/custom_tunnel.rs46
-rw-r--r--mullvad-types/src/lib.rs7
-rw-r--r--mullvad-types/src/location.rs5
-rw-r--r--mullvad-types/src/relay_endpoint.rs72
-rw-r--r--mullvad-types/src/relay_list.rs44
10 files changed, 127 insertions, 87 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d54055a31e..717f93bddc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -702,6 +702,7 @@ dependencies = [
"jsonrpc-client-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-client-http 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mullvad-types 0.1.0",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index d4de632817..1619205669 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -48,10 +48,10 @@ use futures::Future;
use jsonrpc_core::futures::sync::oneshot::Sender as OneshotSender;
use management_interface::{BoxFuture, ManagementInterfaceServer, TunnelCommand};
use mullvad_rpc::{AccountsProxy, HttpHandle};
+use mullvad_types::CustomTunnelEndpoint;
use mullvad_types::account::{AccountData, AccountToken};
use mullvad_types::relay_constraints::{Constraint, OpenVpnConstraints, RelayConstraints,
RelayConstraintsUpdate, TunnelConstraints};
-use mullvad_types::relay_endpoint::RelayEndpoint;
use mullvad_types::states::{DaemonState, SecurityState, TargetState};
use rand::Rng;
@@ -561,16 +561,11 @@ impl Daemon {
Constraint::Only(port) => port,
};
- let endpoint = RelayEndpoint {
+ CustomTunnelEndpoint {
host,
- port,
- protocol,
- }.to_endpoint()
- .chain_err(|| "Unable to construct a valid relay")?;
- Ok(TunnelEndpoint {
- address: endpoint.address.ip(),
tunnel: TunnelParameters::OpenVpn(OpenVpnParameters { port, protocol }),
- })
+ }.to_tunnel_endpoint()
+ .chain_err(|| "Unable to construct a valid relay")
}
fn spawn_tunnel_monitor(
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 28b905390d..a71dddfb35 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -449,9 +449,11 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem
fn get_location(&self) -> Result<Location, Error> {
trace!("get_location");
Ok(Location {
- latlong: [1.0, 2.0],
- country: "narnia".to_owned(),
- city: "Le city".to_owned(),
+ country: String::from("narnia"),
+ country_code: String::from("na"),
+ city: String::from("Le city"),
+ city_code: String::from("le"),
+ position: [1.0, 2.0],
})
}
diff --git a/mullvad-rpc/Cargo.toml b/mullvad-rpc/Cargo.toml
index 41f7fccb2d..d49557cb96 100644
--- a/mullvad-rpc/Cargo.toml
+++ b/mullvad-rpc/Cargo.toml
@@ -9,5 +9,6 @@ license = "GPL-3.0"
chrono = { version = "0.4", features = ["serde"] }
jsonrpc-client-core = "0.2.1"
jsonrpc-client-http = "0.2.1"
+serde_json = "1.0"
mullvad-types = { path = "../mullvad-types" }
diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs
index 9174f1e684..f0d32ad9ee 100644
--- a/mullvad-rpc/src/lib.rs
+++ b/mullvad-rpc/src/lib.rs
@@ -10,6 +10,7 @@ extern crate chrono;
#[macro_use]
extern crate jsonrpc_client_core;
extern crate jsonrpc_client_http;
+extern crate serde_json;
extern crate mullvad_types;
@@ -21,11 +22,16 @@ pub use jsonrpc_client_core::{Error, ErrorKind};
pub use jsonrpc_client_http::{Error as HttpError, HttpHandle};
use mullvad_types::account::AccountToken;
+use mullvad_types::relay_list::RelayList;
static MASTER_API_URI: &str = "https://api.mullvad.net/rpc/";
+pub fn connect() -> Result<HttpHandle, HttpError> {
+ HttpTransport::new()?.handle(MASTER_API_URI)
+}
+
jsonrpc_client!(pub struct AccountsProxy {
pub fn get_expiry(&mut self, account_token: AccountToken) -> RpcRequest<DateTime<Utc>>;
});
@@ -47,3 +53,14 @@ impl ProblemReportProxy<HttpHandle> {
Ok(ProblemReportProxy::new(transport))
}
}
+
+jsonrpc_client!(pub struct RelayListProxy {
+ pub fn relay_list(&mut self) -> RpcRequest<RelayList>;
+});
+
+impl RelayListProxy<HttpHandle> {
+ pub fn connect() -> Result<Self, HttpError> {
+ let transport = HttpTransport::new()?.handle(MASTER_API_URI)?;
+ Ok(RelayListProxy::new(transport))
+ }
+}
diff --git a/mullvad-types/src/custom_tunnel.rs b/mullvad-types/src/custom_tunnel.rs
new file mode 100644
index 0000000000..788587568b
--- /dev/null
+++ b/mullvad-types/src/custom_tunnel.rs
@@ -0,0 +1,46 @@
+use std::net::{IpAddr, ToSocketAddrs};
+
+use talpid_types::net::{TunnelEndpoint, TunnelParameters};
+
+error_chain!{
+ errors {
+ InvalidHost(host: String) {
+ display("Invalid host: {}", host)
+ }
+ }
+}
+
+
+#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
+pub struct CustomTunnelEndpoint {
+ pub host: String,
+ pub tunnel: TunnelParameters,
+}
+
+impl CustomTunnelEndpoint {
+ pub fn to_tunnel_endpoint(&self) -> Result<TunnelEndpoint> {
+ Ok(TunnelEndpoint {
+ address: resolve_to_ip(&self.host)?,
+ tunnel: self.tunnel,
+ })
+ }
+}
+
+/// Does a DNS lookup if the host isn't an IP.
+/// Returns the first IPv4 address if one exists, otherwise the first IPv6 address.
+/// Rust only provides means to resolve a socket addr, not just a host, for some reason. So
+/// because of this we do the resolving with port zero and then pick out the IPs.
+fn resolve_to_ip(host: &str) -> Result<IpAddr> {
+ let (mut ipv4, mut ipv6): (Vec<IpAddr>, Vec<IpAddr>) = (host, 0)
+ .to_socket_addrs()
+ .chain_err(|| ErrorKind::InvalidHost(host.to_owned()))?
+ .map(|addr| addr.ip())
+ .partition(|addr| addr.is_ipv4());
+
+ ipv4.pop()
+ .or_else(|| {
+ info!("No IPv4 for host {}", host);
+ ipv6.pop()
+ })
+ .ok_or(ErrorKind::InvalidHost(host.to_owned()).into())
+}
diff --git a/mullvad-types/src/lib.rs b/mullvad-types/src/lib.rs
index 82022bbf9a..cd3a3bcb97 100644
--- a/mullvad-types/src/lib.rs
+++ b/mullvad-types/src/lib.rs
@@ -21,6 +21,9 @@ extern crate error_chain;
pub mod account;
pub mod location;
-pub mod states;
-pub mod relay_endpoint;
pub mod relay_constraints;
+pub mod relay_list;
+pub mod states;
+
+mod custom_tunnel;
+pub use custom_tunnel::*;
diff --git a/mullvad-types/src/location.rs b/mullvad-types/src/location.rs
index 72146998b3..6789e77ead 100644
--- a/mullvad-types/src/location.rs
+++ b/mullvad-types/src/location.rs
@@ -1,8 +1,11 @@
pub type CountryCode = String;
+pub type CityCode = String;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Location {
- pub latlong: [f64; 2],
pub country: String,
+ pub country_code: CountryCode,
pub city: String,
+ pub city_code: CityCode,
+ pub position: [f64; 2],
}
diff --git a/mullvad-types/src/relay_endpoint.rs b/mullvad-types/src/relay_endpoint.rs
deleted file mode 100644
index 8a53d16393..0000000000
--- a/mullvad-types/src/relay_endpoint.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use std::fmt;
-use std::net::{SocketAddr, ToSocketAddrs};
-use talpid_types;
-use talpid_types::net::TransportProtocol;
-
-error_chain!{
- errors {
- InvalidHost(host: String) {
- display("Invalid host: {}", host)
- }
- }
-}
-
-#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
-pub struct RelayEndpoint {
- pub host: String,
- pub port: u16,
- pub protocol: TransportProtocol,
-}
-
-impl RelayEndpoint {
- pub fn to_endpoint(&self) -> Result<talpid_types::net::Endpoint> {
- let socket_addrs = to_socket_addrs(self.host.as_str(), self.port)?;
- ensure!(
- socket_addrs.len() > 0,
- ErrorKind::InvalidHost(self.host.clone())
- );
-
- let socket_addr = choose_ip(&socket_addrs).unwrap();
-
- if socket_addrs.len() > 1 {
- info!(
- "{} resolved to more than one IP, ignoring all but {}",
- self.host,
- socket_addr.ip()
- )
- }
-
- Ok(talpid_types::net::Endpoint::new(
- socket_addr.ip(),
- socket_addr.port(),
- self.protocol,
- ))
- }
-}
-
-/// Does a DNS lookup if the host isn't an IP.
-fn to_socket_addrs(host: &str, port: u16) -> Result<Vec<SocketAddr>> {
- Ok(
- (host, port)
- .to_socket_addrs()
- .chain_err(|| ErrorKind::InvalidHost(host.to_owned()))?
- .collect(),
- )
-}
-
-fn choose_ip(socket_addrs: &Vec<SocketAddr>) -> Option<SocketAddr> {
- // We prefer IPv4 addresses, so we split the addresses into
- // IPv4 ad IPv6s and take form the IPv4 pile if any.
-
- let (mut ipv4, mut ipv6): (Vec<SocketAddr>, Vec<SocketAddr>) =
- socket_addrs.into_iter().partition(|addr| addr.is_ipv4());
-
- // If there are many IP:s, we simply ignore the rest
- ipv4.pop().or(ipv6.pop())
-}
-
-impl fmt::Display for RelayEndpoint {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "{}:{} - {}", self.host, self.port, self.protocol)
- }
-}
diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs
new file mode 100644
index 0000000000..829665efa3
--- /dev/null
+++ b/mullvad-types/src/relay_list.rs
@@ -0,0 +1,44 @@
+use location::{CityCode, CountryCode, Location};
+
+use std::net::Ipv4Addr;
+
+use talpid_types::net::{OpenVpnParameters, WireguardParameters};
+
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct RelayList {
+ pub countries: Vec<RelayListCountry>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct RelayListCountry {
+ pub name: String,
+ pub code: CountryCode,
+ pub cities: Vec<RelayListCity>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct RelayListCity {
+ pub name: String,
+ pub code: CityCode,
+ pub position: [f64; 2],
+ #[serde(skip_serializing_if = "Vec::is_empty", default)] pub relays: Vec<Relay>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Relay {
+ pub hostname: String,
+ pub ipv4_addr_in: Ipv4Addr,
+ pub ipv4_addr_exit: Ipv4Addr,
+ pub include_in_country: bool,
+ pub weight: u64,
+ pub tunnels: RelayTunnels,
+ #[serde(skip)] pub location: Option<Location>,
+}
+
+#[derive(Debug, Default, Clone, Deserialize, Serialize)]
+#[serde(default)]
+pub struct RelayTunnels {
+ pub openvpn: Vec<OpenVpnParameters>,
+ pub wireguard: Vec<WireguardParameters>,
+}