| // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/third_party/quiche/src/quic/quartc/test/quartc_data_source.h" |
| |
| #include "net/third_party/quiche/src/quic/core/quic_data_reader.h" |
| #include "net/third_party/quiche/src/quic/core/quic_data_writer.h" |
| |
| namespace quic { |
| namespace test { |
| |
| namespace { |
| |
| class SendAlarmDelegate : public QuicAlarm::Delegate { |
| public: |
| explicit SendAlarmDelegate(QuartcDataSource* source) : source_(source) {} |
| |
| void OnAlarm() override { source_->OnSendAlarm(); } |
| |
| private: |
| QuartcDataSource* source_; |
| }; |
| |
| } // namespace |
| |
| bool ParsedQuartcDataFrame::Parse(QuicStringPiece data, |
| ParsedQuartcDataFrame* out) { |
| QuicDataReader reader(data.data(), data.size()); |
| |
| uint32_t source_id; |
| if (!reader.ReadUInt32(&source_id)) { |
| return false; |
| } |
| |
| uint64_t sequence_number; |
| if (!reader.ReadUInt64(&sequence_number)) { |
| return false; |
| } |
| |
| uint64_t time_bits; |
| if (!reader.ReadUInt64(&time_bits)) { |
| return false; |
| } |
| QuicStringPiece payload = reader.ReadRemainingPayload(); |
| |
| out->source_id = source_id; |
| out->sequence_number = sequence_number; |
| out->send_time = |
| QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(time_bits); |
| out->size = data.size(); |
| out->payload = std::string(payload.data(), payload.size()); |
| |
| return true; |
| } |
| |
| QuartcDataSource::QuartcDataSource(const QuicClock* clock, |
| QuicAlarmFactory* alarm_factory, |
| QuicRandom* random, |
| const Config& config, |
| Delegate* delegate) |
| : clock_(clock), |
| alarm_factory_(alarm_factory), |
| random_(random), |
| config_(config), |
| delegate_(delegate), |
| send_alarm_(alarm_factory_->CreateAlarm(new SendAlarmDelegate(this))), |
| sequence_number_(0), |
| allocated_bandwidth_(config_.min_bandwidth), |
| last_send_time_(QuicTime::Zero()) {} |
| |
| void QuartcDataSource::OnSendAlarm() { |
| QuicTime now = clock_->Now(); |
| QuicTime::Delta time_since_last_send(QuicTime::Delta::Zero()); |
| if (last_send_time_.IsInitialized()) { |
| // If previous frames have been sent, use the actual time since the last |
| // send to compute the frame size. |
| time_since_last_send = now - last_send_time_; |
| } else { |
| // For the first frame, use the configured frame interval. |
| time_since_last_send = config_.frame_interval; |
| } |
| |
| QuicByteCount bytes = |
| allocated_bandwidth_.ToBytesPerPeriod(time_since_last_send); |
| while (config_.max_frame_size > 0 && bytes > config_.max_frame_size) { |
| GenerateFrame(config_.max_frame_size, now); |
| bytes -= config_.max_frame_size; |
| } |
| GenerateFrame(bytes, now); |
| |
| // Reset alarm. |
| last_send_time_ = now; |
| send_alarm_->Set(now + config_.frame_interval); |
| } |
| |
| QuicBandwidth QuartcDataSource::AllocateBandwidth(QuicBandwidth bandwidth) { |
| allocated_bandwidth_ = std::max(config_.min_bandwidth, |
| std::min(bandwidth, config_.max_bandwidth)); |
| return std::max(bandwidth - allocated_bandwidth_, QuicBandwidth::Zero()); |
| } |
| |
| bool QuartcDataSource::Enabled() const { |
| return send_alarm_->IsSet(); |
| } |
| |
| void QuartcDataSource::SetEnabled(bool value) { |
| if (Enabled() == value) { |
| return; |
| } |
| |
| if (!value) { |
| send_alarm_->Cancel(); |
| |
| // Reset the last send time. When re-enabled, the data source should |
| // produce a frame of approximately the right size for its current |
| // bandwidth allocation and frame interval, not a huge frame accounting for |
| // all the time since it was disabled. |
| last_send_time_ = QuicTime::Zero(); |
| return; |
| } |
| |
| send_alarm_->Set(clock_->Now()); |
| } |
| |
| void QuartcDataSource::GenerateFrame(QuicByteCount frame_size, QuicTime now) { |
| frame_size = std::max(frame_size, kDataFrameHeaderSize); |
| if (buffer_.size() < frame_size) { |
| buffer_.resize(frame_size); |
| } |
| |
| // Generate data. |
| QuicDataWriter writer(frame_size, buffer_.data()); |
| writer.WriteUInt32(config_.id); |
| writer.WriteUInt64(sequence_number_++); |
| writer.WriteUInt64((now - QuicTime::Zero()).ToMicroseconds()); |
| writer.WriteRandomBytes(random_, writer.remaining()); |
| |
| delegate_->OnDataProduced(writer.data(), writer.length()); |
| } |
| |
| } // namespace test |
| } // namespace quic |