Skip to content

Commit

Permalink
Add RTP support (#530)
Browse files Browse the repository at this point in the history
This commit adds support for the Real-time Transport Protocol (RTP) as
defined in RFC 3550. Some tests have also been added to ensure that the
RTP PDU class functionality is working as expected.

Signed-off-by: James Raphael Tiovalen <[email protected]>
  • Loading branch information
jamestiotio authored Mar 31, 2024
1 parent bbac2ec commit fe22186
Show file tree
Hide file tree
Showing 8 changed files with 822 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/tins/pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class TINS_API PDU {
MPLS,
DOT11_CONTROL_TA,
VXLAN,
RTP,
UNKNOWN = 999,
USER_DEFINED_PDU = 1000
};
Expand Down
328 changes: 328 additions & 0 deletions include/tins/rtp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
#ifndef TINS_RTP_H
#define TINS_RTP_H

#include <tins/endianness.h>
#include <tins/pdu.h>
#include <tins/pdu_option.h>
#include <tins/small_uint.h>

namespace Tins {

/**
* \class RTP
* \brief Represents a RTP PDU.
*
* This class represents a RTP PDU.
*
* \sa RawPDU
*/
class TINS_API RTP : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RTP;

/**
* The type used to store CSRC identifiers.
*/
typedef std::vector<uint32_t> csrc_ids_type;

/**
* The type used to store extension header data.
*/
typedef std::vector<uint32_t> extension_header_data_type;

/**
* Default constructor.
*/
RTP();

/**
* \brief Constructs a RTP object from a buffer.
*
* \param data The buffer from which this PDU will be constructed.
* \param size The size of the data buffer.
*/
RTP(const uint8_t* data, uint32_t size);

/**
* \brief Getter for the version.
*/
small_uint<2> version() const { return header_.version; }

/**
* \brief Getter for the padding bit.
*/
small_uint<1> padding_bit() const { return header_.padding; }

/**
* \brief Getter for the extension bit.
*/
small_uint<1> extension_bit() const { return header_.extension; }

/**
* \brief Getter for the CSRC count.
*/
small_uint<4> csrc_count() const { return header_.csrc_count; }

/**
* \brief Getter for the marker bit.
*/
small_uint<1> marker_bit() const { return header_.marker; }

/**
* \brief Getter for the payload type.
*/
small_uint<7> payload_type() const { return header_.payload_type; }

/**
* \brief Getter for the sequence number.
*/
uint16_t sequence_number() const { return Endian::be_to_host(header_.seq_num); }

/**
* \brief Getter for the timestamp.
*/
uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); }

/**
* \brief Getter for the SSRC identifier.
*/
uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); }

/**
* \brief Getter for the CSRC identifiers.
*/
const csrc_ids_type& csrc_ids() const {
return csrc_ids_;
}

/**
* \brief Getter for the padding size.
*/
uint8_t padding_size() const { return padding_size_; }

/**
* \brief Getter for the extension header profile.
*/
uint16_t extension_profile() const { return Endian::be_to_host(ext_header_.profile); }

/**
* \brief Getter for the extension header length.
*/
uint16_t extension_length() const { return Endian::be_to_host(ext_header_.length); }

/**
* \brief Getter for the extension header data.
*/
const extension_header_data_type& extension_data() const {
return ext_data_;
}

/**
* \brief Setter for the version.
* \param version The new version.
*/
void version(small_uint<2> version) { header_.version = version; }

/**
* \brief Setter for the extension bit.
* \param extension The new extension bit.
*/
void extension_bit(small_uint<1> extension) { header_.extension = extension; }

/**
* \brief Setter for the marker bit.
* \param marker The new marker bit.
*/
void marker_bit(small_uint<1> marker) { header_.marker = marker; }

/**
* \brief Setter for the payload type.
* \param payload_type The new payload type.
*/
void payload_type(small_uint<7> payload_type) { header_.payload_type = payload_type; }

/**
* \brief Setter for the sequence number.
* \param seq_num The new sequence number.
*/
void sequence_number(uint16_t seq_num) { header_.seq_num = Endian::host_to_be(seq_num); }

/**
* \brief Setter for the timestamp.
* \param timestamp The new timestamp.
*/
void timestamp(uint32_t timestamp) { header_.timestamp = Endian::host_to_be(timestamp); }

/**
* \brief Setter for the SSRC identifier.
* \param ssrc_id The new SSRC identifier.
*/
void ssrc_id(uint32_t ssrc_id) { header_.ssrc_id = Endian::host_to_be(ssrc_id); }

/**
* \brief Setter for the padding size.
* \param size The new padding size.
*/
void padding_size(uint8_t size) {
padding_bit(size > 0);
padding_size_ = size;
}

/**
* \brief Setter for the extension header profile.
* \param profile The new extension header profile.
*/
void extension_profile(uint16_t profile) { ext_header_.profile = Endian::host_to_be(profile); }

/**
* \brief Adds a word of extension header data.
*
* The word is added after the last word of extension header data.
*
* \param value The value of the extension header data to be added.
*/
void add_extension_data(const uint32_t value);

