fec在quic新版本中废弃了,据官方说法,在大部分情况下,作用不大。fec从本质上讲是基于冗余的,会浪费带宽。只能恢复随机丢包。大块丢包也无能为力。
不过,quic实现还是代表了一种十分优美的方案,算法简单实用。
quic fec 只能恢复fecgroup里一个包
比如: 10个包+加上一个fec包
接收端:
- fec包。fecqroup记录这个,初始化为第一个接受到的group组包
- 然后group每来一个数据包,做xor
- 当组结束时,检查丢包,如果只有一个丢失,则恭喜,fec包就是丢的那个
- 恢复完成
//这里才是数据包的起始入口,哇咔哇
void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
const QuicEncryptedPacket& packet) {
if (!connected_) {
return;
}
#if 0
// TODO(rtenneti): Remove ScopedTracker below once crbug.com/462789 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"462789 QuicConnection::ProcessUdpPacket"));
#endif
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPacketReceived(self_address, peer_address, packet);
}
last_size_ = packet.length();
CheckForAddressMigration(self_address, peer_address);
stats_.bytes_received += packet.length();
++stats_.packets_received;
if (!framer_.ProcessPacket(packet)) {
// If we are unable to decrypt this packet, it might be
// because the CHLO or SHLO packet was lost.
if (framer_.error() == QUIC_DECRYPTION_FAILURE) {
if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
undecryptable_packets_.size() < max_undecryptable_packets_) {
QueueUndecryptablePacket(packet);
} else if (debug_visitor_ != nullptr) {
debug_visitor_->OnUndecryptablePacket();
}
}
DVLOG(1) << ENDPOINT << "Unable to process packet. Last packet processed: "
<< last_header_.packet_sequence_number;
return;
}
++stats_.packets_processed;
MaybeProcessUndecryptablePackets();
//here for check revive packet
MaybeProcessRevivedPacket();
MaybeSendInResponseToPacket();
SetPingAlarm();
}
bool QuicFramer::ProcessDataPacket(const QuicPacketPublicHeader& public_header,
const QuicEncryptedPacket& packet,
char* decrypted_buffer,
size_t buffer_length) {
QuicPacketHeader header(public_header);
if (!ProcessPacketHeader(&header, packet, decrypted_buffer, buffer_length)) {
DLOG(WARNING) << "Unable to process packet header. Stopping parsing.";
return false;
}
if (!visitor_->OnPacketHeader(header)) {
// The visitor suppresses further processing of the packet.
return true;
}
if (packet.length() > kMaxPacketSize) {
DLOG(WARNING) << "Packet too large: " << packet.length();
return RaiseError(QUIC_PACKET_TOO_LARGE);
}
// Handle the payload.
if (!header.fec_flag) {
if (header.is_in_fec_group == IN_FEC_GROUP) {
StringPiece payload = reader_->PeekRemainingPayload();
//to do xor payload.update fec_
visitor_->OnFecProtectedPayload(payload);
}
if (!ProcessFrameData(header)) {
DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
DLOG(WARNING) << "Unable to process frame data.";
return false;
}
} else {
QuicFecData fec_data;
fec_data.fec_group = header.fec_group;
fec_data.redundancy = reader_->ReadRemainingPayload();
// save fec payload
visitor_->OnFecData(fec_data);
}
visitor_->OnPacketComplete();
return true;
}
min_protected_packet_ 是fec_group 组号
max_protected_packet_ 是group 最大的那个seqnumber
发送端:
是先发fec包??
最后发的!!
ReliableQuicStream::WriteOrBufferData—>
ReliableQuicStream::WritevData—>
QuicConnection::SendStreamData—>
QuicPacketGenerator::ConsumeData—>
QuicPacketGenerator::MaybeStartFecProtection—>
QuicPacketCreator::SerializeFec—>
QuicPacketCreator::SerializePacket—>
OnBuiltFecProtectedPayload
(header, packet->
FecProtectedData
());