/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ #include #include #include namespace quic { template inline folly::Optional AckScheduler::writeNextAcks( PacketBuilderInterface& builder, AckMode mode) { switch (mode) { case AckMode::Immediate: { return writeAcksImpl(builder); } case AckMode::Pending: { return writeAcksIfPending(builder); } } folly::assume_unreachable(); } template inline folly::Optional AckScheduler::writeAcksIfPending( PacketBuilderInterface& builder) { if (ackState_.needsToSendAckImmediately) { return writeAcksImpl(builder); } return folly::none; } template folly::Optional AckScheduler::writeAcksImpl( PacketBuilderInterface& builder) { // Use default ack delay for long headers. Usually long headers are sent // before crypto negotiation, so the peer might not know about the ack delay // exponent yet, so we use the default. uint8_t ackDelayExponentToUse = builder.getPacketHeader().getHeaderForm() == HeaderForm::Long ? kDefaultAckDelayExponent : conn_.transportSettings.ackDelayExponent; auto largestAckedPacketNum = *largestAckToSend(ackState_); auto ackingTime = ClockType::now(); DCHECK(ackState_.largestRecvdPacketTime.hasValue()) << "Missing received time for the largest acked packet"; // assuming that we're going to ack the largest received with hightest pri auto receivedTime = *ackState_.largestRecvdPacketTime; std::chrono::microseconds ackDelay = (ackingTime > receivedTime ? std::chrono::duration_cast( ackingTime - receivedTime) : 0us); AckFrameMetaData meta(ackState_.acks, ackDelay, ackDelayExponentToUse); auto ackWriteResult = writeAckFrame(meta, builder); if (!ackWriteResult) { return folly::none; } return largestAckedPacketNum; } } // namespace quic