use maidsafe_utilities::event_sender;
use std::cell::{RefCell, RefMut};
use std::fmt;
use std::io;
use std::rc::Rc;
use super::support::{self, Endpoint, Network, ServiceHandle, ServiceImpl};
pub const DEFAULT_BEACON_PORT: u16 = 5484;
pub struct Service(Rc<RefCell<ServiceImpl>>, Network);
impl Service {
pub fn new(event_sender: CrustEventSender) -> Result<Self, Error> {
Self::with_handle(&support::get_current(), event_sender, DEFAULT_BEACON_PORT)
}
pub fn with_handle(handle: &ServiceHandle,
event_sender: CrustEventSender,
beacon_port: u16)
-> Result<Self, Error> {
let network = handle.0.borrow().network.clone();
let service = Service(handle.0.clone(), network);
service.lock_and_poll(|imp| imp.start(event_sender, beacon_port));
Ok(service)
}
pub fn restart(&self, event_sender: CrustEventSender) {
self.lock_and_poll(|imp| imp.restart(event_sender, DEFAULT_BEACON_PORT))
}
pub fn stop_bootstrap(&self) {
}
pub fn start_service_discovery(&mut self) {
trace!("[MOCK] start_service_discovery not implemented in mock");
}
pub fn start_listening_tcp(&mut self) -> io::Result<()> {
self.lock().listening_tcp = true;
Ok(())
}
pub fn start_listening_utp(&mut self) -> io::Result<()> {
self.lock().listening_udp = true;
Ok(())
}
pub fn prepare_connection_info(&mut self, result_token: u32) {
self.lock_and_poll(|imp| imp.prepare_connection_info(result_token))
}
pub fn connect(&self, our_info: OurConnectionInfo, their_info: TheirConnectionInfo) {
self.lock_and_poll(|imp| imp.connect(our_info, their_info))
}
pub fn disconnect(&self, peer_id: &PeerId) -> bool {
self.lock_and_poll(|imp| imp.disconnect(peer_id))
}
pub fn send(&self, id: &PeerId, data: Vec<u8>) -> io::Result<()> {
if self.lock_and_poll(|imp| imp.send_message(id, data)) {
Ok(())
} else {
let msg = format!("No connection to peer {:?}", id);
Err(io::Error::new(io::ErrorKind::Other, msg))
}
}
pub fn id(&self) -> PeerId {
self.lock().peer_id
}
fn lock(&self) -> RefMut<ServiceImpl> {
self.0.borrow_mut()
}
fn lock_and_poll<F, R>(&self, f: F) -> R
where F: FnOnce(&mut ServiceImpl) -> R
{
let result = f(&mut *self.lock());
self.1.poll();
result
}
}
impl Drop for Service {
fn drop(&mut self) {
self.lock_and_poll(|imp| imp.disconnect_all());
}
}
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
pub struct PeerId(pub usize, pub u64);
impl fmt::Debug for PeerId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "PeerId({})", self.0)
}
}
#[derive(Debug)]
pub enum Event {
NewMessage(PeerId, Vec<u8>),
BootstrapConnect(PeerId),
BootstrapAccept(PeerId),
NewPeer(io::Result<()>, PeerId),
LostPeer(PeerId),
BootstrapFinished,
ConnectionInfoPrepared(ConnectionInfoResult),
}
pub type CrustEventSender = event_sender::MaidSafeObserver<Event>;
#[derive(Debug)]
pub struct OurConnectionInfo(pub PeerId, pub Endpoint);
impl OurConnectionInfo {
pub fn to_their_connection_info(&self) -> TheirConnectionInfo {
TheirConnectionInfo(self.0, self.1)
}
}
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct TheirConnectionInfo(pub PeerId, pub Endpoint);
impl TheirConnectionInfo {
pub fn id(&self) -> PeerId {
self.0
}
}
#[derive(Debug)]
pub struct ConnectionInfoResult {
pub result_token: u32,
pub result: io::Result<OurConnectionInfo>,
}
#[derive(Debug)]
pub struct Error;