| // 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 |