diff --git a/connections/implementation/BUILD b/connections/implementation/BUILD index e437a4ff..e5f2f69a 100644 --- a/connections/implementation/BUILD +++ b/connections/implementation/BUILD @@ -159,6 +159,7 @@ cc_library( "//connections/implementation/mediums:webrtc_utils", "//connections/implementation/mediums/advertisements:dct_advertisement", "//connections/implementation/mediums/advertisements:util", + "//connections/implementation/mediums/ble_v2:ble_advertisement_header", "//connections/implementation/proto:offline_wire_formats_cc_proto", "//connections/v3:v3_types", "//internal/analytics:event_logger", diff --git a/connections/implementation/mediums/ble_v2.cc b/connections/implementation/mediums/ble_v2.cc index ba683703..5d750e22 100644 --- a/connections/implementation/mediums/ble_v2.cc +++ b/connections/implementation/mediums/ble_v2.cc @@ -836,6 +836,43 @@ ErrorOr BleV2::Connect(const std::string& service_id, return socket; } +ErrorOr BleV2::ConnectOverL2cap( + const std::string& service_id, const BleV2Peripheral& peripheral, + CancellationFlag* cancellation_flag) { + MutexLock lock(&mutex_); + + if (service_id.empty()) { + LOG(WARNING) << "Refusing to create client Ble L2CAP socket because " + "service_id is empty."; + return {Error(OperationResultCode::NEARBY_LOCAL_CLIENT_STATE_WRONG)}; + } + + if (!IsAvailableLocked()) { + LOG(INFO) << "Can't create client Ble L2CAP socket [service_id=" + << service_id << "]; Ble isn't available."; + return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)}; + } + + if (cancellation_flag->Cancelled()) { + LOG(WARNING) << "Can't create client Ble L2CAP socket due to cancel."; + return {Error(OperationResultCode:: + CLIENT_CANCELLATION_CANCEL_BLE_OUTGOING_CONNECTION)}; + } + + BleL2capSocket socket = medium_.ConnectOverL2cap( + service_id, PowerLevelToTxPowerLevel(PowerLevel::kHighPower), peripheral, + cancellation_flag); + + if (!socket.IsValid()) { + LOG(WARNING) << "Failed to Connect via Ble L2CAP [service_id=" << service_id + << "]"; + return {Error(OperationResultCode:: + CONNECTIVITY_L2CAP_CLIENT_SOCKET_CREATION_FAILURE)}; + } + + return socket; +} + bool BleV2::IsAvailableLocked() const { return medium_.IsValid(); } bool BleV2::IsAdvertisingLocked(const std::string& service_id) const { diff --git a/connections/implementation/mediums/ble_v2.h b/connections/implementation/mediums/ble_v2.h index 29120c94..959634fd 100644 --- a/connections/implementation/mediums/ble_v2.h +++ b/connections/implementation/mediums/ble_v2.h @@ -182,6 +182,13 @@ class BleV2 final { CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); + // Establishes connection to Ble peripheral. + // Returns socket instance. On success, BleSocket.IsValid() return true. + ErrorOr ConnectOverL2cap(const std::string& service_id, + const BleV2Peripheral& peripheral, + CancellationFlag* cancellation_flag) + ABSL_LOCKS_EXCLUDED(mutex_); + // Returns true if this object owns a valid platform implementation. bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) { MutexLock lock(&mutex_); diff --git a/connections/implementation/p2p_cluster_pcp_handler.cc b/connections/implementation/p2p_cluster_pcp_handler.cc index 6ec6a6d0..acbcfacf 100644 --- a/connections/implementation/p2p_cluster_pcp_handler.cc +++ b/connections/implementation/p2p_cluster_pcp_handler.cc @@ -45,6 +45,7 @@ #include "connections/implementation/mediums/advertisements/advertisement_util.h" #include "connections/implementation/mediums/advertisements/dct_advertisement.h" #include "connections/implementation/mediums/ble_v2.h" +#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h" #include "connections/implementation/mediums/bluetooth_classic.h" #include "connections/implementation/mediums/mediums.h" #include "connections/implementation/mediums/utils.h" @@ -2715,6 +2716,36 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleV2ConnectImpl( VLOG(1) << "Client " << client->GetClientId() << " is attempting to connect to (" << peripheral.ToReadableString() << ") over BLE."; + + if (NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_connections_feature::kEnableBleL2cap) && + peripheral.GetPsm() != + mediums::BleAdvertisementHeader::kDefaultPsmValue) { + ErrorOr ble_l2cap_socket_result = + ble_v2_medium_.ConnectOverL2cap( + endpoint->service_id, peripheral, + client->GetCancellationFlag(endpoint->endpoint_id)); + if (!ble_l2cap_socket_result.has_error()) { + LOG(INFO) << "In BleV2ConnectImpl(), connected to Ble L2CAP device " + << absl::BytesToHexString(peripheral.GetId().data()) + << " for endpoint(id=" << endpoint->endpoint_id << ")."; + auto channel = std::make_unique( + endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, + ble_l2cap_socket_result.value()); + return BasePcpHandler::ConnectImplResult{ + .medium = BLE, + .status = {Status::kSuccess}, + .operation_result_code = OperationResultCode::DETAIL_SUCCESS, + .endpoint_channel = std::move(channel), + }; + } else { + LOG(WARNING) << "In BleV2ConnectImpl(), failed to connect to Ble L2CAP " + "device " + << absl::BytesToHexString(peripheral.GetId().data()) + << " for endpoint(id=" << endpoint->endpoint_id << ")."; + } + } + ErrorOr ble_socket_result = ble_v2_medium_.Connect( endpoint->service_id, peripheral, client->GetCancellationFlag(endpoint->endpoint_id)); diff --git a/internal/platform/ble_v2.cc b/internal/platform/ble_v2.cc index fed6f162..684bf8ce 100644 --- a/internal/platform/ble_v2.cc +++ b/internal/platform/ble_v2.cc @@ -268,6 +268,13 @@ BleV2Socket BleV2Medium::Connect(const std::string& service_id, return socket; } +BleL2capSocket BleV2Medium::ConnectOverL2cap( + const std::string& service_id, TxPowerLevel tx_power_level, + const BleV2Peripheral& peripheral, CancellationFlag* cancellation_flag) { + // TODO(mingshiouwu): Replace with a real implementation connecting flow. + return BleL2capSocket(peripheral, nullptr); +} + bool BleV2Medium::IsExtendedAdvertisementsAvailable() { return IsValid() && impl_->IsExtendedAdvertisementsAvailable(); } diff --git a/internal/platform/ble_v2.h b/internal/platform/ble_v2.h index 82069d30..7b6d8c7c 100644 --- a/internal/platform/ble_v2.h +++ b/internal/platform/ble_v2.h @@ -516,13 +516,20 @@ class BleV2Medium final { // On Success, BleL2capServerSocket::IsValid() returns true. BleL2capServerSocket OpenL2capServerSocket(const std::string& service_id); - // Returns a new BleLanSocket. - // On Success, BleLanSocket::IsValid() returns true. + // Returns a new BleV2Socket. + // On Success, BleV2Socket::IsValid() returns true. BleV2Socket Connect(const std::string& service_id, api::ble_v2::TxPowerLevel tx_power_level, const BleV2Peripheral& peripheral, CancellationFlag* cancellation_flag); + // Returns a new BleL2capSocket. + // On Success, BleL2capSocket::IsValid() returns true. + BleL2capSocket ConnectOverL2cap(const std::string& service_id, + api::ble_v2::TxPowerLevel tx_power_level, + const BleV2Peripheral& peripheral, + CancellationFlag* cancellation_flag); + bool IsExtendedAdvertisementsAvailable(); bool IsValid() const { return impl_ != nullptr; } diff --git a/internal/platform/implementation/ble_v2.h b/internal/platform/implementation/ble_v2.h index 0e50973a..bafb9975 100644 --- a/internal/platform/implementation/ble_v2.h +++ b/internal/platform/implementation/ble_v2.h @@ -580,6 +580,16 @@ class BleMedium { const std::string& service_id, TxPowerLevel tx_power_level, BlePeripheral& peripheral, CancellationFlag* cancellation_flag) = 0; + // Connects to a BLE peripheral over L2CAP. + // + // On success, returns a new BleL2capSocket. + // On error, returns nullptr. + virtual std::unique_ptr ConnectOverL2cap( + const std::string& service_id, TxPowerLevel tx_power_level, + BlePeripheral& peripheral, CancellationFlag* cancellation_flag) { + return nullptr; + }; + // Requests if support extended advertisement. virtual bool IsExtendedAdvertisementsAvailable() = 0;