blob: fb49923a4c580006d7665447d5d935eb540e13e9 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "pdu_generator.h"
#include <zircon/assert.h>
#include <algorithm>
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
namespace bt {
namespace l2cap {
namespace internal {
namespace {
constexpr static hci::ConnectionHandle kTestHandle = 0x0001;
constexpr static ChannelId kTestChannelId = 0x0001;
} // namespace
PduGenerator::PduGenerator(const uint8_t* input_buf, size_t buflen, size_t num_pdus)
: input_buf_(input_buf),
buf_len_bytes_(buflen),
pdu_len_bytes_(
std::min<size_t>(num_pdus ? buflen / num_pdus : buflen + 1, kMaxBasicFramePayloadSize)),
fragmenter_(kTestHandle),
input_pos_(0) {
ZX_ASSERT(input_buf_);
}
std::optional<PDU> PduGenerator::GetNextPdu() {
if (pdu_len_bytes_ == 0) {
// Avoid infinite-loop, if the provided buffer is too small to provide at
// least 1 byte for each PDU.
return std::nullopt;
}
ZX_ASSERT(input_pos_ <= buf_len_bytes_); // Ensure no underflow below.
const size_t avail = buf_len_bytes_ - input_pos_;
if (pdu_len_bytes_ > avail) {
return std::nullopt;
}
// For the rationale behind using a Fragmenter to build the PDU, see the
// comment in basic_mode_rx_engine_fuzztest.cc.
auto pdu =
fragmenter_.BuildFrame(kTestChannelId, BufferView(input_buf_ + input_pos_, pdu_len_bytes_),
FrameCheckSequenceOption::kNoFcs);
input_pos_ += pdu_len_bytes_;
return std::move(pdu);
}
} // namespace internal
} // namespace l2cap
} // namespace bt