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
/// SIP-Version
/// ex. `SIP/2.0 -> SipVersion(2, 0)`
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct SipVersion(pub u8, pub u8);

#[derive(Debug, PartialEq)]
pub enum MessageType {
    Request,
    Response,
    Unknown,
}

const SIP: &'static [u8] = &['S' as u8, 'I' as u8, 'P' as u8]; // SIP
                                                               // First 3 letters of Request Method
const ACK: &'static [u8] = &['A' as u8, 'C' as u8, 'K' as u8]; // ACK
const BYE: &'static [u8] = &['B' as u8, 'Y' as u8, 'E' as u8]; // BYE
const REG: &'static [u8] = &['R' as u8, 'E' as u8, 'G' as u8]; // REGISTER
const CAN: &'static [u8] = &['C' as u8, 'A' as u8, 'N' as u8]; // CANCEL
const INF: &'static [u8] = &['I' as u8, 'N' as u8, 'F' as u8]; // INFO
const INV: &'static [u8] = &['I' as u8, 'N' as u8, 'V' as u8]; // INVITE
const MES: &'static [u8] = &['M' as u8, 'E' as u8, 'S' as u8]; // MESSAGE
const NOT: &'static [u8] = &['N' as u8, 'O' as u8, 'T' as u8]; // NOTIFY
const OPT: &'static [u8] = &['O' as u8, 'P' as u8, 'T' as u8]; // OPTIONS
const PRA: &'static [u8] = &['P' as u8, 'R' as u8, 'A' as u8]; // PRACK
const PUB: &'static [u8] = &['P' as u8, 'U' as u8, 'B' as u8]; // PUBLISH
const REF: &'static [u8] = &['R' as u8, 'E' as u8, 'F' as u8]; // REFER
const SUB: &'static [u8] = &['S' as u8, 'U' as u8, 'B' as u8]; // SUBSCRIBE
const UPD: &'static [u8] = &['U' as u8, 'P' as u8, 'D' as u8]; // UPDATE

/// Fast determinates message type and minimal validate for further transmission to suitable parser.
/// Does not validate full first line, just first 3 bytes.
/// ```rust
/// assert_eq!(
///     sipmsg::get_sip_message_type(
///         "INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0".as_bytes()
///     ),
///     sipmsg::SipMessageType::Request
/// );
/// ```
pub fn get_message_type(mt: &[u8]) -> MessageType {
    if mt.len() < 3 {
        MessageType::Unknown
    } else {
        match &mt[0..3] {
            SIP => MessageType::Response,
            ACK => MessageType::Request,
            BYE => MessageType::Request,
            REG => MessageType::Request,
            CAN => MessageType::Request,
            INF => MessageType::Request,
            INV => MessageType::Request,
            MES => MessageType::Request,
            NOT => MessageType::Request,
            OPT => MessageType::Request,
            PRA => MessageType::Request,
            PUB => MessageType::Request,
            REF => MessageType::Request,
            SUB => MessageType::Request,
            UPD => MessageType::Request,
            _ => MessageType::Unknown,
        }
    }
}