1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
11 #define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
12 
13 #include <string>
14 #include <vector>
15 
16 #include "absl/types/optional.h"
17 #include "api/array_view.h"
18 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
19 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
20 #include "rtc_base/copy_on_write_buffer.h"
21 
22 namespace webrtc {
23 
24 class RtpPacket {
25  public:
26   using ExtensionType = RTPExtensionType;
27   using ExtensionManager = RtpHeaderExtensionMap;
28 
29   // |extensions| required for SetExtension/ReserveExtension functions during
30   // packet creating and used if available in Parse function.
31   // Adding and getting extensions will fail until |extensions| is
32   // provided via constructor or IdentifyExtensions function.
33   RtpPacket();
34   explicit RtpPacket(const ExtensionManager* extensions);
35   RtpPacket(const RtpPacket&);
36   RtpPacket(const ExtensionManager* extensions, size_t capacity);
37   ~RtpPacket();
38 
39   RtpPacket& operator=(const RtpPacket&) = default;
40 
41   // Parse and copy given buffer into Packet.
42   // Does not require extension map to be registered (map is only required to
43   // read or allocate extensions in methods GetExtension, AllocateExtension,
44   // etc.)
45   bool Parse(const uint8_t* buffer, size_t size);
46   bool Parse(rtc::ArrayView<const uint8_t> packet);
47 
48   // Parse and move given buffer into Packet.
49   bool Parse(rtc::CopyOnWriteBuffer packet);
50 
51   // Maps extensions id to their types.
52   void IdentifyExtensions(const ExtensionManager& extensions);
53 
54   // Header.
Marker()55   bool Marker() const { return marker_; }
PayloadType()56   uint8_t PayloadType() const { return payload_type_; }
SequenceNumber()57   uint16_t SequenceNumber() const { return sequence_number_; }
Timestamp()58   uint32_t Timestamp() const { return timestamp_; }
Ssrc()59   uint32_t Ssrc() const { return ssrc_; }
60   std::vector<uint32_t> Csrcs() const;
61 
headers_size()62   size_t headers_size() const { return payload_offset_; }
63 
64   // Payload.
payload_size()65   size_t payload_size() const { return payload_size_; }
padding_size()66   size_t padding_size() const { return padding_size_; }
payload()67   rtc::ArrayView<const uint8_t> payload() const {
68     return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
69   }
PayloadBuffer()70   rtc::CopyOnWriteBuffer PayloadBuffer() const {
71     return buffer_.Slice(payload_offset_, payload_size_);
72   }
73 
74   // Buffer.
Buffer()75   rtc::CopyOnWriteBuffer Buffer() const { return buffer_; }
capacity()76   size_t capacity() const { return buffer_.capacity(); }
size()77   size_t size() const {
78     return payload_offset_ + payload_size_ + padding_size_;
79   }
data()80   const uint8_t* data() const { return buffer_.cdata(); }
FreeCapacity()81   size_t FreeCapacity() const { return capacity() - size(); }
MaxPayloadSize()82   size_t MaxPayloadSize() const { return capacity() - headers_size(); }
83 
84   // Reset fields and buffer.
85   void Clear();
86 
87   // Header setters.
88   void CopyHeaderFrom(const RtpPacket& packet);
89   void SetMarker(bool marker_bit);
90   void SetPayloadType(uint8_t payload_type);
91   void SetSequenceNumber(uint16_t seq_no);
92   void SetTimestamp(uint32_t timestamp);
93   void SetSsrc(uint32_t ssrc);
94 
95   // Fills with zeroes mutable extensions,
96   // which are modified after FEC protection is generated.
97   void ZeroMutableExtensions();
98 
99   // Removes extension of given |type|, returns false is extension was not
100   // registered in packet's extension map or not present in the packet. Only
101   // extension that should be removed must be registered, other extensions may
102   // not be registered and will be preserved as is.
103   bool RemoveExtension(ExtensionType type);
104 
105   // Writes csrc list. Assumes:
106   // a) There is enough room left in buffer.
107   // b) Extension headers, payload or padding data has not already been added.
108   void SetCsrcs(rtc::ArrayView<const uint32_t> csrcs);
109 
110   // Header extensions.
111   template <typename Extension>
112   bool HasExtension() const;
113   bool HasExtension(ExtensionType type) const;
114 
115   template <typename Extension, typename FirstValue, typename... Values>
116   bool GetExtension(FirstValue, Values...) const;
117 
118   template <typename Extension>
119   absl::optional<typename Extension::value_type> GetExtension() const;
120 
121   // Returns view of the raw extension or empty view on failure.
122   template <typename Extension>
123   rtc::ArrayView<const uint8_t> GetRawExtension() const;
124 
125   template <typename Extension, typename... Values>
126   bool SetExtension(const Values&...);
127 
128   template <typename Extension>
129   bool ReserveExtension();
130 
131   // Find or allocate an extension |type|. Returns view of size |length|
132   // to write raw extension to or an empty view on failure.
133   rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
134 
135   // Find an extension |type|.
136   // Returns view of the raw extension or empty view on failure.
137   rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
138 
139   // Reserve size_bytes for payload. Returns nullptr on failure.
140   uint8_t* SetPayloadSize(size_t size_bytes);
141   // Same as SetPayloadSize but doesn't guarantee to keep current payload.
142   uint8_t* AllocatePayload(size_t size_bytes);
143 
144   bool SetPadding(size_t padding_size);
145 
146   // Returns debug string of RTP packet (without detailed extension info).
147   std::string ToString() const;
148 
149  private:
150   struct ExtensionInfo {
ExtensionInfoExtensionInfo151     explicit ExtensionInfo(uint8_t id) : ExtensionInfo(id, 0, 0) {}
ExtensionInfoExtensionInfo152     ExtensionInfo(uint8_t id, uint8_t length, uint16_t offset)
153         : id(id), length(length), offset(offset) {}
154     uint8_t id;
155     uint8_t length;
156     uint16_t offset;
157   };
158 
159   // Helper function for Parse. Fill header fields using data in given buffer,
160   // but does not touch packet own buffer, leaving packet in invalid state.
161   bool ParseBuffer(const uint8_t* buffer, size_t size);
162 
163   // Returns pointer to extension info for a given id. Returns nullptr if not
164   // found.
165   const ExtensionInfo* FindExtensionInfo(int id) const;
166 
167   // Returns reference to extension info for a given id. Creates a new entry
168   // with the specified id if not found.
169   ExtensionInfo& FindOrCreateExtensionInfo(int id);
170 
171   // Allocates and returns place to store rtp header extension.
172   // Returns empty arrayview on failure.
173   rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
174 
175   // Promotes existing one-byte header extensions to two-byte header extensions
176   // by rewriting the data and updates the corresponding extension offsets.
177   void PromoteToTwoByteHeaderExtension();
178 
179   uint16_t SetExtensionLengthMaybeAddZeroPadding(size_t extensions_offset);
180 
WriteAt(size_t offset)181   uint8_t* WriteAt(size_t offset) { return buffer_.data() + offset; }
WriteAt(size_t offset,uint8_t byte)182   void WriteAt(size_t offset, uint8_t byte) { buffer_.data()[offset] = byte; }
ReadAt(size_t offset)183   const uint8_t* ReadAt(size_t offset) const { return buffer_.data() + offset; }
184 
185   // Header.
186   bool marker_;
187   uint8_t payload_type_;
188   uint8_t padding_size_;
189   uint16_t sequence_number_;
190   uint32_t timestamp_;
191   uint32_t ssrc_;
192   size_t payload_offset_;  // Match header size with csrcs and extensions.
193   size_t payload_size_;
194 
195   ExtensionManager extensions_;
196   std::vector<ExtensionInfo> extension_entries_;
197   size_t extensions_size_ = 0;  // Unaligned.
198   rtc::CopyOnWriteBuffer buffer_;
199 };
200 
201 template <typename Extension>
HasExtension()202 bool RtpPacket::HasExtension() const {
203   return HasExtension(Extension::kId);
204 }
205 
206 template <typename Extension, typename FirstValue, typename... Values>
GetExtension(FirstValue first,Values...values)207 bool RtpPacket::GetExtension(FirstValue first, Values... values) const {
208   auto raw = FindExtension(Extension::kId);
209   if (raw.empty())
210     return false;
211   return Extension::Parse(raw, first, values...);
212 }
213 
214 template <typename Extension>
GetExtension()215 absl::optional<typename Extension::value_type> RtpPacket::GetExtension() const {
216   absl::optional<typename Extension::value_type> result;
217   auto raw = FindExtension(Extension::kId);
218   if (raw.empty() || !Extension::Parse(raw, &result.emplace()))
219     result = absl::nullopt;
220   return result;
221 }
222 
223 template <typename Extension>
GetRawExtension()224 rtc::ArrayView<const uint8_t> RtpPacket::GetRawExtension() const {
225   return FindExtension(Extension::kId);
226 }
227 
228 template <typename Extension, typename... Values>
SetExtension(const Values &...values)229 bool RtpPacket::SetExtension(const Values&... values) {
230   const size_t value_size = Extension::ValueSize(values...);
231   auto buffer = AllocateExtension(Extension::kId, value_size);
232   if (buffer.empty())
233     return false;
234   return Extension::Write(buffer, values...);
235 }
236 
237 template <typename Extension>
ReserveExtension()238 bool RtpPacket::ReserveExtension() {
239   auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
240   if (buffer.empty())
241     return false;
242   memset(buffer.data(), 0, Extension::kValueSizeBytes);
243   return true;
244 }
245 
246 }  // namespace webrtc
247 
248 #endif  // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
249