Skip to content

Commit fe22186

Browse files
authored
Add RTP support (#530)
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]>
1 parent bbac2ec commit fe22186

File tree

8 files changed

+822
-0
lines changed

8 files changed

+822
-0
lines changed

include/tins/pdu.h

+1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class TINS_API PDU {
181181
MPLS,
182182
DOT11_CONTROL_TA,
183183
VXLAN,
184+
RTP,
184185
UNKNOWN = 999,
185186
USER_DEFINED_PDU = 1000
186187
};

include/tins/rtp.h

+328
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
#ifndef TINS_RTP_H
2+
#define TINS_RTP_H
3+
4+
#include <tins/endianness.h>
5+
#include <tins/pdu.h>
6+
#include <tins/pdu_option.h>
7+
#include <tins/small_uint.h>
8+
9+
namespace Tins {
10+
11+
/**
12+
* \class RTP
13+
* \brief Represents a RTP PDU.
14+
*
15+
* This class represents a RTP PDU.
16+
*
17+
* \sa RawPDU
18+
*/
19+
class TINS_API RTP : public PDU {
20+
public:
21+
/**
22+
* \brief This PDU's flag.
23+
*/
24+
static const PDU::PDUType pdu_flag = PDU::RTP;
25+
26+
/**
27+
* The type used to store CSRC identifiers.
28+
*/
29+
typedef std::vector<uint32_t> csrc_ids_type;
30+
31+
/**
32+
* The type used to store extension header data.
33+
*/
34+
typedef std::vector<uint32_t> extension_header_data_type;
35+
36+
/**
37+
* Default constructor.
38+
*/
39+
RTP();
40+
41+
/**
42+
* \brief Constructs a RTP object from a buffer.
43+
*
44+
* \param data The buffer from which this PDU will be constructed.
45+
* \param size The size of the data buffer.
46+
*/
47+
RTP(const uint8_t* data, uint32_t size);
48+
49+
/**
50+
* \brief Getter for the version.
51+
*/
52+
small_uint<2> version() const { return header_.version; }
53+
54+
/**
55+
* \brief Getter for the padding bit.
56+
*/
57+
small_uint<1> padding_bit() const { return header_.padding; }
58+
59+
/**
60+
* \brief Getter for the extension bit.
61+
*/
62+
small_uint<1> extension_bit() const { return header_.extension; }
63+
64+
/**
65+
* \brief Getter for the CSRC count.
66+
*/
67+
small_uint<4> csrc_count() const { return header_.csrc_count; }
68+
69+
/**
70+
* \brief Getter for the marker bit.
71+
*/
72+
small_uint<1> marker_bit() const { return header_.marker; }
73+
74+
/**
75+
* \brief Getter for the payload type.
76+
*/
77+
small_uint<7> payload_type() const { return header_.payload_type; }
78+
79+
/**
80+
* \brief Getter for the sequence number.
81+
*/
82+
uint16_t sequence_number() const { return Endian::be_to_host(header_.seq_num); }
83+
84+
/**
85+
* \brief Getter for the timestamp.
86+
*/
87+
uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); }
88+
89+
/**
90+
* \brief Getter for the SSRC identifier.
91+
*/
92+
uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); }
93+
94+
/**
95+
* \brief Getter for the CSRC identifiers.
96+
*/
97+
const csrc_ids_type& csrc_ids() const {
98+
return csrc_ids_;
99+
}
100+
101+
/**
102+
* \brief Getter for the padding size.
103+
*/
104+
uint8_t padding_size() const { return padding_size_; }
105+
106+
/**
107+
* \brief Getter for the extension header profile.
108+
*/
109+
uint16_t extension_profile() const { return Endian::be_to_host(ext_header_.profile); }
110+
111+
/**
112+
* \brief Getter for the extension header length.
113+
*/
114+
uint16_t extension_length() const { return Endian::be_to_host(ext_header_.length); }
115+
116+
/**
117+
* \brief Getter for the extension header data.
118+
*/
119+
const extension_header_data_type& extension_data() const {
120+
return ext_data_;
121+
}
122+
123+
/**
124+
* \brief Setter for the version.
125+
* \param version The new version.
126+
*/
127+
void version(small_uint<2> version) { header_.version = version; }
128+
129+
/**
130+
* \brief Setter for the extension bit.
131+
* \param extension The new extension bit.
132+
*/
133+
void extension_bit(small_uint<1> extension) { header_.extension = extension; }
134+
135+
/**
136+
* \brief Setter for the marker bit.
137+
* \param marker The new marker bit.
138+
*/
139+
void marker_bit(small_uint<1> marker) { header_.marker = marker; }
140+
141+
/**
142+
* \brief Setter for the payload type.
143+
* \param payload_type The new payload type.
144+
*/
145+
void payload_type(small_uint<7> payload_type) { header_.payload_type = payload_type; }
146+
147+
/**
148+
* \brief Setter for the sequence number.
149+
* \param seq_num The new sequence number.
150+
*/
151+
void sequence_number(uint16_t seq_num) { header_.seq_num = Endian::host_to_be(seq_num); }
152+
153+
/**
154+
* \brief Setter for the timestamp.
155+
* \param timestamp The new timestamp.
156+
*/
157+
void timestamp(uint32_t timestamp) { header_.timestamp = Endian::host_to_be(timestamp); }
158+
159+
/**
160+
* \brief Setter for the SSRC identifier.
161+
* \param ssrc_id The new SSRC identifier.
162+
*/
163+
void ssrc_id(uint32_t ssrc_id) { header_.ssrc_id = Endian::host_to_be(ssrc_id); }
164+
165+
/**
166+
* \brief Setter for the padding size.
167+
* \param size The new padding size.
168+
*/
169+
void padding_size(uint8_t size) {
170+
padding_bit(size > 0);
171+
padding_size_ = size;
172+
}
173+
174+
/**
175+
* \brief Setter for the extension header profile.
176+
* \param profile The new extension header profile.
177+
*/
178+
void extension_profile(uint16_t profile) { ext_header_.profile = Endian::host_to_be(profile); }
179+
180+
/**
181+
* \brief Adds a word of extension header data.
182+
*
183+
* The word is added after the last word of extension header data.
184+
*
185+
* \param value The value of the extension header data to be added.
186+
*/
187+
void add_extension_data(const uint32_t value);
188+
189+
/**
190+
* \brief Removes a word of extension header data.
191+
*
192+
* If there are multiple words of extension header data of the given value,
193+
* only the first one will be removed.
194+
*
195+
* \param value The value of the extension header data to be removed.
196+
* \return true if the extension header data was removed, false otherwise.
197+
*/
198+
bool remove_extension_data(const uint32_t value);
199+
200+
/**
201+
* \brief Searches for extension header data that matches the given value.
202+
* \param value The extension header data to be searched.
203+
* \return true if the extension header data was found, false otherwise.
204+
*/
205+
bool search_extension_data(const uint32_t value);
206+
207+
/**
208+
* \brief Adds a CSRC identifier.
209+
*
210+
* The CSRC identifier is added after the last CSRC identifier in the extension
211+
* header.
212+
*
213+
* \param csrc_id The CSRC identifier to be added
214+
*/
215+
void add_csrc_id(const uint32_t csrc_id);
216+
217+
/**
218+
* \brief Removes a CSRC identifier.
219+
*
220+
* If there are multiple CSRC identifiers of the given value, only the first one
221+
* will be removed.
222+
*
223+
* \param value The value of the CSRC identifier to be removed.
224+
* \return true if the CSRC identifier was removed, false otherwise.
225+
*/
226+
bool remove_csrc_id(const uint32_t value);
227+
228+
/**
229+
* \brief Searches for a CSRC identifier that matches the given value.
230+
* \param value The CSRC identifier to be searched.
231+
* \return true if the CSRC identifier was found, false otherwise.
232+
*/
233+
bool search_csrc_id(const uint32_t value);
234+
235+
/**
236+
* \brief Returns the RTP packet's header length.
237+
*
238+
* This method overrides PDU::header_size.
239+
*
240+
* \return An uint32_t with the header's size.
241+
* \sa PDU::header_size
242+
*/
243+
uint32_t header_size() const;
244+
245+
/**
246+
* \brief Returns the RTP packet's trailer length.
247+
*
248+
* This method overrides PDU::trailer_size.
249+
*
250+
* \return An uint32_t with the trailer's size.
251+
* \sa PDU::trailer_size
252+
*/
253+
uint32_t trailer_size() const { return static_cast<uint32_t>(padding_size_); }
254+
255+
/**
256+
* \brief Getter for the PDU's type.
257+
* \sa PDU::pdu_type
258+
*/
259+
PDUType pdu_type() const { return pdu_flag; }
260+
261+
/**
262+
* \sa PDU::clone
263+
*/
264+
RTP *clone() const { return new RTP(*this); }
265+
266+
private:
267+
TINS_BEGIN_PACK
268+
struct rtp_header {
269+
#if TINS_IS_BIG_ENDIAN
270+
uint16_t version:2,
271+
padding:1,
272+
extension:1,
273+
csrc_count:4,
274+
marker:1,
275+
payload_type:7;
276+
#elif TINS_IS_LITTLE_ENDIAN
277+
uint16_t csrc_count:4,
278+
extension:1,
279+
padding:1,
280+
version:2,
281+
payload_type:7,
282+
marker:1;
283+
#endif
284+
uint16_t seq_num;
285+
uint32_t timestamp;
286+
uint32_t ssrc_id;
287+
} TINS_END_PACK;
288+
289+
TINS_BEGIN_PACK
290+
struct rtp_extension_header {
291+
uint16_t profile;
292+
uint16_t length;
293+
} TINS_END_PACK;
294+
295+
void write_serialization(uint8_t* buffer, uint32_t size);
296+
csrc_ids_type::const_iterator search_csrc_id_iterator(const uint32_t csrc_id) const;
297+
csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id);
298+
extension_header_data_type::const_iterator search_extension_data_iterator(const uint32_t data) const;
299+
extension_header_data_type::iterator search_extension_data_iterator(const uint32_t data);
300+
301+
/**
302+
* \brief Setter for the padding bit.
303+
* \param padding The new padding bit.
304+
*/
305+
void padding_bit(small_uint<1> padding) { header_.padding = padding; }
306+
307+
/**
308+
* \brief Setter for the CSRC count. Hidden from the public interface.
309+
* \param csrc_count The new CSRC count.
310+
*/
311+
void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; }
312+
313+
/**
314+
* \brief Setter for the extension header length. Hidden from the public interface.
315+
* \param length The new extension header length.
316+
*/
317+
void extension_length(uint16_t length) { ext_header_.length = Endian::host_to_be(length); }
318+
319+
rtp_header header_;
320+
csrc_ids_type csrc_ids_;
321+
rtp_extension_header ext_header_;
322+
extension_header_data_type ext_data_;
323+
uint8_t padding_size_;
324+
};
325+
326+
} // Tins
327+
328+
#endif // TINS_RTP_H

