google quic QuicFramer模块原理-封包和解包

2023-10-21  本文已影响0人  JeffreyLau

前言

QuicFramer quic报文封装分析

QuicFramer quic报文解包分析

bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
                                       QuicPacketHeader* header,
                                       const QuicEncryptedPacket& packet,
                                       char* decrypted_buffer,
                                       size_t buffer_length) {
  ...
  // 1) 处理ietf 头长度字段(如果收到的是聚合包,这里需要分离聚合包),并将聚合的后面一部分送到QuicConnection模块,在下一个回合使用
  if (!MaybeProcessIetfLength(encrypted_reader, header)) {
    return false;
  }

  absl::string_view associated_data;
  std::vector<char> ad_storage;
  QuicPacketNumber base_packet_number;
  //2) short 格式,或long 格式非版本协商包
  if (header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
      header->long_packet_type != VERSION_NEGOTIATION) {
    QUICHE_DCHECK(header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
                  header->long_packet_type == INITIAL ||
                  header->long_packet_type == HANDSHAKE ||
                  header->long_packet_type == ZERO_RTT_PROTECTED);
    // Process packet number.默认为true
    if (supports_multiple_packet_number_spaces_) {
      PacketNumberSpace pn_space = GetPacketNumberSpace(*header);
      if (pn_space == NUM_PACKET_NUMBER_SPACES) {
        return RaiseError(QUIC_INVALID_PACKET_HEADER);
      }
      base_packet_number = largest_decrypted_packet_numbers_[pn_space];
    } else {
      base_packet_number = largest_packet_number_;
    }
    uint64_t full_packet_number;
    bool hp_removal_failed = false;
    if (version_.HasHeaderProtection()) {
      // 移除头部加密,在封包的时候EncryptPayload(...)函数中会通过ApplyHeaderProtection()对头部做一些特殊处理
      // 作为收包端这个地方需要进行还原操作经过该步骤,我们可以得到packet_number_length字段,以及packet_number字段
      if (!RemoveHeaderProtection(encrypted_reader, packet, header,
                                  &full_packet_number, &ad_storage)) {
        hp_removal_failed = true;
      }
      associated_data = absl::string_view(ad_storage.data(), ad_storage.size());
    } 
    .....
    header->packet_number = QuicPacketNumber(full_packet_number);
  }
  ....

  absl::string_view encrypted = encrypted_reader->ReadRemainingPayload();
  ....

  size_t decrypted_length = 0;
  EncryptionLevel decrypted_level;
  //3) 解密payload data
  if (!DecryptPayload(packet.length(), encrypted, associated_data, *header,
                      decrypted_buffer, buffer_length, &decrypted_length,
                      &decrypted_level)) {
    ....
    return RaiseError(QUIC_DECRYPTION_FAILURE);
  }
  QuicDataReader reader(decrypted_buffer, decrypted_length);
  ....
  // Update the largest packet number after we have decrypted the packet
  // so we are confident is not attacker controlled.
  // 这里更新largest_decrypted_packet_numbers_,根据当前收到的最大的PakcteNumber号
  if (supports_multiple_packet_number_spaces_) {
    largest_decrypted_packet_numbers_[QuicUtils::GetPacketNumberSpace(
                                          decrypted_level)]
        .UpdateMax(header->packet_number);
  } else {
    largest_packet_number_.UpdateMax(header->packet_number);
  }
  
  // 4) 回调到QuicConnection模块进行相应业务处理,如更新connection Id等信息
  if (!visitor_->OnPacketHeader(*header)) {
    RecordDroppedPacketReason(DroppedPacketReason::INVALID_PACKET_NUMBER);
    // The visitor suppresses further processing of the packet.
    return true;
  }
  .....
  //5) Handle the payload.处理payload 
  if (VersionHasIetfQuicFrames(version_.transport_version)) {
    current_received_frame_type_ = 0;
    previously_received_frame_type_ = 0;
    if (!ProcessIetfFrameData(&reader, *header, decrypted_level)) {
      current_received_frame_type_ = 0;
      previously_received_frame_type_ = 0;
      ....
      return false;
    }
    current_received_frame_type_ = 0;
    previously_received_frame_type_ = 0;
  } 
  // 6) 完成一个报文的解析   
  visitor_->OnPacketComplete();
  return true;
}

QuicFramer MaybeProcessIetfLength分析

