22
33#include < array>
44#include < cstddef>
5+ #include < limits>
56#include < string>
67#include < string_view>
78
@@ -226,6 +227,43 @@ void append_parameter(std::vector<std::uint8_t>& out,
226227 }
227228}
228229
230+ void append_parameter_delta (std::vector<std::uint8_t >& out,
231+ std::uint64_t & previous_type,
232+ std::uint64_t type,
233+ std::span<const std::uint8_t > value) {
234+ const std::uint64_t delta = type - previous_type;
235+ append_varint (out, delta);
236+ if ((type & 0x1ULL ) == 0 ) {
237+ out.insert (out.end (), value.begin (), value.end ());
238+ } else {
239+ append_varint (out, value.size ());
240+ out.insert (out.end (), value.begin (), value.end ());
241+ }
242+ previous_type = type;
243+ }
244+
245+ bool decode_parameter_type (std::span<const std::uint8_t > bytes,
246+ std::size_t & offset,
247+ std::uint64_t & previous_type,
248+ bool delta_encoded,
249+ std::uint64_t & parameter_type) {
250+ std::uint64_t encoded_type = 0 ;
251+ if (!decode_varint_impl (bytes, offset, encoded_type)) {
252+ return false ;
253+ }
254+ if (!delta_encoded) {
255+ parameter_type = encoded_type;
256+ previous_type = parameter_type;
257+ return true ;
258+ }
259+ if (encoded_type > std::numeric_limits<std::uint64_t >::max () - previous_type) {
260+ return false ;
261+ }
262+ parameter_type = previous_type + encoded_type;
263+ previous_type = parameter_type;
264+ return true ;
265+ }
266+
229267std::uint64_t draft_version_number (DraftVersion draft) {
230268 switch (draft) {
231269 case DraftVersion::kDraft14 :
@@ -323,15 +361,28 @@ std::vector<std::uint8_t> encode_setup_message(const SetupMessage& message) {
323361
324362 const bool include_native_quic_location = message.transport == TransportKind::kRawQuic ;
325363 append_varint (payload, include_native_quic_location ? 3 : 1 );
364+ std::uint64_t previous_parameter_type = 0 ;
326365 if (include_native_quic_location) {
327- const std::vector<std::uint8_t > authority = to_bytes (message.authority );
328366 const std::vector<std::uint8_t > path = to_bytes (message.path );
329- append_parameter (payload, kSetupParamAuthority , authority);
330- append_parameter (payload, kSetupParamPath , path);
367+ const std::vector<std::uint8_t > authority = to_bytes (message.authority );
368+ if (message.draft == DraftVersion::kDraft16 ) {
369+ append_parameter_delta (payload, previous_parameter_type, kSetupParamPath , path);
370+ } else {
371+ append_parameter (payload, kSetupParamAuthority , authority);
372+ append_parameter (payload, kSetupParamPath , path);
373+ }
331374 }
332375 std::vector<std::uint8_t > max_request_id;
333376 append_varint (max_request_id, message.max_request_id );
334- append_parameter (payload, kSetupParamMaxRequestId , max_request_id);
377+ if (message.draft == DraftVersion::kDraft16 ) {
378+ append_parameter_delta (payload, previous_parameter_type, kSetupParamMaxRequestId , max_request_id);
379+ if (include_native_quic_location) {
380+ const std::vector<std::uint8_t > authority = to_bytes (message.authority );
381+ append_parameter_delta (payload, previous_parameter_type, kSetupParamAuthority , authority);
382+ }
383+ } else {
384+ append_parameter (payload, kSetupParamMaxRequestId , max_request_id);
385+ }
335386
336387 std::vector<std::uint8_t > message_bytes;
337388 append_varint (message_bytes, kClientSetupType );
@@ -366,10 +417,16 @@ bool decode_server_setup_message(std::span<const std::uint8_t> bytes, ServerSetu
366417 const std::uint8_t first_payload_byte = bytes[offset];
367418 if ((first_payload_byte & 0xc0 ) == 0xc0 ) {
368419 std::uint64_t selected_version = 0 ;
369- if (!decode_varint_impl (payload_bytes, offset, selected_version) || selected_version != kDraft14Version ) {
420+ if (!decode_varint_impl (payload_bytes, offset, selected_version)) {
421+ return false ;
422+ }
423+ if (selected_version == kDraft14Version ) {
424+ message.draft = DraftVersion::kDraft14 ;
425+ } else if (selected_version == kDraft16Version ) {
426+ message.draft = DraftVersion::kDraft16 ;
427+ } else {
370428 return false ;
371429 }
372- message.draft = DraftVersion::kDraft14 ;
373430 } else {
374431 message.draft = DraftVersion::kDraft16 ;
375432 }
@@ -379,9 +436,11 @@ bool decode_server_setup_message(std::span<const std::uint8_t> bytes, ServerSetu
379436 return false ;
380437 }
381438
439+ std::uint64_t previous_parameter_type = 0 ;
440+ const bool delta_encoded = message.draft == DraftVersion::kDraft16 ;
382441 for (std::uint64_t parameter_index = 0 ; parameter_index < parameter_count; ++parameter_index) {
383442 std::uint64_t parameter_type = 0 ;
384- if (!decode_varint_impl (payload_bytes, offset, parameter_type)) {
443+ if (!decode_parameter_type (payload_bytes, offset, previous_parameter_type, delta_encoded , parameter_type)) {
385444 return false ;
386445 }
387446
@@ -413,9 +472,14 @@ std::vector<std::uint8_t> encode_server_setup_message(const ServerSetupMessage&
413472 }
414473
415474 append_varint (payload, 1 );
475+ std::uint64_t previous_parameter_type = 0 ;
416476 std::vector<std::uint8_t > max_request_id;
417477 append_varint (max_request_id, message.max_request_id );
418- append_parameter (payload, kSetupParamMaxRequestId , max_request_id);
478+ if (message.draft == DraftVersion::kDraft16 ) {
479+ append_parameter_delta (payload, previous_parameter_type, kSetupParamMaxRequestId , max_request_id);
480+ } else {
481+ append_parameter (payload, kSetupParamMaxRequestId , max_request_id);
482+ }
419483
420484 std::vector<std::uint8_t > message_bytes;
421485 append_varint (message_bytes, kServerSetupType );
0 commit comments