include/tins/tins.h

+1
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,6 @@
8080
#include <tins/ip_reassembler.h>
8181
#include <tins/pdu_iterator.h>
8282
#include <tins/vxlan.h>
83+
#include <tins/rtp.h>
8384

8485
#endif // TINS_TINS_H

src/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ set(SOURCES
5454
radiotap.cpp
5555
rawpdu.cpp
5656
rsn_information.cpp
57+
rtp.cpp
5758
sll.cpp
5859
snap.cpp
5960
stp.cpp
@@ -131,6 +132,7 @@ set(HEADERS
131132
${LIBTINS_INCLUDE_DIR}/tins/radiotap.h
132133
${LIBTINS_INCLUDE_DIR}/tins/rawpdu.h
133134
${LIBTINS_INCLUDE_DIR}/tins/rsn_information.h
135+
${LIBTINS_INCLUDE_DIR}/tins/rtp.h
134136
${LIBTINS_INCLUDE_DIR}/tins/sll.h
135137
${LIBTINS_INCLUDE_DIR}/tins/small_uint.h
136138
${LIBTINS_INCLUDE_DIR}/tins/snap.h

src/detail/pdu_helpers.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ Tins::PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size
169169
return new Tins::IEEE802_3(buffer, size);
170170
case Tins::PDU::PPPOE:
171171
return new Tins::PPPoE(buffer, size);
172+
case Tins::PDU::RAW:
173+
return new Tins::RawPDU(buffer, size);
172174
#ifdef TINS_HAVE_DOT11
173175
case Tins::PDU::RADIOTAP:
174176
return new Tins::RadioTap(buffer, size);

0 commit comments

Comments
 (0)