Browse Source

Split API off from Fleck, reorganized Service trait.

Kestrel 2 years ago
parent
commit
54a9a84d96

+ 5 - 4
fleck/examples/simple_node.rs

@@ -6,14 +6,15 @@ fn main() {
     pretty_env_logger::init_timed();
 
     let fleck = fleck::Fleck::new();
+    let api = fleck.api();
 
     // generate ephemeral keypair
-    fleck.with_service(|ns: &fleck_core::NodeService| {
+    api.with_service(|ns: &fleck_core::NodeService| {
         ns.self_node().gen_keypair();
     });
 
     // create UDP socket for communication with a local multicast group
-    let sockref = fleck.with_service(|io: &fleck_core::io::IOService| {
+    let sockref = api.with_service(|io: &fleck_core::io::IOService| {
         fleck_core::io::UdpSocketBuilder::default()
             .bind_to(SocketAddr::new(
                 std::net::Ipv4Addr::UNSPECIFIED.into(),
@@ -24,11 +25,11 @@ fn main() {
     });
 
     // enable local discovery
-    fleck.with_service(|ld: &fleck_core::discovery::LocalDiscovery| {
+    api.with_service(|ld: &fleck_core::discovery::LocalDiscovery| {
         for peer in sockref.multicast_peers() {
             ld.add_multicast_peer(peer);
         }
     });
 
-    fleck.run();
+    api.run();
 }

+ 10 - 7
fleck/src/fleck_core.rs

@@ -42,25 +42,28 @@ pub type MajorTickChannel = (channel_tags::MajorTickTag, ());
 #[derive(Default)]
 pub struct CoreInitService {}
 
-impl crate::service::Service for std::rc::Rc<CoreInitService> {
-    fn setup(&self, api: &crate::Fleck) {
+impl crate::service::DefaultService for CoreInitService {
+    fn setup(self: &std::rc::Rc<Self>, api: std::rc::Rc<crate::API>) {
         api.create_channel::<MinorTickChannel>();
         api.create_channel::<MajorTickChannel>();
-        api.with_service(|io: &io::IOService| {
+        let io_api = api.clone();
+        api.with_service(move |io: &io::IOService| {
+            let minor_api = io_api.clone();
+            let major_api = io_api.clone();
             io::TimerFdBuilder::default()
                 .interval(std::time::Duration::from_secs(1))
-                .trigger(|api| api.queue::<MinorTickChannel>(()))
+                .trigger(move || minor_api.queue::<MinorTickChannel>(()))
                 .build(io);
             io::TimerFdBuilder::default()
                 .interval(std::time::Duration::from_secs(15))
-                .trigger(|api| api.queue::<MajorTickChannel>(()))
+                .trigger(move || major_api.queue::<MajorTickChannel>(()))
                 .build(io);
         });
 
-        api.add_service::<msg::MessageService>();
+        /*api.add_service::<msg::MessageService>();
         api.add_service::<node::NodeService>();
         api.add_service::<discovery::LocalDiscovery>();
         api.add_service::<peer::PeerService>();
-        api.add_service::<crypto::SignPacket>();
+        api.add_service::<crypto::SignPacket>();*/
     }
 }

+ 30 - 30
fleck/src/fleck_core/crypto.rs

@@ -32,12 +32,12 @@ pub struct SymmetricKey {
 #[derive(Default)]
 pub(crate) struct VerifyPacketSignature {}
 
-impl Service for std::rc::Rc<VerifyPacketSignature> {
-    fn setup(&self, api: &crate::Fleck) {
+impl DefaultService for VerifyPacketSignature {
+    fn setup(self: &std::rc::Rc<Self>, api: std::rc::Rc<crate::API>) {
         api.channel::<fleck_core::ReceivePacketChannel>().sub_opt(
             fleck_core::ReceiveOrder::Verify,
             self,
-            VerifyPacketSignature::check,
+            Self::check,
         );
     }
 }
@@ -45,7 +45,6 @@ impl Service for std::rc::Rc<VerifyPacketSignature> {
 impl VerifyPacketSignature {
     fn check(
         &self,
-        api: &crate::Fleck,
         mut message: fleck_core::msg::Message,
     ) -> Option<fleck_core::msg::Message> {
         match message.crypto_header {
@@ -69,21 +68,25 @@ impl VerifyPacketSignature {
     }
 }
 
-#[derive(Default)]
-pub(crate) struct SignPacket {}
+pub(crate) struct SignPacket {
+    api: std::rc::Rc<crate::API>,
+}
 
-impl Service for std::rc::Rc<SignPacket> {
-    fn setup(&self, api: &crate::Fleck) {
-        api.channel::<fleck_core::SendPacketChannel>().sub_ref(
+impl Service for SignPacket {
+    fn new(api: std::rc::Rc<crate::API>) -> Self {
+        Self { api }
+    }
+    fn setup(self: &std::rc::Rc<Self>) {
+        self.api.channel::<fleck_core::SendPacketChannel>().sub_ref(
             fleck_core::SendOrder::Sign,
             self,
-            SignPacket::sign,
+            Self::sign,
         );
     }
 }
 
 impl SignPacket {
-    fn sign(&self, api: &crate::Fleck, message: &mut fleck_core::msg::Message) {
+    fn sign(&self, message: &mut fleck_core::msg::Message) {
         let params = message
             .saved_params
             .expect("packet got to signing stage without saved parameters?");
@@ -93,7 +96,7 @@ impl SignPacket {
             return;
         }
 
-        api.with_service(|ns: &fleck_core::NodeService| {
+        self.api.with_service(|ns: &fleck_core::NodeService| {
             let keypair = ns.self_node().keypair().unwrap();
             let sign_data = bincode::serialize(&message.content).unwrap();
             message.crypto_header = PacketHeader::Signed(keypair.sign(&sign_data));
@@ -120,39 +123,36 @@ pub enum KeyExchangeState {
 }
 
 pub struct EncryptionService {
+    api: std::rc::Rc<crate::API>,
     state: RefCell<HashMap<fleck_core::peer::Peer, KeyExchangeState>>,
 }
 
-impl Default for EncryptionService {
-    fn default() -> Self {
-        Self {
-            state: Default::default(),
-        }
+impl Service for EncryptionService {
+    fn new(api: std::rc::Rc<crate::API>) -> Self {
+        Self { api, state: Default::default() }
     }
-}
 
-impl Service for std::rc::Rc<EncryptionService> {
-    fn setup(&self, api: &crate::Fleck) {
-        api.channel::<fleck_core::node::NodeRegistrationChannel>().sub_ref(self, EncryptionService::new_node);
-        api.channel::<fleck_core::msg::MessageChannel<KeyExchange>>().sub_eat(self, EncryptionService::incoming);
+    fn setup(self: &std::rc::Rc<Self>) {
+        self.api.channel::<fleck_core::node::NodeRegistrationChannel>().sub_ref(self, Self::new_node);
+        self.api.channel::<fleck_core::msg::MessageChannel<KeyExchange>>().sub_eat(self, Self::incoming);
     }
 }
 
 impl EncryptionService {
-    fn new_node(&self, api: &crate::Fleck, node: &mut std::rc::Rc<fleck_core::node::Node>) {
+    fn new_node(&self, node: &mut std::rc::Rc<fleck_core::node::Node>) {
         match node.peer().as_ref() {
-            Some(peer) => self.begin_handshake(api, peer),
+            Some(peer) => self.begin_handshake(peer),
             None => (),
         }
     }
 
-    fn begin_handshake(&self, api: &crate::Fleck, with: &fleck_core::peer::Peer) {
+    fn begin_handshake(&self, with: &fleck_core::peer::Peer) {
         use rand::SeedableRng;
         let mut csprng = rand::rngs::StdRng::from_entropy();
         let secret = x25519_dalek::EphemeralSecret::new(&mut csprng);
 
         // send notification with new secret
-        api.queue::<fleck_core::SendPacketChannel>(fleck_core::msg::Message::build(
+        self.api.queue::<fleck_core::SendPacketChannel>(fleck_core::msg::Message::build(
             KeyExchange {
                 key: x25519_dalek::PublicKey::from(&secret)
             }
@@ -183,7 +183,7 @@ impl EncryptionService {
         }
     }
 
-    fn incoming(&self, api: &crate::Fleck, msg: (fleck_core::msg::Metadata, KeyExchange)) {
+    fn incoming(&self, msg: (fleck_core::msg::Metadata, KeyExchange)) {
         let mut states = self.state.borrow_mut();
         let peer = msg.0.peer.expect("incoming KeyExchange should have a peer?");
         // let state = states.entry(peer.clone()).or_insert(KeyExchangeState::NoState);
@@ -193,7 +193,7 @@ impl EncryptionService {
                 states.insert(peer.clone(), KeyExchangeState::Given(msg.1.key));
 
                 drop(states);
-                self.begin_handshake(api, &peer);
+                self.begin_handshake(&peer);
             },
             KeyExchangeState::Given(peer_pubkey) => {
                 if peer_pubkey != msg.1.key {
@@ -202,7 +202,7 @@ impl EncryptionService {
                 }
 
                 drop(states);
-                self.begin_handshake(api, &peer);
+                self.begin_handshake(&peer);
             },
             KeyExchangeState::WaitForResponse(secret) => {
                 // key handshake is finished!
@@ -223,7 +223,7 @@ impl EncryptionService {
                 // it's a new pubkey, so we want to restart the handshake
                 states.insert(peer.clone(), KeyExchangeState::Given(msg.1.key));
                 drop(states);
-                self.begin_handshake(api, &peer);
+                self.begin_handshake(&peer);
             },
         }
     }

+ 18 - 12
fleck/src/fleck_core/discovery.rs

@@ -3,8 +3,8 @@ use crate::prelude::*;
 use serde::{Deserialize, Serialize};
 use std::{cell::RefCell, rc::Rc};
 
-#[derive(Default)]
 pub struct LocalDiscovery {
+    api: Rc<crate::API>,
     targets: RefCell<Vec<fleck_core::peer::Peer>>,
 }
 
@@ -18,14 +18,20 @@ impl fleck_core::msg::MessageParams for DiscoveryMsg {
     const ENCRYPTED: bool = false;
 }
 
-impl Service for Rc<LocalDiscovery> {
-    fn setup(&self, api: &crate::Fleck) {
-        api.with_service(|m: &fleck_core::MessageService| {
-            m.add_message_type::<DiscoveryMsg>(api);
+impl Service for LocalDiscovery {
+    fn new(api: Rc<crate::API>) -> Self {
+        Self {
+            api,
+            targets: Default::default(),
+        }
+    }
+    fn setup(self: &Rc<Self>) {
+        self.api.with_service(|m: &fleck_core::MessageService| {
+            m.add_message_type::<DiscoveryMsg>();
         });
-        api.channel::<fleck_core::MajorTickChannel>()
+        self.api.channel::<fleck_core::MajorTickChannel>()
             .sub_ref(self, LocalDiscovery::process_major_tick);
-        api.channel::<fleck_core::msg::MessageChannel<DiscoveryMsg>>()
+        self.api.channel::<fleck_core::msg::MessageChannel<DiscoveryMsg>>()
             .sub_eat(self, LocalDiscovery::discovery);
     }
 }
@@ -35,12 +41,12 @@ impl LocalDiscovery {
         self.targets.borrow_mut().push(peer);
     }
 
-    fn discovery(&self, api: &crate::Fleck, msg: (fleck_core::msg::Metadata, DiscoveryMsg)) {
+    fn discovery(&self, msg: (fleck_core::msg::Metadata, DiscoveryMsg)) {
         let discovery = msg.1;
         log::trace!("received discovery message");
 
         // this will automatically ignore self-messages because we already know the pubkey
-        api.with_service(|ns: &fleck_core::NodeService| {
+        self.api.with_service(|ns: &fleck_core::NodeService| {
             if ns.node_by_pubkey(&discovery.pkey).is_none() {
                 ns.inform_of_peer(msg.0.peer.unwrap());
                 // let node = fleck_core::node::Node::build_with_peer(msg.0.peer);
@@ -50,16 +56,16 @@ impl LocalDiscovery {
         });
     }
 
-    fn process_major_tick(&self, api: &crate::Fleck, _: &mut ()) {
+    fn process_major_tick(&self, _: &mut ()) {
         for peer in self.targets.borrow().iter() {
             let msg = fleck_core::msg::Message::build(DiscoveryMsg {
-                pkey: api.with_service(|ns: &fleck_core::NodeService| {
+                pkey: self.api.with_service(|ns: &fleck_core::NodeService| {
                     ns.self_node().pubkey().unwrap().to_owned()
                 }),
             })
             .with_peer(peer.clone());
 
-            api.queue::<fleck_core::SendPacketChannel>(msg);
+            self.api.queue::<fleck_core::SendPacketChannel>(msg);
         }
     }
 }

+ 27 - 26
fleck/src/fleck_core/io.rs

@@ -28,20 +28,22 @@ impl InterestRegistration {
 }
 
 pub trait FdHandler {
-    fn ready_read(&self, rc: &Rc<dyn FdHandler>, api: &crate::Fleck);
-    fn ready_write(&self, rc: &Rc<dyn FdHandler>, api: &crate::Fleck);
-    fn dispatch(&self, api: &crate::Fleck, msg: super::msg::Message);
+    fn ready_read(&self, rc: &Rc<dyn FdHandler>);
+    fn ready_write(&self, rc: &Rc<dyn FdHandler>);
+    fn dispatch(&self, msg: super::msg::Message);
 }
 
 pub struct IOService {
+    api: Rc<crate::API>,
     poll: Rc<RefCell<mio::Poll>>,
     next_token: Cell<mio::Token>,
     handlers: RefCell<HashMap<mio::Token, Rc<dyn FdHandler>>>,
 }
 
-impl Default for IOService {
-    fn default() -> Self {
+impl Service for IOService {
+    fn new(api: Rc<crate::API>) -> Self {
         Self {
+            api,
             poll: Rc::new(RefCell::new(
                 mio::Poll::new().expect("couldn't create poll?"),
             )),
@@ -49,12 +51,9 @@ impl Default for IOService {
             handlers: Default::default(),
         }
     }
-}
-
-impl Service for Rc<IOService> {
-    fn setup(&self, api: &crate::Fleck) {
-        api.create_channel::<super::ReceivePacketChannel>();
-        api.create_channel::<super::SendPacketChannel>();
+    fn setup(self: &Rc<Self>) {
+        self.api.create_channel::<super::ReceivePacketChannel>();
+        self.api.create_channel::<super::SendPacketChannel>();
     }
 }
 
@@ -85,7 +84,7 @@ impl IOService {
         }
     }
 
-    pub(crate) fn run(&self, api: &crate::Fleck) {
+    pub(crate) fn run(&self) {
         let mut events = mio::Events::with_capacity(128);
         loop {
             let pr = self.poll.borrow_mut().poll(&mut events, None);
@@ -96,14 +95,14 @@ impl IOService {
             for evt in &events {
                 let h = handlers.get(&evt.token()).unwrap();
                 if evt.is_readable() {
-                    h.ready_read(h, api);
+                    h.ready_read(h);
                 }
                 if evt.is_writable() {
-                    h.ready_write(h, api);
+                    h.ready_write(h);
                 }
             }
 
-            api.services.event_root().fire_all(api);
+            self.api.services.borrow().event_root().fire_all();
         }
     }
 }
@@ -147,6 +146,7 @@ impl UdpSocketBuilder {
         }
 
         let sock = Rc::new(UdpSocket {
+            api: io.api.clone(),
             interest,
             socket,
             queue: Default::default(),
@@ -180,6 +180,7 @@ impl UdpSocketRef {
 }
 
 struct UdpSocket {
+    api: std::rc::Rc<crate::API>,
     interest: InterestRegistration,
     socket: mio::net::UdpSocket,
     queue: RefCell<VecDeque<(std::net::SocketAddr, Vec<u8>)>>,
@@ -203,17 +204,17 @@ impl UdpSocket {
 }
 
 impl FdHandler for UdpSocket {
-    fn ready_read(&self, rc: &Rc<dyn FdHandler>, api: &crate::Fleck) {
+    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));
-                api.queue::<super::ReceivePacketChannel>(msg);
+                self.api.queue::<super::ReceivePacketChannel>(msg);
             }
         }
     }
 
-    fn ready_write(&self, _rc: &Rc<dyn FdHandler>, _api: &crate::Fleck) {
+    fn ready_write(&self, _rc: &Rc<dyn FdHandler>) {
         let mut queue = self.queue.borrow_mut();
         while !queue.is_empty() {
             let packet = queue.front().unwrap();
@@ -237,7 +238,7 @@ impl FdHandler for UdpSocket {
         self.interest.update_interest(mio::Interest::READABLE);
     }
 
-    fn dispatch(&self, _api: &crate::Fleck, msg: fleck_core::msg::Message) {
+    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 {
@@ -256,7 +257,7 @@ impl FdHandler for UdpSocket {
 #[derive(Default)]
 pub struct TimerFdBuilder {
     interval: Option<std::time::Duration>,
-    trigger: Option<Box<dyn Fn(&crate::Fleck)>>,
+    trigger: Option<Box<dyn Fn()>>,
 }
 
 impl TimerFdBuilder {
@@ -265,7 +266,7 @@ impl TimerFdBuilder {
         self
     }
 
-    pub fn trigger<F: 'static + Fn(&crate::Fleck)>(mut self, f: F) -> Self {
+    pub fn trigger<F: 'static + Fn()>(mut self, f: F) -> Self {
         self.trigger = Some(Box::new(f));
         self
     }
@@ -298,20 +299,20 @@ impl TimerFdBuilder {
 struct TimerFd {
     interest: InterestRegistration,
     timer: timerfd::TimerFd,
-    trigger: Box<dyn Fn(&crate::Fleck)>,
+    trigger: Box<dyn Fn()>,
 }
 
 impl FdHandler for TimerFd {
-    fn ready_read(&self, _rc: &Rc<dyn FdHandler>, api: &crate::Fleck) {
+    fn ready_read(&self, _rc: &Rc<dyn FdHandler>) {
         self.timer.read();
-        (self.trigger)(api);
+        (self.trigger)();
     }
 
-    fn ready_write(&self, _rc: &Rc<dyn FdHandler>, _api: &crate::Fleck) {
+    fn ready_write(&self, _rc: &Rc<dyn FdHandler>) {
         unreachable!()
     }
 
-    fn dispatch(&self, _api: &crate::Fleck, _msg: fleck_core::msg::Message) {
+    fn dispatch(&self, _msg: fleck_core::msg::Message) {
         unreachable!()
     }
 }

+ 16 - 12
fleck/src/fleck_core/msg.rs

@@ -103,32 +103,36 @@ impl Message {
 pub struct MessageChannelTag;
 pub type MessageChannel<M> = (MessageChannelTag, (Metadata, M));
 
-type Deserializer = dyn Fn(&crate::Fleck, &Message) -> ();
-#[derive(Default)]
+type Deserializer = dyn Fn(&Message) -> ();
+
 pub struct MessageService {
+    api: Rc<crate::API>,
     deser: RefCell<HashMap<u16, Box<Deserializer>>>,
 }
 
-impl Service for Rc<MessageService> {
-    fn setup(&self, api: &crate::Fleck) {
-        api.channel::<fleck_core::ReceivePacketChannel>().sub_opt(
+impl Service for MessageService {
+    fn new(api: Rc<crate::API>) -> Self {
+        Self { api, deser: Default::default() }
+    }
+    fn setup(self: &Rc<Self>) {
+        self.api.channel::<fleck_core::ReceivePacketChannel>().sub_opt(
             fleck_core::ReceiveOrder::Parse,
             self,
-            MessageService::parse,
+            Self::parse,
         );
     }
 }
 
 impl MessageService {
     pub fn add_message_type<MT: std::fmt::Debug + MessageParams + Serialize + DeserializeOwned>(
-        &self,
-        api: &crate::Fleck,
+        &self
     ) {
         let derived_typeid = message_type::<MT>();
+        let api = self.api.clone();
         self.deser.borrow_mut().insert(
             derived_typeid,
             Box::new(
-                |api, message| match bincode::deserialize::<MT>(&message.content.data) {
+                move |message| match bincode::deserialize::<MT>(&message.content.data) {
                     Ok(content) => {
                         api.queue::<MessageChannel<MT>>((message.metadata(), content));
                     }
@@ -139,12 +143,12 @@ impl MessageService {
             ),
         );
 
-        api.create_channel::<MessageChannel<MT>>();
+        self.api.create_channel::<MessageChannel<MT>>();
     }
 
-    fn parse(&self, api: &crate::Fleck, msg: Message) -> Option<Message> {
+    fn parse(&self, msg: Message) -> Option<Message> {
         // try deserializing
-        (self.deser.borrow().get(&msg.content.ty)?)(api, &msg);
+        (self.deser.borrow().get(&msg.content.ty)?)(&msg);
         None
     }
 }

+ 2 - 2
fleck/src/fleck_core/node.rs

@@ -149,8 +149,8 @@ impl NodeService {
     }
 }
 
-impl Service for Rc<NodeService> {
-    fn setup(&self, api: &crate::Fleck) {
+impl DefaultService for NodeService {
+    fn setup(self: &Rc<Self>, api: Rc<crate::API>) {
         api.create_channel::<NodeRegistrationChannel>();
     }
 }

+ 4 - 5
fleck/src/fleck_core/peer.rs

@@ -66,18 +66,17 @@ impl Eq for Peer {
 #[derive(Default)]
 pub struct PeerService {}
 
-impl Service for std::rc::Rc<PeerService> {
-    fn setup(&self, api: &crate::Fleck) {
+impl DefaultService for PeerService {
+    fn setup(self: &Rc<Self>, api: Rc<crate::API>) {
         api.channel::<fleck_core::SendPacketChannel>()
             .as_ref()
-            .sub_opt(fleck_core::SendOrder::Dispatch, self, PeerService::dispatch);
+            .sub_opt(fleck_core::SendOrder::Dispatch, self, Self::dispatch);
     }
 }
 
 impl PeerService {
     fn dispatch(
         &self,
-        api: &crate::Fleck,
         msg: super::msg::Message,
     ) -> Option<super::msg::Message> {
         if msg.peer.is_none() {
@@ -85,7 +84,7 @@ impl PeerService {
             return None;
         }
         let peer = msg.peer.clone().unwrap();
-        peer.data.io.dispatch(api, msg);
+        peer.data.io.dispatch(msg);
 
         None
     }

+ 34 - 19
fleck/src/lib.rs

@@ -7,68 +7,83 @@ pub mod service;
 pub mod prelude {
     pub use crate::fleck_core;
     pub use crate::helper::{AsAny, IntoWeak};
-    pub use crate::service::{ChannelSpec, EventRoot, Service};
+    pub use crate::service::{ChannelSpec, Service, DefaultService};
 }
 
 use prelude::*;
 
-pub struct Fleck {
-    services: service::ServiceStack,
+pub struct API {
+    services: std::cell::RefCell<service::ServiceStack>,
 }
 
-impl Fleck {
+impl API {
     pub fn new() -> Rc<Self> {
         let res = Rc::new(Self {
             services: Default::default(),
         });
 
+        res.services.borrow_mut().give_api(Rc::downgrade(&res));
+
         res.add_service::<fleck_core::io::IOService>();
         res.add_service::<fleck_core::CoreInitService>();
 
         res
     }
 
-    pub fn run(&self) {
+    pub fn run(self: &Rc<Self>) {
         self.with_service(|io: &fleck_core::io::IOService| {
-            io.run(self);
+            io.run();
         });
     }
 }
 
-impl Fleck {
+impl API {
     /// Add a service to the Fleck instance.
-    pub fn add_service<S: Default + 'static>(&self)
-    where
-        Rc<S>: Service,
+    pub fn add_service<S: Service + 'static>(&self)
     {
-        self.services.give_service::<S>(self);
+        self.services.borrow().give_service::<S>();
     }
     /// Access a pre-existing service
-    pub fn with_service<S: 'static, R, F: FnOnce(&S) -> R>(&self, f: F) -> R
-    where
-        Rc<S>: Service,
+    pub fn with_service<S: Service + 'static, R, F: FnOnce(&S) -> R>(&self, f: F) -> R
     {
-        self.services.with_service(f)
+        self.services.borrow().with_service(f)
     }
     /// Create an event channel from a specification
     pub fn create_channel<CS: service::ChannelSpec>(
         &self,
-    ) -> Rc<service::event::Channel<CS::Tag, Self, CS::Data, CS::Priority>> {
-        self.services.event_root().create_channel::<CS>();
+    ) -> Rc<service::event::Channel<CS::Tag, CS::Data, CS::Priority>> {
+        self.services.borrow().event_root().create_channel::<CS>();
         self.channel::<CS>()
     }
     /// Get an existing channel
     pub fn channel<CS: service::ChannelSpec>(
         &self,
-    ) -> Rc<service::event::Channel<CS::Tag, Self, CS::Data, CS::Priority>> {
-        self.services.event_root().channel::<CS>()
+    ) -> Rc<service::event::Channel<CS::Tag, CS::Data, CS::Priority>> {
+        self.services.borrow().event_root().channel::<CS>()
     }
     /// Queue a message onto a channel
     pub fn queue<CS: service::ChannelSpec>(&self, data: CS::Data) {
         self.services
+            .borrow()
             .event_root()
             .channel::<CS>()
             .as_ref()
             .queue(data);
     }
 }
+
+pub struct Fleck {
+    api: Rc<API>,
+}
+
+impl Fleck {
+    pub fn new() -> Self {
+        Self {
+            api: API::new()
+        }
+    }
+
+    pub fn api(&self) -> Rc<API> {
+        self.api.clone()
+    }
+}

+ 35 - 31
fleck/src/service.rs

@@ -2,72 +2,76 @@ use std::any::TypeId;
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::ops::Deref;
-use std::rc::Rc;
+use std::rc::{Weak, Rc};
 
 pub(crate) mod event;
 
 pub use event::ChannelSpec;
 
-use crate::fleck_core;
-
-pub type EventRoot = event::EventRoot<crate::Fleck>;
-
 #[allow(unused_variables)]
 pub trait Service: std::any::Any + crate::helper::AsAny {
-    fn setup(&self, api: &crate::Fleck) {}
+    fn new(api: Rc<crate::API>) -> Self;
+    fn setup(self: &Rc<Self>);
+
+    /// Please don't implement this.
+    #[doc(hidden)]
+    fn _setup_wrapper(self: &Rc<Self>, _api: Rc<crate::API>) { self.setup(); }
 }
 
-trait ServiceExt {
-    fn build() -> Self;
+#[allow(unused_variables)]
+pub trait DefaultService: Default {
+    fn setup(self: &Rc<Self>, api: Rc<crate::API>);
 }
 
-impl<T: Service + Default> ServiceExt for T {
-    fn build() -> Self {
-        Default::default()
+impl<T: 'static + DefaultService> Service for T {
+    fn new(api: Rc<crate::API>) -> Self {
+        Self::default()
+    }
+    fn setup(self: &Rc<Self>) {}
+
+    fn _setup_wrapper(self: &Rc<Self>, api: Rc<crate::API>) {
+        <T as DefaultService>::setup(self, api);
     }
 }
 
+
 #[derive(Default)]
 pub struct ServiceStack {
-    services: RefCell<Vec<Box<dyn Service>>>,
+    service_map: RefCell<HashMap<TypeId, Rc<dyn std::any::Any>>>,
 
-    service_map: RefCell<HashMap<TypeId, Box<dyn Service>>>,
+    api: Weak<crate::API>,
 
-    eroot: EventRoot,
+    eroot: event::EventRoot,
 }
 
 impl ServiceStack {
-    pub(crate) fn give_service<S: 'static + Default>(&self, api: &crate::Fleck)
-    where
-        Rc<S>: Service,
+    pub(crate) fn give_api(&mut self, api: Weak<crate::API>) {
+        self.api = api;
+    }
+    pub(crate) fn give_service<S: 'static + Service>(&self)
     {
-        self.add_service(api, Rc::new(S::default()));
+        let srv = S::new(self.api.upgrade().expect("no API given"));
+        self.add_service(srv);
     }
 
-    pub(crate) fn add_service<S: 'static>(&self, api: &crate::Fleck, srv: Rc<S>)
-    where
-        Rc<S>: Service,
+    pub(crate) fn add_service<S: 'static + Service>(&self, srv: S)
     {
-        srv.setup(api);
-
+        let srv = Rc::new(srv);
+        srv._setup_wrapper(self.api.upgrade().expect("no API given"));
         self.service_map
             .borrow_mut()
-            .insert(TypeId::of::<S>(), Box::new(srv.clone()));
-        self.services.borrow_mut().push(Box::new(srv));
+            .insert(TypeId::of::<S>(), srv);
     }
 
-    pub fn with_service<S: 'static, R, F: FnOnce(&S) -> R>(&self, f: F) -> R
-    where
-        Rc<S>: Service,
+    pub fn with_service<'l, S: Service + 'static, R, F: 'l + FnOnce(&S) -> R>(&'l self, f: F) -> R
     {
         let id = TypeId::of::<S>();
 
+        // note: we don't want to hold a reference to service_map when invoking f()
         let svc = {
             let svcs = self.service_map.borrow();
             svcs.get(&id)
                 .expect("asked for service that doesn't exist!")
-                .deref()
-                .as_any()
                 .downcast_ref::<Rc<S>>()
                 .unwrap()
                 .clone()
@@ -76,7 +80,7 @@ impl ServiceStack {
         f(svc.as_ref())
     }
 
-    pub fn event_root(&self) -> &EventRoot {
+    pub fn event_root(&self) -> &event::EventRoot {
         &self.eroot
     }
 }

+ 57 - 59
fleck/src/service/event.rs

@@ -4,64 +4,64 @@ use std::{
     rc::{Rc, Weak},
 };
 
-pub enum SubscriptionFunction<Host: 'static, Context: 'static + ?Sized, Data: 'static> {
-    ByRef(Box<dyn Fn(&Host, &Context, &mut Data)>),
-    ByValue(Box<dyn Fn(&Host, &Context, Data) -> Option<Data>>),
-    Consume(Box<dyn Fn(&Host, &Context, Data) -> ()>),
+pub enum SubscriptionFunction<Host: 'static, Data: 'static> {
+    ByRef(Box<dyn Fn(&Host, &mut Data)>),
+    ByValue(Box<dyn Fn(&Host, Data) -> Option<Data>>),
+    Consume(Box<dyn Fn(&Host, Data) -> ()>),
 }
 
-impl<Host: 'static, Context: 'static + ?Sized, Data: 'static>
-    SubscriptionFunction<Host, Context, Data>
+impl<Host: 'static, Data: 'static>
+    SubscriptionFunction<Host, Data>
 {
-    fn invoke(&self, host: &Host, context: &Context, mut data: Data) -> Option<Data> {
+    fn invoke(&self, host: &Host, mut data: Data) -> Option<Data> {
         match self {
             Self::ByRef(f) => {
-                f(host, context, &mut data);
+                f(host, &mut data);
                 Some(data)
             }
-            Self::ByValue(f) => f(host, context, data),
+            Self::ByValue(f) => f(host, data),
             Self::Consume(f) => {
-                f(host, context, data);
+                f(host, data);
                 None
             }
         }
     }
 }
 
-struct ConcreteEventSub<Host: 'static, Context: 'static + ?Sized, Data: 'static> {
+struct ConcreteEventSub<Host: 'static, Data: 'static> {
     host: Weak<Host>,
-    callback: SubscriptionFunction<Host, Context, Data>,
+    callback: SubscriptionFunction<Host, Data>,
 }
 
-trait EventSub<Context: 'static + ?Sized, Data: 'static> {
+trait EventSub<Data: 'static> {
     fn is_healthy(&self) -> bool;
-    fn invoke(&self, context: &Context, data: Data) -> Option<Data>;
+    fn invoke(&self, data: Data) -> Option<Data>;
 }
 
-impl<Host: 'static, Context: 'static + ?Sized, Data: 'static> EventSub<Context, Data>
-    for ConcreteEventSub<Host, Context, Data>
+impl<Host: 'static, Data: 'static> EventSub<Data>
+    for ConcreteEventSub<Host, Data>
 {
     fn is_healthy(&self) -> bool {
         self.host.strong_count() > 0
     }
-    fn invoke(&self, context: &Context, data: Data) -> Option<Data> {
+    fn invoke(&self, data: Data) -> Option<Data> {
         self.host
             .upgrade()
-            .map(|h| self.callback.invoke(h.as_ref(), context, data))
+            .map(|h| self.callback.invoke(h.as_ref(), data))
             .flatten()
     }
 }
 
-pub struct Channel<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static> {
-    subs: RefCell<Vec<(Priority, Rc<dyn EventSub<Context, Data>>)>>,
+pub struct Channel<Tag: 'static, Data: 'static, Priority: 'static> {
+    subs: RefCell<Vec<(Priority, Rc<dyn EventSub<Data>>)>>,
 
     queue: RefCell<VecDeque<Data>>,
 
     _ghost: std::marker::PhantomData<(Tag, Priority)>,
 }
 
-impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static> Default
-    for Channel<Tag, Context, Data, Priority>
+impl<Tag: 'static, Data: 'static, Priority: 'static> Default
+    for Channel<Tag, Data, Priority>
 {
     fn default() -> Self {
         Self {
@@ -72,13 +72,13 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static>
     }
 }
 
-impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static>
-    Channel<Tag, Context, Data, NoPriorityTag>
+impl<Tag: 'static, Data: 'static>
+    Channel<Tag, Data, NoPriorityTag>
 {
     pub fn sub_ref<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, &mut Data) + 'static,
+        CB: Fn(&Host, &mut Data) + 'static,
     >(
         &self,
         who: HC,
@@ -95,7 +95,7 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static>
     pub fn sub_opt<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, Data) -> Option<Data> + 'static,
+        CB: Fn(&Host, Data) -> Option<Data> + 'static,
     >(
         &self,
         who: HC,
@@ -112,7 +112,7 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static>
     pub fn sub_eat<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, Data) + 'static,
+        CB: Fn(&Host, Data) + 'static,
     >(
         &self,
         who: HC,
@@ -127,13 +127,13 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static>
     }
 }
 
-impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: PartialOrd>
-    Channel<Tag, Context, Data, Priority>
+impl<Tag: 'static, Data: 'static, Priority: PartialOrd>
+    Channel<Tag, Data, Priority>
 {
     pub fn sub_ref<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, &mut Data) + 'static,
+        CB: Fn(&Host, &mut Data) + 'static,
     >(
         &self,
         p: Priority,
@@ -154,7 +154,7 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: PartialOr
     pub fn sub_opt<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, Data) -> Option<Data> + 'static,
+        CB: Fn(&Host, Data) -> Option<Data> + 'static,
     >(
         &self,
         p: Priority,
@@ -175,7 +175,7 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: PartialOr
     pub fn sub_eat<
         Host: 'static,
         HC: crate::helper::IntoWeak<Host>,
-        CB: Fn(&Host, &Context, Data) + 'static,
+        CB: Fn(&Host, Data) + 'static,
     >(
         &self,
         p: Priority,
@@ -191,21 +191,21 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: PartialOr
     }
 }
 
-impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static>
-    Channel<Tag, Context, Data, Priority>
+impl<Tag: 'static, Data: 'static, Priority: 'static>
+    Channel<Tag, Data, Priority>
 {
     pub fn queue(&self, data: Data) {
         self.queue.borrow_mut().push_back(data);
     }
 
-    fn do_fire_all(&self, context: &Context) -> usize {
+    fn do_fire_all(&self) -> usize {
         let mut count = 0;
 
         while !self.queue.borrow().is_empty() {
             let mut event = self.queue.borrow_mut().pop_front();
 
             for sub in self.subs.borrow().iter() {
-                event = sub.1.invoke(context, event.unwrap());
+                event = sub.1.invoke(event.unwrap());
                 if event.is_none() {
                     break;
                 }
@@ -218,20 +218,20 @@ impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static>
     }
 }
 
-trait ChannelMetadata<Context: 'static + ?Sized> {
+trait ChannelMetadata {
     fn queue_len(&self) -> usize;
-    fn fire_all(&self, context: &Context) -> usize;
+    fn fire_all(&self) -> usize;
 }
 
-impl<Tag: 'static, Context: 'static + ?Sized, Data: 'static, Priority: 'static>
-    ChannelMetadata<Context> for Channel<Tag, Context, Data, Priority>
+impl<Tag: 'static, Data: 'static, Priority: 'static>
+    ChannelMetadata for Channel<Tag, Data, Priority>
 {
     fn queue_len(&self) -> usize {
         self.queue.borrow().len()
     }
 
-    fn fire_all(&self, context: &Context) -> usize {
-        self.do_fire_all(context)
+    fn fire_all(&self) -> usize {
+        self.do_fire_all()
     }
 }
 
@@ -258,27 +258,25 @@ impl<Tag: 'static, Data: 'static> ChannelSpec for (Tag, Data) {
     type Priority = NoPriorityTag;
 }
 
-pub struct EventRoot<Context: 'static + ?Sized> {
+pub struct EventRoot {
     pub(crate) channels: RefCell<HashMap<std::any::TypeId, Rc<dyn std::any::Any>>>,
-    metadata: RefCell<HashMap<std::any::TypeId, (&'static str, Rc<dyn ChannelMetadata<Context>>)>>,
-    _ghost: std::marker::PhantomData<Context>,
+    metadata: RefCell<HashMap<std::any::TypeId, (&'static str, Rc<dyn ChannelMetadata>)>>,
 }
 
-impl<Context: 'static + ?Sized> Default for EventRoot<Context> {
+impl Default for EventRoot {
     fn default() -> Self {
         Self {
             channels: Default::default(),
             metadata: Default::default(),
-            _ghost: std::marker::PhantomData,
         }
     }
 }
 
-impl<Context: 'static + ?Sized> EventRoot<Context> {
+impl EventRoot {
     pub fn create_channel<CS: ChannelSpec>(&self) {
-        let tid = std::any::TypeId::of::<Channel<CS::Tag, Context, CS::Data, CS::Priority>>();
+        let tid = std::any::TypeId::of::<Channel<CS::Tag, CS::Data, CS::Priority>>();
 
-        let ch = Rc::new(Channel::<CS::Tag, Context, CS::Data, CS::Priority>::default());
+        let ch = Rc::new(Channel::<CS::Tag, CS::Data, CS::Priority>::default());
         self.metadata
             .borrow_mut()
             .insert(tid, (std::any::type_name::<CS>(), ch.clone()));
@@ -287,8 +285,8 @@ impl<Context: 'static + ?Sized> EventRoot<Context> {
 
     pub fn channel<'l, 's: 'l, CS: ChannelSpec>(
         &'s self,
-    ) -> Rc<Channel<CS::Tag, Context, CS::Data, CS::Priority>> {
-        let tid = std::any::TypeId::of::<Channel<CS::Tag, Context, CS::Data, CS::Priority>>();
+    ) -> Rc<Channel<CS::Tag, CS::Data, CS::Priority>> {
+        let tid = std::any::TypeId::of::<Channel<CS::Tag, CS::Data, CS::Priority>>();
 
         let own = self.channels.borrow();
 
@@ -296,7 +294,7 @@ impl<Context: 'static + ?Sized> EventRoot<Context> {
             let entry = own.get(&tid).unwrap().clone();
 
             entry
-                .downcast::<Channel<CS::Tag, Context, CS::Data, CS::Priority>>()
+                .downcast::<Channel<CS::Tag, CS::Data, CS::Priority>>()
                 .expect("internal inconsistency?")
         } else {
             panic!(
@@ -306,13 +304,13 @@ impl<Context: 'static + ?Sized> EventRoot<Context> {
         }
     }
 
-    pub(crate) fn fire_all(&self, context: &Context) {
+    pub(crate) fn fire_all(&self) {
         let mut any = true;
         while any {
             any = false;
 
             for ch in self.metadata.borrow().iter() {
-                let count = ch.1 .1.fire_all(context);
+                let count = ch.1 .1.fire_all();
                 if count > 0 {
                     log::trace!("Queue {} processed {} event(s)", ch.1 .0, count);
                 }
@@ -337,7 +335,7 @@ mod tests {
     }
 
     impl Receiver {
-        fn receive_i32(&self, _ctx: &(), _val: &mut i32) {
+        fn receive_i32(&self, _val: &mut i32) {
             self.int_count.set(self.int_count.get() + 1);
         }
     }
@@ -348,7 +346,7 @@ mod tests {
     }
 
     impl OrderedReceiver {
-        fn receive_i32(&self, _ctx: &(), _val: &mut i32) {
+        fn receive_i32(&self, _val: &mut i32) {
             self.order.borrow_mut().push(self.id)
         }
     }
@@ -378,7 +376,7 @@ mod tests {
             .sub_ref(&recv, Receiver::receive_i32);
         root.channel::<IntChannel>().queue(0i32);
         assert_eq!(recv.int_count.get(), 0);
-        root.channel::<IntChannel>().do_fire_all(&());
+        root.channel::<IntChannel>().do_fire_all();
         assert_eq!(recv.int_count.get(), 1);
     }
 
@@ -420,7 +418,7 @@ mod tests {
         );
         root.channel::<IntPriorityChannel>().queue(0i32);
         assert_eq!(order.borrow().deref(), &vec![]);
-        root.channel::<IntPriorityChannel>().do_fire_all(&());
+        root.channel::<IntPriorityChannel>().do_fire_all();
         assert_eq!(order.borrow().deref(), &vec![1, 2, 3]);
     }
 }