dsf_core/net/
mod.rs

1//! Net module contains high-level message objects used to communicate between peers
2//! to maintain the network, publish and subscribe to services, and exchange data.
3//! These can be converted to and from base objects for encoding/decoding.
4
5use crate::base::Base;
6use crate::error::Error;
7use crate::types::*;
8
9pub mod request;
10pub use request::{Request, RequestKind};
11
12pub mod response;
13pub use response::{Response, ResponseKind, Status};
14
15pub const BUFF_SIZE: usize = 10 * 1024;
16
17/// Message is a network request or response message
18#[derive(Clone, PartialEq, Debug)]
19pub enum Message {
20    Request(Request),
21    Response(Response),
22}
23
24impl Message {
25    pub fn request(req: Request) -> Self {
26        Self::Request(req)
27    }
28
29    pub fn response(resp: Response) -> Self {
30        Self::Response(resp)
31    }
32
33    pub fn request_id(&self) -> RequestId {
34        match self {
35            Message::Request(req) => req.id,
36            Message::Response(resp) => resp.id,
37        }
38    }
39
40    pub fn from(&self) -> Id {
41        match self {
42            Message::Request(req) => req.from.clone(),
43            Message::Response(resp) => resp.from.clone(),
44        }
45    }
46
47    pub fn flags_mut(&mut self) -> &mut Flags {
48        match self {
49            Message::Request(req) => req.flags(),
50            Message::Response(resp) => resp.flags(),
51        }
52    }
53
54    pub fn pub_key(&self) -> Option<PublicKey> {
55        match self {
56            Message::Request(req) => req.public_key.clone(),
57            Message::Response(resp) => resp.public_key.clone(),
58        }
59    }
60
61    pub fn set_public_key(&mut self, pub_key: PublicKey) {
62        match self {
63            Message::Request(req) => req.common.public_key = Some(pub_key),
64            Message::Response(resp) => resp.common.public_key = Some(pub_key),
65        }
66    }
67}
68
69impl Into<Base> for Message {
70    fn into(self) -> Base {
71        match self {
72            Message::Request(req) => req.into(),
73            Message::Response(resp) => resp.into(),
74        }
75    }
76}
77
78impl Message {
79    /// Parses an array containing a page into a page object
80    /// fn v(id, data, sig)
81    pub fn parse<'a, V, T: AsRef<[u8]>>(data: T, pub_key_s: V) -> Result<(Message, usize), Error>
82    where
83        V: Fn(&Id) -> Option<PublicKey>,
84    {
85        let (b, n) = Base::parse(data, &pub_key_s, |_id| None)?;
86
87        let m = Message::convert(b, &pub_key_s)?;
88
89        Ok((m, n))
90    }
91}
92
93impl Message {
94    pub fn convert<V>(base: Base, key_source: V) -> Result<Message, Error>
95    where
96        V: Fn(&Id) -> Option<PublicKey>,
97    {
98        let header = base.header();
99        let app_id = header.application_id();
100        let kind = header.kind();
101
102        // Check for DSF messages
103        if app_id != 0 {
104            error!(
105                "Error converting application-specific base object {:?} to message",
106                kind
107            );
108            return Err(Error::InvalidMessageType);
109        }
110
111        // Parse request and response types
112        if kind.is_request() {
113            Ok(Message::Request(Request::convert(base, key_source)?))
114        } else if kind.is_response() {
115            Ok(Message::Response(Response::convert(base, key_source)?))
116        } else {
117            error!("Error converting base object of kind {:?} to message", kind);
118            Err(Error::InvalidMessageType)
119        }
120    }
121}
122
123#[derive(Clone, Debug)]
124pub struct Common {
125    pub from: Id,
126    pub id: RequestId,
127    pub flags: Flags,
128
129    pub remote_address: Option<Address>,
130    pub public_key: Option<PublicKey>,
131}
132
133#[cfg(test)]
134mod tests {
135
136    use std::net::{IpAddr, Ipv4Addr, SocketAddr};
137
138    use super::*;
139    use crate::base::{Body, Header};
140    use crate::page::{Page, PageInfo, PageOptions};
141    use crate::types::PageKind;
142
143    use crate::crypto;
144    #[test]
145    fn encode_decode_messages() {
146        let mut buff = vec![0u8; BUFF_SIZE];
147
148        let (pub_key, pri_key) =
149            crypto::new_pk().expect("Error generating new public/private key pair");
150        let id = crypto::hash(&pub_key).expect("Error generating new ID");
151        let fake_id = crypto::hash(&[0, 1, 2, 3, 4]).expect("Error generating fake target ID");
152        let flags = Flags::ADDRESS_REQUEST;
153        let request_id = 120;
154
155        // Create and sign page
156        let header = Header {
157            kind: PageKind::Generic.into(),
158            ..Default::default()
159        };
160        let mut page = Page::new(
161            id.clone(),
162            header,
163            PageInfo::primary(pub_key.clone()),
164            Body::None,
165            PageOptions::default(),
166        );
167
168        let mut b = Base::from(&page);
169        let n = b
170            .encode(Some(&pri_key), None, &mut buff)
171            .expect("Error signing page");
172        let sig = b.signature().clone().unwrap();
173
174        page.set_signature(sig);
175        page.raw = Some(buff[0..n].to_vec());
176
177        let messages: Vec<Message> = vec![
178            Message::Request(Request::new(
179                id.clone(),
180                0,
181                RequestKind::Hello,
182                flags.clone(),
183            )),
184            Message::Request(Request::new(
185                id.clone(),
186                1,
187                RequestKind::Ping,
188                flags.clone(),
189            )),
190            Message::Request(Request::new(
191                id.clone(),
192                request_id,
193                RequestKind::FindNode(fake_id.clone()),
194                flags.clone(),
195            )),
196            Message::Request(Request::new(
197                id.clone(),
198                request_id,
199                RequestKind::Store(id.clone(), vec![page.clone()]),
200                flags.clone(),
201            )),
202            Message::Request(Request::new(
203                id.clone(),
204                request_id,
205                RequestKind::Subscribe(fake_id.clone()),
206                flags.clone(),
207            )),
208            Message::Request(Request::new(
209                id.clone(),
210                request_id,
211                RequestKind::Query(fake_id.clone()),
212                flags.clone(),
213            )),
214            Message::Request(Request::new(
215                id.clone(),
216                request_id,
217                RequestKind::PushData(id.clone(), vec![page.clone()]),
218                flags.clone(),
219            )),
220            Message::Response(Response::new(
221                id.clone(),
222                request_id,
223                ResponseKind::Status(Status::Ok),
224                flags.clone(),
225            )),
226            // TODO: put node information here
227            Message::Response(Response::new(
228                id.clone(),
229                request_id,
230                ResponseKind::NodesFound(
231                    fake_id.clone(),
232                    vec![(
233                        fake_id.clone(),
234                        SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080).into(),
235                        pub_key.clone(),
236                    )],
237                ),
238                flags.clone(),
239            )),
240            Message::Response(Response::new(
241                id.clone(),
242                request_id,
243                ResponseKind::ValuesFound(fake_id.clone(), vec![page.clone()]),
244                flags.clone(),
245            )),
246            Message::Response(Response::new(
247                id.clone(),
248                request_id,
249                ResponseKind::NoResult,
250                flags.clone(),
251            )),
252            Message::Response(Response::new(
253                id.clone(),
254                request_id,
255                ResponseKind::PullData(fake_id.clone(), vec![page.clone()]),
256                flags.clone(),
257            )),
258        ];
259
260        for message in messages {
261            // Cast to base
262            let mut b: Base = message.clone().into();
263            // Encode base
264            let n = b
265                .encode(Some(&pri_key), None, &mut buff)
266                .expect("error encoding message");
267            // Parse base and check instances match
268            let (mut d, m) = Base::parse(&buff[..n], |_id| Some(pub_key.clone()), |_id| None)
269                .expect("error parsing message");
270
271            assert_eq!(n, m);
272
273            d.raw = None;
274            b.raw = None;
275
276            assert_eq!(b, d);
277
278            // Cast to message and check instances match
279            let message2 = Message::convert(d, |_id| Some(pub_key.clone()))
280                .expect("error converting base object to message");
281
282            assert_eq!(message, message2);
283
284            assert_eq!(message.request_id(), message2.request_id());
285        }
286    }
287}