bool QuicFramer::MaybeProcessIetfLength(QuicDataReader* encrypted_reader,
                                        QuicPacketHeader* header) {
  ...
  //1) 读取quic报头的length信息,包括length是用多少字节来描述的,以及length的值是多少
  // header->length_length 标识当前quic报文的length是用几个字节来描述
  // header->remaining_packet_length 标识当前quic报文截止length字段之后还余下多少字节
  header->length_length = encrypted_reader->PeekVarInt62Length();
  if (!encrypted_reader->ReadVarInt62(&header->remaining_packet_length)) {
    set_detailed_error("Unable to read long header payload length.");
    return RaiseError(QUIC_INVALID_PACKET_HEADER);
  }
  //2) 这里第一个quic报文头解析完后自第一个报文的length字段到整个包末尾还有多少长度
  uint64_t remaining_bytes_length = encrypted_reader->BytesRemaining();
  if (header->remaining_packet_length > remaining_bytes_length) {
    set_detailed_error("Long header payload length longer than packet.");
    return RaiseError(QUIC_INVALID_PACKET_HEADER);
  }
  //3) 聚合报文处理,比如服务端回复客户端的initial的包就是使用的聚合包(initial + handshake)
  MaybeProcessCoalescedPacket(*encrypted_reader, remaining_bytes_length,
                              *header);
  //4) 冗余截断,当聚合包分离后,修改encrypted_reader内存中的偏移信息
  if (!encrypted_reader->TruncateRemaining(header->remaining_packet_length)) {
    set_detailed_error("Length TruncateRemaining failed.");
    QUIC_BUG(quic_bug_10850_54) << "Length TruncateRemaining failed.";
    return RaiseError(QUIC_INVALID_PACKET_HEADER);
  }
  return true;
}
void QuicFramer::MaybeProcessCoalescedPacket(
    const QuicDataReader& encrypted_reader, uint64_t remaining_bytes_length,
    const QuicPacketHeader& header) {
  // 3.1) 以此来判断是否是聚合包
  if (header.remaining_packet_length >= remaining_bytes_length) {
    // There is no coalesced packet.
    return;
  }
 
  absl::string_view remaining_data = encrypted_reader.PeekRemainingPayload();
  QUICHE_DCHECK_EQ(remaining_data.length(), remaining_bytes_length);
  //3.2) 这里得到Handshake包的起始地址
  const char* coalesced_data =
      remaining_data.data() + header.remaining_packet_length;
  uint64_t coalesced_data_length =
      remaining_bytes_length - header.remaining_packet_length;
  QuicDataReader coalesced_reader(coalesced_data, coalesced_data_length);
  //3.3) 解析聚合包(handshake)的头部信息
  QuicPacketHeader coalesced_header;
  if (!ProcessIetfPacketHeader(&coalesced_reader, &coalesced_header)) {
    .....
    return;
  }
  
  QuicEncryptedPacket coalesced_packet(coalesced_data, coalesced_data_length,
                                       /*owns_buffer=*/false);
  // 3.4) bypass到QuicConnection模块,进行缓存,等initial包处理完后会继续处理该包
  visitor_->OnCoalescedPacket(coalesced_packet);
}
class QUIC_EXPORT_PRIVATE QuicConnection
    : public QuicFramerVisitorInterface,
      ... {
 public:
  ...
  void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
  ...
 protected:
  ...
  // Collection of coalesced packets which were received while processing
  // the current packet.
  quiche::QuicheCircularDeque<std::unique_ptr<QuicEncryptedPacket>>
      received_coalesced_packets_;  
};
void QuicConnection::OnCoalescedPacket(const QuicEncryptedPacket& packet) {
  QueueCoalescedPacket(packet);
}

void QuicConnection::QueueCoalescedPacket(const QuicEncryptedPacket& packet) {
  received_coalesced_packets_.push_back(packet.Clone());
  ++stats_.num_coalesced_packets_received;
}

QuicFramer ProcessIetfFrameData分析

PADDING Frame {
  Type (i) = 0x00,
}
PING Frame {
  Type (i) = 0x01,
}
CRYPTO Frame {
  Type (i) = 0x06,
  Offset (i),
  Length (i),
  Crypto Data (..),
}
bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
                                      const QuicPacketHeader& header,
                                      EncryptionLevel decrypted_level) {
  ...
  // 直到读完
  while (!reader->IsDoneReading()) {
    ....
    uint64_t frame_type;
    // Will be the number of bytes into which frame_type was encoded.
    size_t encoded_bytes = reader->BytesRemaining();
    if (!reader->ReadVarInt62(&frame_type)) {
      set_detailed_error("Unable to read frame type.");
      return RaiseError(QUIC_INVALID_FRAME_DATA);
    }
    ....
    // Is now the number of bytes into which the frame type was encoded.
    encoded_bytes -= reader->BytesRemaining();
      
    // Check that the frame type is minimally encoded.
    if (encoded_bytes !=
        static_cast<size_t>(QuicDataWriter::GetVarInt62Len(frame_type))) {
      // The frame type was not minimally encoded.
      return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION);
    }

    if (IS_IETF_STREAM_FRAME(frame_type)) {
      QuicStreamFrame frame;
      if (!ProcessIetfStreamFrame(reader, frame_type, &frame)) {
        return RaiseError(QUIC_INVALID_STREAM_DATA);
      }
      if (!visitor_->OnStreamFrame(frame)) {
        ....
        return true;
      }
    } else {
      switch (frame_type) {
        case IETF_PADDING: {
          QuicPaddingFrame frame;
          ProcessPaddingFrame(reader, &frame);
          if (!visitor_->OnPaddingFrame(frame)) {
            // Returning true since there was no parsing error.
            return true;
          }
          break;
        }
        case IETF_PING: {
          // Ping has no payload.
          QuicPingFrame ping_frame;
          if (!visitor_->OnPingFrame(ping_frame)) {
            // Returning true since there was no parsing error.
            return true;
          }
          break;
        }
        case IETF_CRYPTO: {
          QuicCryptoFrame frame;
          if (!ProcessCryptoFrame(reader, GetEncryptionLevel(header), &frame)) {
            return RaiseError(QUIC_INVALID_FRAME_DATA);
          }
          if (!visitor_->OnCryptoFrame(frame)) {
            return true;
          }
          break;
        }
        .....
      }
    }
  }
  return true;
}

总结:

参考文献:

上一篇 下一篇

猜你喜欢

热点阅读