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