Skip to main content

rings_core/message/handlers/
custom.rs

1use async_trait::async_trait;
2
3use crate::dht::Did;
4use crate::error::Result;
5use crate::message::effects::CoreEffect;
6use crate::message::effects::PayloadRelayFunctor;
7use crate::message::types::CustomMessage;
8use crate::message::HandleMsg;
9use crate::message::MessageHandler;
10use crate::message::MessagePayload;
11
12pub(crate) fn custom_message_effects<'payload>(
13    local: Did,
14    ctx: &'payload MessagePayload,
15) -> Option<CoreEffect<'payload>> {
16    if ctx.should_forward_from(local) {
17        Some(PayloadRelayFunctor::forward_payload(ctx, None).into())
18    } else {
19        None
20    }
21}
22
23#[cfg_attr(feature = "wasm", async_trait(?Send))]
24#[cfg_attr(not(feature = "wasm"), async_trait)]
25impl HandleMsg<CustomMessage> for MessageHandler {
26    async fn handle(&self, ctx: &MessagePayload, _: &CustomMessage) -> Result<()> {
27        self.run_effects(custom_message_effects(self.dht.did, ctx))
28            .await
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35    use crate::ecc::SecretKey;
36    use crate::error::Error;
37    use crate::message::Message;
38    use crate::session::SessionSk;
39
40    fn custom_payload(destination: Did) -> Result<MessagePayload> {
41        let key = SecretKey::random();
42        let session_sk = SessionSk::new_with_seckey(&key)?;
43        MessagePayload::new_send(
44            Message::custom(b"hello")?,
45            &session_sk,
46            destination,
47            destination,
48        )
49    }
50
51    #[test]
52    fn local_custom_message_has_no_core_effects() -> Result<()> {
53        let local = SecretKey::random().address().into();
54        let payload = custom_payload(local)?;
55
56        assert!(custom_message_effects(local, &payload).is_none());
57        Ok(())
58    }
59
60    #[test]
61    fn remote_custom_message_forwards_payload() -> Result<()> {
62        let local = SecretKey::random().address().into();
63        let remote = SecretKey::random().address().into();
64        let payload = custom_payload(remote)?;
65        let effect = custom_message_effects(local, &payload)
66            .ok_or_else(|| Error::InvalidMessage("expected ForwardPayload effect".to_string()))?;
67
68        match effect {
69            CoreEffect::Payload(PayloadRelayFunctor::ForwardPayload {
70                payload: forwarded,
71                next_hop,
72            }) => {
73                assert!(std::ptr::eq(forwarded, &payload));
74                assert_eq!(next_hop, None);
75            }
76            effect => {
77                return Err(Error::InvalidMessage(format!(
78                    "expected ForwardPayload, got {effect:?}"
79                )))
80            }
81        }
82        Ok(())
83    }
84}