use maidsafe_utilities::event_sender;
use std::cell::{RefCell, RefMut};
use std::collections::HashSet;
use std::fmt;
use std::io;
use std::net::SocketAddr;
use std::rc::Rc;
use super::support::{self, Endpoint, Network, ServiceHandle, ServiceImpl};
pub const LISTENER_PORT: u16 = 5485;
pub struct Service(Rc<RefCell<ServiceImpl>>, Network);
impl Service {
pub fn new(event_sender: CrustEventSender) -> Result<Self, CrustError> {
Self::with_handle(&support::get_current(), event_sender)
}
pub fn with_handle(handle: &ServiceHandle,
event_sender: CrustEventSender)
-> Result<Self, CrustError> {
let network = handle.0.borrow().network.clone();
let service = Service(handle.0.clone(), network);
service.lock_and_poll(|imp| imp.start(event_sender));
Ok(service)
}
pub fn restart(&self, event_sender: CrustEventSender) {
self.lock_and_poll(|imp| imp.restart(event_sender))
}
pub fn start_bootstrap(&mut self, blacklist: HashSet<SocketAddr>) -> Result<(), CrustError> {
self.lock_and_poll(|imp| imp.start_bootstrap(blacklist));
Ok(())
}
pub fn stop_bootstrap(&mut self) -> Result<(), CrustError> {
Ok(())
}
pub fn start_service_discovery(&mut self) {
trace!("[MOCK] start_service_discovery not implemented in mock");
}
pub fn set_service_discovery_listen(&self, _listen: bool) {
trace!("[MOCK] set_service_discovery_listen not implemented in mock");
}
pub fn has_peers_on_lan(&self) -> bool {
false
}
pub fn start_listening_tcp(&mut self) -> Result<(), CrustError> {
self.lock().start_listening_tcp(LISTENER_PORT);
Ok(())
}
pub fn prepare_connection_info(&self, result_token: u32) {
self.lock_and_poll(|imp| imp.prepare_connection_info(result_token))
}
pub fn connect(&self,
our_info: PrivConnectionInfo,
their_info: PubConnectionInfo)
-> Result<(), CrustError> {
self.lock_and_poll(|imp| imp.connect(our_info, their_info));
Ok(())
}
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>, _priority: 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 is_connected(&self, peer_id: &PeerId) -> bool {
self.lock_and_poll(|imp| imp.is_peer_connected(peer_id))
}
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);
impl fmt::Debug for PeerId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "PeerId({})", self.0)
}
}
#[derive(Debug)]
pub enum Event {
BootstrapAccept(PeerId),
BootstrapConnect(PeerId, SocketAddr),
BootstrapFailed,
ListenerStarted(u16),
ListenerFailed,
ConnectionInfoPrepared(ConnectionInfoResult),
ConnectSuccess(PeerId),
ConnectFailure(PeerId),
LostPeer(PeerId),
NewMessage(PeerId, Vec<u8>),
WriteMsgSizeProhibitive(PeerId, Vec<u8>),
}
pub type CrustEventSender = event_sender::MaidSafeObserver<Event>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PrivConnectionInfo(pub PeerId, pub Endpoint);
impl PrivConnectionInfo {
pub fn to_pub_connection_info(&self) -> PubConnectionInfo {
PubConnectionInfo(self.0, self.1)
}
}
#[derive(Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable)]
pub struct PubConnectionInfo(pub PeerId, pub Endpoint);
impl PubConnectionInfo {
pub fn id(&self) -> PeerId {
self.0
}
}
#[derive(Debug)]
pub struct ConnectionInfoResult {
pub result_token: u32,
pub result: Result<PrivConnectionInfo, CrustError>,
}
#[derive(Debug)]
pub struct CrustError;