dsf_core/net/
response.rs

1use core::convert::TryFrom;
2use core::ops::Deref;
3
4#[cfg(feature = "alloc")]
5use alloc::prelude::v1::*;
6
7use byteorder::{ByteOrder, NetworkEndian};
8use slice_ext::SplitBefore;
9
10use crate::base::{Base, BaseOptions, Body, Header};
11use crate::error::Error;
12use crate::options::Options;
13use crate::page::Page;
14use crate::types::*;
15
16use super::Common;
17use super::BUFF_SIZE;
18
19/// Generic Response message
20#[derive(Clone, Debug)]
21pub struct Response {
22    pub common: Common,
23    pub data: ResponseKind,
24}
25
26/// Response message kinds
27#[derive(Clone, PartialEq, Debug)]
28#[cfg_attr(feature = "strum", derive(strum_macros::Display))]
29pub enum ResponseKind {
30    Status(Status),
31    NodesFound(Id, Vec<(Id, Address, PublicKey)>),
32    ValuesFound(Id, Vec<Page>),
33    NoResult,
34    PullData(Id, Vec<Page>),
35}
36
37mod status {
38    pub const OK: u32 = 0x0000_0000;
39    pub const INVALID_REQUEST: u32 = 0x0000_0001;
40}
41
42/// Status response codes
43#[derive(Clone, PartialEq, Debug)]
44pub enum Status {
45    Ok,
46    InvalidRequest,
47    Unknown(u32),
48}
49
50impl From<u32> for Status {
51    fn from(v: u32) -> Self {
52        match v {
53            status::OK => Status::Ok,
54            status::INVALID_REQUEST => Status::InvalidRequest,
55            _ => Status::Unknown(v),
56        }
57    }
58}
59
60impl Into<u32> for Status {
61    fn into(self) -> u32 {
62        match self {
63            Status::Ok => status::OK,
64            Status::InvalidRequest => status::INVALID_REQUEST,
65            Status::Unknown(v) => v,
66        }
67    }
68}
69
70impl Deref for Response {
71    type Target = Common;
72
73    fn deref(&self) -> &Common {
74        &self.common
75    }
76}
77
78impl Response {
79    pub fn new(from: Id, id: RequestId, data: ResponseKind, flags: Flags) -> Response {
80        let common = Common {
81            from,
82            id,
83            flags,
84            public_key: None,
85            remote_address: None,
86        };
87        Response { common, data }
88    }
89
90    pub fn flags(&mut self) -> &mut Flags {
91        &mut self.common.flags
92    }
93
94    pub fn with_remote_address(mut self, addr: Address) -> Self {
95        self.common.remote_address = Some(addr);
96        self
97    }
98
99    pub fn set_public_key(&mut self, pk: PublicKey) {
100        self.common.public_key = Some(pk);
101    }
102
103    pub fn with_public_key(mut self, pk: PublicKey) -> Self {
104        self.common.public_key = Some(pk);
105        self
106    }
107}
108
109#[cfg(nope)]
110impl fmt::Debug for ResponseKind {
111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112        match self {
113            ResponseKind::Status => write!(f, "status"),
114            ResponseKind::NodesFound(id, nodes) => {
115                write!(f, "NodesFound({:?}): [", id)?;
116                for n in nodes {
117                    write!(f, "\n    - {:?}", n)?;
118                }
119                writeln!(f, "]")
120            }
121            ResponseKind::ValuesFound(id, values) => {
122                write!(f, "ValuesFound({:?}): [", id)?;
123                for v in values {
124                    write!(f, "\n    - {:?}", v)?;
125                }
126                writeln!(f, "]")
127            }
128            ResponseKind::NoResult => write!(f, "NoResult"),
129            ResponseKind::PullData(id, values) => {
130                write!(f, "PullData({:?}): [", id)?;
131                for v in values {
132                    write!(f, "\n    - {:?}", v)?;
133                }
134                writeln!(f, "]")
135            }
136        }
137    }
138}
139
140impl PartialEq for Response {
141    fn eq(&self, b: &Self) -> bool {
142        self.from == b.from && self.flags == b.flags && self.data == b.data
143    }
144}
145
146impl Response {
147    pub fn convert<V>(base: Base, key_source: V) -> Result<Response, Error>
148    where
149        V: Fn(&Id) -> Option<PublicKey>,
150    {
151        let header = base.header();
152
153        let empty_body = vec![];
154        let body = match base.body() {
155            Body::Cleartext(d) => d,
156            Body::None => &empty_body,
157            Body::Encrypted(_e) => {
158                panic!("Attempting to convert encrypted object to response message")
159            }
160        };
161
162        let remote_address = None;
163
164        let _public_options = base.public_options().to_vec();
165        //let _private_options = base.private_options().to_vec();
166
167        let kind = match MessageKind::try_from(header.kind()) {
168            Ok(k) => k,
169            Err(_) => return Err(Error::InvalidMessageKind),
170        };
171
172        let data = match kind {
173            MessageKind::Status => {
174                let status = NetworkEndian::read_u32(&body);
175                ResponseKind::Status(status.into())
176            }
177            MessageKind::NoResult => ResponseKind::NoResult,
178            MessageKind::NodesFound => {
179                let mut id = Id::default();
180                id.copy_from_slice(&body[..ID_LEN]);
181
182                // Build options array from body
183                let (options, _n) = Options::parse_vec(&body[ID_LEN..]).unwrap();
184
185                let nodes: Vec<_> = (&options[..])
186                    .split_before(|o| match o {
187                        Options::PeerId(_) => true,
188                        _ => false,
189                    })
190                    .filter_map(|opts| {
191                        let id = Base::peer_id_option(&opts);
192                        let addr = Base::address_option(&opts);
193                        let key = Base::pub_key_option(&opts);
194
195                        match (id, addr, key) {
196                            (Some(id), Some(addr), Some(key)) => Some((id, addr, key)),
197                            // TODO: warn here
198                            _ => None,
199                        }
200                    })
201                    .collect();
202
203                ResponseKind::NodesFound(id, nodes)
204            }
205            MessageKind::ValuesFound => {
206                let mut id = Id::default();
207                id.copy_from_slice(&body[0..ID_LEN]);
208
209                let pages = Page::decode_pages(&body[ID_LEN..], key_source).unwrap();
210
211                ResponseKind::ValuesFound(id, pages)
212            }
213            MessageKind::PullData => {
214                let mut id = Id::default();
215                id.copy_from_slice(&body[0..ID_LEN]);
216
217                let pages = Page::decode_pages(&body[ID_LEN..], key_source).unwrap();
218
219                ResponseKind::PullData(id, pages)
220            }
221            _ => {
222                error!(
223                    "Error converting base object of kind {:?} to response message",
224                    header.kind()
225                );
226                return Err(Error::InvalidMessageKind);
227            }
228        };
229
230        // Fetch other key options
231        let public_key = base.public_key.clone();
232
233        //let remote_address = Base::filter_address_option(&mut public_options);
234
235        let common = Common {
236            from: base.id().clone(),
237            id: header.index(),
238            flags: header.flags(),
239            public_key,
240            remote_address,
241        };
242        Ok(Response { common, data })
243    }
244}
245
246impl Into<Base> for Response {
247    fn into(self) -> Base {
248        let kind: MessageKind;
249        let body: Vec<u8>;
250
251        let mut buff = vec![0; BUFF_SIZE];
252
253        let mut base_options = BaseOptions::default();
254
255        match &self.data {
256            ResponseKind::Status(code) => {
257                kind = MessageKind::Status;
258                NetworkEndian::write_u32(&mut buff, code.clone().into());
259                body = (&buff[0..4]).to_vec();
260            }
261            ResponseKind::NoResult => {
262                kind = MessageKind::NoResult;
263                //TODO?: (&mut body[..ID_LEN]).copy_from_slice(&id);
264                body = vec![];
265            }
266            ResponseKind::NodesFound(id, nodes) => {
267                kind = MessageKind::NodesFound;
268                (&mut buff[..ID_LEN]).copy_from_slice(&id);
269
270                // Build options list from nodes
271                let mut options = Vec::with_capacity(nodes.len() * 3);
272                for n in nodes {
273                    options.push(Options::peer_id(n.0.clone()));
274                    options.push(Options::address(n.1));
275                    options.push(Options::pub_key(n.2.clone()));
276                }
277
278                // Encode options list to body
279                let n = Options::encode_vec(&options, &mut buff[ID_LEN..]).unwrap();
280
281                body = buff[..ID_LEN + n].to_vec();
282            }
283            ResponseKind::ValuesFound(id, pages) => {
284                kind = MessageKind::ValuesFound;
285                (&mut buff[..ID_LEN]).copy_from_slice(&id);
286
287                let n = Page::encode_pages(&pages, &mut buff[ID_LEN..]).unwrap();
288
289                body = buff[..ID_LEN + n].to_vec();
290            }
291            ResponseKind::PullData(id, pages) => {
292                kind = MessageKind::PullData;
293                (&mut buff[..ID_LEN]).copy_from_slice(&id);
294
295                let n = Page::encode_pages(&pages, &mut buff[ID_LEN..]).unwrap();
296
297                body = buff[..ID_LEN + n].to_vec();
298            }
299        }
300
301        // Create header
302        let header = Header {
303            kind: kind.into(),
304            index: self.common.id.clone(),
305            flags: self.common.flags,
306            ..Default::default()
307        };
308
309        // Write public key and address if provided
310        base_options.public_key = self.common.public_key.clone();
311        if let Some(a) = self.remote_address {
312            base_options.append_public_option(Options::address(a));
313        }
314
315        // Build base object
316        Base::new(
317            self.common.from.clone(),
318            header,
319            Body::from(body),
320            base_options,
321        )
322    }
323}