Loading system/gd/l2cap/internal/basic_mode_channel_data_controller.cc +9 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include "l2cap/internal/basic_mode_channel_data_controller.h" #include "l2cap/l2cap_packets.h" namespace bluetooth { namespace l2cap { namespace internal { Loading @@ -31,11 +33,15 @@ void BasicModeDataController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> s scheduler_->OnPacketsReady(cid_, 1); } void BasicModeDataController::OnPdu(BasicFrameView pdu) { enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(pdu.GetPayload()), handler_); void BasicModeDataController::OnPdu(packet::PacketView<true> pdu) { auto basic_frame_view = BasicFrameView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(basic_frame_view.GetPayload()), handler_); } std::unique_ptr<BasicFrameBuilder> BasicModeDataController::GetNextPacket() { std::unique_ptr<packet::BasePacketBuilder> BasicModeDataController::GetNextPacket() { auto next = std::move(pdu_queue_.front()); pdu_queue_.pop(); return next; Loading system/gd/l2cap/internal/basic_mode_channel_data_controller.h +3 −3 Original line number Diff line number Diff line Loading @@ -46,9 +46,9 @@ class BasicModeDataController : public DataController { void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override; void OnPdu(BasicFrameView pdu) override; void OnPdu(packet::PacketView<true> pdu) override; std::unique_ptr<BasicFrameBuilder> GetNextPacket() override; std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() override; void EnableFcs(bool enabled) override {} void SetRetransmissionAndFlowControlOptions(const RetransmissionAndFlowControlConfigurationOption& option) override {} Loading @@ -58,7 +58,7 @@ class BasicModeDataController : public DataController { Cid remote_cid_; os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_; os::Handler* handler_; std::queue<std::unique_ptr<BasicFrameBuilder>> pdu_queue_; std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_; Scheduler* scheduler_; }; Loading system/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc +11 −5 Original line number Diff line number Diff line Loading @@ -74,22 +74,28 @@ TEST_F(BasicModeDataControllerTest, transmit) { testing::MockScheduler scheduler; BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; EXPECT_CALL(scheduler, OnPacketsReady(1, 1)); controller.OnSdu(CreateSdu({1, 2, 3})); controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); auto next_packet = controller.GetNextPacket(); EXPECT_NE(next_packet, nullptr); auto view = GetPacketView(std::move(next_packet)); auto pdu_view = BasicFrameView::Create(view); EXPECT_TRUE(pdu_view.IsValid()); auto payload = pdu_view.GetPayload(); std::string data = std::string(payload.begin(), payload.end()); EXPECT_EQ(data, "abcd"); } TEST_F(BasicModeDataControllerTest, receive) { common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; testing::MockScheduler scheduler; BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; auto base_view = GetPacketView(CreateSdu({0, 0, 1, 0})); auto basic_frame_view = BasicFrameView::Create(base_view); EXPECT_TRUE(basic_frame_view.IsValid()); controller.OnPdu(basic_frame_view); auto base_view = GetPacketView(BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c', 'd'}))); controller.OnPdu(base_view); sync_handler(queue_handler_); auto packet_view = channel_queue.GetUpEnd()->TryDequeue(); EXPECT_NE(packet_view, nullptr); std::string data = std::string(packet_view->begin(), packet_view->end()); EXPECT_EQ(data, "abcd"); } } // namespace Loading system/gd/l2cap/internal/data_controller.h +2 −2 Original line number Diff line number Diff line Loading @@ -34,10 +34,10 @@ class DataController { virtual void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) = 0; // PDUs -> SDU and enqueue to channel queue end virtual void OnPdu(BasicFrameView pdu) = 0; virtual void OnPdu(packet::PacketView<true> pdu) = 0; // Used by Scheduler to get next PDU virtual std::unique_ptr<BasicFrameBuilder> GetNextPacket() = 0; virtual std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() = 0; // Set FCS mode. This only applies to some modes (ERTM). virtual void EnableFcs(bool enabled) = 0; Loading system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc +85 −16 Original line number Diff line number Diff line Loading @@ -555,14 +555,24 @@ struct ErtmController::impl { void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<CopyablePacketBuilder> segment, uint8_t req_seq, uint8_t tx_seq, uint16_t sdu_size = 0, Final f = Final::NOT_SET) { std::unique_ptr<EnhancedInformationFrameBuilder> builder; std::unique_ptr<packet::BasePacketBuilder> builder; if (sar == SegmentationAndReassembly::START) { if (controller_->fcs_enabled_) { builder = EnhancedInformationStartFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); } else { builder = EnhancedInformationStartFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); } } else { if (controller_->fcs_enabled_) { builder = EnhancedInformationFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar, std::move(segment)); } else { builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar, std::move(segment)); } } controller_->send_pdu(std::move(builder)); } Loading @@ -575,7 +585,6 @@ struct ErtmController::impl { std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder = std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(next_tx_seq_)->second)); _send_i_frame(sar, std::move(copyable_packet_builder), buffer_seq_, next_tx_seq_, sdu_size, f); // TODO hsz fix me unacked_frames_++; frames_sent_++; retry_i_frames_[next_tx_seq_] = 1; Loading @@ -599,7 +608,12 @@ struct ErtmController::impl { } void _send_s_frame(SupervisoryFunction s, uint8_t req_seq, Poll p, Final f) { auto builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); std::unique_ptr<packet::BasePacketBuilder> builder; if (controller_->fcs_enabled_) { builder = EnhancedSupervisoryFrameWithFcsBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); } else { builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); } controller_->send_pdu(std::move(builder)); } Loading Loading @@ -770,13 +784,9 @@ struct ErtmController::impl { // Segmentation is handled here void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { // TODO: Optimize the calculation. We don't need to count for SDU length in CONTINUATION or END packets. We don't need // to FCS when disabled. size_t size_each_packet = (remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - 2 /* Extended control */ - 2 /* FCS */); auto sdu_size = sdu->size(); std::vector<std::unique_ptr<packet::RawBuilder>> segments; packet::FragmentingInserter fragmenting_inserter(size_each_packet, std::back_insert_iterator(segments)); packet::FragmentingInserter fragmenting_inserter(size_each_packet_, std::back_insert_iterator(segments)); sdu->Serialize(fragmenting_inserter); fragmenting_inserter.finalize(); if (segments.size() == 1) { Loading @@ -790,8 +800,20 @@ void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back())); } void ErtmController::OnPdu(BasicFrameView pdu) { auto standard_frame_view = StandardFrameView::Create(pdu); void ErtmController::OnPdu(packet::PacketView<true> pdu) { if (fcs_enabled_) { on_pdu_fcs(pdu); } else { on_pdu_no_fcs(pdu); } } void ErtmController::on_pdu_no_fcs(const packet::PacketView<true>& pdu) { auto basic_frame_view = BasicFrameView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } auto standard_frame_view = StandardFrameView::Create(basic_frame_view); if (!standard_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; Loading Loading @@ -833,7 +855,54 @@ void ErtmController::OnPdu(BasicFrameView pdu) { } } std::unique_ptr<BasicFrameBuilder> ErtmController::GetNextPacket() { void ErtmController::on_pdu_fcs(const packet::PacketView<true>& pdu) { auto basic_frame_view = BasicFrameWithFcsView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } auto standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view); if (!standard_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } auto type = standard_frame_view.GetFrameType(); if (type == FrameType::I_FRAME) { auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_frame_view); if (!i_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } pimpl_->recv_i_frame(i_frame_view.GetF(), i_frame_view.GetTxSeq(), i_frame_view.GetReqSeq(), i_frame_view.GetSar(), i_frame_view.GetPayload()); } else if (type == FrameType::S_FRAME) { auto s_frame_view = EnhancedSupervisoryFrameWithFcsView::Create(standard_frame_view); if (!s_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } auto req_seq = s_frame_view.GetReqSeq(); auto f = s_frame_view.GetF(); auto p = s_frame_view.GetP(); switch (s_frame_view.GetS()) { case SupervisoryFunction::RECEIVER_READY: pimpl_->recv_rr(req_seq, p, f); break; case SupervisoryFunction::RECEIVER_NOT_READY: pimpl_->recv_rnr(req_seq, p, f); break; case SupervisoryFunction::REJECT: pimpl_->recv_rej(req_seq, p, f); break; case SupervisoryFunction::SELECT_REJECT: pimpl_->recv_srej(req_seq, p, f); break; } } else { LOG_WARN("Received invalid frame"); } } std::unique_ptr<packet::BasePacketBuilder> ErtmController::GetNextPacket() { auto next = std::move(pdu_queue_.front()); pdu_queue_.pop(); return next; Loading Loading @@ -879,7 +948,7 @@ void ErtmController::EnableFcs(bool enabled) { fcs_enabled_ = enabled; } void ErtmController::send_pdu(std::unique_ptr<BasicFrameBuilder> pdu) { void ErtmController::send_pdu(std::unique_ptr<packet::BasePacketBuilder> pdu) { pdu_queue_.emplace(std::move(pdu)); scheduler_->OnPacketsReady(cid_, 1); } Loading Loading
system/gd/l2cap/internal/basic_mode_channel_data_controller.cc +9 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include "l2cap/internal/basic_mode_channel_data_controller.h" #include "l2cap/l2cap_packets.h" namespace bluetooth { namespace l2cap { namespace internal { Loading @@ -31,11 +33,15 @@ void BasicModeDataController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> s scheduler_->OnPacketsReady(cid_, 1); } void BasicModeDataController::OnPdu(BasicFrameView pdu) { enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(pdu.GetPayload()), handler_); void BasicModeDataController::OnPdu(packet::PacketView<true> pdu) { auto basic_frame_view = BasicFrameView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(basic_frame_view.GetPayload()), handler_); } std::unique_ptr<BasicFrameBuilder> BasicModeDataController::GetNextPacket() { std::unique_ptr<packet::BasePacketBuilder> BasicModeDataController::GetNextPacket() { auto next = std::move(pdu_queue_.front()); pdu_queue_.pop(); return next; Loading
system/gd/l2cap/internal/basic_mode_channel_data_controller.h +3 −3 Original line number Diff line number Diff line Loading @@ -46,9 +46,9 @@ class BasicModeDataController : public DataController { void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override; void OnPdu(BasicFrameView pdu) override; void OnPdu(packet::PacketView<true> pdu) override; std::unique_ptr<BasicFrameBuilder> GetNextPacket() override; std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() override; void EnableFcs(bool enabled) override {} void SetRetransmissionAndFlowControlOptions(const RetransmissionAndFlowControlConfigurationOption& option) override {} Loading @@ -58,7 +58,7 @@ class BasicModeDataController : public DataController { Cid remote_cid_; os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_; os::Handler* handler_; std::queue<std::unique_ptr<BasicFrameBuilder>> pdu_queue_; std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_; Scheduler* scheduler_; }; Loading
system/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc +11 −5 Original line number Diff line number Diff line Loading @@ -74,22 +74,28 @@ TEST_F(BasicModeDataControllerTest, transmit) { testing::MockScheduler scheduler; BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; EXPECT_CALL(scheduler, OnPacketsReady(1, 1)); controller.OnSdu(CreateSdu({1, 2, 3})); controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); auto next_packet = controller.GetNextPacket(); EXPECT_NE(next_packet, nullptr); auto view = GetPacketView(std::move(next_packet)); auto pdu_view = BasicFrameView::Create(view); EXPECT_TRUE(pdu_view.IsValid()); auto payload = pdu_view.GetPayload(); std::string data = std::string(payload.begin(), payload.end()); EXPECT_EQ(data, "abcd"); } TEST_F(BasicModeDataControllerTest, receive) { common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; testing::MockScheduler scheduler; BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; auto base_view = GetPacketView(CreateSdu({0, 0, 1, 0})); auto basic_frame_view = BasicFrameView::Create(base_view); EXPECT_TRUE(basic_frame_view.IsValid()); controller.OnPdu(basic_frame_view); auto base_view = GetPacketView(BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c', 'd'}))); controller.OnPdu(base_view); sync_handler(queue_handler_); auto packet_view = channel_queue.GetUpEnd()->TryDequeue(); EXPECT_NE(packet_view, nullptr); std::string data = std::string(packet_view->begin(), packet_view->end()); EXPECT_EQ(data, "abcd"); } } // namespace Loading
system/gd/l2cap/internal/data_controller.h +2 −2 Original line number Diff line number Diff line Loading @@ -34,10 +34,10 @@ class DataController { virtual void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) = 0; // PDUs -> SDU and enqueue to channel queue end virtual void OnPdu(BasicFrameView pdu) = 0; virtual void OnPdu(packet::PacketView<true> pdu) = 0; // Used by Scheduler to get next PDU virtual std::unique_ptr<BasicFrameBuilder> GetNextPacket() = 0; virtual std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() = 0; // Set FCS mode. This only applies to some modes (ERTM). virtual void EnableFcs(bool enabled) = 0; Loading
system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc +85 −16 Original line number Diff line number Diff line Loading @@ -555,14 +555,24 @@ struct ErtmController::impl { void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<CopyablePacketBuilder> segment, uint8_t req_seq, uint8_t tx_seq, uint16_t sdu_size = 0, Final f = Final::NOT_SET) { std::unique_ptr<EnhancedInformationFrameBuilder> builder; std::unique_ptr<packet::BasePacketBuilder> builder; if (sar == SegmentationAndReassembly::START) { if (controller_->fcs_enabled_) { builder = EnhancedInformationStartFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); } else { builder = EnhancedInformationStartFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); } } else { if (controller_->fcs_enabled_) { builder = EnhancedInformationFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar, std::move(segment)); } else { builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar, std::move(segment)); } } controller_->send_pdu(std::move(builder)); } Loading @@ -575,7 +585,6 @@ struct ErtmController::impl { std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder = std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(next_tx_seq_)->second)); _send_i_frame(sar, std::move(copyable_packet_builder), buffer_seq_, next_tx_seq_, sdu_size, f); // TODO hsz fix me unacked_frames_++; frames_sent_++; retry_i_frames_[next_tx_seq_] = 1; Loading @@ -599,7 +608,12 @@ struct ErtmController::impl { } void _send_s_frame(SupervisoryFunction s, uint8_t req_seq, Poll p, Final f) { auto builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); std::unique_ptr<packet::BasePacketBuilder> builder; if (controller_->fcs_enabled_) { builder = EnhancedSupervisoryFrameWithFcsBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); } else { builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); } controller_->send_pdu(std::move(builder)); } Loading Loading @@ -770,13 +784,9 @@ struct ErtmController::impl { // Segmentation is handled here void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { // TODO: Optimize the calculation. We don't need to count for SDU length in CONTINUATION or END packets. We don't need // to FCS when disabled. size_t size_each_packet = (remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - 2 /* Extended control */ - 2 /* FCS */); auto sdu_size = sdu->size(); std::vector<std::unique_ptr<packet::RawBuilder>> segments; packet::FragmentingInserter fragmenting_inserter(size_each_packet, std::back_insert_iterator(segments)); packet::FragmentingInserter fragmenting_inserter(size_each_packet_, std::back_insert_iterator(segments)); sdu->Serialize(fragmenting_inserter); fragmenting_inserter.finalize(); if (segments.size() == 1) { Loading @@ -790,8 +800,20 @@ void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back())); } void ErtmController::OnPdu(BasicFrameView pdu) { auto standard_frame_view = StandardFrameView::Create(pdu); void ErtmController::OnPdu(packet::PacketView<true> pdu) { if (fcs_enabled_) { on_pdu_fcs(pdu); } else { on_pdu_no_fcs(pdu); } } void ErtmController::on_pdu_no_fcs(const packet::PacketView<true>& pdu) { auto basic_frame_view = BasicFrameView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } auto standard_frame_view = StandardFrameView::Create(basic_frame_view); if (!standard_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; Loading Loading @@ -833,7 +855,54 @@ void ErtmController::OnPdu(BasicFrameView pdu) { } } std::unique_ptr<BasicFrameBuilder> ErtmController::GetNextPacket() { void ErtmController::on_pdu_fcs(const packet::PacketView<true>& pdu) { auto basic_frame_view = BasicFrameWithFcsView::Create(pdu); if (!basic_frame_view.IsValid()) { return; } auto standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view); if (!standard_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } auto type = standard_frame_view.GetFrameType(); if (type == FrameType::I_FRAME) { auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_frame_view); if (!i_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } pimpl_->recv_i_frame(i_frame_view.GetF(), i_frame_view.GetTxSeq(), i_frame_view.GetReqSeq(), i_frame_view.GetSar(), i_frame_view.GetPayload()); } else if (type == FrameType::S_FRAME) { auto s_frame_view = EnhancedSupervisoryFrameWithFcsView::Create(standard_frame_view); if (!s_frame_view.IsValid()) { LOG_WARN("Received invalid frame"); return; } auto req_seq = s_frame_view.GetReqSeq(); auto f = s_frame_view.GetF(); auto p = s_frame_view.GetP(); switch (s_frame_view.GetS()) { case SupervisoryFunction::RECEIVER_READY: pimpl_->recv_rr(req_seq, p, f); break; case SupervisoryFunction::RECEIVER_NOT_READY: pimpl_->recv_rnr(req_seq, p, f); break; case SupervisoryFunction::REJECT: pimpl_->recv_rej(req_seq, p, f); break; case SupervisoryFunction::SELECT_REJECT: pimpl_->recv_srej(req_seq, p, f); break; } } else { LOG_WARN("Received invalid frame"); } } std::unique_ptr<packet::BasePacketBuilder> ErtmController::GetNextPacket() { auto next = std::move(pdu_queue_.front()); pdu_queue_.pop(); return next; Loading Loading @@ -879,7 +948,7 @@ void ErtmController::EnableFcs(bool enabled) { fcs_enabled_ = enabled; } void ErtmController::send_pdu(std::unique_ptr<BasicFrameBuilder> pdu) { void ErtmController::send_pdu(std::unique_ptr<packet::BasePacketBuilder> pdu) { pdu_queue_.emplace(std::move(pdu)); scheduler_->OnPacketsReady(cid_, 1); } Loading