use super::*;
use nom::{
number::complete::be_u64,
combinator::rest,
};
use tox_binary_io::*;
use tox_crypto::*;
use crate::dht::errors::*;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NodesRequest {
pub pk: PublicKey,
pub nonce: Nonce,
pub payload: Vec<u8>,
}
impl ToBytes for NodesRequest {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_be_u8!(0x02) >>
gen_slice!(self.pk.as_ref()) >>
gen_slice!(self.nonce.as_ref()) >>
gen_slice!(self.payload.as_slice())
)
}
}
impl FromBytes for NodesRequest {
named!(from_bytes<NodesRequest>, do_parse!(
tag!("\x02") >>
pk: call!(PublicKey::from_bytes) >>
nonce: call!(Nonce::from_bytes) >>
payload: map!(rest, |bytes| bytes.to_vec() ) >>
(NodesRequest { pk, nonce, payload })
));
}
impl NodesRequest {
pub fn new(shared_secret: &PrecomputedKey, pk: &PublicKey, payload: &NodesRequestPayload) -> NodesRequest {
let nonce = gen_nonce();
let mut buf = [0; MAX_DHT_PACKET_SIZE];
let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
let payload = seal_precomputed(&buf[..size], &nonce, shared_secret);
NodesRequest {
pk: *pk,
nonce,
payload,
}
}
pub fn get_payload(&self, shared_secret: &PrecomputedKey) -> Result<NodesRequestPayload, GetPayloadError> {
let decrypted = open_precomputed(&self.payload, &self.nonce, shared_secret)
.map_err(|()| {
GetPayloadError::decrypt()
})?;
match NodesRequestPayload::from_bytes(&decrypted) {
Err(error) => {
Err(GetPayloadError::deserialize(error, decrypted.clone()))
},
Ok((_, payload)) => {
Ok(payload)
}
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct NodesRequestPayload {
pub pk: PublicKey,
pub id: u64,
}
impl ToBytes for NodesRequestPayload {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_slice!(self.pk.as_ref()) >>
gen_be_u64!(self.id)
)
}
}
impl FromBytes for NodesRequestPayload {
named!(from_bytes<NodesRequestPayload>, do_parse!(
pk: call!(PublicKey::from_bytes) >>
id: be_u64 >>
eof!() >>
(NodesRequestPayload { pk, id })
));
}
#[cfg(test)]
mod tests {
use crate::dht::nodes_request::*;
use crate::dht::Packet;
encode_decode_test!(
tox_crypto::crypto_init().unwrap(),
nodes_request_payload_encode_decode,
NodesRequestPayload { pk: gen_keypair().0, id: 42 }
);
dht_packet_encode_decode!(nodes_request_encode_decode, NodesRequest);
dht_packet_encrypt_decrypt!(
nodes_request_payload_encrypt_decrypt,
NodesRequest,
NodesRequestPayload { pk: gen_keypair().0, id: 42 }
);
dht_packet_encrypt_decrypt_invalid_key!(
nodes_request_payload_encrypt_decrypt_invalid_key,
NodesRequest,
NodesRequestPayload { pk: gen_keypair().0, id: 42 }
);
dht_packet_decode_invalid!(nodes_request_decode_invalid, NodesRequest);
}