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 "fake_l2cap.h"
17 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
18 #include "pw_bluetooth_sapphire/internal/host/common/packet_view.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
20 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
21 #include "pw_bluetooth_sapphire/internal/host/testing/fake_dynamic_channel.h"
22 
23 namespace bt::testing {
24 
25 // This class unpacks signaling packets (generally received over a FakeL2cap
26 // link). Each FakePeer should own its own FakeSignalingServer.
27 class FakeSignalingServer final {
28  public:
29   FakeSignalingServer() = default;
30 
31   // Registers this FakeSignalingServer's HandleSdu function with |l2cap_| on
32   // kSignalingChannelId such that all packets processed by |l2cap_| with the
33   // ChannelId kSignalingChanneld will be processed by this server.
34   // FakeL2cap will also handle actually sending packets generated by this
35   // FakeSignalingServer instance.
36   void RegisterWithL2cap(FakeL2cap* l2cap_);
37 
38   // Handles the service data unit |sdu| received over link with handle |conn|
39   // by confirming that the received packet is valid and then calling
40   // ProcessSignalingPacket.
41   void HandleSdu(hci_spec::ConnectionHandle conn, const ByteBuffer& sdu);
42 
43   // Parses the InformationRequest signaling packet |info_req| and then
44   // calls the appropriate function to construct and send a response packet
45   // over handle |conn| and ID |id|.
46   void ProcessInformationRequest(hci_spec::ConnectionHandle conn,
47                                  l2cap::CommandId id,
48                                  const ByteBuffer& info_req);
49 
50   // Handle incoming ConnectionRequest |connection_req| by validating the
51   // request, creating a FakeDynamicChannel object, and registering that
52   // channel with the associated FakeL2cap module. Also will use the server's
53   // SendFrameCallback to send a ConnectionResponse and ConfigurationRequest
54   // over handle |conn| and ID |id|.
55   void ProcessConnectionRequest(hci_spec::ConnectionHandle conn,
56                                 l2cap::CommandId id,
57                                 const ByteBuffer& connection_req);
58 
59   // Handle incoming ConfigurationRequest |configuration_req|. Note that
60   // because the all channels here are basic mode, this is simply part of the
61   // connection process and does not actually configure specific parameters
62   // of the associated FakeDynamicChannel aside from enabling data transfer
63   // when both sides send and receive connection requests.
64   // The emulator assumes that the ProcessConnectionRequest function handles
65   // sending the initial ConfigurationRequest from FakePeer, so if the emulator
66   // received a ConfigurationRequest from bt-host, it will assume the
67   // channel is ready to open.
68   // FakePeer will still respond with a ConfigurationResponse over handle
69   // |conn| using the ID |id| and send it using the FakeL2cap instance's
70   // SendFrameCallback.
71   void ProcessConfigurationRequest(hci_spec::ConnectionHandle conn,
72                                    l2cap::CommandId id,
73                                    const ByteBuffer& configuration_req);
74 
75   // Handle configuration responses sent by bt-host. The emulator assumes that
76   // the ProcessConnectionRequest function handles sending the initial
77   // ConfigurationRequest from FakePeer, so it disregards this
78   // ConnfigurationResponse and instead only processes bt-host's inbound
79   // ConfigurationRequest.
80   void ProcessConfigurationResponse(hci_spec::ConnectionHandle conn,
81                                     l2cap::CommandId id,
82                                     const ByteBuffer& configuration_res);
83 
84   // Upon receiving the disconnection request |disconnection_req|, close and
85   // delete the associated channel from the map associated with fake_l2cap_,
86   // and then send back a disconnection response with connection handle
87   //  |conn| and ID |id| and send it using the FakeL2cap instance's
88   // SendFrameCallback..
89   void ProcessDisconnectionRequest(hci_spec::ConnectionHandle conn,
90                                    l2cap::CommandId id,
91                                    const ByteBuffer& disconnection_req);
92 
93   // Helper function for sending an individual payload buffer |payload_buffer|
94   // by assembling a header with CommandCode |code| and CommandId |id| and then
95   // send it over handle |conn| and with the FakeL2cap instance's
96   // SendFrameCallback.
97   void SendCFrame(hci_spec::ConnectionHandle conn,
98                   l2cap::CommandCode code,
99                   l2cap::CommandId id,
100                   DynamicByteBuffer& payload_buffer);
101 
102   // Reject a command packet for some |reason|. Assemble a command reject
103   // packet using the handle |conn| and the CommandId |id| and send with the
104   // FakeL2cap instance's SendFrameCallback.
105   void SendCommandReject(hci_spec::ConnectionHandle conn,
106                          l2cap::CommandId id,
107                          l2cap::RejectReason reason);
108 
109   // Respond to a received fixed channels InformationRequest packet with a
110   // InformationResponse. Assemble the InformationResponse using the handle
111   // |conn| and id |id|. Send with the FakeL2cap instance's SendFrameCallback.
112   void SendInformationResponseFixedChannels(hci_spec::ConnectionHandle conn,
113                                             l2cap::CommandId id);
114 
115   // Respond to a received extended features InformationRequest packet with a
116   // InformationResponse. Assemble the InformationResponse using the handle
117   // |conn| and id |id|. Send with the FakeL2cap instance's SendFrameCallback.
118   void SendInformationResponseExtendedFeatures(hci_spec::ConnectionHandle conn,
119                                                l2cap::CommandId id);
120 
121   // Respond to a received ConnectionRequest packet with a ConnectionResponse.
122   // Assemble the ConnectionResponse using the handle |conn|, id |id|, local
123   // channel |local_id|, remote channel |remote_id|, ConnectionResult |result|,
124   // and ConnectionStatus |status|. Send with the FakeL2cap instance's
125   // SendFrameCallback.
126   void SendConnectionResponse(hci_spec::ConnectionHandle conn,
127                               l2cap::CommandId id,
128                               l2cap::ChannelId local_cid,
129                               l2cap::ChannelId remote_id,
130                               l2cap::ConnectionResult result,
131                               l2cap::ConnectionStatus status);
132 
133   // Send a ConfigurationRequest packet following a ConnectionResponse.
134   // Assemble the ConfigurationRequest using the handle |conn|, id |id|,
135   // and remote ID |remote_cid|. Send with the FakeL2cap instance's
136   // SendFrameCallback.
137   void SendConfigurationRequest(hci_spec::ConnectionHandle conn,
138                                 l2cap::CommandId id,
139                                 l2cap::ChannelId remote_cid);
140 
141   // Respond to a received ConfigurationRequest packet with a
142   // ConfigurationResposne. Assemble the ConfigurationResposne using the handle
143   // |conn|, id |id|, local ID |local_cid|, and ConfigurationResult |result|.
144   // Send with the
145   /// FakeL2cap instance's SendFrameCallback.
146   void SendConfigurationResponse(hci_spec::ConnectionHandle conn,
147                                  l2cap::CommandId id,
148                                  l2cap::ChannelId local_cid,
149                                  l2cap::ConfigurationResult result);
150 
151   // Respond to a received DisconnectionRequest packet with a
152   // DisconnectionResponse. Assemble the DisconnectionREsponse using the handle
153   // |conn|, id |id|, local ID |local_cid|, and remote ID |remote_cid|. Send
154   // with the FakeL2cap instance's SendFrameCallback.
155   void SendDisconnectionResponse(hci_spec::ConnectionHandle conn,
156                                  l2cap::CommandId id,
157                                  l2cap::ChannelId local_cid,
158                                  l2cap::ChannelId remote_cid);
159 
160   // Return the FakeL2cap instance associated with this FakeSignalingServer.
fake_l2cap()161   FakeL2cap* fake_l2cap() { return fake_l2cap_; }
162 
163  private:
164   // FakeL2cap instance associated with this server, populated after this
165   // FakeSignalingServer registers itself with FakeL2cap.
166   FakeL2cap* fake_l2cap_;
167 
168   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeSignalingServer);
169 };
170 
171 }  // namespace bt::testing
172