1 // Copyright 2020 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of 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, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef PLATFORM_IMPL_G3_BLE_H_ 16 #define PLATFORM_IMPL_G3_BLE_H_ 17 18 #include <memory> 19 #include <string> 20 21 #include "platform/api/ble.h" 22 #include "platform/base/byte_array.h" 23 #include "platform/base/input_stream.h" 24 #include "platform/base/output_stream.h" 25 #include "platform/impl/g3/bluetooth_adapter.h" 26 #include "platform/impl/g3/bluetooth_classic.h" 27 #include "platform/impl/g3/multi_thread_executor.h" 28 #include "platform/impl/g3/pipe.h" 29 #include "absl/container/flat_hash_map.h" 30 #include "absl/container/flat_hash_set.h" 31 #include "absl/strings/escaping.h" 32 #include "absl/synchronization/mutex.h" 33 34 namespace location { 35 namespace nearby { 36 namespace g3 { 37 38 class BleMedium; 39 40 class BleSocket : public api::BleSocket { 41 public: 42 BleSocket() = default; BleSocket(BlePeripheral * peripheral)43 explicit BleSocket(BlePeripheral* peripheral) : peripheral_(peripheral) {} 44 ~BleSocket() override; 45 46 // Connect to another BleSocket, to form a functional low-level channel. 47 // from this point on, and until Close is called, connection exists. 48 void Connect(BleSocket& other) ABSL_LOCKS_EXCLUDED(mutex_); 49 50 // Returns the InputStream of this connected BleSocket. 51 InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_); 52 53 // Returns the OutputStream of this connected BleSocket. 54 // This stream is for local side to write. 55 OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_); 56 57 // Returns address of a remote BleSocket or nullptr. 58 BleSocket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_); 59 60 // Returns true if connection exists to the (possibly closed) remote socket. 61 bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); 62 63 // Returns true if socket is closed. 64 bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); 65 66 // Returns Exception::kIo on error, Exception::kSuccess otherwise. 67 Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_); 68 69 // Returns valid BlePeripheral pointer if there is a connection, and 70 // nullptr otherwise. 71 BlePeripheral* GetRemotePeripheral() override 72 ABSL_LOCKS_EXCLUDED(mutex_); 73 74 private: 75 void DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 76 77 // Returns true if connection exists to the (possibly closed) remote socket. 78 bool IsConnectedLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 79 80 // Returns InputStream of our side of a connection. 81 // This is what the remote side is supposed to read from. 82 // This is a helper for GetInputStream() method. 83 InputStream& GetLocalInputStream() ABSL_LOCKS_EXCLUDED(mutex_); 84 85 // Returns OutputStream of our side of a connection. 86 // This is what the local size is supposed to write to. 87 // This is a helper for GetOutputStream() method. 88 OutputStream& GetLocalOutputStream() ABSL_LOCKS_EXCLUDED(mutex_); 89 90 // Output pipe is initialized by constructor, it remains always valid, until 91 // it is closed. it represents output part of a local socket. Input part of a 92 // local socket comes from the peer socket, after connection. 93 std::shared_ptr<Pipe> output_ {new Pipe}; 94 std::shared_ptr<Pipe> input_; 95 mutable absl::Mutex mutex_; 96 BlePeripheral* peripheral_; 97 BleSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; 98 bool closed_ ABSL_GUARDED_BY(mutex_) = false; 99 }; 100 101 class BleServerSocket { 102 public: 103 ~BleServerSocket(); 104 105 // Blocks until either: 106 // - at least one incoming connection request is available, or 107 // - ServerSocket is closed. 108 // On success, returns connected socket, ready to exchange data. 109 // Returns nullptr on error. 110 // Once error is reported, it is permanent, and ServerSocket has to be closed. 111 // 112 // Called by the server side of a connection. 113 // Returns BleSocket to the server side. 114 // If not null, returned socket is connected to its remote (client-side) peer. 115 std::unique_ptr<api::BleSocket> Accept(BlePeripheral* peripheral) 116 ABSL_LOCKS_EXCLUDED(mutex_); 117 118 // Blocks until either: 119 // - connection is available, or 120 // - server socket is closed, or 121 // - error happens. 122 // 123 // Called by the client side of a connection. 124 // Returns true, if socket is successfully connected. 125 bool Connect(BleSocket& socket) ABSL_LOCKS_EXCLUDED(mutex_); 126 127 // Called by the server side of a connection before passing ownership of 128 // BleServerSocker to user, to track validity of a pointer to this 129 // server socket, 130 void SetCloseNotifier(std::function<void()> notifier) 131 ABSL_LOCKS_EXCLUDED(mutex_); 132 133 // Returns Exception::kIo on error, Exception::kSuccess otherwise. 134 // Calls close_notifier if it was previously set, and marks socket as closed. 135 Exception Close() ABSL_LOCKS_EXCLUDED(mutex_); 136 137 private: 138 Exception DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 139 140 absl::Mutex mutex_; 141 absl::CondVar cond_; 142 absl::flat_hash_set<BleSocket*> pending_sockets_ ABSL_GUARDED_BY(mutex_); 143 std::function<void()> close_notifier_ ABSL_GUARDED_BY(mutex_); 144 bool closed_ ABSL_GUARDED_BY(mutex_) = false; 145 }; 146 147 // Container of operations that can be performed over the BLE medium. 148 class BleMedium : public api::BleMedium { 149 public: 150 explicit BleMedium(api::BluetoothAdapter& adapter); 151 ~BleMedium() override; 152 153 // Returns true once the Ble advertising has been initiated. 154 bool StartAdvertising( 155 const std::string& service_id, const ByteArray& advertisement_bytes, 156 const std::string& fast_advertisement_service_uuid) override 157 ABSL_LOCKS_EXCLUDED(mutex_); 158 bool StopAdvertising(const std::string& service_id) override 159 ABSL_LOCKS_EXCLUDED(mutex_); 160 161 // Returns true once the Ble scanning has been initiated. 162 bool StartScanning(const std::string& service_id, 163 const std::string& fast_advertisement_service_uuid, 164 DiscoveredPeripheralCallback callback) override 165 ABSL_LOCKS_EXCLUDED(mutex_); 166 167 // Returns true once Ble scanning for service_id is well and truly 168 // stopped; after this returns, there must be no more invocations of the 169 // DiscoveredPeripheralCallback passed in to StartScanning() for service_id. 170 bool StopScanning(const std::string& service_id) override 171 ABSL_LOCKS_EXCLUDED(mutex_); 172 173 // Returns true once Ble socket connection requests to service_id can be 174 // accepted. 175 bool StartAcceptingConnections(const std::string& service_id, 176 AcceptedConnectionCallback callback) 177 override ABSL_LOCKS_EXCLUDED(mutex_); 178 bool StopAcceptingConnections(const std::string& service_id) override 179 ABSL_LOCKS_EXCLUDED(mutex_); 180 181 // Connects to existing remote Ble peripheral. 182 // 183 // On success, returns a new BleSocket. 184 // On error, returns nullptr. 185 std::unique_ptr<api::BleSocket> Connect( 186 api::BlePeripheral& remote_peripheral, 187 const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_); 188 GetAdapter()189 BluetoothAdapter& GetAdapter() { return *adapter_; } 190 191 private: 192 static constexpr int kMaxConcurrentAcceptLoops = 5; 193 194 struct AdvertisingInfo { EmptyAdvertisingInfo195 bool Empty() const { return service_id.empty(); } ClearAdvertisingInfo196 void Clear() { service_id.clear(); } 197 198 std::string service_id; 199 }; 200 201 struct ScanningInfo { EmptyScanningInfo202 bool Empty() const { return service_id.empty(); } ClearScanningInfo203 void Clear() { service_id.clear(); } 204 205 std::string service_id; 206 }; 207 208 absl::Mutex mutex_; 209 BluetoothAdapter* adapter_; // Our device adapter; read-only. 210 211 // A thread pool dedicated to running all the accept loops from 212 // StartAdvertising(). 213 MultiThreadExecutor accept_loops_runner_{kMaxConcurrentAcceptLoops}; 214 std::atomic_bool acceptance_thread_running_ = false; 215 216 // A thread pool dedicated to wait to complete the accept_loops_runner_. 217 MultiThreadExecutor close_accept_loops_runner_{kMaxConcurrentAcceptLoops}; 218 219 // A server socket is established when start advertising. 220 std::unique_ptr<BleServerSocket> server_socket_; 221 AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_); 222 ScanningInfo scanning_info_ ABSL_GUARDED_BY(mutex_); 223 }; 224 225 } // namespace g3 226 } // namespace nearby 227 } // namespace location 228 229 #endif // PLATFORM_IMPL_G3_BLE_H_ 230