当前位置:   article > 正文

Quic处理包具体解析_quicstreamsequencer

quicstreamsequencer

在QuicFramer::ProcessDataPacket()中调用ProcessFrameData(),
在ProcessFrameData()调用了ProcessStreamFrame()将包中数据处理完成,
处理完后便会对数据进行上抛。
调用OnStreamFrame(frame),最后会上抛到 QuicStreamSequencerBuffer::OnStreamData()。
根据Quic的发包处理,每个包都会有一个严格递增的packetid,但这并不是丢包后能将重传包排序的标志,而是每个包内容的offset值。
在QuicStreamSequencerBuffer::OnStreamData()中,会有对于这个steam流的一个gap表,这个gap记录了每个缺失的offset的区间。

  *bytes_buffered = 0;
  QuicStreamOffset offset = starting_offset;
  size_t size = data.size();
  if (size == 0) {
    *error_details = "Received empty stream frame without FIN.";
    return QUIC_EMPTY_STREAM_FRAME_NO_FIN;
  }

  // Find the first gap not ending before |offset|. This gap maybe the gap to
  // fill if the arriving frame doesn't overlaps with previous ones.
  std::list<Gap>::iterator current_gap = gaps_.begin();
  while (current_gap != gaps_.end() && current_gap->end_offset <= offset) {
    ++current_gap;
  }         //找到包能填充的丢失区间

  DCHECK(current_gap != gaps_.end());

  // "duplication": might duplicate with data alread filled,but also might
  // overlap across different QuicStringPiece objects already written.
  // In both cases, don't write the data,
  // and allow the caller of this method to handle the result.
  if (offset < current_gap->begin_offset &&
      offset + size <= current_gap->begin_offset) {
    QUIC_DVLOG(1) << "Duplicated data at offset: " << offset
                  << " length: " << size;
    return QUIC_NO_ERROR;
  }//重传包
  if (offset < current_gap->begin_offset &&
      offset + size > current_gap->begin_offset) {
    // Beginning of new data overlaps data before current gap.
    string prefix(data.data(), data.length() < 128 ? data.length() : 128);
    *error_details =
        QuicStrCat("Beginning of received data overlaps with buffered data.\n",
                   "New frame range [", offset, ", ", offset + size,
                   ") with first 128 bytes: ", prefix, "\n",
                   "Currently received frames: ", GapsDebugString(), "\n",
                   "Current gaps: ", ReceivedFramesDebugString());
    return QUIC_OVERLAPPING_STREAM_DATA;
  }//意思是说新包的数据覆盖了丢失区域且将其它区域也覆盖了
  if (offset + size > current_gap->end_offset) {
    // End of new data overlaps with data after current gap.
    string prefix(data.data(), data.length() < 128 ? data.length() : 128);
    *error_details = QuicStrCat(
        "End of received data overlaps with buffered data.\nNew frame range [",
        offset, ", ", offset + size, ") with first 128 bytes: ", prefix, "\n",
        "Currently received frames: ", ReceivedFramesDebugString(), "\n",
        "Current gaps: ", GapsDebugString());
    return QUIC_OVERLAPPING_STREAM_DATA;
  }//同上

  // Write beyond the current range this buffer is covering.
  if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) {
    *error_details = "Received data beyond available range.";
    return QUIC_INTERNAL_ERROR;
  }//超出缓冲区

  if (current_gap->begin_offset != starting_offset &&
      current_gap->end_offset != starting_offset + data.length() &&
      gaps_.size() >= kMaxNumGapsAllowed) {
    // This frame is going to create one more gap which exceeds max number of
    // gaps allowed. Stop processing.
    *error_details = "Too many gaps created for this stream.";
    return QUIC_TOO_MANY_FRAME_GAPS;
  }//这个包太大??
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

当一个流上的包都接收后,会跳转到OnDataAvailable(),在quic-proto中有简单实现例子

void QuicSimpleServerStream::OnDataAvailable() {
  while (HasBytesToRead()) {
    struct iovec iov;
    if (GetReadableRegions(&iov, 1) == 0) {
      // No more data to read.
      break;
    }
    QUIC_DVLOG(1) << "Stream " << id() << " processed " << iov.iov_len
                  << " bytes.";
    body_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
//在这里将会把一个流上传的所有包的数据按顺序添加到body_里,所以当你在client端在流上发送完一个数据时可以在这里将数据打印出来
    if (content_length_ >= 0 &&
        body_.size() > static_cast<uint64_t>(content_length_)) {
      QUIC_DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
                    << content_length_ << ").";
      SendErrorResponse();
      return;
    }
    MarkConsumed(iov.iov_len);
  }
  if (!sequencer()->IsClosed()) {
    sequencer()->SetUnblocked();
    return;
  }

  // If the sequencer is closed, then all the body, including the fin, has been
  // consumed.
  OnFinRead();

  if (write_side_closed() || fin_buffered()) {
    return;
  }

  SendResponse(); //因为quic-proto的例子是请求网页数据,server端会给予返回,可以根据这个函数查看怎么发送一个完整的数据
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

以上为初学者理解,仅供参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/626404
推荐阅读
相关标签
  

闽ICP备14008679号