• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "l2cap/internal/receiver.h"
18 
19 #include "common/bidi_queue.h"
20 #include "l2cap/cid.h"
21 #include "l2cap/internal/data_pipeline_manager.h"
22 #include "l2cap/l2cap_packets.h"
23 #include "packet/packet_view.h"
24 
25 namespace bluetooth {
26 namespace l2cap {
27 namespace internal {
Receiver(LowerQueueUpEnd * link_queue_up_end,os::Handler * handler,DataPipelineManager * data_pipeline_manager_)28 Receiver::Receiver(
29     LowerQueueUpEnd* link_queue_up_end, os::Handler* handler, DataPipelineManager* data_pipeline_manager_)
30     : link_queue_up_end_(link_queue_up_end),
31       handler_(handler),
32       buffer_timer_(handler),
33       data_pipeline_manager_(data_pipeline_manager_) {
34   ASSERT(link_queue_up_end_ != nullptr && handler_ != nullptr);
35   link_queue_up_end_->RegisterDequeue(handler_,
36                                       common::Bind(&Receiver::link_queue_dequeue_callback, common::Unretained(this)));
37 }
38 
39 // Invoked from external handler/thread (ModuleRegistry)
~Receiver()40 Receiver::~Receiver() {
41   link_queue_up_end_->UnregisterDequeue();
42 }
43 
44 // Invoked from external (Queue Reactable)
link_queue_dequeue_callback()45 void Receiver::link_queue_dequeue_callback() {
46   auto packet = link_queue_up_end_->TryDequeue();
47   auto basic_frame_view = BasicFrameView::Create(*packet);
48   if (!basic_frame_view.IsValid()) {
49     LOG_WARN("Received an invalid basic frame");
50     return;
51   }
52   Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId());
53   auto* data_controller = data_pipeline_manager_->GetDataController(cid);
54   if (data_controller == nullptr) {
55     // TODO(b/150170271): Buffer a few packets before data controller is attached
56     LOG_WARN("Received a packet without data controller. cid: %d", cid);
57     buffered_packets_.emplace(*packet);
58     LOG_WARN("Enqueued the unexpected packet. Current queue size: %zu", buffered_packets_.size());
59     buffer_timer_.Schedule(
60         common::BindOnce(&Receiver::check_buffered_packets, common::Unretained(this)), std::chrono::milliseconds(500));
61 
62     return;
63   }
64   data_controller->OnPdu(*packet);
65 }
66 
check_buffered_packets()67 void Receiver::check_buffered_packets() {
68   while (!buffered_packets_.empty()) {
69     auto packet = buffered_packets_.front();
70     buffered_packets_.pop();
71     auto basic_frame_view = BasicFrameView::Create(packet);
72     if (!basic_frame_view.IsValid()) {
73       LOG_WARN("Received an invalid basic frame");
74       return;
75     }
76     Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId());
77     auto* data_controller = data_pipeline_manager_->GetDataController(cid);
78     if (data_controller == nullptr) {
79       LOG_ERROR("Dropping a packet with invalid cid: %d", cid);
80     } else {
81       data_controller->OnPdu(packet);
82     }
83   }
84 }
85 
86 }  // namespace internal
87 }  // namespace l2cap
88 }  // namespace bluetooth
89