1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <lib/fit/function.h>
17 
18 #include <memory>
19 
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
22 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
23 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
24 #include "pw_bluetooth_sapphire/internal/host/l2cap/types.h"
25 
26 namespace bt::testing {
27 
28 // Manages individual FakeDynamicChannel instances as created by
29 // FakeSignalingServer. There are two potential states that an indiviudal
30 // channel can be in - open and closed.
31 // If the channel is open, then device has received a ConnectionRequest
32 // associated with this channel, sent out a corresponding ConfigurationRequest,
33 // and received a ConfigurationRequest in response. The channel is ready to
34 // handle packets.
35 // Closed: The channel is not ready to handle packets. It may still be
36 // registered with the FakeL2cap instance managing it.
37 // Note that when the device has received a ConnectionRequest and sent out a
38 // ConfigurationRequest but is still awaiting a ConfigurationRequest from
39 // bt-host, it will still be connected (as there will be a local channel ID
40 // assigned to it) but it is not Open state.
41 class FakeDynamicChannel {
42  public:
43   // Callback associated with handling packet |sdu| sent across the channel.
44   // Set by the service associated with the channel's PSM.
45   using PacketHandlerCallback = fit::function<void(const ByteBuffer& sdu)>;
46 
47   // Callback associated with sending packet |sdu| through this dynamic
48   // channel. Set by the service associated with the channel's PSM.
49   using SendPacketCallback = fit::function<void(const ByteBuffer& sdu)>;
50 
51   // Callback associated with closing and tearing down this dynamic channel.
52   // Set by the service associated with the channel's PSM.
53   using ChannelDeletedCallback = fit::function<void()>;
54 
55   // Create a FakeDynamicChannel with Connection Handle |conn|, Protocol
56   // Service Multiplexer (PSM) |psm| locally registered Channel ID |local_cid|,
57   // and remote Channel ID |remote_cid|. Set to closed upon creation.
58   FakeDynamicChannel(hci_spec::ConnectionHandle conn,
59                      l2cap::Psm psm,
60                      l2cap::ChannelId local_cid,
61                      l2cap::ChannelId remote_cid);
62 
63   // Call the ChannelDeletedCallback instance associated with the server upon
64   // destroying the channel instance.
~FakeDynamicChannel()65   ~FakeDynamicChannel() {
66     if (channel_deleted_callback_) {
67       channel_deleted_callback_();
68     }
69   }
70 
set_opened()71   void set_opened() { opened_ = true; }
set_closed()72   void set_closed() { opened_ = false; }
set_configuration_request_received()73   void set_configuration_request_received() {
74     configuration_request_received_ = true;
75   }
set_configuration_response_received()76   void set_configuration_response_received() {
77     configuration_response_received_ = true;
78   }
set_packet_handler_callback(PacketHandlerCallback packet_handler_callback)79   void set_packet_handler_callback(
80       PacketHandlerCallback packet_handler_callback) {
81     packet_handler_callback_ = std::move(packet_handler_callback);
82   }
set_send_packet_callback(SendPacketCallback send_packet_callback)83   void set_send_packet_callback(SendPacketCallback send_packet_callback) {
84     send_packet_callback_ = std::move(send_packet_callback);
85   }
set_channel_deleted_callback(ChannelDeletedCallback channel_deleted_callback)86   void set_channel_deleted_callback(
87       ChannelDeletedCallback channel_deleted_callback) {
88     channel_deleted_callback_ = std::move(channel_deleted_callback);
89   }
90 
handle()91   hci_spec::ConnectionHandle handle() const { return handle_; }
opened()92   bool opened() const { return opened_; }
configuration_request_received()93   bool configuration_request_received() const {
94     return configuration_request_received_;
95   }
configuration_response_received()96   bool configuration_response_received() const {
97     return configuration_response_received_;
98   }
psm()99   l2cap::Psm psm() const { return psm_; }
local_cid()100   l2cap::ChannelId local_cid() const { return local_cid_; }
remote_cid()101   l2cap::ChannelId remote_cid() const { return remote_cid_; }
packet_handler_callback()102   PacketHandlerCallback& packet_handler_callback() {
103     return packet_handler_callback_;
104   }
send_packet_callback()105   SendPacketCallback& send_packet_callback() { return send_packet_callback_; }
channel_deleted_callback()106   ChannelDeletedCallback& channel_deleted_callback() {
107     return channel_deleted_callback_;
108   }
109 
110   // Return a WeakPtr instance of this FakeDynamicChannel
111   using WeakPtr = WeakSelf<FakeDynamicChannel>::WeakPtr;
AsWeakPtr()112   FakeDynamicChannel::WeakPtr AsWeakPtr() { return weak_self_.GetWeakPtr(); }
113 
114  private:
115   // ConnectionHandle associated with what
116   hci_spec::ConnectionHandle handle_;
117 
118   // If the device is connected  and so is ready to communicate over the
119   // channel.
120   bool opened_;
121 
122   // If the initial ConfigurationRequest needed to open the channel has been
123   // received. There must be a ConfigurationRequest and ConfigurationResponse
124   // received in order to open up the channel.
125   bool configuration_request_received_;
126 
127   // If the initial ConfigurationResponse needed to open the channel has been
128   // received. There must be a ConfigurationRequest and ConfigurationResponse
129   // received in order to open up the channel.
130   bool configuration_response_received_;
131 
132   // The Protocol Service Multiplexer (PSM) associated with the channel.
133   const l2cap::Psm psm_;
134 
135   // Identifies the local device's endpoint of this channel. Will be unique on
136   // this device as long as this channel remains open.
137   const l2cap::ChannelId local_cid_;
138 
139   // Identifies the endpoint of this channel on the peer device. Set upon
140   // connection completion.
141   const l2cap::ChannelId remote_cid_;
142 
143   // Callback associated with handling data packets sent to this channel.
144   PacketHandlerCallback packet_handler_callback_;
145 
146   // Callback associated with sending data packets using this channel.
147   SendPacketCallback send_packet_callback_;
148 
149   // Callback associated with closing the dynamic channel.
150   ChannelDeletedCallback channel_deleted_callback_;
151 
152   // Any management of FakeDynamicChannel instances outside of FakeL2cap
153   // should be done through the use of WeakPtrs.
154   WeakSelf<FakeDynamicChannel> weak_self_;
155 
156   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeDynamicChannel);
157 };
158 
159 }  // namespace bt::testing
160