Commit f47dd313 authored by jan.koester's avatar jan.koester
Browse files

bugfix rtt

parent da47e0f9
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -2937,6 +2937,52 @@ void quic::processRetryPacket(const uint8_t* data, size_t len) {
    applyHeaderProtection(packet, EncryptionLevel::Initial, _initial_keys.send);
    buffer send_buf(reinterpret_cast<const char*>(packet.data()), packet.size());
    udp::sendData(send_buf, 0);

    // This server requires a Retry round trip (accept()'s always-Retry
    // policy for a token-less first Initial), which just changed our DCID —
    // any 0-RTT packets already sent under the old DCID are now
    // unreachable and would otherwise just sit in _sent_packets waiting on
    // their PTO timer, which retransmits only the single oldest unacked
    // packet at a time and backs off exponentially on each subsequent
    // firing (checkLossAndRetransmit()) — recovering a handful of early
    // packets one at a time that way could take multiple seconds. Resend
    // them all immediately instead, right alongside the retried Initial:
    // this is what actually makes offering 0-RTT worthwhile against a
    // server whose default policy always Retries an unrecognized client.
    if (!_sent_packets.empty()) {
        std::vector<SentPacket> early_resend;
        for (auto it = _sent_packets.begin(); it != _sent_packets.end(); ) {
            if (it->second.sent_as_early_data) {
                early_resend.push_back(std::move(it->second));
                it = _sent_packets.erase(it);
            } else {
                ++it;
            }
        }
        for (auto& sp : early_resend) {
            uint8_t frame_type = 0x08 | 0x02; // STREAM, LEN bit
            if (sp.stream_offset > 0) frame_type |= 0x04; // OFF bit
            if (sp.fin) frame_type |= 0x01;
            std::vector<uint8_t> frame;
            frame.reserve(1 + 8 + 8 + 8 + sp.data_length);
            frame.push_back(frame_type);
            uint8_t vb[8]; size_t vl;
            vl = encodeVarInt(sp.stream_id, vb); frame.insert(frame.end(), vb, vb + vl);
            if (sp.stream_offset > 0) {
                vl = encodeVarInt(sp.stream_offset, vb); frame.insert(frame.end(), vb, vb + vl);
            }
            vl = encodeVarInt(sp.data_length, vb); frame.insert(frame.end(), vb, vb + vl);
            frame.insert(frame.end(), sp.stream_data.begin(), sp.stream_data.end());

            uint64_t new_pn = _app_pn_send;
            std::vector<uint8_t> early_packet = buildZeroRTTPacket(frame);
            applyHeaderProtection(early_packet, EncryptionLevel::EarlyData, _early_keys.send);
            sendPacket(early_packet.data(), early_packet.size());
            recordSentPacket(new_pn, sp.stream_id, sp.stream_offset, sp.stream_data.data(),
                              sp.stream_data.size(), sp.fin, early_packet.size(),
                              /*sent_as_early_data=*/true);
        }
    }
}

void quic::processShortHeaderPacket(const uint8_t* data, size_t len) {