summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluwenpeng <[email protected]>2023-07-28 14:02:23 +0800
committerluwenpeng <[email protected]>2023-08-01 11:44:26 +0800
commit7749538385eff149da2a7de73f485cdd00baa129 (patch)
tree8866ef8aa830a5e456dd323e71330253dddb6b31
parent9dd56a85f858f73fbc03079349f4c4b9b3295b79 (diff)
[feature] Support UDP Decode
-rw-r--r--src/protocol/mod.rs3
-rw-r--r--src/protocol/udp.rs106
2 files changed, 108 insertions, 1 deletions
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
index 7a3bb05..2591e5b 100644
--- a/src/protocol/mod.rs
+++ b/src/protocol/mod.rs
@@ -1,4 +1,5 @@
pub mod ethernet;
pub mod ip;
pub mod ipv4;
-pub mod ipv6; \ No newline at end of file
+pub mod ipv6;
+pub mod udp; \ No newline at end of file
diff --git a/src/protocol/udp.rs b/src/protocol/udp.rs
new file mode 100644
index 0000000..c5fab65
--- /dev/null
+++ b/src/protocol/udp.rs
@@ -0,0 +1,106 @@
+use nom::number;
+use nom::IResult;
+
+/******************************************************************************
+ * Struct
+ ******************************************************************************/
+
+/*
+ * User Datagram Header Format
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Source Port | Destination Port |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Length | Checksum |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Data |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct UdpHeader {
+ pub source_port: u16,
+ pub dest_port: u16,
+ pub length: u16,
+ pub checksum: u16,
+}
+
+/******************************************************************************
+ * API
+ ******************************************************************************/
+
+impl UdpHeader {
+ pub fn decode(input: &[u8]) -> IResult<&[u8], UdpHeader> {
+ let (input, source_port) = number::streaming::be_u16(input)?;
+ let (input, dest_port) = number::streaming::be_u16(input)?;
+ let (input, length) = number::streaming::be_u16(input)?;
+ let (input, checksum) = number::streaming::be_u16(input)?;
+
+ Ok((
+ input,
+ UdpHeader {
+ source_port,
+ dest_port,
+ length,
+ checksum,
+ },
+ ))
+ }
+}
+
+/******************************************************************************
+ * TEST
+ ******************************************************************************/
+
+#[cfg(test)]
+mod tests {
+ use super::UdpHeader;
+
+ const LAST_SLICE: &'static [u8] = &[0xff];
+
+ #[test]
+ fn udp_header_decode() {
+ /*
+ * User Datagram Protocol, Src Port: 9993, Dst Port: 9993
+ * Source Port: 9993
+ * Destination Port: 9993
+ * Length: 145
+ * Checksum: 0x57d3 [correct]
+ * [Calculated Checksum: 0x57d3]
+ * [Checksum Status: Good]
+ * [Stream index: 3]
+ * [Timestamps]
+ * [Time since first frame: 0.000000000 seconds]
+ * [Time since previous frame: 0.000000000 seconds]
+ * UDP payload (137 bytes)
+ * Data (137 bytes)
+ */
+
+ let bytes = [
+ 0x27, 0x09, /* Source Port */
+ 0x27, 0x09, /* Destination Port */
+ 0x00, 0x91, /* Length */
+ 0x57, 0xd3, /* Checksum */
+ 0xff, /* Payload */
+ ];
+
+ let expectation = UdpHeader {
+ source_port: 9993,
+ dest_port: 9993,
+ length: 145,
+ checksum: 0x57d3,
+ };
+
+ assert_eq!(UdpHeader::decode(&bytes), Ok((LAST_SLICE, expectation)));
+
+ // example
+ let result = UdpHeader::decode(&bytes);
+ if let Ok((payload, header)) = result {
+ println!("return: {:?}, payload: {}", header, payload.len());
+ } else {
+ println!("return: Incomplete data");
+ }
+ }
+}