/**
* \brief Removes a word of extension header data.
*
* If there are multiple words of extension header data of the given value,
* only the first one will be removed.
*
* \param value The value of the extension header data to be removed.
* \return true if the extension header data was removed, false otherwise.
*/
bool remove_extension_data(const uint32_t value);

/**
* \brief Searches for extension header data that matches the given value.
* \param value The extension header data to be searched.
* \return true if the extension header data was found, false otherwise.
*/
bool search_extension_data(const uint32_t value);

/**
* \brief Adds a CSRC identifier.
*
* The CSRC identifier is added after the last CSRC identifier in the extension
* header.
*
* \param csrc_id The CSRC identifier to be added
*/
void add_csrc_id(const uint32_t csrc_id);

/**
* \brief Removes a CSRC identifier.
*
* If there are multiple CSRC identifiers of the given value, only the first one
* will be removed.
*
* \param value The value of the CSRC identifier to be removed.
* \return true if the CSRC identifier was removed, false otherwise.
*/
bool remove_csrc_id(const uint32_t value);

/**
* \brief Searches for a CSRC identifier that matches the given value.
* \param value The CSRC identifier to be searched.
* \return true if the CSRC identifier was found, false otherwise.
*/
bool search_csrc_id(const uint32_t value);

/**
* \brief Returns the RTP packet's header length.
*
* This method overrides PDU::header_size.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size
*/
uint32_t header_size() const;

/**
* \brief Returns the RTP packet's trailer length.
*
* This method overrides PDU::trailer_size.
*
* \return An uint32_t with the trailer's size.
* \sa PDU::trailer_size
*/
uint32_t trailer_size() const { return static_cast<uint32_t>(padding_size_); }

/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }

/**
* \sa PDU::clone
*/
RTP *clone() const { return new RTP(*this); }

private:
TINS_BEGIN_PACK
struct rtp_header {
#if TINS_IS_BIG_ENDIAN
uint16_t version:2,
padding:1,
extension:1,
csrc_count:4,
marker:1,
payload_type:7;
#elif TINS_IS_LITTLE_ENDIAN
uint16_t csrc_count:4,
extension:1,
padding:1,
version:2,
payload_type:7,
marker:1;
#endif
uint16_t seq_num;
uint32_t timestamp;
uint32_t ssrc_id;
} TINS_END_PACK;

TINS_BEGIN_PACK
struct rtp_extension_header {
uint16_t profile;
uint16_t length;
} TINS_END_PACK;

void write_serialization(uint8_t* buffer, uint32_t size);
csrc_ids_type::const_iterator search_csrc_id_iterator(const uint32_t csrc_id) const;
csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id);
extension_header_data_type::const_iterator search_extension_data_iterator(const uint32_t data) const;
extension_header_data_type::iterator search_extension_data_iterator(const uint32_t data);

/**
* \brief Setter for the padding bit.
* \param padding The new padding bit.
*/
void padding_bit(small_uint<1> padding) { header_.padding = padding; }

/**
* \brief Setter for the CSRC count. Hidden from the public interface.
* \param csrc_count The new CSRC count.
*/
void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; }

/**
* \brief Setter for the extension header length. Hidden from the public interface.
* \param length The new extension header length.
*/
void extension_length(uint16_t length) { ext_header_.length = Endian::host_to_be(length); }

rtp_header header_;
csrc_ids_type csrc_ids_;
rtp_extension_header ext_header_;
extension_header_data_type ext_data_;
uint8_t padding_size_;
};

} // Tins

#endif // TINS_RTP_H
1 change: 1 addition & 0 deletions include/tins/tins.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,6 @@
#include <tins/ip_reassembler.h>
#include <tins/pdu_iterator.h>
#include <tins/vxlan.h>
#include <tins/rtp.h>

#endif // TINS_TINS_H
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ set(SOURCES
radiotap.cpp
rawpdu.cpp
rsn_information.cpp
rtp.cpp
sll.cpp
snap.cpp
stp.cpp
Expand Down Expand Up @@ -131,6 +132,7 @@ set(HEADERS
${LIBTINS_INCLUDE_DIR}/tins/radiotap.h
${LIBTINS_INCLUDE_DIR}/tins/rawpdu.h
${LIBTINS_INCLUDE_DIR}/tins/rsn_information.h
${LIBTINS_INCLUDE_DIR}/tins/rtp.h
${LIBTINS_INCLUDE_DIR}/tins/sll.h
${LIBTINS_INCLUDE_DIR}/tins/small_uint.h
${LIBTINS_INCLUDE_DIR}/tins/snap.h
Expand Down
2 changes: 2 additions & 0 deletions src/detail/pdu_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ Tins::PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size
return new Tins::IEEE802_3(buffer, size);
case Tins::PDU::PPPOE:
return new Tins::PPPoE(buffer, size);
case Tins::PDU::RAW:
return new Tins::RawPDU(buffer, size);
#ifdef TINS_HAVE_DOT11
case Tins::PDU::RADIOTAP:
return new Tins::RadioTap(buffer, size);
Expand Down
Loading

0 comments on commit fe22186

Please sign in to comment.