2020-01-13 16:53:28 +00:00
|
|
|
use crate::{
|
2020-02-04 15:42:04 +00:00
|
|
|
internal::RemoteParticipant,
|
|
|
|
message::{self, OutGoingMessage},
|
|
|
|
worker::{
|
|
|
|
types::{CtrlMsg, Pid, RtrnMsg, Sid, TokenObjects},
|
2020-02-10 17:25:47 +00:00
|
|
|
Channel, Controller, TcpChannel,
|
2020-02-04 15:42:04 +00:00
|
|
|
},
|
2020-01-13 16:53:28 +00:00
|
|
|
};
|
2019-12-20 13:56:01 +00:00
|
|
|
use enumset::*;
|
|
|
|
use mio::{
|
|
|
|
self,
|
|
|
|
net::{TcpListener, TcpStream},
|
2020-01-13 16:53:28 +00:00
|
|
|
PollOpt, Ready,
|
2019-12-20 13:56:01 +00:00
|
|
|
};
|
2020-02-04 15:42:04 +00:00
|
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
|
|
use std::{
|
|
|
|
collections::HashMap,
|
|
|
|
marker::PhantomData,
|
|
|
|
sync::{mpsc::TryRecvError, Arc, RwLock},
|
|
|
|
};
|
2020-01-22 16:44:32 +00:00
|
|
|
use tlid;
|
2020-01-13 16:53:28 +00:00
|
|
|
use tracing::*;
|
|
|
|
use uuid::Uuid;
|
|
|
|
use uvth::ThreadPool;
|
2019-12-20 13:56:01 +00:00
|
|
|
|
2020-01-13 16:53:28 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2019-12-20 13:56:01 +00:00
|
|
|
pub enum Address {
|
|
|
|
Tcp(std::net::SocketAddr),
|
|
|
|
Udp(std::net::SocketAddr),
|
|
|
|
}
|
|
|
|
|
2020-01-22 16:44:32 +00:00
|
|
|
#[derive(Serialize, Deserialize, EnumSetType, Debug)]
|
|
|
|
#[enumset(serialize_repr = "u8")]
|
2019-12-20 13:56:01 +00:00
|
|
|
pub enum Promise {
|
|
|
|
InOrder,
|
|
|
|
NoCorrupt,
|
|
|
|
GuaranteedDelivery,
|
|
|
|
Encrypted,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Participant {
|
|
|
|
addr: Address,
|
2020-02-10 17:25:47 +00:00
|
|
|
remote_pid: Pid,
|
2019-12-20 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Connection {}
|
|
|
|
|
2020-02-04 15:42:04 +00:00
|
|
|
pub struct Stream {
|
|
|
|
sid: Sid,
|
|
|
|
}
|
2019-12-20 13:56:01 +00:00
|
|
|
|
|
|
|
pub trait Events {
|
2020-01-13 16:53:28 +00:00
|
|
|
fn on_remote_connection_open(net: &Network<Self>, con: &Connection)
|
2019-12-20 13:56:01 +00:00
|
|
|
where
|
|
|
|
Self: std::marker::Sized;
|
2020-01-13 16:53:28 +00:00
|
|
|
fn on_remote_connection_close(net: &Network<Self>, con: &Connection)
|
2019-12-20 13:56:01 +00:00
|
|
|
where
|
|
|
|
Self: std::marker::Sized;
|
2020-01-13 16:53:28 +00:00
|
|
|
fn on_remote_stream_open(net: &Network<Self>, st: &Stream)
|
2019-12-20 13:56:01 +00:00
|
|
|
where
|
|
|
|
Self: std::marker::Sized;
|
2020-01-13 16:53:28 +00:00
|
|
|
fn on_remote_stream_close(net: &Network<Self>, st: &Stream)
|
2019-12-20 13:56:01 +00:00
|
|
|
where
|
|
|
|
Self: std::marker::Sized;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Network<E: Events> {
|
2020-01-22 16:44:32 +00:00
|
|
|
token_pool: tlid::Pool<tlid::Wrapping<usize>>,
|
2020-02-04 15:42:04 +00:00
|
|
|
worker_pool: tlid::Pool<tlid::Wrapping<u64>>,
|
|
|
|
controller: Arc<Vec<Controller>>,
|
2020-01-13 16:53:28 +00:00
|
|
|
thread_pool: Arc<ThreadPool>,
|
2020-02-04 15:42:04 +00:00
|
|
|
participant_id: Pid,
|
|
|
|
remotes: Arc<RwLock<HashMap<Pid, RemoteParticipant>>>,
|
2019-12-20 13:56:01 +00:00
|
|
|
_pe: PhantomData<E>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Events> Network<E> {
|
2020-01-13 16:53:28 +00:00
|
|
|
pub fn new(participant_id: Uuid, thread_pool: Arc<ThreadPool>) -> Self {
|
2020-01-22 16:44:32 +00:00
|
|
|
let mut token_pool = tlid::Pool::new_full();
|
2020-02-04 15:42:04 +00:00
|
|
|
let mut worker_pool = tlid::Pool::new_full();
|
|
|
|
let remotes = Arc::new(RwLock::new(HashMap::new()));
|
|
|
|
for _ in 0..participant_id.as_u128().rem_euclid(64) {
|
|
|
|
worker_pool.next();
|
|
|
|
//random offset from 0 for tests where multiple networks are
|
|
|
|
// created and we do not want to polute the traces with
|
|
|
|
// network pid everytime
|
|
|
|
}
|
|
|
|
let controller = Arc::new(vec![Controller::new(
|
|
|
|
worker_pool.next(),
|
2020-01-22 16:44:32 +00:00
|
|
|
participant_id,
|
2020-01-13 16:53:28 +00:00
|
|
|
thread_pool.clone(),
|
2020-01-22 16:44:32 +00:00
|
|
|
token_pool.subpool(1000000).unwrap(),
|
2020-02-04 15:42:04 +00:00
|
|
|
remotes.clone(),
|
2020-01-13 16:53:28 +00:00
|
|
|
)]);
|
2019-12-20 13:56:01 +00:00
|
|
|
Self {
|
2020-01-22 16:44:32 +00:00
|
|
|
token_pool,
|
2020-02-04 15:42:04 +00:00
|
|
|
worker_pool,
|
|
|
|
controller,
|
2019-12-20 13:56:01 +00:00
|
|
|
thread_pool,
|
2020-01-13 16:53:28 +00:00
|
|
|
participant_id,
|
2020-02-04 15:42:04 +00:00
|
|
|
remotes,
|
2019-12-20 13:56:01 +00:00
|
|
|
_pe: PhantomData::<E> {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-04 15:42:04 +00:00
|
|
|
fn get_lowest_worker<'a: 'b, 'b>(list: &'a Arc<Vec<Controller>>) -> &'a Controller { &list[0] }
|
|
|
|
|
|
|
|
pub fn send<M: Serialize>(&self, msg: M, stream: &Stream) {
|
|
|
|
let messagebuffer = Arc::new(message::serialize(&msg));
|
|
|
|
//transfer message to right worker to right channel to correct stream
|
|
|
|
//TODO: why do we need a look here, i want my own local directory which is
|
|
|
|
// updated by workes via a channel and needs to be intepreted on a send but it
|
|
|
|
// should almost ever be empty except for new channel creations and stream
|
|
|
|
// creations!
|
|
|
|
for worker in self.controller.iter() {
|
2020-02-10 17:25:47 +00:00
|
|
|
worker
|
|
|
|
.get_tx()
|
|
|
|
.send(CtrlMsg::Send(OutGoingMessage {
|
|
|
|
buffer: messagebuffer.clone(),
|
|
|
|
cursor: 0,
|
|
|
|
mid: None,
|
|
|
|
sid: stream.sid,
|
|
|
|
}))
|
|
|
|
.unwrap();
|
2020-02-04 15:42:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn recv<M: DeserializeOwned>(&self, stream: &Stream) -> Option<M> {
|
|
|
|
for worker in self.controller.iter() {
|
|
|
|
let msg = match worker.get_rx().try_recv() {
|
|
|
|
Ok(msg) => msg,
|
|
|
|
Err(TryRecvError::Empty) => {
|
|
|
|
return None;
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
panic!("Unexpected error '{}'", err);
|
|
|
|
},
|
|
|
|
};
|
2020-01-13 16:53:28 +00:00
|
|
|
|
2020-02-04 15:42:04 +00:00
|
|
|
match msg {
|
|
|
|
RtrnMsg::Receive(m) => {
|
|
|
|
info!("delivering a message");
|
|
|
|
return Some(message::deserialize(m.buffer));
|
|
|
|
},
|
|
|
|
_ => unimplemented!("woopsie"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
2020-01-13 16:53:28 +00:00
|
|
|
}
|
2019-12-20 13:56:01 +00:00
|
|
|
|
2020-02-10 17:25:47 +00:00
|
|
|
pub fn open(&self, part: &Participant, prio: u8, promises: EnumSet<Promise>) -> Stream {
|
|
|
|
for worker in self.controller.iter() {
|
|
|
|
worker
|
|
|
|
.get_tx()
|
|
|
|
.send(CtrlMsg::OpenStream {
|
|
|
|
pid: uuid::Uuid::new_v4(),
|
|
|
|
prio,
|
|
|
|
promises,
|
|
|
|
})
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
Stream { sid: 0 }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn close(&self, stream: Stream) {}
|
|
|
|
|
|
|
|
pub async fn listen(&self, address: &Address) -> Result<(), NetworkError> {
|
|
|
|
let span = span!(Level::TRACE, "listen", ?address);
|
2020-02-04 15:42:04 +00:00
|
|
|
let worker = Self::get_lowest_worker(&self.controller);
|
2020-02-10 17:25:47 +00:00
|
|
|
let _enter = span.enter();
|
|
|
|
match address {
|
|
|
|
Address::Tcp(a) => {
|
|
|
|
let tcp_listener = TcpListener::bind(&a)?;
|
|
|
|
info!("listening");
|
|
|
|
worker.get_tx().send(CtrlMsg::Register(
|
|
|
|
TokenObjects::TcpListener(tcp_listener),
|
|
|
|
Ready::readable(),
|
|
|
|
PollOpt::edge(),
|
|
|
|
))?;
|
|
|
|
},
|
|
|
|
Address::Udp(_) => unimplemented!("lazy me"),
|
|
|
|
};
|
|
|
|
Ok(())
|
2019-12-20 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
2020-02-10 17:25:47 +00:00
|
|
|
pub async fn connect(&self, address: &Address) -> Result<Participant, NetworkError> {
|
2020-02-04 15:42:04 +00:00
|
|
|
let worker = Self::get_lowest_worker(&self.controller);
|
2020-01-22 16:44:32 +00:00
|
|
|
let pid = self.participant_id;
|
2020-02-04 15:42:04 +00:00
|
|
|
let remotes = self.remotes.clone();
|
2020-02-10 17:25:47 +00:00
|
|
|
let mut span = span!(Level::INFO, "connect", ?address);
|
|
|
|
let _enter = span.enter();
|
|
|
|
match address {
|
|
|
|
Address::Tcp(a) => {
|
|
|
|
info!("connecting");
|
|
|
|
let tcp_stream = TcpStream::connect(&a)?;
|
|
|
|
let tcp_channel = TcpChannel::new(tcp_stream);
|
|
|
|
let mut channel = Channel::new(pid, tcp_channel, remotes);
|
|
|
|
let (ctrl_tx, ctrl_rx) = mio_extras::channel::channel::<Pid>();
|
|
|
|
worker.get_tx().send(CtrlMsg::Register(
|
|
|
|
TokenObjects::TcpChannel(channel, Some(ctrl_tx)),
|
|
|
|
Ready::readable() | Ready::writable(),
|
|
|
|
PollOpt::edge(),
|
|
|
|
))?;
|
|
|
|
// wait for a return
|
|
|
|
},
|
|
|
|
Address::Udp(_) => unimplemented!("lazy me"),
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Participant {
|
|
|
|
addr: address.clone(),
|
|
|
|
remote_pid: uuid::Uuid::new_v4(),
|
|
|
|
})
|
2019-12-20 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
2020-02-10 17:25:47 +00:00
|
|
|
//TODO: evaluate if move to Participant
|
|
|
|
pub async fn _disconnect(&self, participant: Participant) -> Result<(), NetworkError> {
|
|
|
|
panic!("sda");
|
2020-01-22 16:44:32 +00:00
|
|
|
}
|
2020-01-13 16:53:28 +00:00
|
|
|
|
2020-02-10 17:25:47 +00:00
|
|
|
pub fn participants(&self) -> Vec<Participant> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _connected(&self) -> Result<Participant, NetworkError> {
|
|
|
|
// returns if a Participant connected and is ready
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _disconnected(&self) -> Result<Participant, NetworkError> {
|
|
|
|
// returns if a Participant connected and is ready
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn multisend<M: Serialize>(
|
|
|
|
&self,
|
|
|
|
streams: Vec<Stream>,
|
|
|
|
msg: M,
|
|
|
|
) -> Result<(), NetworkError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Participant {
|
|
|
|
pub async fn _open(
|
|
|
|
&self,
|
|
|
|
prio: u8,
|
|
|
|
promises: EnumSet<Promise>,
|
|
|
|
) -> Result<Stream, ParticipantError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _close(&self, stream: Stream) -> Result<(), ParticipantError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _opened(&self) -> Result<Stream, ParticipantError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _closed(&self) -> Result<Stream, ParticipantError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stream {
|
|
|
|
//TODO: What about SEND instead of Serializeable if it goes via PIPE ?
|
|
|
|
//TODO: timeout per message or per stream ? stream or ?
|
|
|
|
|
|
|
|
pub async fn _send<M: Serialize>(&self, msg: M) -> Result<(), StreamError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn _recv<M: DeserializeOwned>(&self) -> Result<M, StreamError> {
|
|
|
|
panic!("sda");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum NetworkError {
|
|
|
|
NetworkDestroyed,
|
|
|
|
WorkerDestroyed,
|
|
|
|
IoError(std::io::Error),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ParticipantError {
|
|
|
|
ParticipantDisconected,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum StreamError {
|
|
|
|
StreamClosed,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<std::io::Error> for NetworkError {
|
|
|
|
fn from(err: std::io::Error) -> Self { NetworkError::IoError(err) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<mio_extras::channel::SendError<T>> for NetworkError {
|
|
|
|
fn from(err: mio_extras::channel::SendError<T>) -> Self { NetworkError::WorkerDestroyed }
|
2019-12-20 13:56:01 +00:00
|
|
|
}
|