|
@@ -1,12 +1,17 @@
|
|
|
use std::{
|
|
|
cell::{Cell, RefCell},
|
|
|
- collections::{HashMap, VecDeque},
|
|
|
- os::unix::prelude::{AsRawFd, RawFd},
|
|
|
+ collections::HashMap,
|
|
|
+ os::unix::prelude::RawFd,
|
|
|
rc::Rc,
|
|
|
};
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
|
|
|
+mod udp;
|
|
|
+pub use udp::UdpSocketBuilder;
|
|
|
+mod timerfd;
|
|
|
+pub use self::timerfd::TimerFdBuilder;
|
|
|
+
|
|
|
pub struct InterestRegistration {
|
|
|
poll: Rc<RefCell<mio::Poll>>,
|
|
|
token: mio::Token,
|
|
@@ -106,216 +111,3 @@ impl IOService {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-#[derive(Default)]
|
|
|
-pub struct UdpSocketBuilder {
|
|
|
- bind: Option<std::net::SocketAddr>,
|
|
|
- multicast: Vec<(std::net::IpAddr, std::net::IpAddr)>,
|
|
|
-}
|
|
|
-
|
|
|
-impl UdpSocketBuilder {
|
|
|
- pub fn bind_to(mut self, addr: std::net::SocketAddr) -> Self {
|
|
|
- self.bind = Some(addr);
|
|
|
- self
|
|
|
- }
|
|
|
-
|
|
|
- pub fn join_multicast(mut self, group: std::net::IpAddr, iface: std::net::IpAddr) -> Self {
|
|
|
- self.multicast.push((group, iface));
|
|
|
- self
|
|
|
- }
|
|
|
-
|
|
|
- pub fn build(self, io: &IOService) -> UdpSocketRef {
|
|
|
- let socket =
|
|
|
- mio::net::UdpSocket::bind(self.bind.expect("no bind address given to UDP socket!"))
|
|
|
- .expect("couldn't bind UDP socket");
|
|
|
- let interest = io.register_interest(socket.as_raw_fd());
|
|
|
-
|
|
|
- for mcast in &self.multicast {
|
|
|
- use std::net::IpAddr;
|
|
|
- match (mcast.0, mcast.1) {
|
|
|
- (IpAddr::V4(group), IpAddr::V4(iface)) => {
|
|
|
- socket
|
|
|
- .join_multicast_v4(&group, &iface)
|
|
|
- .expect("couldn't join multicast group");
|
|
|
- }
|
|
|
- (IpAddr::V6(_group), IpAddr::V6(_iface)) => {
|
|
|
- todo!()
|
|
|
- }
|
|
|
- _ => panic!("Multicast specification mixes ipv4 and ipv6 addresses!"),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let sock = Rc::new(UdpSocket {
|
|
|
- api: io.api.clone(),
|
|
|
- interest,
|
|
|
- socket,
|
|
|
- queue: Default::default(),
|
|
|
- peers: Default::default(),
|
|
|
- multicast_joined: self.multicast.iter().map(|e| e.0).collect(),
|
|
|
- });
|
|
|
-
|
|
|
- io.register_handler(&sock.interest, sock.clone());
|
|
|
-
|
|
|
- UdpSocketRef { sock }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub struct UdpSocketRef {
|
|
|
- sock: Rc<UdpSocket>,
|
|
|
-}
|
|
|
-
|
|
|
-impl UdpSocketRef {
|
|
|
- pub fn multicast_peers(&self) -> Vec<fleck_core::peer::Peer> {
|
|
|
- let port = self.sock.socket.local_addr().unwrap().port();
|
|
|
- let rh: Rc<dyn FdHandler> = self.sock.clone();
|
|
|
- self.sock
|
|
|
- .multicast_joined
|
|
|
- .iter()
|
|
|
- .map(|ip| {
|
|
|
- self.sock
|
|
|
- .peer_for(&rh, &std::net::SocketAddr::new(*ip, port))
|
|
|
- })
|
|
|
- .collect()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-struct UdpSocket {
|
|
|
- api: std::rc::Rc<crate::API>,
|
|
|
- interest: InterestRegistration,
|
|
|
- socket: mio::net::UdpSocket,
|
|
|
- queue: RefCell<VecDeque<(std::net::SocketAddr, Vec<u8>)>>,
|
|
|
- peers: RefCell<HashMap<std::net::SocketAddr, super::peer::Peer>>,
|
|
|
- multicast_joined: Vec<std::net::IpAddr>,
|
|
|
-}
|
|
|
-
|
|
|
-impl UdpSocket {
|
|
|
- fn peer_for(&self, rc: &Rc<dyn FdHandler>, addr: &std::net::SocketAddr) -> super::peer::Peer {
|
|
|
- let mut peers = self.peers.borrow_mut();
|
|
|
- if let Some(peer) = peers.get(addr) {
|
|
|
- peer.clone()
|
|
|
- } else {
|
|
|
- let peer = super::peer::Peer {
|
|
|
- data: Rc::new(super::peer::PeerData::new(
|
|
|
- rc.clone(),
|
|
|
- super::peer::PeerAddress::Udp(*addr),
|
|
|
- )),
|
|
|
- };
|
|
|
- peers.insert(*addr, peer.clone());
|
|
|
- peer
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl FdHandler for UdpSocket {
|
|
|
- fn ready_read(&self, rc: &Rc<dyn FdHandler>) {
|
|
|
- let mut buf = [0u8; 2048];
|
|
|
- while let Ok((bytes, addr)) = self.socket.recv_from(&mut buf) {
|
|
|
- if let Ok(mut msg) = bincode::deserialize::<super::msg::Message>(&buf[..bytes]) {
|
|
|
- msg.peer = Some(self.peer_for(rc, &addr));
|
|
|
- self.api.queue::<super::ReceivePacketChannel>(msg);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fn ready_write(&self, _rc: &Rc<dyn FdHandler>) {
|
|
|
- let mut queue = self.queue.borrow_mut();
|
|
|
- while !queue.is_empty() {
|
|
|
- let packet = queue.front().unwrap();
|
|
|
-
|
|
|
- if let Ok(len) = self.socket.send_to(&packet.1, packet.0) {
|
|
|
- if len != packet.1.len() {
|
|
|
- log::error!(
|
|
|
- "Sent packet truncated to {} of {} bytes",
|
|
|
- len,
|
|
|
- packet.1.len()
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- drop(packet);
|
|
|
- queue.pop_front();
|
|
|
- } else {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- self.interest.update_interest(mio::Interest::READABLE);
|
|
|
- }
|
|
|
-
|
|
|
- fn dispatch(&self, msg: fleck_core::msg::Message) {
|
|
|
- let peer = msg.peer.clone().unwrap(); // if we got this far, the peer points to us
|
|
|
-
|
|
|
- if let super::peer::PeerAddress::Udp(addr) = peer.data.address_info {
|
|
|
- self.queue.borrow_mut().push_back((
|
|
|
- addr,
|
|
|
- bincode::serialize(&msg).expect("couldn't serialize message?"),
|
|
|
- ));
|
|
|
- self.interest
|
|
|
- .update_interest(mio::Interest::READABLE.add(mio::Interest::WRITABLE));
|
|
|
- } else {
|
|
|
- log::error!("packet dispatched to UdpSocket without UDP address!");
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Default)]
|
|
|
-pub struct TimerFdBuilder {
|
|
|
- interval: Option<std::time::Duration>,
|
|
|
- trigger: Option<Box<dyn Fn()>>,
|
|
|
-}
|
|
|
-
|
|
|
-impl TimerFdBuilder {
|
|
|
- pub fn interval(mut self, interval: std::time::Duration) -> Self {
|
|
|
- self.interval = Some(interval);
|
|
|
- self
|
|
|
- }
|
|
|
-
|
|
|
- pub fn trigger<F: 'static + Fn()>(mut self, f: F) -> Self {
|
|
|
- self.trigger = Some(Box::new(f));
|
|
|
- self
|
|
|
- }
|
|
|
-
|
|
|
- pub fn build(self, io: &IOService) {
|
|
|
- let mut timer = timerfd::TimerFd::new().expect("couldn't create new timerfd?");
|
|
|
-
|
|
|
- timer.set_state(
|
|
|
- timerfd::TimerState::Periodic {
|
|
|
- current: std::time::Duration::from_millis(1),
|
|
|
- interval: self
|
|
|
- .interval
|
|
|
- .expect("building timerfd with no interval set?"),
|
|
|
- },
|
|
|
- timerfd::SetTimeFlags::Default,
|
|
|
- );
|
|
|
-
|
|
|
- let interest = io.register_interest(timer.as_raw_fd());
|
|
|
-
|
|
|
- let sock = Rc::new(TimerFd {
|
|
|
- interest,
|
|
|
- timer,
|
|
|
- trigger: self.trigger.expect("building timerfd with no trigger?"),
|
|
|
- });
|
|
|
-
|
|
|
- io.register_handler(&sock.interest, sock.clone());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-struct TimerFd {
|
|
|
- interest: InterestRegistration,
|
|
|
- timer: timerfd::TimerFd,
|
|
|
- trigger: Box<dyn Fn()>,
|
|
|
-}
|
|
|
-
|
|
|
-impl FdHandler for TimerFd {
|
|
|
- fn ready_read(&self, _rc: &Rc<dyn FdHandler>) {
|
|
|
- self.timer.read();
|
|
|
- (self.trigger)();
|
|
|
- }
|
|
|
-
|
|
|
- fn ready_write(&self, _rc: &Rc<dyn FdHandler>) {
|
|
|
- unreachable!()
|
|
|
- }
|
|
|
-
|
|
|
- fn dispatch(&self, _msg: fleck_core::msg::Message) {
|
|
|
- unreachable!()
|
|
|
- }
|
|
|
-}
|