summaryrefslogtreecommitdiff
path: root/src/protocol/udp.rs
blob: 6e8c7a920e09b417b09298c135e7c7583e2e9aaf (plain)
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
90
91
92
93
94
95
96
97
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 src_port: u16,
    pub dst_port: u16,
    pub length: u16,
    pub checksum: u16,
}

/******************************************************************************
 * Parse
 ******************************************************************************/

pub fn parse_udp(input: &[u8]) -> IResult<&[u8], UdpHeader> {
    let (input, src_port) = number::streaming::be_u16(input)?;
    let (input, dst_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 {
            src_port,
            dst_port,
            length,
            checksum,
        },
    ))
}

/******************************************************************************
 * TEST
 ******************************************************************************/

#[cfg(test)]
mod tests {
    use super::parse_udp;
    use super::UdpHeader;

    const LAST_SLICE: &'static [u8] = &[0xff];

    #[test]
    fn parse_udp_works() {
        /*
         * 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 {
            src_port: 9993,
            dst_port: 9993,
            length: 145,
            checksum: 0x57d3,
        };

        assert_eq!(parse_udp(&bytes), Ok((LAST_SLICE, expectation)));
    }
}