Skip to main content

lxmf_core/message/
mod.rs

1mod container;
2mod delivery;
3mod payload;
4mod state;
5mod types;
6mod wire;
7
8pub use container::MessageContainer;
9pub use delivery::{decide_delivery, DeliveryDecision};
10pub use payload::Payload;
11pub use state::State;
12pub use types::{MessageMethod, MessageState, TransportMethod, UnverifiedReason};
13pub use wire::WireMessage;
14
15use crate::error::LxmfError;
16use alloc::string::String;
17use alloc::vec::Vec;
18use rns_core::identity::PrivateIdentity;
19
20#[cfg(feature = "std")]
21fn now_secs_f64() -> f64 {
22    let now =
23        std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
24    now.as_secs_f64()
25}
26
27#[cfg(not(feature = "std"))]
28fn now_secs_f64() -> f64 {
29    0.0
30}
31
32#[derive(Debug, Clone)]
33pub struct Message {
34    pub destination_hash: Option<[u8; 16]>,
35    pub source_hash: Option<[u8; 16]>,
36    pub signature: Option<[u8; wire::SIGNATURE_LENGTH]>,
37    pub content: Vec<u8>,
38    pub title: Vec<u8>,
39    pub fields: Option<rmpv::Value>,
40    pub stamp: Option<Vec<u8>>,
41    pub timestamp: Option<f64>,
42    state: State,
43}
44
45impl Message {
46    pub fn new() -> Self {
47        Self {
48            destination_hash: None,
49            source_hash: None,
50            signature: None,
51            content: Vec::new(),
52            title: Vec::new(),
53            fields: None,
54            stamp: None,
55            timestamp: None,
56            state: State::Generating,
57        }
58    }
59
60    pub fn set_state(&mut self, state: State) {
61        self.state = state;
62    }
63
64    pub fn is_outbound(&self) -> bool {
65        self.state == State::Outbound
66    }
67
68    pub fn set_title_from_string(&mut self, title: &str) {
69        self.title = title.as_bytes().to_vec();
70    }
71
72    pub fn set_title_from_bytes(&mut self, title: &[u8]) {
73        self.title = title.to_vec();
74    }
75
76    pub fn title_as_string(&self) -> Option<String> {
77        let title = String::from_utf8(self.title.clone());
78        title.ok()
79    }
80
81    pub fn set_content_from_string(&mut self, content: &str) {
82        self.content = content.as_bytes().to_vec();
83    }
84
85    pub fn set_content_from_bytes(&mut self, content: &[u8]) {
86        self.content = content.to_vec();
87    }
88
89    pub fn set_stamp_from_bytes(&mut self, stamp: &[u8]) {
90        self.stamp = Some(stamp.to_vec());
91    }
92
93    pub fn stamp_bytes(&self) -> Option<Vec<u8>> {
94        self.stamp.clone()
95    }
96
97    pub fn content_as_string(&self) -> Option<String> {
98        let content = String::from_utf8(self.content.clone());
99        content.ok()
100    }
101
102    pub fn from_wire(bytes: &[u8]) -> Result<Self, LxmfError> {
103        let wire = WireMessage::unpack(bytes)?;
104        let payload = wire.payload;
105        Ok(Self {
106            destination_hash: Some(wire.destination),
107            source_hash: Some(wire.source),
108            signature: wire.signature,
109            content: payload.content.as_ref().map(|c| c.to_vec()).unwrap_or_default(),
110            title: payload.title.as_ref().map(|t| t.to_vec()).unwrap_or_default(),
111            fields: payload.fields,
112            stamp: payload.stamp.as_ref().map(|s| s.to_vec()),
113            timestamp: Some(payload.timestamp),
114            state: State::Generating,
115        })
116    }
117
118    pub fn to_wire(&self, signer: Option<&PrivateIdentity>) -> Result<Vec<u8>, LxmfError> {
119        let destination =
120            self.destination_hash.ok_or_else(|| LxmfError::Encode("missing destination".into()))?;
121        let source = self.source_hash.ok_or_else(|| LxmfError::Encode("missing source".into()))?;
122
123        let timestamp = self.timestamp.unwrap_or_else(now_secs_f64);
124
125        let payload = Payload::new(
126            timestamp,
127            Some(self.content.clone()),
128            Some(self.title.clone()),
129            self.fields.clone(),
130            self.stamp.clone(),
131        );
132
133        let mut wire = WireMessage::new(destination, source, payload);
134        if let Some(signature) = self.signature {
135            wire.signature = Some(signature);
136        } else if let Some(signer) = signer {
137            wire.sign(signer)?;
138        } else {
139            return Err(LxmfError::Encode("missing signature".into()));
140        }
141
142        wire.pack()
143    }
144}
145
146impl Default for Message {
147    fn default() -> Self {
148        Self::new()
149    }
150}