diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-05-15 12:48:11 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-05-15 12:48:11 +0200 |
| commit | b3ee3c1e75aa68462595aa9d80ea758b76d1aa82 (patch) | |
| tree | 0fa16001c0af8d56f64255e0edecc4d912231492 | |
| parent | 0ce25aeb01ffc054033388d97b2974f04335b859 (diff) | |
| parent | 68078efa3a462fa0c96797458c14896803f5ea76 (diff) | |
| download | mullvadvpn-b3ee3c1e75aa68462595aa9d80ea758b76d1aa82.tar.xz mullvadvpn-b3ee3c1e75aa68462595aa9d80ea758b76d1aa82.zip | |
Merge branch 'ws-jsonrpc-ipc'
| -rw-r--r-- | Cargo.lock | 71 | ||||
| -rw-r--r-- | mullvad_daemon/Cargo.toml | 4 | ||||
| -rw-r--r-- | mullvad_daemon/src/frontend_ipc_router.rs | 145 | ||||
| -rw-r--r-- | mullvad_daemon/src/ipc_api.rs | 90 | ||||
| -rw-r--r-- | mullvad_daemon/src/main.rs | 27 | ||||
| -rw-r--r-- | mullvad_daemon/src/mock_ipc.rs | 230 | ||||
| -rw-r--r-- | talpid_ipc/src/lib.rs | 2 |
7 files changed, 412 insertions, 157 deletions
diff --git a/Cargo.lock b/Cargo.lock index 71e46c965a..b7d4c3f510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,6 +233,26 @@ dependencies = [ ] [[package]] +name = "jsonrpc-macros" +version = "7.0.0" +source = "git+https://github.com/paritytech/jsonrpc#05eca1e1dd80f9b3bd8f1738ca5680d078021c27" +dependencies = [ + "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpc-pubsub" +version = "7.0.0" +source = "git+https://github.com/paritytech/jsonrpc#05eca1e1dd80f9b3bd8f1738ca5680d078021c27" +dependencies = [ + "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "jsonrpc-server-utils" version = "7.0.0" source = "git+https://github.com/paritytech/jsonrpc#05eca1e1dd80f9b3bd8f1738ca5680d078021c27" @@ -342,10 +362,12 @@ dependencies = [ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc)", + "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "talpid_ipc 0.1.0", ] @@ -398,6 +420,36 @@ dependencies = [ ] [[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -532,6 +584,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "smallvec" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "strsim" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -792,6 +854,8 @@ dependencies = [ "checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc)" = "<none>" +"checksum jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc)" = "<none>" +"checksum jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc)" = "<none>" "checksum jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc)" = "<none>" "checksum jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc)" = "<none>" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -808,6 +872,9 @@ dependencies = [ "checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" "checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" +"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum parking_lot 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8b45855d69c6ad53fdbd2f163b33506cf015befef980f7c13a9d60c12a111241" +"checksum parking_lot_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56a19dcbb5d1e32b6cccb8a9aa1fc2a38418c8699652e735e2bf391a3dc0aa16" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" @@ -826,6 +893,8 @@ dependencies = [ "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" +"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)" = "171b739972d9a1bfb169e8077238b51f9ebeaae4ff6e08072f7ba386a8802da2" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" diff --git a/mullvad_daemon/Cargo.toml b/mullvad_daemon/Cargo.toml index 42a00a29f6..c3f4e22ae5 100644 --- a/mullvad_daemon/Cargo.toml +++ b/mullvad_daemon/Cargo.toml @@ -8,10 +8,12 @@ description = "The meat of Mullvad, the core if you wish" error-chain = "0.10" serde = "1.0" serde_derive = "1.0" -serde_json = "1.0" log = "0.3" env_logger = "0.4" jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc" } +jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc" } +jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc" } +jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc" } [dependencies.talpid_ipc] path = "../talpid_ipc" diff --git a/mullvad_daemon/src/frontend_ipc_router.rs b/mullvad_daemon/src/frontend_ipc_router.rs deleted file mode 100644 index 1c1b74950c..0000000000 --- a/mullvad_daemon/src/frontend_ipc_router.rs +++ /dev/null @@ -1,145 +0,0 @@ -extern crate jsonrpc_core; -extern crate serde_json; - -use serde; - -static mut MOCK_IS_CONNECTED: bool = false; -type Result<T> = ::std::result::Result<T, String>; - -pub fn build_router() -> jsonrpc_core::IoHandler { - let mut router = jsonrpc_core::IoHandler::default(); - - add_route(&mut router, "login", mock_login); - add_route(&mut router, "logout", mock_logout); - add_route(&mut router, "connect", mock_connect); - add_route(&mut router, "disconnect", mock_disconnect); - add_route(&mut router, "get_connection", mock_get_connection_info); - add_route(&mut router, "get_location", mock_get_location); - - router -} - -fn add_route<T, U, F>(router: &mut jsonrpc_core::IoHandler, method: &str, handler: F) - where for<'de> T: serde::Deserialize<'de>, - U: serde::Serialize + 'static, - F: Fn(&T) -> Result<U> + Send + Sync + 'static -{ - let c = move |params: jsonrpc_core::params::Params| { - println!("Got rpc request with params {:?}", params); - let parsed_params: T = params.parse()?; - - let response: U = handler(&parsed_params) - .map_err( - |e| { - error!("Failed responding to RPC request: {}", e); - jsonrpc_core::Error::internal_error() - }, - )?; - - serde_json::to_value(response).map_err( - |e| { - error!("Unable to serialize response to RPC request: {}", e); - jsonrpc_core::Error::internal_error() - }, - ) - }; - router.add_method(method, c); -} - -#[derive(Deserialize)] -struct LoginRequest { - #[serde(rename = "accountNumber")] - account_number: String, -} -fn mock_login(request: &LoginRequest) -> Result<::std::collections::HashMap<String, String>> { - let ref account_number = request.account_number; - - let mut reply = ::std::collections::HashMap::new(); - - if account_number.starts_with("1111") { - // accounts starting with 1111 expire in one month - reply.insert( - "paidUntil".to_owned(), - "2018-12-31T16:00:00.000Z".to_owned(), - ); - // res.paidUntil = moment().startOf('day').add(15, 'days').toISOString(); - } else if account_number.starts_with("2222") { - // expired in 2013 - reply.insert( - "paidUntil".to_owned(), - "2012-12-31T16:00:00.000Z".to_owned(), - ); - } else if account_number.starts_with("3333") { - // expire in 2038 - reply.insert( - "paidUntil".to_owned(), - "2037-12-31T16:00:00.000Z".to_owned(), - ); - } else { - bail!("you are not welcome {}!", account_number) - } - - Ok(reply) -} - -fn mock_logout(_: &()) -> Result<()> { - Ok(()) -} - -#[derive(Deserialize)] -struct ConnectRequest { - address: String, -} -fn mock_connect(request: &ConnectRequest) -> Result<()> { - let ref server_address = request.address; - if server_address.starts_with("se") { - bail!("{} is unreachable", server_address) - } - - unsafe { MOCK_IS_CONNECTED = true }; - Ok(()) -} - -fn mock_disconnect(_: &()) -> Result<()> { - unsafe { MOCK_IS_CONNECTED = false }; - Ok(()) -} - -#[derive(Serialize)] -struct ConnectionInfo { - ip: String, -} -fn mock_get_connection_info(_: &()) -> Result<ConnectionInfo> { - let ip = if unsafe { MOCK_IS_CONNECTED } { - "1.2.3.4" - } else { - "192.168.1.2" - } - .to_owned(); - - Ok(ConnectionInfo { ip: ip }) -} - -#[derive(Serialize)] -struct Location { - latlong: [u32; 2], - country: String, - city: String, -} -fn mock_get_location(_: &()) -> Result<Location> { - let response = if unsafe { MOCK_IS_CONNECTED } { - Location { - latlong: [1, 2], - country: "narnia".to_owned(), - city: "Le city".to_owned(), - } - } else { - Location { - latlong: [60, 61], - country: "sweden".to_owned(), - city: "bollebygd".to_owned(), - } - }; - - Ok(response) -} diff --git a/mullvad_daemon/src/ipc_api.rs b/mullvad_daemon/src/ipc_api.rs new file mode 100644 index 0000000000..84932a0b8f --- /dev/null +++ b/mullvad_daemon/src/ipc_api.rs @@ -0,0 +1,90 @@ +use jsonrpc_core::Error; +use jsonrpc_core::futures::BoxFuture; +use jsonrpc_macros::pubsub; +use jsonrpc_pubsub::SubscriptionId; + +use std::collections::HashMap; +use std::net::IpAddr; + +pub type AccountToken = String; +pub type CountryCode = String; + +build_rpc_trait! { + pub trait IpcApi { + type Metadata; + + /// Fetches and returns metadata about an account. Returns an error on non-existing + /// accounts. + #[rpc(name = "get_account_data")] + fn get_account_data(&self, AccountToken) -> Result<AccountData, Error>; + + /// Returns available countries. + #[rpc(name = "get_countries")] + fn get_countries(&self) -> Result<HashMap<CountryCode, String>, Error>; + + /// Set which account to connect with + #[rpc(name = "set_account")] + fn set_account(&self, AccountToken) -> Result<(), Error>; + + /// Set which country to connect to + #[rpc(name = "set_country")] + fn set_country(&self, CountryCode) -> Result<(), Error>; + + /// Set if the backend should automatically establish a tunnel on start or not. + #[rpc(name = "set_autoconnect")] + fn set_autoconnect(&self, bool) -> Result<(), Error>; + + /// Try to connect if disconnected, or do nothing if already connecting/connected. + #[rpc(name = "connect")] + fn connect(&self) -> Result<(), Error>; + + /// Disconnect the VPN tunnel if it is connecting/connected. Does nothing if already + /// disconnected. + #[rpc(name = "disconnect")] + fn disconnect(&self) -> Result<(), Error>; + + /// Returns the current security state of the Mullvad client. Changes to this state will + /// be announced to subscribers of `event`. + #[rpc(name = "get_state")] + fn get_state(&self) -> Result<SecurityState, Error>; + + /// Returns the current public IP of this computer. + #[rpc(name = "get_ip")] + fn get_ip(&self) -> Result<IpAddr, Error>; + + /// Performs a geoIP lookup and returns the current location as perceived by the public + /// internet. + #[rpc(name = "get_location")] + fn get_location(&self) -> Result<Location, Error>; + + #[pubsub(name = "event")] { + /// Subscribes to the `event` notifications. + #[rpc(name = "event_subscribe")] + fn subscribe(&self, Self::Metadata, pubsub::Subscriber<String>); + + /// Unsubscribes from the `event` notifications. + #[rpc(name = "event_unsubscribe")] + fn unsubscribe(&self, SubscriptionId) -> BoxFuture<bool, Error>; + } + } +} + +#[derive(Serialize)] +pub struct AccountData { + pub paid_until: String, +} + +#[derive(Serialize)] +pub struct Location { + pub latlong: [f64; 2], + pub country: String, + pub city: String, +} + +#[derive(Serialize)] +pub enum SecurityState { + Unsecured, + Securing, + Secured, + Unsecuring, +} diff --git a/mullvad_daemon/src/main.rs b/mullvad_daemon/src/main.rs index ff4b62dcb3..5bd9563bfd 100644 --- a/mullvad_daemon/src/main.rs +++ b/mullvad_daemon/src/main.rs @@ -3,12 +3,21 @@ extern crate log; extern crate env_logger; #[macro_use] extern crate error_chain; + extern crate serde; #[macro_use] extern crate serde_derive; + extern crate talpid_ipc; -mod frontend_ipc_router; +extern crate jsonrpc_core; +extern crate jsonrpc_pubsub; +#[macro_use] +extern crate jsonrpc_macros; +extern crate jsonrpc_ws_server; + +pub mod ipc_api; +pub mod mock_ipc; error_chain!{} @@ -16,21 +25,19 @@ quick_main!(run); fn run() -> Result<()> { init_logger()?; - let _server = start_ipc()?; - main_loop() + + let server = start_ipc()?; + main_loop(server) } fn init_logger() -> Result<()> { env_logger::init().chain_err(|| "Failed to bootstrap logging system") } -fn start_ipc() -> Result<talpid_ipc::IpcServer> { - talpid_ipc::IpcServer::start(frontend_ipc_router::build_router().into(), 0) - .chain_err(|| "Failed to start IPC server") +fn start_ipc() -> Result<mock_ipc::IpcServer> { + mock_ipc::IpcServer::start().chain_err(|| "Failed to start IPC server") } -fn main_loop() -> Result<()> { - let (_tx, rx) = ::std::sync::mpsc::channel::<u8>(); - let _ = rx.recv(); - Ok(()) +fn main_loop(server: mock_ipc::IpcServer) -> Result<()> { + server.wait().chain_err(|| "Error while waiting for server to process") } diff --git a/mullvad_daemon/src/mock_ipc.rs b/mullvad_daemon/src/mock_ipc.rs new file mode 100644 index 0000000000..e490357741 --- /dev/null +++ b/mullvad_daemon/src/mock_ipc.rs @@ -0,0 +1,230 @@ +use ipc_api::*; + +use jsonrpc_core::{self, Error, ErrorCode, Metadata}; +use jsonrpc_core::futures::{BoxFuture, Future, future}; +use jsonrpc_macros::pubsub; +use jsonrpc_pubsub::{PubSubHandler, PubSubMetadata, Session, SubscriptionId}; +use jsonrpc_ws_server; + +use std::collections::HashMap; +use std::net::{IpAddr, Ipv4Addr}; +use std::sync::{Arc, RwLock, atomic}; + +use talpid_ipc; + +type ActiveSubscriptions = Arc<RwLock<HashMap<SubscriptionId, pubsub::Sink<String>>>>; + +pub struct IpcServer { + server: talpid_ipc::IpcServer, +} + +impl IpcServer { + pub fn start() -> talpid_ipc::Result<Self> { + let active_subscriptions = ActiveSubscriptions::default(); + let mut last_error = None; + for i in 0..10 { + match Self::try_start(active_subscriptions.clone(), i) { + Ok(server) => { + Self::spawn_broadcast_thread(active_subscriptions); + return Ok(IpcServer { server }); + } + Err(e) => last_error = Some(e), + } + } + bail!(last_error.unwrap()); + } + + pub fn address(&self) -> &str { + &self.server.address() + } + + pub fn wait(self) -> talpid_ipc::Result<()> { + self.server.wait() + } + + fn try_start(active_subscriptions: ActiveSubscriptions, + port_offset: u8) + -> talpid_ipc::Result<talpid_ipc::IpcServer> { + let rpc = MockIpcApi::new(active_subscriptions); + let mut io = PubSubHandler::default(); + io.extend_with(rpc.to_delegate()); + talpid_ipc::IpcServer::start_with_metadata(io.into(), meta_extractor, port_offset) + } + + // TODO(linus): This thread will never die. But this is just mock anyway so not important. + fn spawn_broadcast_thread(active_subscriptions: ActiveSubscriptions) { + ::std::thread::spawn( + move || loop { + { + let subscribers = active_subscriptions.read().unwrap(); + for sink in subscribers.values() { + let _ = sink.notify(Ok("Hello World!".into())).wait(); + } + } + ::std::thread::sleep(::std::time::Duration::from_secs(1)); + }, + ); + } +} + + + +/// The metadata type. There is one instance associated with each connection. In this pubsub +/// scenario they are created by `From<Sender<String>>::from` by the server on each new incoming +/// connection. +#[derive(Clone, Debug, Default)] +pub struct Meta { + session: Option<Arc<Session>>, +} + +/// Make the `Meta` type possible to use as jsonrpc metadata type. +impl Metadata for Meta {} + +/// Make the `Meta` type possible to use as a pubsub metadata type. +impl PubSubMetadata for Meta { + fn session(&self) -> Option<Arc<Session>> { + self.session.clone() + } +} + +/// Metadata extractor function for `Meta`. +fn meta_extractor(context: &jsonrpc_ws_server::RequestContext) -> Meta { + Meta { session: Some(Arc::new(Session::new(context.sender()))) } +} + +/// A mock implementation of the Mullvad frontend API. A very simplified explanation is that for +/// the real implementation `tunnel_is_up` should be replaced with some kind of handle (or proxy to +/// a handle) to the jsonrpc client talking with talpid_core. +pub struct MockIpcApi { + next_subscription_id: atomic::AtomicUsize, + active: ActiveSubscriptions, + country: RwLock<CountryCode>, + tunnel_is_up: atomic::AtomicBool, +} + +impl MockIpcApi { + pub fn new(active: ActiveSubscriptions) -> Self { + MockIpcApi { + next_subscription_id: atomic::AtomicUsize::new(0), + active: active, + country: RwLock::new("se".to_owned()), + tunnel_is_up: atomic::AtomicBool::new(false), + } + } +} + +impl IpcApi for MockIpcApi { + type Metadata = Meta; + + fn get_account_data(&self, account_token: AccountToken) -> Result<AccountData, Error> { + debug!("Login for {}", account_token); + + let paid_until = if account_token.starts_with("1111") { + // accounts starting with 1111 expire in one month + Ok("2018-12-31T16:00:00.000Z".to_owned()) + } else if account_token.starts_with("2222") { + Ok("2012-12-31T16:00:00.000Z".to_owned()) + } else if account_token.starts_with("3333") { + Ok("2037-12-31T16:00:00.000Z".to_owned()) + } else { + Err(jsonrpc_core::Error::invalid_params("You are not welcome")) + }?; + Ok(AccountData { paid_until: paid_until }) + } + + fn get_countries(&self) -> Result<HashMap<CountryCode, String>, Error> { + let mut countries = HashMap::new(); + countries.insert("se".to_owned(), "Sweden".to_owned()); + countries.insert("de".to_owned(), "Denmark".to_owned()); + countries.insert("na".to_owned(), "Narnia".to_owned()); + Ok(countries) + } + + fn set_account(&self, _account_token: AccountToken) -> Result<(), Error> { + Ok(()) + } + + fn set_country(&self, country_code: CountryCode) -> Result<(), Error> { + *self.country.write().unwrap() = country_code; + Ok(()) + } + + fn set_autoconnect(&self, _autoconnect: bool) -> Result<(), Error> { + Ok(()) + } + + fn connect(&self) -> Result<(), Error> { + if self.country.read().unwrap().starts_with("se") { + Err(jsonrpc_core::Error::invalid_params("Invalid server")) + } else { + self.tunnel_is_up.store(true, atomic::Ordering::SeqCst); + Ok(()) + } + } + + fn disconnect(&self) -> Result<(), Error> { + self.tunnel_is_up.store(false, atomic::Ordering::SeqCst); + Ok(()) + } + + fn get_state(&self) -> Result<SecurityState, Error> { + if self.tunnel_is_up.load(atomic::Ordering::SeqCst) { + Ok(SecurityState::Secured) + } else { + Ok(SecurityState::Unsecured) + } + } + + fn get_ip(&self) -> Result<IpAddr, Error> { + let ip = if self.tunnel_is_up.load(atomic::Ordering::SeqCst) { + IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)) + } else { + IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2)) + } + .to_owned(); + Ok(ip) + } + + fn get_location(&self) -> Result<Location, Error> { + Ok( + if self.tunnel_is_up.load(atomic::Ordering::SeqCst) { + Location { + latlong: [1.0, 2.0], + country: "narnia".to_owned(), + city: "Le city".to_owned(), + } + } else { + Location { + latlong: [60.0, 61.0], + country: "sweden".to_owned(), + city: "bollebygd".to_owned(), + } + }, + ) + } + + fn subscribe(&self, _meta: Self::Metadata, subscriber: pubsub::Subscriber<String>) { + let id = self.next_subscription_id.fetch_add(1, atomic::Ordering::SeqCst); + let sub_id = SubscriptionId::Number(id as u64); + if let Ok(sink) = subscriber.assign_id(sub_id.clone()) { + debug!("Accepting new subscription with id {}", id); + self.active.write().unwrap().insert(sub_id, sink); + } + } + + fn unsubscribe(&self, id: SubscriptionId) -> BoxFuture<bool, Error> { + debug!("Unsubscribing id {:?}", id); + if self.active.write().unwrap().remove(&id).is_some() { + future::ok(true).boxed() + } else { + future::err( + Error { + code: ErrorCode::InvalidParams, + message: "Invalid subscription.".into(), + data: None, + }, + ) + .boxed() + } + } +} diff --git a/talpid_ipc/src/lib.rs b/talpid_ipc/src/lib.rs index d1f1b816bd..bad341bb32 100644 --- a/talpid_ipc/src/lib.rs +++ b/talpid_ipc/src/lib.rs @@ -87,10 +87,12 @@ impl IpcServer { &self.address } + /// Consumes the server, stops it and waits for it to finish. pub fn stop(self) { self.server.close(); } + /// Consumes the server and waits for it to finish. pub fn wait(self) -> Result<()> { self.server.wait().chain_err(|| ErrorKind::IpcServerError) } |
