hydra/frame/
hello.rs

1use std::net::SocketAddr;
2
3use sha2::Sha256;
4
5use hmac::Hmac;
6use hmac::Mac;
7
8use bincode::Decode;
9use bincode::Encode;
10
11use crate::node_get_cookie;
12
13/// Hmac using sha256.
14type HmacSha256 = Hmac<Sha256>;
15
16/// The frame used to handshake with other nodes.
17#[derive(Debug, Encode, Decode)]
18pub struct Hello {
19    pub name: String,
20    pub broadcast_address: SocketAddr,
21    pub challenge: Vec<u8>,
22}
23
24impl Hello {
25    /// Constructs a new instance of the [Hello] frame.
26    pub fn new(name: String, broadcast_address: SocketAddr) -> Self {
27        let mut challenge = {
28            let cookie = node_get_cookie();
29            let cookie = cookie
30                .as_ref()
31                .map(|cookie| cookie.as_bytes())
32                .unwrap_or(&[0]);
33
34            HmacSha256::new_from_slice(cookie).unwrap()
35        };
36
37        challenge.update(name.as_bytes());
38        challenge.update(broadcast_address.to_string().as_bytes());
39
40        Self {
41            name,
42            broadcast_address,
43            challenge: challenge.finalize().into_bytes().to_vec(),
44        }
45    }
46
47    /// Validates this [Hello] frame against our cookie.
48    pub fn validate(&mut self) -> bool {
49        let mut challenge = {
50            let cookie = node_get_cookie();
51            let cookie = cookie
52                .as_ref()
53                .map(|cookie| cookie.as_bytes())
54                .unwrap_or(&[0]);
55
56            HmacSha256::new_from_slice(cookie).unwrap()
57        };
58
59        challenge.update(self.name.as_bytes());
60        challenge.update(self.broadcast_address.to_string().as_bytes());
61
62        let wanted = challenge.finalize().into_bytes();
63
64        let challenge = std::mem::take(&mut self.challenge);
65
66        wanted.as_slice() == challenge
67    }
68}