use routing::{
Authority, Client, ClientError, Event, FullId, ImmutableData, MessageId, MutableData, Response,
Value, XorName,
};
use rust_sodium::crypto;
use std::collections::BTreeMap;
use std::sync::mpsc::{self, Receiver};
use std::thread;
use std::time::Duration;
const RESPONSE_TIMEOUT_SECS: u64 = 10;
macro_rules! recv_response {
($client:expr, $resp:ident, $data_id:expr, $req_msg_id:expr) => {
loop {
match $client
.receiver
.recv_timeout(Duration::from_secs(RESPONSE_TIMEOUT_SECS))
{
Ok(Event::Response {
response: Response::$resp { res, msg_id },
..
}) => {
if $req_msg_id != msg_id {
error!(
"{} response for {:?}, but with wrong message_id {:?} \
instead of {:?}.",
stringify!($resp),
$data_id,
msg_id,
$req_msg_id
);
return Err(ClientError::from("Wrong message_id"));
}
if let Err(ref error) = res {
error!(
"{} for {:?} failed: {:?}",
stringify!($resp),
$data_id,
error
);
} else {
trace!("{} for {:?} successful", stringify!($resp), $data_id)
}
return res;
}
Ok(Event::Terminate) | Ok(Event::RestartRequired) => $client.disconnected(),
Ok(_) => (),
Err(_) => return Err(ClientError::from("No response")),
}
}
};
}
pub struct ExampleClient {
client: Client,
receiver: Receiver<Event>,
full_id: FullId,
}
impl ExampleClient {
pub fn new() -> ExampleClient {
let (sender, receiver) = mpsc::channel::<Event>();
let sign_keys = crypto::sign::gen_keypair();
let encrypt_keys = crypto::box_::gen_keypair();
let full_id = FullId::with_keys(encrypt_keys.clone(), sign_keys.clone());
let mut client;
'outer: loop {
client = unwrap!(Client::new(
sender.clone(),
Some(full_id.clone()),
None,
Duration::from_secs(90),
));
for event in receiver.iter() {
match event {
Event::Connected => {
println!("Client Connected to the network");
break 'outer;
}
Event::Terminate => {
println!("Client failed to connect to the network. Restarting.");
thread::sleep(Duration::from_secs(5));
break;
}
_ => (),
}
}
}
ExampleClient {
client: client,
receiver: receiver,
full_id: full_id,
}
}
#[allow(unused)]
pub fn get_idata(&mut self, name: XorName) -> Result<ImmutableData, ClientError> {
let msg_id = MessageId::new();
unwrap!(
self.client
.get_idata(Authority::NaeManager(name), name, msg_id,)
);
recv_response!(self, GetIData, name, msg_id)
}
#[allow(unused)]
pub fn put_idata(&mut self, data: ImmutableData) -> Result<(), ClientError> {
let dst = Authority::ClientManager(*self.name());
let name = *data.name();
let msg_id = MessageId::new();
unwrap!(self.client.put_idata(dst, data, msg_id));
recv_response!(self, PutMData, name, msg_id)
}
#[allow(unused)]
pub fn get_mdata_shell(&mut self, name: XorName, tag: u64) -> Result<MutableData, ClientError> {
let msg_id = MessageId::new();
unwrap!(
self.client
.get_mdata_shell(Authority::NaeManager(name), name, tag, msg_id,)
);
recv_response!(self, GetMDataShell, name, msg_id)
}
#[allow(unused)]
pub fn list_mdata_entries(
&mut self,
name: XorName,
tag: u64,
) -> Result<BTreeMap<Vec<u8>, Value>, ClientError> {
let msg_id = MessageId::new();
unwrap!(
self.client
.list_mdata_entries(Authority::NaeManager(name), name, tag, msg_id,)
);
recv_response!(self, ListMDataEntries, name, msg_id)
}
#[allow(unused)]
pub fn get_mdata_value(
&mut self,
name: XorName,
tag: u64,
key: Vec<u8>,
) -> Result<Value, ClientError> {
let msg_id = MessageId::new();
unwrap!(
self.client
.get_mdata_value(Authority::NaeManager(name), name, tag, key, msg_id,)
);
recv_response!(self, GetMDataValue, name, msg_id)
}
pub fn put_mdata(&mut self, data: MutableData) -> Result<(), ClientError> {
let dst = Authority::ClientManager(*self.name());
let name = *data.name();
let tag = data.tag();
let msg_id = MessageId::new();
let requester = *self.signing_public_key();
unwrap!(self.client.put_mdata(dst, data, msg_id, requester));
recv_response!(self, PutMData, (name, tag), msg_id)
}
fn disconnected(&self) {
panic!("Disconnected from the network.");
}
pub fn name(&self) -> &XorName {
self.full_id.public_id().name()
}
pub fn signing_public_key(&self) -> &crypto::sign::PublicKey {
self.full_id.public_id().signing_public_key()
}
}
impl Default for ExampleClient {
fn default() -> ExampleClient {
ExampleClient::new()
}
}