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