blob: b69f50712760d9f2384265eba2d235942b06baa2 [file] [log] [blame]
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001/*
2 * Copyright (c) 2014 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
11#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
12
Erik Språngc1b9d4e2015-06-08 09:54:14 +020013#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010014#include "webrtc/base/logging.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000015#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000016
17namespace webrtc {
18namespace rtcp {
19namespace {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000020void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000021 buffer[(*offset)++] = value;
22}
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000023void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000024 ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000025 *offset += 2;
26}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000027} // namespace
28
29void RtcpPacket::Append(RtcpPacket* packet) {
30 assert(packet);
31 appended_packets_.push_back(packet);
32}
33
danilchap69e59e62016-02-17 03:11:42 -080034rtc::Buffer RtcpPacket::Build() const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000035 size_t length = 0;
danilchap69e59e62016-02-17 03:11:42 -080036 rtc::Buffer packet(IP_PACKET_SIZE);
Erik Språngc1b9d4e2015-06-08 09:54:14 +020037
38 class PacketVerifier : public PacketReadyCallback {
39 public:
danilchap69e59e62016-02-17 03:11:42 -080040 explicit PacketVerifier(rtc::Buffer* packet)
Erik Språngc1b9d4e2015-06-08 09:54:14 +020041 : called_(false), packet_(packet) {}
42 virtual ~PacketVerifier() {}
43 void OnPacketReady(uint8_t* data, size_t length) override {
henrikg91d6ede2015-09-17 00:24:34 -070044 RTC_CHECK(!called_) << "Fragmentation not supported.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +020045 called_ = true;
danilchap69e59e62016-02-17 03:11:42 -080046 packet_->SetSize(length);
Erik Språngc1b9d4e2015-06-08 09:54:14 +020047 }
48
49 private:
50 bool called_;
danilchap69e59e62016-02-17 03:11:42 -080051 rtc::Buffer* const packet_;
52 } verifier(&packet);
53 CreateAndAddAppended(packet.data(), &length, packet.capacity(), &verifier);
54 OnBufferFull(packet.data(), &length, &verifier);
Erik Språngc1b9d4e2015-06-08 09:54:14 +020055 return packet;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000056}
57
Erik Språngc1b9d4e2015-06-08 09:54:14 +020058bool RtcpPacket::Build(PacketReadyCallback* callback) const {
59 uint8_t buffer[IP_PACKET_SIZE];
60 return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000061}
62
Erik Språngc1b9d4e2015-06-08 09:54:14 +020063bool RtcpPacket::BuildExternalBuffer(uint8_t* buffer,
64 size_t max_length,
65 PacketReadyCallback* callback) const {
66 size_t index = 0;
67 if (!CreateAndAddAppended(buffer, &index, max_length, callback))
68 return false;
69 return OnBufferFull(buffer, &index, callback);
70}
71
72bool RtcpPacket::CreateAndAddAppended(uint8_t* packet,
73 size_t* index,
74 size_t max_length,
75 PacketReadyCallback* callback) const {
76 if (!Create(packet, index, max_length, callback))
77 return false;
78 for (RtcpPacket* appended : appended_packets_) {
79 if (!appended->CreateAndAddAppended(packet, index, max_length, callback))
80 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000081 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +020082 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000083}
84
Erik Språngc1b9d4e2015-06-08 09:54:14 +020085bool RtcpPacket::OnBufferFull(uint8_t* packet,
86 size_t* index,
87 RtcpPacket::PacketReadyCallback* callback) const {
88 if (*index == 0)
89 return false;
90 callback->OnPacketReady(packet, *index);
91 *index = 0;
92 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000093}
94
Erik Språnga3b87692015-07-29 10:46:54 +020095size_t RtcpPacket::HeaderLength() const {
96 size_t length_in_bytes = BlockLength();
97 // Length in 32-bit words minus 1.
98 assert(length_in_bytes > 0);
99 return ((length_in_bytes + 3) / 4) - 1;
100}
101
102// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
103//
104// RTP header format.
105// 0 1 2 3
106// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
107// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108// |V=2|P| RC/FMT | PT | length |
109// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110
111void RtcpPacket::CreateHeader(
112 uint8_t count_or_format, // Depends on packet type.
113 uint8_t packet_type,
114 size_t length,
115 uint8_t* buffer,
sprang73a93e82015-09-14 12:50:39 -0700116 size_t* pos) {
Erik Språnga3b87692015-07-29 10:46:54 +0200117 assert(length <= 0xffff);
118 const uint8_t kVersion = 2;
119 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
120 AssignUWord8(buffer, pos, packet_type);
121 AssignUWord16(buffer, pos, length);
122}
123
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000124} // namespace rtcp
125} // namespace webrtc