ratman_types/
message.rs

1// SPDX-FileCopyrightText: 2019-2022 Katharina Fey <kookie@spacekookie.de>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later WITH LicenseRef-AppStore
4
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "proto")]
8pub use crate::proto::message::Message as ProtoMessage;
9
10use crate::timepair::TimePair;
11use ratman_identity::Identity;
12
13/// Specify the message recipient
14#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
15pub enum Recipient {
16    Standard(Vec<Identity>),
17    Flood(Identity),
18}
19
20impl Recipient {
21    /// Create a standard message recipient
22    pub fn standard<T: Into<Vec<Identity>>>(addrs: T) -> Self {
23        Self::Standard(addrs.into())
24    }
25    /// Create a flood message recipient
26    pub fn flood(namespace: Identity) -> Self {
27        Self::Flood(namespace)
28    }
29}
30
31impl From<Vec<Identity>> for Recipient {
32    fn from(vec: Vec<Identity>) -> Self {
33        Self::Standard(vec)
34    }
35}
36
37/// Main Ratman message type
38///
39/// A message can either be addressed to a single recipient, or a
40/// namespace on the network.
41#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
42pub struct Message {
43    id: Identity,
44    sender: Identity,
45    recipient: Recipient,
46    time: TimePair,
47    payload: Vec<u8>,
48    signature: Vec<u8>,
49}
50
51impl Message {
52    pub fn new(
53        sender: Identity,
54        recipient: impl Into<Recipient>,
55        payload: Vec<u8>,
56        signature: Vec<u8>,
57    ) -> Self {
58        Message {
59            id: Identity::random(),
60            recipient: recipient.into(),
61            time: TimePair::sending(),
62            sender,
63            payload,
64            signature,
65        }
66    }
67
68    pub fn get_payload(&self) -> Vec<u8> {
69        self.payload.clone()
70    }
71
72    pub fn get_sender(&self) -> Identity {
73        self.sender.clone()
74    }
75
76    // return protobuf type Message.
77    #[cfg(feature = "proto")]
78    pub fn received(
79        id: Identity,
80        sender: Identity,
81        recipient: Recipient,
82        payload: Vec<u8>,
83        timesig: String,
84        sign: Vec<u8>,
85    ) -> ProtoMessage {
86        let mut inner = ProtoMessage::new();
87        inner.set_id(id.as_bytes().to_vec());
88        inner.set_sender(sender.as_bytes().to_vec());
89
90        use crate::proto::message::{Recipient as ProtoRecipient, StandardRecipient};
91
92        let mut r = ProtoRecipient::new();
93        match recipient {
94            Recipient::Standard(addrs) => {
95                let mut std_r = StandardRecipient::new();
96                std_r.set_standard(
97                    addrs
98                        .into_iter()
99                        .map(|id| id.as_bytes().to_vec())
100                        .collect::<Vec<_>>()
101                        .into(),
102                );
103                r.set_std(std_r);
104            }
105            Recipient::Flood(ns) => {
106                r.set_flood_scope(ns.as_bytes().to_vec().into());
107            }
108        }
109
110        inner.set_recipient(r);
111        inner.set_time(timesig);
112        inner.set_payload(payload);
113        inner.set_signature(sign);
114
115        inner
116    }
117}
118
119/// Implement RAW `From` protobuf type message
120#[cfg(feature = "proto")]
121impl From<ProtoMessage> for Message {
122    fn from(mut msg: ProtoMessage) -> Self {
123        use crate::proto::message::Recipient_oneof_inner;
124
125        let mut r = msg.take_recipient();
126        let recipient = match r.inner {
127            Some(Recipient_oneof_inner::std(ref mut std)) => Recipient::Standard(
128                std.take_standard()
129                    .into_iter()
130                    .map(|id| Identity::from_bytes(&id))
131                    .collect(),
132            ),
133            Some(Recipient_oneof_inner::flood_scope(ref id)) => {
134                Recipient::Flood(Identity::from_bytes(id))
135            }
136            _ => unreachable!(),
137        };
138
139        Message {
140            id: Identity::from_bytes(msg.get_id()),
141            sender: Identity::from_bytes(msg.get_id()),
142            recipient,
143            time: TimePair::from_string(msg.get_time()),
144            payload: msg.get_payload().to_vec(),
145            signature: msg.get_signature().to_vec(),
146        }
147    }
148}
149
150/// Implement protobuf type message `From` RAW
151#[cfg(feature = "proto")]
152impl From<Message> for ProtoMessage {
153    fn from(msg: Message) -> ProtoMessage {
154        let mut inner = ProtoMessage::new();
155        inner.set_sender(msg.sender.as_bytes().to_vec());
156
157        use crate::proto::message::{Recipient as ProtoRecipient, StandardRecipient};
158
159        let mut r = ProtoRecipient::new();
160        match msg.recipient {
161            Recipient::Standard(addrs) => {
162                let mut std_r = StandardRecipient::new();
163                std_r.set_standard(
164                    addrs
165                        .into_iter()
166                        .map(|id| id.as_bytes().to_vec())
167                        .collect::<Vec<_>>()
168                        .into(),
169                );
170                r.set_std(std_r);
171            }
172            Recipient::Flood(ns) => {
173                r.set_flood_scope(ns.as_bytes().to_vec().into());
174            }
175        }
176
177        inner.set_recipient(r);
178        inner.set_payload(msg.payload);
179        inner.set_signature(msg.signature);
180        inner
181    }
182}