1use std::{
2 fmt::{Display, Formatter, Result as FmtResult},
3 mem,
4 net::SocketAddr,
5};
6
7#[allow(unused_imports)]
8pub use self::{
9 client_hello::{ClientHello, Flags, InvalidFlags},
10 connect::Connect,
11 dissociate::Dissociate,
12 heartbeat::Heartbeat,
13 packet::Packet,
14 server_hello::ServerHello,
15};
16
17mod client_hello;
18mod connect;
19mod dissociate;
20mod heartbeat;
21mod packet;
22mod server_hello;
23
24pub const VERSION: u8 = 0x00;
25
26#[non_exhaustive]
27#[derive(Clone, Debug)]
28pub enum Header {
29 ClientHello(ClientHello),
30 ServerHello(ServerHello),
31 Connect(Connect),
32 Packet(Packet),
33 Dissociate(Dissociate),
34 Heartbeat(Heartbeat),
35}
36
37impl Header {
38 pub const TYPE_CODE_CLIENT_HELLO: u8 = ClientHello::type_code();
39 pub const TYPE_CODE_SERVER_HELLO: u8 = ServerHello::type_code();
40 pub const TYPE_CODE_CONNECT: u8 = Connect::type_code();
41 pub const TYPE_CODE_PACKET: u8 = Packet::type_code();
42 pub const TYPE_CODE_DISSOCIATE: u8 = Dissociate::type_code();
43 pub const TYPE_CODE_HEARTBEAT: u8 = Heartbeat::type_code();
44
45 pub const fn type_code(&self) -> u8 {
47 match self {
48 Self::ClientHello(_) => Self::TYPE_CODE_CLIENT_HELLO,
49 Self::ServerHello(_) => Self::TYPE_CODE_SERVER_HELLO,
50 Self::Connect(_) => Self::TYPE_CODE_CONNECT,
51 Self::Packet(_) => Self::TYPE_CODE_PACKET,
52 Self::Dissociate(_) => Self::TYPE_CODE_DISSOCIATE,
53 Self::Heartbeat(_) => Self::TYPE_CODE_HEARTBEAT,
54 }
55 }
56
57 #[allow(clippy::len_without_is_empty)]
59 pub fn len(&self) -> usize {
60 2 + match self {
61 Self::ClientHello(client_hello) => client_hello.len(),
62 Self::ServerHello(server_hello) => server_hello.len(),
63 Self::Connect(connect) => connect.len(),
64 Self::Packet(packet) => packet.len(),
65 Self::Dissociate(dissociate) => dissociate.len(),
66 Self::Heartbeat(heartbeat) => heartbeat.len(),
67 }
68 }
69}
70
71#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
98pub enum Address {
99 None,
100 SocketAddress(SocketAddr),
101}
102
103impl Address {
104 pub const TYPE_CODE_NONE: u8 = 0xff;
105 pub const TYPE_CODE_IPV4: u8 = 0x01;
106 pub const TYPE_CODE_IPV6: u8 = 0x04;
107
108 pub const fn type_code(&self) -> u8 {
110 match self {
111 Self::None => Self::TYPE_CODE_NONE,
112 Self::SocketAddress(addr) => match addr {
113 SocketAddr::V4(_) => Self::TYPE_CODE_IPV4,
114 SocketAddr::V6(_) => Self::TYPE_CODE_IPV6,
115 },
116 }
117 }
118
119 #[allow(clippy::len_without_is_empty)]
121 pub fn len(&self) -> usize {
122 1 + match self {
123 Address::None => 0,
124 Address::SocketAddress(SocketAddr::V4(_)) => 4 + 2,
125 Address::SocketAddress(SocketAddr::V6(_)) => 16 + 2,
126 }
127 }
128
129 pub fn take(&mut self) -> Self {
131 mem::take(self)
132 }
133
134 pub fn is_none(&self) -> bool {
136 matches!(self, Self::None)
137 }
138
139 pub fn is_ipv4(&self) -> bool {
141 matches!(self, Self::SocketAddress(SocketAddr::V4(_)))
142 }
143
144 pub fn is_ipv6(&self) -> bool {
146 matches!(self, Self::SocketAddress(SocketAddr::V6(_)))
147 }
148}
149
150impl Display for Address {
151 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
152 match self {
153 Self::None => write!(f, "none"),
154 Self::SocketAddress(addr) => write!(f, "{addr}"),
155 }
156 }
157}
158
159impl Default for Address {
160 fn default() -> Self {
161 Self::None
162 }
163}