mod resource_id;
mod endpoint;
mod poll;
mod registry;
mod driver;
mod remote_addr;
mod transport;
mod loader;
pub mod adapter;
pub use adapter::{SendStatus};
pub use resource_id::{ResourceId, ResourceType};
pub use endpoint::{Endpoint};
pub use remote_addr::{RemoteAddr, ToRemoteAddr};
pub use transport::{Transport};
pub use driver::{NetEvent};
use loader::{DriverLoader, ActionControllerList, EventProcessorList};
use poll::{Poll, PollEvent};
use strum::{IntoEnumIterator};
use std::net::{SocketAddr, ToSocketAddrs};
use std::time::{Duration};
use std::io::{self};
pub fn split() -> (NetworkController, NetworkProcessor) {
let mut drivers = DriverLoader::default();
Transport::iter().for_each(|transport| transport.mount_adapter(&mut drivers));
let (poll, controllers, processors) = drivers.take();
let network_controller = NetworkController::new(controllers);
let network_processor = NetworkProcessor::new(poll, processors);
(network_controller, network_processor)
}
pub struct NetworkController {
controllers: ActionControllerList,
}
impl NetworkController {
fn new(controllers: ActionControllerList) -> NetworkController {
Self { controllers }
}
pub fn connect(
&self,
transport: Transport,
addr: impl ToRemoteAddr,
) -> io::Result<(Endpoint, SocketAddr)> {
let addr = addr.to_remote_addr().unwrap();
log::trace!("Connect to {} by adapter: {}", addr, transport.id());
self.controllers[transport.id() as usize].connect(addr).map(|(endpoint, addr)| {
log::trace!("Connected to {}", endpoint);
(endpoint, addr)
})
}
pub fn listen(
&self,
transport: Transport,
addr: impl ToSocketAddrs,
) -> io::Result<(ResourceId, SocketAddr)> {
let addr = addr.to_socket_addrs().unwrap().next().unwrap();
log::trace!("Listen by {} by adapter: {}", addr, transport.id());
self.controllers[transport.id() as usize].listen(addr).map(|(resource_id, addr)| {
log::trace!("Listening by {}", resource_id);
(resource_id, addr)
})
}
pub fn remove(&self, resource_id: ResourceId) -> bool {
log::trace!("Remove {}", resource_id);
let value = self.controllers[resource_id.adapter_id() as usize].remove(resource_id);
log::trace!("Removed: {}", value);
value
}
pub fn send(&self, endpoint: Endpoint, data: &[u8]) -> SendStatus {
log::trace!("Send {} bytes to {}", data.len(), endpoint);
let status =
self.controllers[endpoint.resource_id().adapter_id() as usize].send(endpoint, data);
log::trace!("Send status: {:?}", status);
status
}
}
pub struct NetworkProcessor {
poll: Poll,
processors: EventProcessorList,
}
impl NetworkProcessor {
fn new(poll: Poll, processors: EventProcessorList) -> Self {
Self { poll, processors }
}
pub fn process_poll_event(
&mut self,
timeout: Option<Duration>,
mut event_callback: impl FnMut(NetEvent<'_>),
) {
let processors = &mut self.processors;
self.poll.process_event(timeout, |poll_event| {
match poll_event {
PollEvent::Network(resource_id) => {
let adapter_id = resource_id.adapter_id() as usize;
processors[adapter_id].process(resource_id, &mut |net_event| {
log::trace!("Processed {:?}", net_event);
event_callback(net_event);
});
}
#[allow(dead_code)] PollEvent::Waker => todo!(),
}
});
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::{Duration};
lazy_static::lazy_static! {
static ref TIMEOUT: Duration = Duration::from_millis(1000);
}
#[test]
fn create_remove_listener() {
let (controller, mut processor) = self::split();
let (listener_id, _) = controller.listen(Transport::Tcp, "127.0.0.1:0").unwrap();
assert!(controller.remove(listener_id)); assert!(!controller.remove(listener_id));
let mut was_event = false;
processor.process_poll_event(Some(*TIMEOUT), |_| was_event = true);
assert!(!was_event);
}
#[test]
fn create_remove_listener_with_connection() {
let (controller, mut processor) = self::split();
let (listener_id, addr) = controller.listen(Transport::Tcp, "127.0.0.1:0").unwrap();
controller.connect(Transport::Tcp, addr).unwrap();
let mut was_event = false;
processor.process_poll_event(Some(*TIMEOUT), |net_event| match net_event {
NetEvent::Connected(_, _) => {
assert!(controller.remove(listener_id));
assert!(!controller.remove(listener_id));
was_event = true;
}
_ => unreachable!(),
});
assert!(was_event);
let mut was_event = false;
processor.process_poll_event(Some(*TIMEOUT), |_| was_event = true);
assert!(!was_event);
}
}