1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとりアドベントカレンダー by MasAdvent Calendar 2024

Day 4

VoIPとSIPを通じてRustを勉強する:ざつにRTP parser/builder作成編

Last updated at Posted at 2024-12-03

はじめに

本記事は自分のためでしかないアドベントカレンダー2024の記事です。
記事は25記事書くと思いますが期待はせずにお願いします

RTPパーサ/ビルダ

ざつに作成しました

RTPパーサ

rtp_parser.rs
struct RtpPacketParser<'a> {
    rtp_packet: &'a [u8],
}

impl<'a> RtpPacketParser<'a> {
    pub fn new(rtp_packet: &'a [u8]) -> Self {
        let retval = RtpPacketParser {
            rtp_packet: &rtp_packet,
        };

        return retval;
    }

    fn version(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_0011;
    }

    fn padding(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_0100;
    }

    fn extension(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_1000;
    }

    fn csrc_count(&self) -> u8 {
        return self.rtp_packet[0] & 0b1111_0000;
    }
    fn payload_type(&self) -> u8 {
        return self.rtp_packet[1];
    }
    fn sequence_number(&self) -> u16 {
        return u16::from_be_bytes(self.rtp_packet[2..4].try_into().unwrap());
    }

    fn time_stamp(&self) -> u32 {
        return u32::from_be_bytes(self.rtp_packet[4..8].try_into().unwrap());
    }
    fn ssrc(&self) -> u32 {
        return u32::from_be_bytes(self.rtp_packet[8..12].try_into().unwrap());
    }

    fn payload(&self) -> &'a [u8] {
        return &self.rtp_packet[12..self.rtp_packet.len()];
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_all() {
        let hoge = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1];
        let packet = RtpPacketParser::new(&hoge);

        println!("{:?}", packet.ssrc());
        println!("{:?}", packet.payload_type());
    }
}

RTPビルダ

rtp_builder.rs
pub struct RtpBuilder<'a> {
    version: u8,
    padding: u8,
    extension: u8,
    csrc_count: u8,
    marker: u8,
    payload_type: u8,
    sequence_number: u16,
    time_stamp: u32,
    ssrc: u32,
    payload: Option<&'a [u8]>,
}

impl<'a> RtpBuilder<'a> {
    pub fn new() -> Self {
        RtpBuilder {
            version: 0,
            padding: 0,
            extension: 0,
            csrc_count: 0,
            marker: 0,
            payload_type: 0xFF,
            sequence_number: 0,
            time_stamp: 0,
            ssrc: 0,
            payload: None,
        }
    }
    fn version(mut self, version: u8) -> Self {
        self.version = version;
        self
    }
    fn padding(mut self, padding: u8) -> Self {
        self.padding = padding;
        self
    }
    fn extension(mut self, extension: u8) -> Self {
        self.extension = extension;
        self
    }
    fn csrc_count(mut self, csrc_count: u8) -> Self {
        self.csrc_count = csrc_count;
        self
    }
    fn marker(mut self, marker: u8) -> Self {
        self.marker = marker;
        self
    }
    fn payload_type(mut self, payload_type: u8) -> Self {
        self.payload_type = payload_type;
        self
    }
    fn sequence_number(mut self, sequence_number: u16) -> Self {
        self.sequence_number = sequence_number;
        self
    }
    fn time_stamp(mut self, time_stamp: u32) -> Self {
        self.time_stamp = time_stamp;
        self
    }
    fn ssrc(mut self, ssrc: u32) -> Self {
        self.ssrc = ssrc;
        self
    }

    fn payload(mut self, payload: &'a [u8]) -> Self {
        self.payload = Some(payload);
        self
    }

    fn build(&self, rtp_packet: &mut [u8]) {
        rtp_packet[0] = self.version;
        rtp_packet[0] |= self.padding << 2;
        rtp_packet[0] |= self.extension << 3;
        rtp_packet[0] |= self.csrc_count << 4;

        rtp_packet[1] = self.payload_type;

        rtp_packet[2..4].copy_from_slice(&self.sequence_number.to_be_bytes());
        rtp_packet[4..8].copy_from_slice(&self.time_stamp.to_be_bytes());
        rtp_packet[8..12].copy_from_slice(&self.ssrc.to_be_bytes());
        if let Some(payload) = self.payload {
            rtp_packet[12..(12 + payload.len())].copy_from_slice(payload);
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_all() {
        let payload = [1u8; 4];
        let mut hoge = [0u8; 16];
        let packet: () = RtpBuilder::new()
            .payload_type(1)
            .payload(&payload)
            .build(hoge.as_mut_slice());
        println!("{:?}", hoge);
    }
}

おわりに

Rust何もわからん

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?