summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-03-07 07:19:30 +0100
committerLinus Färnstrand <linus@mullvad.net>2017-03-07 07:19:30 +0100
commit6fbf16b682fe6c399e5c7f5d5f4a8f96a5071093 (patch)
tree522a35c6d9c6577d9b8016159382c4cb035900c4
parentc354d79ea9634f77eb1a58b3c22d9e8f8229454f (diff)
parenta84b3c4086459a1fed5dfe7b4dc1359056e156d0 (diff)
downloadmullvadvpn-6fbf16b682fe6c399e5c7f5d5f4a8f96a5071093.tar.xz
mullvadvpn-6fbf16b682fe6c399e5c7f5d5f4a8f96a5071093.zip
Merge branch 'serde'
-rw-r--r--Cargo.lock38
-rw-r--r--talpid_ipc/Cargo.toml2
-rw-r--r--talpid_ipc/src/lib.rs12
-rw-r--r--talpid_ipc/src/nop_ipc.rs26
-rw-r--r--talpid_ipc/src/zmq_ipc.rs76
-rw-r--r--talpid_ipc/tests/zmq_integration_tests.rs26
6 files changed, 128 insertions, 52 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a7edc49b38..63d6b95fa8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -92,6 +92,11 @@ dependencies = [
]
[[package]]
+name = "dtoa"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "env_logger"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -119,6 +124,11 @@ version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "itoa"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -156,6 +166,11 @@ dependencies = [
]
[[package]]
+name = "num-traits"
+version = "0.1.37"
+source = "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"
@@ -183,6 +198,22 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "serde"
+version = "0.9.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_json"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (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"
@@ -213,6 +244,8 @@ version = "0.1.0"
dependencies = [
"assert_matches 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
"zmq 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -322,19 +355,24 @@ dependencies = [
"checksum clap 2.20.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f89819450aa94325998aa83ce7ea142db11ad24c725d6bc48459845e0d6d9f18"
"checksum clonablechild 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4a4946a850c1e921fbdd9a1f92bf1298c41a301c0f6e9bacbabf95ea7d6d0225"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46"
"checksum gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "291055c78f59ca3d84c99026c9501c469413d386bb46be1e1cf1d285cd1db3b0"
+"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151"
+"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
+"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
+"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71662702fe5cd2cf95edd4ad655eea42f24a87a0e44059cbaa4e55260b7bc331"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
diff --git a/talpid_ipc/Cargo.toml b/talpid_ipc/Cargo.toml
index 6bacc0f9a7..369abcb128 100644
--- a/talpid_ipc/Cargo.toml
+++ b/talpid_ipc/Cargo.toml
@@ -6,6 +6,8 @@ description = "IPC client and server for talpid"
[dependencies]
error-chain = "0.8"
+serde = "0.9"
+serde_json = "0.9"
[target.'cfg(not(windows))'.dependencies]
zmq = "0.8"
diff --git a/talpid_ipc/src/lib.rs b/talpid_ipc/src/lib.rs
index 324fb36f05..8698adb55c 100644
--- a/talpid_ipc/src/lib.rs
+++ b/talpid_ipc/src/lib.rs
@@ -1,6 +1,8 @@
#[macro_use]
extern crate error_chain;
+extern crate serde;
+
#[cfg(windows)]
#[path = "nop_ipc.rs"]
mod ipc_impl;
@@ -11,23 +13,21 @@ mod ipc_impl;
pub use self::ipc_impl::*;
-/// The type signature for functions accepting messages from the server.
-/// If the server fails in delivering the message for any reason it will
-/// put the cause in the Err part of the `Result`.
-pub type OnMessage<MessageType> = FnMut(Result<MessageType>) + Send + 'static;
/// An Id created by the Ipc server that the client can use to connect to it
-type IpcServerId = String;
+pub type IpcServerId = String;
error_chain!{
errors {
ReadFailure {
description("Could not read IPC message")
}
+ ParseFailure {
+ description("Unable to serialize/deserialize message")
+ }
CouldNotStartServer {
description("Failed to start the IPC server")
}
-
SendError {
description("Unable to send message")
}
diff --git a/talpid_ipc/src/nop_ipc.rs b/talpid_ipc/src/nop_ipc.rs
index 8faa58ea34..9a767f229d 100644
--- a/talpid_ipc/src/nop_ipc.rs
+++ b/talpid_ipc/src/nop_ipc.rs
@@ -1,4 +1,6 @@
-use super::{OnMessage, ErrorKind, Result, IpcServerId};
+use super::{ErrorKind, Result, IpcServerId};
+
+use serde;
/// This implementation only exists because we cannot get ZeroMQ to work on
/// Windows. This is not a valid IPC implementation and us using
@@ -6,17 +8,27 @@ use super::{OnMessage, ErrorKind, Result, IpcServerId};
///
/// We plan on trying with ZMQ again in the future.
/// Erik, 2017-02-09
-fn start_new_server(_on_message: Box<OnMessage<Vec<u8>>>) -> Result<IpcServerId> {
+pub fn start_new_server<T, F>(_on_message: F) -> Result<IpcServerId>
+ where T: serde::Deserialize + 'static,
+ F: FnMut(Result<T>) + Send + 'static
+{
Err(ErrorKind::CouldNotStartServer.into())
}
-pub struct IpcClient;
-impl IpcClient {
- pub fn new(server_id: IpcServerId) -> Self {
- IpcClient
+pub struct IpcClient<T>
+ where T: serde::Serialize
+{
+ _phantom: ::std::marker::PhantomData<T>,
+}
+
+impl<T> IpcClient<T>
+ where T: serde::Serialize
+{
+ pub fn new(_server_id: IpcServerId) -> Self {
+ IpcClient { _phantom: ::std::marker::PhantomData }
}
- pub fn send(mut self, message: &[u8]) -> Result<()> {
+ pub fn send(&mut self, _message: &T) -> Result<()> {
Err(ErrorKind::SendError.into())
}
}
diff --git a/talpid_ipc/src/zmq_ipc.rs b/talpid_ipc/src/zmq_ipc.rs
index b7e77a15c4..f0111af254 100644
--- a/talpid_ipc/src/zmq_ipc.rs
+++ b/talpid_ipc/src/zmq_ipc.rs
@@ -1,21 +1,24 @@
extern crate zmq;
+extern crate serde_json;
+
+use super::{ErrorKind, Result, ResultExt, IpcServerId};
+
+use serde;
-use super::{OnMessage, ErrorKind, Result, ResultExt, IpcServerId};
use std::thread;
-/// Starts listening to incoming IPC connections on a random port.
-/// Messages are sent to the `on_message` callback. If anything went wrong
-/// when reading the message, the message will be an `Err`.
-/// NOTE that this does not apply to errors regarding whether the server
-/// could start or not, those are returned directly by this function.
+/// Starts the server end of an IPC channel. The returned `IpcServerId` is the unique identifier
+/// allowing an `IpcClient` to connect to this server instance. Returns an error if unable to set
+/// up the server.
///
-/// This function is non-blocking and thus spawns a thread where it
-/// listens to messages.
+/// Incoming messages are sent as `Ok` results to the `on_message` callback. IO errors will be sent
+/// as `Err` results to the `on_message` callback.
///
-/// The value returned from this function should be used by the clients to
-/// the server.
-pub fn start_new_server(on_message: Box<OnMessage<Vec<u8>>>) -> Result<IpcServerId> {
-
+/// This function is non-blocking and thus spawns a thread where it listens to messages.
+pub fn start_new_server<T, F>(on_message: F) -> Result<IpcServerId>
+ where T: serde::Deserialize + 'static,
+ F: FnMut(Result<T>) + Send + 'static
+{
for port in 5000..5010 {
let connection_string = format!("tcp://127.0.0.1:{}", port);
if let Ok(socket) = start_zmq_server(&connection_string) {
@@ -36,29 +39,54 @@ fn start_zmq_server(connection_string: &str) -> zmq::Result<zmq::Socket> {
Ok(socket)
}
-fn start_receive_loop(socket: zmq::Socket,
- mut on_message: Box<OnMessage<Vec<u8>>>)
- -> thread::JoinHandle<()> {
-
+fn start_receive_loop<T, F>(socket: zmq::Socket, mut on_message: F) -> thread::JoinHandle<()>
+ where T: serde::Deserialize + 'static,
+ F: FnMut(Result<T>) + Send + 'static
+{
thread::spawn(move || loop {
- let read_res = socket.recv_bytes(0).chain_err(|| ErrorKind::ReadFailure);
+ let read_res = socket.recv_bytes(0)
+ .chain_err(|| ErrorKind::ReadFailure)
+ .and_then(|a| parse_message(&a));
on_message(read_res);
})
}
-pub struct IpcClient {
- server_address: IpcServerId,
+fn parse_message<T>(message: &[u8]) -> Result<T>
+ where T: serde::Deserialize + 'static
+{
+ serde_json::from_slice(message).chain_err(|| ErrorKind::ParseFailure)
+}
+
+
+pub struct IpcClient<T>
+ where T: serde::Serialize
+{
+ server_id: IpcServerId,
socket: Option<zmq::Socket>,
+ _phantom: ::std::marker::PhantomData<T>,
}
-impl IpcClient {
+
+impl<T> IpcClient<T>
+ where T: serde::Serialize
+{
pub fn new(server_id: IpcServerId) -> Self {
IpcClient {
- server_address: server_id,
+ server_id: server_id,
socket: None,
+ _phantom: ::std::marker::PhantomData,
}
}
- pub fn send(&mut self, message: &[u8]) -> Result<()> {
+ pub fn send(&mut self, message: &T) -> Result<()> {
+ let bytes = Self::serialize(message)?;
+ self.send_bytes(bytes.as_slice())
+ }
+
+ fn serialize(t: &T) -> Result<Vec<u8>> {
+ serde_json::to_vec(t).chain_err(|| ErrorKind::ParseFailure)
+ }
+
+ fn send_bytes(&mut self, message: &[u8]) -> Result<()> {
if self.socket.is_none() {
self.connect().chain_err(|| ErrorKind::SendError)?;
}
@@ -71,8 +99,8 @@ impl IpcClient {
let ctx = zmq::Context::new();
let socket = ctx.socket(zmq::PUSH)
.chain_err(|| "Could not create ZeroMQ PUSH socket".to_owned())?;
- socket.connect(&self.server_address)
- .chain_err(|| format!("Could not connect to {:?}", self.server_address))?;
+ socket.connect(&self.server_id)
+ .chain_err(|| format!("Could not connect to {:?}", self.server_id))?;
self.socket = Some(socket);
Ok(())
diff --git a/talpid_ipc/tests/zmq_integration_tests.rs b/talpid_ipc/tests/zmq_integration_tests.rs
index 07469a8f50..498c3af820 100644
--- a/talpid_ipc/tests/zmq_integration_tests.rs
+++ b/talpid_ipc/tests/zmq_integration_tests.rs
@@ -1,38 +1,34 @@
-#[macro_use]
-extern crate error_chain;
-
-#[macro_use]
-extern crate assert_matches;
-
#[cfg(all(test, not(windows)))]
mod zmq_integration_tests {
+ extern crate serde;
extern crate talpid_ipc;
- extern crate zmq;
- use self::talpid_ipc::{Result, IpcClient};
+ use self::talpid_ipc::{Result, IpcServerId, IpcClient};
+
use std::sync::mpsc::{self, Receiver};
use std::time::Duration;
#[test]
fn can_connect_and_send_and_receive_messages() {
- let (connection_string, new_messages_rx) = start_server();
+ let (connection_string, new_messages_rx) = start_server::<String>();
let mut ipc_client = IpcClient::new(connection_string);
- ipc_client.send(&[1, 3, 3, 7]).expect("Could not send message");
+ let msg = "Hello".to_owned();
+ ipc_client.send(&msg).expect("Could not send message");
let message = new_messages_rx.recv_timeout(Duration::from_millis(1000))
.expect("Did not receive a message");
- assert_eq!(message.unwrap(),
- &[1, 3, 3, 7],
- "Read data does not match sent data");
+ assert_eq!(message.unwrap(), "Hello", "Got wrong message");
}
- fn start_server() -> (String, Receiver<Result<Vec<u8>>>) {
+ fn start_server<T>() -> (IpcServerId, Receiver<Result<T>>)
+ where T: serde::Deserialize + Send + 'static
+ {
let (tx, rx) = mpsc::channel();
let connection_string =
- talpid_ipc::start_new_server(Box::new(move |message| { let _ = tx.send(message); }))
+ talpid_ipc::start_new_server(move |message: Result<T>| { let _ = tx.send(message); })
.expect("Could not start the server");
(connection_string, rx)