dns_message_parser/rr/edns/
rfc_7873.rs

1use hex::encode;
2use std::fmt::{Display, Formatter, Result as FmtResult};
3use thiserror::Error;
4
5pub const CLIENT_COOKIE_LENGTH: usize = 8;
6pub const MINIMUM_SERVER_COOKIE_LENGTH: usize = 8;
7pub const MAXIMUM_SERVER_COOKIE_LENGTH: usize = 32;
8
9#[derive(Debug, PartialEq, Clone, Eq, Hash)]
10pub struct Cookie {
11    pub client_cookie: [u8; 8],
12    server_cookie: Option<Vec<u8>>,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Error)]
16pub enum CookieError {
17    #[error("Server cookie length is not between {MINIMUM_SERVER_COOKIE_LENGTH} and {MAXIMUM_SERVER_COOKIE_LENGTH}: {0}]")]
18    ServerCookieLength(usize),
19}
20
21impl Cookie {
22    pub fn new(
23        client_cookie: [u8; 8],
24        server_cookie: Option<Vec<u8>>,
25    ) -> Result<Cookie, CookieError> {
26        let mut cookie = Cookie {
27            client_cookie,
28            server_cookie: None,
29        };
30        cookie.set_server_cookie(server_cookie)?;
31        Ok(cookie)
32    }
33
34    pub fn set_server_cookie(&mut self, server_cookie: Option<Vec<u8>>) -> Result<(), CookieError> {
35        match server_cookie {
36            Some(server_cookie) => {
37                let server_cookie_len = server_cookie.len();
38                if (MINIMUM_SERVER_COOKIE_LENGTH..MAXIMUM_SERVER_COOKIE_LENGTH)
39                    .contains(&server_cookie_len)
40                {
41                    self.server_cookie.replace(server_cookie);
42                    Ok(())
43                } else {
44                    Err(CookieError::ServerCookieLength(server_cookie_len))
45                }
46            }
47            None => {
48                self.server_cookie.take();
49                Ok(())
50            }
51        }
52    }
53
54    pub fn get_server_cookie(&self) -> Option<&[u8]> {
55        self.server_cookie.as_deref()
56    }
57}
58
59impl Display for Cookie {
60    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
61        write!(f, "Cookie {}", encode(self.client_cookie))?;
62        match &self.server_cookie {
63            Some(server_cookie) => write!(f, " {}", encode(server_cookie)),
64            None => Ok(()),
65        }
66    }
67}