1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Handles parsing of UDP header
use binator::{
base::primitive::u16_be,
utils::UtilsAtom,
Contexting,
CoreAtom,
Parse,
Parsed,
Streaming,
Success,
};
/// Data of a UDP Header
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UdpHeader {
/// This field identifies the sender's port, when used, and should be assumed
/// to be the port to reply to if needed. If not used, it should be zero. If
/// the source host is the client, the port number is likely to be an
/// ephemeral port. If the source host is the server, the port number is
/// likely to be a well-known port number from 0 to 1023.
pub source_port: u16,
/// This field identifies the receiver's port and is required. Similar to
/// source port number, if the client is the destination host then the port
/// number will likely be an ephemeral port number and if the destination host
/// is the server then the port number will likely be a well-known port
/// number.
pub dest_port: u16,
/// This field specifies the length in bytes of the UDP header and UDP data.
pub length: u16,
/// The checksum field may be used for error-checking of the header and data.
/// This field is optional in IPv4, and mandatory in most cases in IPv6. The
/// field carries all-zeros if unused.
pub checksum: u16,
}
/// UDP header parser
pub fn udp_header<Stream, Context>(stream: Stream) -> Parsed<UdpHeader, Stream, Context>
where
Stream: Streaming,
Stream: Eq,
Stream::Item: Into<u8>,
Context: Contexting<CoreAtom<Stream>>,
Context: Contexting<UtilsAtom<Stream>>,
{
let Success {
token: (source_port, dest_port, length, checksum),
stream,
} = (u16_be, u16_be, u16_be, u16_be).parse(stream)?;
Parsed::Success {
token: UdpHeader {
source_port,
dest_port,
length,
checksum,
},
stream,
}
}
#[cfg(test)]
mod tests {
use binator::{
context::Ignore,
Parsed,
};
use super::UdpHeader;
#[test]
fn udp_header_works() {
let bytes = [0x00, 0x12, 0x11, 0x11, 0x00, 0x1B, 0x21, 0x0F];
let expectation = UdpHeader {
source_port: 0x12,
dest_port: 0x1111,
length: 0x1B,
checksum: 0x210F,
};
assert_eq!(
super::udp_header::<_, Ignore>(&bytes[..]),
Parsed::Success {
token: expectation,
stream: &[][..]
}
);
}
}