1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_fec_group.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
12 using base::StringPiece
;
13 using std::numeric_limits
;
19 const QuicPacketSequenceNumber kNoSequenceNumber
= kuint64max
;
22 QuicFecGroup::QuicFecGroup()
23 : min_protected_packet_(kNoSequenceNumber
),
24 max_protected_packet_(kNoSequenceNumber
),
25 payload_parity_len_(0),
26 entropy_parity_(false) {
29 QuicFecGroup::~QuicFecGroup() {}
31 bool QuicFecGroup::Update(const QuicPacketHeader
& header
,
32 StringPiece decrypted_payload
) {
33 if (received_packets_
.count(header
.packet_sequence_number
) != 0) {
36 if (min_protected_packet_
!= kNoSequenceNumber
&&
37 max_protected_packet_
!= kNoSequenceNumber
&&
38 (header
.packet_sequence_number
< min_protected_packet_
||
39 header
.packet_sequence_number
> max_protected_packet_
)) {
40 DLOG(ERROR
) << "FEC group does not cover received packet: "
41 << header
.packet_sequence_number
;
44 if (!UpdateParity(decrypted_payload
, header
.entropy_flag
)) {
47 received_packets_
.insert(header
.packet_sequence_number
);
51 bool QuicFecGroup::UpdateFec(
52 QuicPacketSequenceNumber fec_packet_sequence_number
,
53 bool fec_packet_entropy
,
54 const QuicFecData
& fec
) {
55 if (min_protected_packet_
!= kNoSequenceNumber
) {
58 SequenceNumberSet::const_iterator it
= received_packets_
.begin();
59 while (it
!= received_packets_
.end()) {
60 if ((*it
< fec
.fec_group
) ||
61 (*it
>= fec_packet_sequence_number
)) {
62 DLOG(ERROR
) << "FEC group does not cover received packet: " << *it
;
67 if (!UpdateParity(fec
.redundancy
, fec_packet_entropy
)) {
70 min_protected_packet_
= fec
.fec_group
;
71 max_protected_packet_
= fec_packet_sequence_number
- 1;
75 bool QuicFecGroup::CanRevive() const {
76 // We can revive if we're missing exactly 1 packet.
77 return NumMissingPackets() == 1;
80 bool QuicFecGroup::IsFinished() const {
81 // We are finished if we are not missing any packets.
82 return NumMissingPackets() == 0;
85 size_t QuicFecGroup::Revive(QuicPacketHeader
* header
,
86 char* decrypted_payload
,
87 size_t decrypted_payload_len
) {
92 // Identify the packet sequence number to be resurrected.
93 QuicPacketSequenceNumber missing
= kNoSequenceNumber
;
94 for (QuicPacketSequenceNumber i
= min_protected_packet_
;
95 i
<= max_protected_packet_
; ++i
) {
96 // Is this packet missing?
97 if (received_packets_
.count(i
) == 0) {
102 DCHECK_NE(kNoSequenceNumber
, missing
);
104 DCHECK_LE(payload_parity_len_
, decrypted_payload_len
);
105 if (payload_parity_len_
> decrypted_payload_len
) {
108 for (size_t i
= 0; i
< payload_parity_len_
; ++i
) {
109 decrypted_payload
[i
] = payload_parity_
[i
];
112 header
->packet_sequence_number
= missing
;
113 header
->entropy_flag
= entropy_parity_
;
115 received_packets_
.insert(missing
);
116 return payload_parity_len_
;
119 bool QuicFecGroup::ProtectsPacketsBefore(QuicPacketSequenceNumber num
) const {
120 if (max_protected_packet_
!= kNoSequenceNumber
) {
121 return max_protected_packet_
< num
;
123 // Since we might not yet have recevied the FEC packet, we must check
124 // the packets we have received.
125 return *received_packets_
.begin() < num
;
128 bool QuicFecGroup::UpdateParity(StringPiece payload
, bool entropy
) {
129 DCHECK_LE(payload
.size(), kMaxPacketSize
);
130 if (payload
.size() > kMaxPacketSize
) {
131 DLOG(ERROR
) << "Illegal payload size: " << payload
.size();
134 if (payload_parity_len_
< payload
.size()) {
135 payload_parity_len_
= payload
.size();
137 DCHECK_LE(payload
.size(), kMaxPacketSize
);
138 if (received_packets_
.empty() &&
139 min_protected_packet_
== kNoSequenceNumber
) {
140 // Initialize the parity to the value of this payload
141 memcpy(payload_parity_
, payload
.data(), payload
.size());
142 if (payload
.size() < kMaxPacketSize
) {
143 // TODO(rch): expand as needed.
144 memset(payload_parity_
+ payload
.size(), 0,
145 kMaxPacketSize
- payload
.size());
147 entropy_parity_
= entropy
;
150 // Update the parity by XORing in the data (padding with 0s if necessary).
151 for (size_t i
= 0; i
< kMaxPacketSize
; ++i
) {
152 uint8 byte
= i
< payload
.size() ? payload
[i
] : 0x00;
153 payload_parity_
[i
] ^= byte
;
155 // xor of boolean values.
156 entropy_parity_
= (entropy_parity_
!= entropy
);
160 size_t QuicFecGroup::NumMissingPackets() const {
161 if (min_protected_packet_
== kNoSequenceNumber
)
162 return numeric_limits
<size_t>::max();
163 return (max_protected_packet_
- min_protected_packet_
+ 1) -
164 received_packets_
.size();