mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Merged from google/nearby main
This commit is contained in:
@@ -13,6 +13,25 @@
|
||||
# limitations under the License.
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "account_manager",
|
||||
hdrs = ["account_manager.h"],
|
||||
visibility = [
|
||||
"//fastpair:__subpackages__",
|
||||
"//internal/account:__pkg__",
|
||||
"//internal/platform/implementation:__subpackages__",
|
||||
"//internal/test:__subpackages__",
|
||||
"//location/nearby/cpp/sharing/clients/cpp:__subpackages__",
|
||||
"//location/nearby/sharing/sdk/quick_share_server:__pkg__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "types",
|
||||
hdrs = [
|
||||
@@ -39,6 +58,7 @@ cc_library(
|
||||
"timer.h",
|
||||
],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
"//connections/implementation/analytics:__subpackages__",
|
||||
"//fastpair:__subpackages__",
|
||||
"//internal/crypto_cros:__pkg__",
|
||||
@@ -47,14 +67,14 @@ cc_library(
|
||||
"//internal/preferences:__subpackages__",
|
||||
"//internal/test:__subpackages__",
|
||||
"//location/nearby/analytics/cpp:__subpackages__",
|
||||
"//location/nearby/cpp/common:__subpackages__",
|
||||
"//location/nearby/cpp/sharing:__subpackages__",
|
||||
"//presence:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//internal/crypto_cros",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation/shared:crypto", # Non-chromium impl
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/strings",
|
||||
@@ -64,6 +84,24 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "wifi_utils",
|
||||
srcs = [
|
||||
"wifi_utils.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"wifi.h",
|
||||
"wifi_utils.h",
|
||||
],
|
||||
visibility = [
|
||||
"//:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "comm",
|
||||
hdrs = [
|
||||
@@ -84,11 +122,11 @@ cc_library(
|
||||
copts = ["-DNO_WEBRTC"],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
"//fastpair/internal:__pkg__",
|
||||
"//fastpair/internal/mediums:__pkg__",
|
||||
"//internal/network:__subpackages__",
|
||||
"//internal/platform:__pkg__",
|
||||
"//internal/platform/implementation:__subpackages__",
|
||||
"//presence:__subpackages__",
|
||||
"//presence/implementation:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
@@ -121,8 +159,9 @@ cc_library(
|
||||
"//internal/platform:__pkg__",
|
||||
"//internal/platform/implementation:__subpackages__",
|
||||
"//location/nearby/analytics/cpp:__subpackages__",
|
||||
"//location/nearby/apps/better_together/plugins/preferences_native:__subpackages__",
|
||||
"//location/nearby/cpp/sharing:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":comm",
|
||||
@@ -132,3 +171,17 @@ cc_library(
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "wifi_utils_test",
|
||||
size = "small",
|
||||
timeout = "moderate",
|
||||
srcs = ["wifi_utils_test.cc"],
|
||||
shard_count = 8,
|
||||
deps = [
|
||||
":wifi_utils",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_API_ACCOUNT_MANAGER_H_
|
||||
#define PLATFORM_API_ACCOUNT_MANAGER_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
// AccountManager manages the accounts are used to access Nearby backend.
|
||||
// In current design, AccountManager only support one active account.
|
||||
class AccountManager {
|
||||
public:
|
||||
// Describes a Nearby account. The account class will have more properties
|
||||
// and methods in the future based on the new feature added.
|
||||
struct Account {
|
||||
std::string id; // The unique identify of the account.
|
||||
std::string display_name;
|
||||
std::string family_name;
|
||||
std::string given_name;
|
||||
std::string picture_url;
|
||||
std::string email;
|
||||
};
|
||||
|
||||
// Observes the activity of the account manager.
|
||||
class Observer {
|
||||
public:
|
||||
virtual ~Observer() = default;
|
||||
|
||||
virtual void OnLoginSucceeded(absl::string_view account_id) = 0;
|
||||
// |credential_error| is true if the logout is due to critical auth error.
|
||||
virtual void OnLogoutSucceeded(absl::string_view account_id,
|
||||
bool credential_error) = 0;
|
||||
};
|
||||
|
||||
virtual ~AccountManager() = default;
|
||||
|
||||
// Gets current active account. If no login user, return std::nullopt.
|
||||
virtual std::optional<Account> GetCurrentAccount() = 0;
|
||||
|
||||
// Initializes the login process for a Google account from 1P client.
|
||||
// |login_success_callback| is called when the login succeeded. Account
|
||||
// information is passed to callback.
|
||||
// |login_failure_callback| is called when the login fails.
|
||||
virtual void Login(
|
||||
absl::AnyInvocable<void(Account)> login_success_callback,
|
||||
absl::AnyInvocable<void(absl::Status)> login_failure_callback) = 0;
|
||||
|
||||
// Initializes the login process for a Google account from an oauth client.
|
||||
// |client_id| GCP client_id of the client
|
||||
// |client_secret| GCP client_secret of the client
|
||||
// |login_success_callback| is called when the login succeeded. Account
|
||||
// information is passed to callback.
|
||||
// |login_failure_callback| is called when the login fails.
|
||||
virtual void Login(
|
||||
absl::string_view client_id, absl::string_view client_secret,
|
||||
absl::AnyInvocable<void(Account)> login_success_callback,
|
||||
absl::AnyInvocable<void(absl::Status)> login_failure_callback) = 0;
|
||||
|
||||
// Logs out current active account. |logout_callback| is called when logout is
|
||||
// completed.
|
||||
virtual void Logout(
|
||||
absl::AnyInvocable<void(absl::Status)> logout_callback) = 0;
|
||||
|
||||
// Gets access token for the active account.
|
||||
// |success_callback| is called when an access token is fetched successfully.
|
||||
// |failure_callback| is called when fetching an access token failed.
|
||||
//
|
||||
// Returns false if account_id is empty or callback is null.
|
||||
virtual bool GetAccessToken(
|
||||
absl::string_view account_id,
|
||||
absl::AnyInvocable<void(absl::string_view)> success_callback,
|
||||
absl::AnyInvocable<void(absl::Status)> failure_callback) = 0;
|
||||
|
||||
// Returns a pair containing the client id and client secret used in the most
|
||||
// recent Login request.
|
||||
// If no current user is logged in, returns empty string for both.
|
||||
virtual std::pair<std::string, std::string> GetOAuthClientCredential() = 0;
|
||||
|
||||
virtual void AddObserver(Observer* observer) = 0;
|
||||
virtual void RemoveObserver(Observer* observer) = 0;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
#endif // PLATFORM_API_ACCOUNT_MANAGER_H_
|
||||
@@ -17,7 +17,7 @@ package(default_visibility = [
|
||||
"//connections:__subpackages__",
|
||||
"//internal/platform/implementation/apple:__subpackages__",
|
||||
"//location/nearby:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
])
|
||||
|
||||
objc_library(
|
||||
@@ -25,7 +25,6 @@ objc_library(
|
||||
srcs = [
|
||||
"crypto.mm",
|
||||
"device_info.mm",
|
||||
"log_message.mm",
|
||||
"multi_thread_executor.mm",
|
||||
"platform.mm",
|
||||
"preferences_manager.mm",
|
||||
@@ -35,7 +34,6 @@ objc_library(
|
||||
],
|
||||
hdrs = [
|
||||
"device_info.h",
|
||||
"log_message.h",
|
||||
"multi_thread_executor.h",
|
||||
"preferences_manager.h",
|
||||
"scheduled_executor.h",
|
||||
@@ -50,23 +48,25 @@ objc_library(
|
||||
":Platform_cc",
|
||||
":Shared",
|
||||
":ble_v2",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/apple/Mediums",
|
||||
"//internal/platform/implementation/shared:file",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"//third_party/apple_frameworks:Network",
|
||||
"//third_party/objective_c/google_toolbox_for_mac:GTM_Logger",
|
||||
# Required Reason API File: third_party/nearby/internal/platform/implementation/apple/preferences_manager.mm
|
||||
"//releasetools/apple/privacy/privacymanifests/requiredreasonsapi:user_defaults-user_defaults-read_write_app_data_ca92_1",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:span",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"//third_party/apple_frameworks:Network",
|
||||
"@nlohmann_json//:json",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/apple/Mediums",
|
||||
"//internal/platform/implementation/shared:file",
|
||||
"//third_party/objective_c/google_toolbox_for_mac:GTM_Logger",
|
||||
] + select({
|
||||
"@platforms//os:platform_ios": [
|
||||
"//third_party/apple_frameworks:UIKit",
|
||||
@@ -148,8 +148,10 @@ cc_library(
|
||||
"mutex.h",
|
||||
],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@com_google_absl//absl/time",
|
||||
@@ -168,6 +170,7 @@ cc_test(
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":Platform_cc",
|
||||
"//internal/platform/implementation/g3:crypto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@com_google_absl//absl/time",
|
||||
|
||||
@@ -49,6 +49,14 @@ typedef void (^GNCGetCharacteristicCompletionHandler)(
|
||||
typedef void (^GNCReadCharacteristicValueCompletionHandler)(NSData *_Nullable value,
|
||||
NSError *_Nullable error);
|
||||
|
||||
/**
|
||||
* A block to be invoked after a call to @c disconnect, requesting that the local connection to the
|
||||
* remote peripheral be cancelled.
|
||||
*
|
||||
* @param peripheral The remote peripheral to disconnect from.
|
||||
*/
|
||||
typedef void (^GNCRequestDisconnectionHandler)(id<GNCPeripheral> peripheral);
|
||||
|
||||
/**
|
||||
* An object that can be used to discover, explore, and interact with GATT services and
|
||||
* characteristics available on a remote peripheral.
|
||||
@@ -64,8 +72,11 @@ typedef void (^GNCReadCharacteristicValueCompletionHandler)(NSData *_Nullable va
|
||||
* Initializes the GATT client with a specified peripheral.
|
||||
*
|
||||
* @param peripheral The peripheral instance.
|
||||
* @param requestDisconnectionHandler Called on a private queue with @c peripheral when the
|
||||
* connection to the peripheral should be cancelled.
|
||||
*/
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral;
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
|
||||
|
||||
/**
|
||||
* Discovers the specified characteristics of a service.
|
||||
@@ -112,6 +123,9 @@ typedef void (^GNCReadCharacteristicValueCompletionHandler)(NSData *_Nullable va
|
||||
completionHandler:
|
||||
(nullable GNCReadCharacteristicValueCompletionHandler)completionHandler;
|
||||
|
||||
/** Cancels an active or pending local connection to a peripheral. */
|
||||
- (void)disconnect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -49,6 +49,7 @@ static NSError *AlreadyReadingCharacteristicError() {
|
||||
@implementation GNCBLEGATTClient {
|
||||
dispatch_queue_t _queue;
|
||||
id<GNCPeripheral> _peripheral;
|
||||
GNCRequestDisconnectionHandler _requestDisconnectionHandler;
|
||||
|
||||
/**
|
||||
* A map of service UUIDs with each service holding a map of a list of characterisitcs to a
|
||||
@@ -70,15 +71,18 @@ static NSError *AlreadyReadingCharacteristicError() {
|
||||
*_readCharacteristicValueCompletionHandlers;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral {
|
||||
return [self
|
||||
initWithPeripheral:peripheral
|
||||
queue:dispatch_queue_create(kGNCBLEGATTClientQueueLabel, DISPATCH_QUEUE_SERIAL)];
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
|
||||
return [self initWithPeripheral:peripheral
|
||||
queue:dispatch_queue_create(kGNCBLEGATTClientQueueLabel,
|
||||
DISPATCH_QUEUE_SERIAL)
|
||||
requestDisconnectionHandler:requestDisconnectionHandler];
|
||||
};
|
||||
|
||||
// Private.
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
queue:(nullable dispatch_queue_t)queue {
|
||||
queue:(nullable dispatch_queue_t)queue
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_queue = queue ?: dispatch_get_main_queue();
|
||||
@@ -86,6 +90,7 @@ static NSError *AlreadyReadingCharacteristicError() {
|
||||
_peripheral.peripheralDelegate = self;
|
||||
_discoverCharacteristicsCompletionHandlers = [[NSMutableDictionary alloc] init];
|
||||
_readCharacteristicValueCompletionHandlers = [[NSMutableDictionary alloc] init];
|
||||
_requestDisconnectionHandler = requestDisconnectionHandler;
|
||||
}
|
||||
return self;
|
||||
};
|
||||
@@ -173,6 +178,12 @@ static NSError *AlreadyReadingCharacteristicError() {
|
||||
});
|
||||
}
|
||||
|
||||
- (void)disconnect {
|
||||
dispatch_async(_queue, ^{
|
||||
_requestDisconnectionHandler(_peripheral);
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
- (CBCharacteristic *)synchronousCharacteristicWithUUID:(CBUUID *)characteristicUUID
|
||||
|
||||
@@ -245,7 +245,13 @@ static NSError *AlreadyScanningError() {
|
||||
GNCGATTConnectionCompletionHandler handler = _connectionCompletionHandlers[peripheral.identifier];
|
||||
_connectionCompletionHandlers[peripheral.identifier] = nil;
|
||||
if (handler) {
|
||||
GNCBLEGATTClient *client = [[GNCBLEGATTClient alloc] initWithPeripheral:peripheral];
|
||||
GNCBLEGATTClient *client =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:peripheral
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> peripheral) {
|
||||
dispatch_async(_queue, ^{
|
||||
[_centralManager cancelPeripheralConnection:peripheral];
|
||||
});
|
||||
}];
|
||||
handler(client, nil);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)connectPeripheral:(id<GNCPeripheral>)peripheral
|
||||
options:(nullable NSDictionary<NSString *, id> *)options;
|
||||
|
||||
/**
|
||||
* Cancels an active or pending local connection to a peripheral.
|
||||
*
|
||||
* This method is nonblocking, and any @c CBPeripheral class commands that are still pending to
|
||||
* @c peripheral may not complete. Because other apps may still have a connection to the peripheral,
|
||||
* canceling a local connection doesn’t guarantee that the underlying physical link is immediately
|
||||
* disconnected. From the app’s perspective, however, the peripheral is effectively disconnected,
|
||||
* and the central manager object calls the @c centralManager:didDisconnectPeripheral:error: method
|
||||
* of its delegate object.
|
||||
*
|
||||
* @param peripheral The peripheral to which the central manager is either trying to connect or has
|
||||
* already connected.
|
||||
*/
|
||||
- (void)cancelPeripheralConnection:(id<GNCPeripheral>)peripheral;
|
||||
|
||||
/** Asks the central manager to stop scanning for peripherals. */
|
||||
- (void)stopScan;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ NSData *GNCMGenerateBLEFramesIntroductionPacket(NSData *serviceIDHash) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
NSData *GNCMParseBLEFramesIntroductionPacket(NSData *data) {
|
||||
NSData *_Nullable GNCMParseBLEFramesIntroductionPacket(NSData *data) {
|
||||
::location::nearby::mediums::SocketControlFrame socket_control_frame;
|
||||
NSUInteger prefixLength = sizeof(kGNCMControlPacketServiceIDHash);
|
||||
NSData *packet = [data subdataWithRange:NSMakeRange(prefixLength, data.length - prefixLength)];
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("//tools/build_defs/swift:swift_explicit_module_build_test.bzl", "swift_explicit_module_build_test")
|
||||
load("//third_party/nearby:minimum_os.bzl", "IOS_MINIMUM_OS")
|
||||
load("//tools/build_defs/swift:swift_explicit_module_build_test.bzl", "swift_explicit_module_build_test")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
@@ -32,9 +32,7 @@ objc_library(
|
||||
deps = [
|
||||
":Shared",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:CoreFoundation",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"//third_party/apple_frameworks:QuartzCore",
|
||||
"//third_party/objective_c/google_toolbox_for_mac:GTM_Logger",
|
||||
],
|
||||
)
|
||||
|
||||
+5
-1
@@ -728,7 +728,11 @@ static NSString *PeripheralStateString(CBPeripheralState state) {
|
||||
packet.version);
|
||||
[_connectionConfirmTimer invalidate];
|
||||
_connectionConfirmTimer = nil;
|
||||
_socket.packetSize = packet.packetSize;
|
||||
// Weave is using `CBCharacteristicWriteWithResponse` for writes, so we must query max value since
|
||||
// it can have a smaller value than the `GNSWeaveConnectionConfirmPacket` size.
|
||||
NSUInteger maxWriteLength =
|
||||
[_socket.peerAsPeripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithResponse];
|
||||
_socket.packetSize = MIN(packet.packetSize, maxWriteLength);
|
||||
[_socket didConnect];
|
||||
if (packet.data) {
|
||||
// According to the Weave BLE protocol the data received during the connection handshake should
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
|
||||
load("//third_party/nearby:minimum_os.bzl", "IOS_LATEST_TEST_RUNNER", "IOS_MINIMUM_OS")
|
||||
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
|
||||
@@ -31,9 +31,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param peripheral The peripheral instance.
|
||||
* @param queue The queue to run on, this must match the queue that the peripheral's delegate is
|
||||
* running on. Defaults to the main queue when @c nil.
|
||||
* @param requestDisconnectionHandler Called on a private queue with @c peripheral when the
|
||||
* connection to the peripheral should be cancelled.
|
||||
*/
|
||||
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
|
||||
queue:(nullable dispatch_queue_t)queue;
|
||||
queue:(nullable dispatch_queue_t)queue
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTCharacteristic.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCPeripheral.h"
|
||||
#import "internal/platform/implementation/apple/Tests/GNCBLEGATTClient+Testing.h"
|
||||
#import "internal/platform/implementation/apple/Tests/GNCFakePeripheral.h"
|
||||
|
||||
@@ -37,8 +38,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDiscoverCharacteristics {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -64,8 +68,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
|
||||
fakePeripheral.discoverServicesError = [NSError errorWithDomain:@"fake" code:0 userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -97,8 +104,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
code:0
|
||||
userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -123,8 +133,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDuplicateDiscoverCharacteristics {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -163,8 +176,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDiscoverCharacteristicsMultipleCallsWithDifferentServices {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID1 = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *serviceUUID2 = [CBUUID UUIDWithString:kServiceUUID2];
|
||||
@@ -209,8 +225,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDiscoverCharacteristicsMultipleCallsWithDifferentCharacteristics {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID1 = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -256,8 +275,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testGetCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -287,8 +309,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
|
||||
fakePeripheral.discoverServicesError = [NSError errorWithDomain:@"fake" code:0 userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -324,8 +349,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
code:0
|
||||
userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -353,8 +381,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDuplicateGetCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -400,8 +431,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testGetNonExistentCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -425,8 +459,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testReadValueForCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -461,8 +498,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
|
||||
fakePeripheral.discoverServicesError = [NSError errorWithDomain:@"fake" code:0 userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -503,8 +543,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
code:0
|
||||
userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -541,8 +584,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
code:0
|
||||
userInfo:nil];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -576,8 +622,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testDuplicateReadValueForCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -630,8 +679,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testReadValueForMultipleCharacteristics {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID1 = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -691,8 +743,11 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
- (void)testReadValueForUndiscoveredCharacteristic {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
@@ -714,13 +769,33 @@ static NSString *const kCharacteristicUUID2 = @"00000000-0000-3000-8000-00000000
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
- (void)testDisconnect {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"Disconnect."];
|
||||
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> peripheral) {
|
||||
XCTAssertNotNil(peripheral);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[gattClient disconnect];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:3];
|
||||
}
|
||||
|
||||
#pragma mark - Delegate Calls
|
||||
|
||||
- (void)testUnexpectedDelegateCalls {
|
||||
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
|
||||
|
||||
GNCBLEGATTClient *gattClient = [[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil];
|
||||
GNCBLEGATTClient *gattClient =
|
||||
[[GNCBLEGATTClient alloc] initWithPeripheral:fakePeripheral
|
||||
queue:nil
|
||||
requestDisconnectionHandler:^(id<GNCPeripheral> __unused peripheral){
|
||||
}];
|
||||
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID1];
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID1];
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTClient.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTServer.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCPeripheral.h"
|
||||
#import "internal/platform/implementation/apple/Tests/GNCBLEMedium+Testing.h"
|
||||
@@ -313,8 +314,6 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
|
||||
- (void)testDisconnect {
|
||||
GNCFakeCentralManager *fakeCentralManager = [[GNCFakeCentralManager alloc] init];
|
||||
GNCBLEMedium *medium = [[GNCBLEMedium alloc] initWithCentralManager:fakeCentralManager queue:nil];
|
||||
XCTestExpectation *connectExpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Connect."];
|
||||
XCTestExpectation *disconnectExpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Disconnect."];
|
||||
|
||||
@@ -327,13 +326,9 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
|
||||
completionHandler:^(GNCBLEGATTClient *client, NSError *error) {
|
||||
XCTAssertNotNil(client);
|
||||
XCTAssertNil(error);
|
||||
[connectExpectation fulfill];
|
||||
[client disconnect];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ connectExpectation ] timeout:3];
|
||||
|
||||
[fakeCentralManager simulateCentralManagerDidDisconnectPeripheral:peripheral];
|
||||
|
||||
[self waitForExpectations:@[ disconnectExpectation ] timeout:3];
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
[centralDelegate gnc_centralManager:self didConnectPeripheral:peripheral];
|
||||
}
|
||||
|
||||
- (void)cancelPeripheralConnection:(id<GNCPeripheral>)peripheral {
|
||||
[centralDelegate gnc_centralManager:self didDisconnectPeripheral:peripheral error:nil];
|
||||
}
|
||||
|
||||
- (void)stopScan {
|
||||
}
|
||||
|
||||
|
||||
@@ -127,8 +127,9 @@ bool GattClient::SetCharacteristicSubscription(
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
void GattClient::Disconnect() {}
|
||||
void GattClient::Disconnect() {
|
||||
[gatt_client_ disconnect];
|
||||
}
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
|
||||
@@ -145,9 +145,15 @@ void BleMedium::HandleAdvertisementFound(id<GNCPeripheral> peripheral,
|
||||
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession> BleMedium::StartScanning(
|
||||
const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanningCallback callback) {
|
||||
absl::MutexLock lock(&peripherals_mutex_);
|
||||
CBUUID *serviceUUID = CBUUID128FromCPP(service_uuid);
|
||||
scanning_cb_ = std::move(callback);
|
||||
|
||||
// Clear the map of discovered peripherals only when we are starting a new scan. If we cleared the
|
||||
// map every time we stopped a scan, we would not be able to connect to peripherals that we
|
||||
// discovered in that scan session.
|
||||
peripherals_.clear();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUID ]];
|
||||
|
||||
@@ -171,9 +177,15 @@ std::unique_ptr<api::ble_v2::BleMedium::ScanningSession> BleMedium::StartScannin
|
||||
|
||||
bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanCallback callback) {
|
||||
absl::MutexLock lock(&peripherals_mutex_);
|
||||
CBUUID *serviceUUID = CBUUID128FromCPP(service_uuid);
|
||||
scan_cb_ = std::move(callback);
|
||||
|
||||
// Clear the map of discovered peripherals only when we are starting a new scan. If we cleared the
|
||||
// map every time we stopped a scan, we would not be able to connect to peripherals that we
|
||||
// discovered in that scan session.
|
||||
peripherals_.clear();
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUID ]];
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/apple/count_down_latch.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/exception.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
#ifndef PLATFORM_IMPL_APPLE_COUNT_DOWN_LATCH_H_
|
||||
#define PLATFORM_IMPL_APPLE_COUNT_DOWN_LATCH_H_
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/count_down_latch.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
|
||||
#include "internal/platform/implementation/apple/count_down_latch.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "thread/fiber/fiber.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -56,11 +59,11 @@ TEST(CountDownLatchTest, LatchAwaitWithTimeoutCanExpire) {
|
||||
|
||||
auto response = latch.Await(absl::Milliseconds(100));
|
||||
|
||||
EXPECT_TRUE(response.ok());
|
||||
EXPECT_FALSE(response.ok());
|
||||
EXPECT_FALSE(response.result());
|
||||
}
|
||||
|
||||
TEST(CountDownLatchTest, InitialCountZero_AwaitDoesNotBlock) {
|
||||
TEST(CountDownLatchTest, InitialCountZeroAwaitDoesNotBlock) {
|
||||
CountDownLatch latch(0);
|
||||
|
||||
auto response = latch.Await();
|
||||
@@ -68,7 +71,7 @@ TEST(CountDownLatchTest, InitialCountZero_AwaitDoesNotBlock) {
|
||||
EXPECT_TRUE(response.Ok());
|
||||
}
|
||||
|
||||
TEST(CountDownLatchTest, InitialCountNegative_AwaitDoesNotBlock) {
|
||||
TEST(CountDownLatchTest, InitialCountNegativeAwaitDoesNotBlock) {
|
||||
CountDownLatch latch(-1);
|
||||
|
||||
auto response = latch.Await();
|
||||
|
||||
@@ -28,16 +28,13 @@ namespace apple {
|
||||
|
||||
class DeviceInfo : public api::DeviceInfo {
|
||||
public:
|
||||
std::optional<std::u16string> GetOsDeviceName() const override;
|
||||
std::optional<std::string> GetOsDeviceName() const override;
|
||||
|
||||
api::DeviceInfo::DeviceType GetDeviceType() const override;
|
||||
|
||||
api::DeviceInfo::OsType GetOsType() const override;
|
||||
|
||||
std::optional<std::u16string> GetFullName() const override;
|
||||
std::optional<std::u16string> GetGivenName() const override;
|
||||
std::optional<std::u16string> GetLastName() const override;
|
||||
std::optional<std::string> GetProfileUserName() const override;
|
||||
std::optional<std::string> GetGivenName() const override;
|
||||
|
||||
std::optional<std::filesystem::path> GetDownloadPath() const override;
|
||||
|
||||
|
||||
@@ -33,15 +33,15 @@
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetOsDeviceName() const {
|
||||
std::optional<std::string> DeviceInfo::GetOsDeviceName() const {
|
||||
#if TARGET_OS_IPHONE
|
||||
NSString *name = UIDevice.currentDevice.name;
|
||||
const char16_t *cName = (const char16_t *)[name cStringUsingEncoding:NSUTF16StringEncoding];
|
||||
return std::u16string(cName);
|
||||
const char *cName = (const char *)[name cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
return std::string(cName);
|
||||
#elif TARGET_OS_OSX
|
||||
NSString *name = NSHost.currentHost.localizedName;
|
||||
const char16_t *cName = (const char16_t *)[name cStringUsingEncoding:NSUTF16StringEncoding];
|
||||
return std::u16string(cName);
|
||||
const char *cName = (const char *)[name cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
return std::string(cName);
|
||||
#else
|
||||
return std::nullopt;
|
||||
#endif
|
||||
@@ -78,10 +78,7 @@ api::DeviceInfo::OsType DeviceInfo::GetOsType() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetFullName() const { return std::nullopt; }
|
||||
std::optional<std::u16string> DeviceInfo::GetGivenName() const { return std::nullopt; }
|
||||
std::optional<std::u16string> DeviceInfo::GetLastName() const { return std::nullopt; }
|
||||
std::optional<std::string> DeviceInfo::GetProfileUserName() const { return std::nullopt; }
|
||||
std::optional<std::string> DeviceInfo::GetGivenName() const { return std::nullopt; }
|
||||
|
||||
std::optional<std::filesystem::path> DeviceInfo::GetDownloadPath() const {
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_APPLE_LOG_MESSAGE_H_
|
||||
#define PLATFORM_IMPL_APPLE_LOG_MESSAGE_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/log_message.h"
|
||||
#include "GoogleToolboxForMac/GTMLogger.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
class LogStreamer final {
|
||||
public:
|
||||
explicit LogStreamer(GTMLoggerLevel severity, absl::string_view func);
|
||||
|
||||
~LogStreamer();
|
||||
|
||||
std::ostream& stream() { return stream_; }
|
||||
|
||||
private:
|
||||
GTMLoggerLevel severity_;
|
||||
std::string func_;
|
||||
std::ostringstream stream_;
|
||||
};
|
||||
|
||||
// Concrete LogMessage implementation
|
||||
class LogMessage : public api::LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line, Severity severity);
|
||||
~LogMessage() override = default;
|
||||
|
||||
LogMessage(const LogMessage&) = delete;
|
||||
LogMessage& operator=(const LogMessage&) = delete;
|
||||
|
||||
void Print(const char* format, ...) override;
|
||||
|
||||
std::ostream& Stream() override;
|
||||
|
||||
private:
|
||||
LogStreamer log_streamer_;
|
||||
GTMLoggerLevel severity_;
|
||||
std::string func_;
|
||||
};
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
|
||||
#endif // PLATFORM_IMPL_APPLE_LOG_MESSAGE_H_
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/apple/log_message.h"
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "internal/platform/implementation/log_message.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
api::LogMessage::Severity gMinLogSeverity = api::LogMessage::Severity::kInfo;
|
||||
|
||||
GTMLoggerLevel ConvertSeverity(api::LogMessage::Severity severity) {
|
||||
switch (severity) {
|
||||
case api::LogMessage::Severity::kVerbose:
|
||||
return kGTMLoggerLevelDebug;
|
||||
case api::LogMessage::Severity::kInfo:
|
||||
return kGTMLoggerLevelInfo;
|
||||
case api::LogMessage::Severity::kWarning:
|
||||
return kGTMLoggerLevelInfo;
|
||||
case api::LogMessage::Severity::kError:
|
||||
return kGTMLoggerLevelError;
|
||||
case api::LogMessage::Severity::kFatal:
|
||||
return kGTMLoggerLevelAssert;
|
||||
}
|
||||
}
|
||||
|
||||
// GTMLogger expects a function name, but we only have file and line. So format the info as
|
||||
// {basename(file)}:{line} and use that as the function name.
|
||||
std::string ConvertFileAndLine(absl::string_view filepath, int line) {
|
||||
size_t path = filepath.find_last_of('/');
|
||||
if (path != filepath.npos) filepath.remove_prefix(path + 1);
|
||||
return std::string(filepath) + ":" + std::to_string(line);
|
||||
}
|
||||
|
||||
LogStreamer::LogStreamer(GTMLoggerLevel severity, absl::string_view func)
|
||||
: severity_(severity), func_(func) {}
|
||||
|
||||
LogStreamer::~LogStreamer() {
|
||||
switch (severity_) {
|
||||
case kGTMLoggerLevelDebug:
|
||||
[[GTMLogger sharedLogger] logFuncDebug:func_.c_str() msg:@"%@", @(stream_.str().c_str())];
|
||||
break;
|
||||
case kGTMLoggerLevelInfo:
|
||||
[[GTMLogger sharedLogger] logFuncInfo:func_.c_str() msg:@"%@", @(stream_.str().c_str())];
|
||||
break;
|
||||
case kGTMLoggerLevelError:
|
||||
[[GTMLogger sharedLogger] logFuncError:func_.c_str() msg:@"%@", @(stream_.str().c_str())];
|
||||
break;
|
||||
case kGTMLoggerLevelAssert:
|
||||
[[GTMLogger sharedLogger] logFuncAssert:func_.c_str() msg:@"%@", @(stream_.str().c_str())];
|
||||
break;
|
||||
case kGTMLoggerLevelUnknown:
|
||||
// no-op
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, Severity severity)
|
||||
: log_streamer_(ConvertSeverity(severity), ConvertFileAndLine(file, line)),
|
||||
severity_(ConvertSeverity(severity)),
|
||||
func_(ConvertFileAndLine(file, line)) {}
|
||||
|
||||
void LogMessage::Print(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
NSString *msg = [[NSString alloc] initWithFormat:@(format) arguments:ap];
|
||||
switch (severity_) {
|
||||
case kGTMLoggerLevelDebug:
|
||||
[[GTMLogger sharedLogger] logFuncDebug:func_.c_str() msg:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelInfo:
|
||||
[[GTMLogger sharedLogger] logFuncInfo:func_.c_str() msg:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelError:
|
||||
[[GTMLogger sharedLogger] logFuncError:func_.c_str() msg:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelAssert:
|
||||
[[GTMLogger sharedLogger] logFuncAssert:func_.c_str() msg:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelUnknown:
|
||||
// no-op
|
||||
break;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
std::ostream& LogMessage::Stream() { return log_streamer_.stream(); }
|
||||
|
||||
} // namespace apple
|
||||
|
||||
namespace api {
|
||||
|
||||
// static
|
||||
void LogMessage::SetMinLogSeverity(Severity severity) { apple::gMinLogSeverity = severity; }
|
||||
|
||||
// static
|
||||
bool LogMessage::ShouldCreateLogMessage(Severity severity) {
|
||||
return severity >= apple::gMinLogSeverity;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace nearby
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "internal/platform/implementation/apple/condition_variable.h"
|
||||
#include "internal/platform/implementation/apple/count_down_latch.h"
|
||||
#include "internal/platform/implementation/apple/device_info.h"
|
||||
#import "internal/platform/implementation/apple/log_message.h"
|
||||
#import "internal/platform/implementation/apple/multi_thread_executor.h"
|
||||
#include "internal/platform/implementation/apple/mutex.h"
|
||||
#include "internal/platform/implementation/apple/preferences_manager.h"
|
||||
@@ -135,11 +134,6 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(const std::
|
||||
return shared::IOFile::CreateOutputFile(file_path);
|
||||
}
|
||||
|
||||
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
|
||||
const char* file, int line, LogMessage::Severity severity) {
|
||||
return std::make_unique<apple::LogMessage>(file, line, severity);
|
||||
}
|
||||
|
||||
// Java-like Executors
|
||||
std::unique_ptr<SubmittableExecutor> ImplementationPlatform::CreateSingleThreadExecutor() {
|
||||
return std::make_unique<apple::SingleThreadExecutor>();
|
||||
@@ -228,7 +222,7 @@ absl::StatusOr<WebResponse> ImplementationPlatform::SendRequest(const WebRequest
|
||||
[condition unlock];
|
||||
|
||||
if (blockResponse == nil) {
|
||||
return absl::UnknownError([[blockError localizedDescription] UTF8String]);
|
||||
return absl::FailedPreconditionError([[blockError localizedDescription] UTF8String]);
|
||||
}
|
||||
|
||||
WebResponse webResponse;
|
||||
|
||||
@@ -460,12 +460,14 @@ class BleMedium {
|
||||
absl::AnyInvocable<void(BlePeripheral& peripheral,
|
||||
BleAdvertisementData advertisement_data)>
|
||||
advertisement_found_cb = [](BlePeripheral&, BleAdvertisementData) {};
|
||||
absl::AnyInvocable<void(BlePeripheral& peripheral)>
|
||||
advertisement_lost_cb = [](BlePeripheral&) {};
|
||||
};
|
||||
|
||||
// Async interface for StartScanning.
|
||||
// Result status will be passed to start_advertising_result callback.
|
||||
// To stop advertising, invoke the stop_advertising callback in
|
||||
// AdvertisingSession.
|
||||
// Result status will be passed to start_scanning_result callback.
|
||||
// To stop scanning, invoke the stop_scanning callback in
|
||||
// ScanningSession.
|
||||
virtual std::unique_ptr<ScanningSession> StartScanning(
|
||||
const Uuid& service_uuid, TxPowerLevel tx_power_level,
|
||||
ScanningCallback callback) = 0;
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
#ifndef PLATFORM_API_CRYPTO_H_
|
||||
#define PLATFORM_API_CRYPTO_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#ifdef NEARBY_CHROMIUM
|
||||
#include "crypto/random.h"
|
||||
#else
|
||||
#include "internal/crypto_cros/random.h"
|
||||
#endif
|
||||
#include "absl/types/span.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -36,12 +35,23 @@ class Crypto {
|
||||
static ByteArray Sha256(absl::string_view input);
|
||||
};
|
||||
|
||||
// Fills the given buffer with |length| random bytes of cryptographically
|
||||
// secure random numbers.
|
||||
// |length| must be positive.
|
||||
//
|
||||
// TODO(crbug.com/40284755): Convert all callers in Nearby to use spans
|
||||
// and remove this RandBytes overload.
|
||||
void RandBytes(void *bytes, size_t length);
|
||||
|
||||
// Fills |bytes| with cryptographically-secure random bits.
|
||||
void RandBytes(absl::Span<uint8_t> bytes);
|
||||
|
||||
// Creates an object of type T initialized with random data.
|
||||
// This template should be used for simple data types: int, char, etc.
|
||||
template <typename T>
|
||||
T RandData() {
|
||||
T data;
|
||||
::crypto::RandBytes(&data, sizeof(data));
|
||||
RandBytes(&data, sizeof(data));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,15 +41,12 @@ class DeviceInfo {
|
||||
virtual ~DeviceInfo() = default;
|
||||
|
||||
// Gets device name.
|
||||
virtual std::optional<std::u16string> GetOsDeviceName() const = 0;
|
||||
virtual std::optional<std::string> GetOsDeviceName() const = 0;
|
||||
virtual DeviceType GetDeviceType() const = 0;
|
||||
virtual OsType GetOsType() const = 0;
|
||||
|
||||
// Gets basic information of current user.
|
||||
virtual std::optional<std::u16string> GetFullName() const = 0;
|
||||
virtual std::optional<std::u16string> GetGivenName() const = 0;
|
||||
virtual std::optional<std::u16string> GetLastName() const = 0;
|
||||
virtual std::optional<std::string> GetProfileUserName() const = 0;
|
||||
virtual std::optional<std::string> GetGivenName() const = 0;
|
||||
|
||||
// Gets known paths of current user.
|
||||
virtual std::optional<std::filesystem::path> GetDownloadPath() const = 0;
|
||||
|
||||
@@ -17,7 +17,6 @@ cc_library(
|
||||
name = "types",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"log_message.cc",
|
||||
"preferences_manager.cc",
|
||||
"scheduled_executor.cc",
|
||||
"system_clock.cc",
|
||||
@@ -27,7 +26,6 @@ cc_library(
|
||||
"atomic_reference.h",
|
||||
"condition_variable.h",
|
||||
"device_info.h",
|
||||
"log_message.h",
|
||||
"multi_thread_executor.h",
|
||||
"mutex.h",
|
||||
"preferences_manager.h",
|
||||
@@ -35,17 +33,12 @@ cc_library(
|
||||
"single_thread_executor.h",
|
||||
"timer.h",
|
||||
],
|
||||
visibility = [
|
||||
"//internal/test:__subpackages__",
|
||||
"//location/nearby/cpp:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":preferences_repository",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:util",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/platform/implementation/shared:posix_mutex",
|
||||
@@ -53,11 +46,12 @@ cc_library(
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:btree",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/log:log_streamer",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:span",
|
||||
"@com_google_glog//:glog",
|
||||
"@com_google_nisaba//nisaba/port:thread_pool",
|
||||
"@nlohmann_json//:json",
|
||||
],
|
||||
@@ -73,7 +67,6 @@ cc_library(
|
||||
"bluetooth_adapter.cc",
|
||||
"bluetooth_classic.cc",
|
||||
"credential_storage_impl.cc",
|
||||
"webrtc.cc",
|
||||
"wifi_direct.cc",
|
||||
"wifi_hotspot.cc",
|
||||
"wifi_lan.cc",
|
||||
@@ -85,7 +78,6 @@ cc_library(
|
||||
"bluetooth_classic.h",
|
||||
"credential_storage_impl.h",
|
||||
"socket_base.h",
|
||||
"webrtc.h",
|
||||
"wifi.h",
|
||||
"wifi_direct.h",
|
||||
"wifi_hotspot.h",
|
||||
@@ -94,6 +86,16 @@ cc_library(
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":types",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/proto:credential_cc_proto",
|
||||
# TODO: Support WebRTC
|
||||
"//third_party/webrtc/files/stable/webrtc/api:scoped_refptr",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
@@ -104,17 +106,7 @@ cc_library(
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/proto:credential_cc_proto",
|
||||
# TODO: Support WebRTC
|
||||
"//third_party/webrtc/files/stable/webrtc/api/task_queue:default_task_queue_factory",
|
||||
"//third_party/webrtc/files/stable/webrtc/rtc_base:checks",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -124,7 +116,7 @@ cc_library(
|
||||
srcs = [
|
||||
"crypto.cc",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
visibility = ["//internal/platform/implementation:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:types",
|
||||
@@ -140,11 +132,13 @@ cc_library(
|
||||
srcs = [
|
||||
"platform.cc",
|
||||
],
|
||||
defines = ["NO_WEBRTC"],
|
||||
visibility = [
|
||||
"//connections:__subpackages__",
|
||||
"//fastpair:__subpackages__",
|
||||
"//internal/account:__subpackages__",
|
||||
"//internal/auth:__subpackages__",
|
||||
"//internal/crypto:__subpackages__",
|
||||
"//internal/data:__subpackages__",
|
||||
"//internal/flags:__subpackages__",
|
||||
"//internal/network:__subpackages__",
|
||||
@@ -154,24 +148,28 @@ cc_library(
|
||||
"//internal/test:__subpackages__",
|
||||
"//internal/weave:__subpackages__",
|
||||
"//location/nearby/cpp:__subpackages__",
|
||||
"//location/nearby/sharing/sdk:__subpackages__",
|
||||
"//presence:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":comm",
|
||||
":crypto", # build_cleaner: keep
|
||||
":types",
|
||||
"//file/base:path",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/platform/implementation/shared:file",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_nisaba//nisaba/port:thread_pool",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
@@ -64,8 +65,8 @@ bool BleServerSocket::Connect(BleSocket& socket) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (closed_) return false;
|
||||
if (socket.IsConnected()) {
|
||||
NEARBY_LOG(ERROR,
|
||||
"Failed to connect to Ble server socket: already connected");
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to connect to Ble server socket: already connected";
|
||||
return true; // already connected.
|
||||
}
|
||||
// add client socket to the pending list
|
||||
@@ -126,8 +127,8 @@ BleMedium::~BleMedium() {
|
||||
StopScanning(scanning_info_.service_id);
|
||||
|
||||
accept_loops_runner_.Shutdown();
|
||||
NEARBY_LOG(INFO, "BleMedium dtor advertising_accept_thread_running_ = %d",
|
||||
acceptance_thread_running_.load());
|
||||
NEARBY_LOGS(INFO) << "BleMedium dtor advertising_accept_thread_running_ = "
|
||||
<< acceptance_thread_running_.load();
|
||||
// If acceptance thread is still running, wait to finish.
|
||||
if (acceptance_thread_running_) {
|
||||
while (acceptance_thread_running_) {
|
||||
@@ -142,10 +143,11 @@ bool BleMedium::StartAdvertising(
|
||||
const std::string& service_id, const ByteArray& advertisement_bytes,
|
||||
const std::string& fast_advertisement_service_uuid) {
|
||||
NEARBY_LOGS(INFO) << "G3 Ble StartAdvertising: service_id=" << service_id
|
||||
<< ", advertisement bytes=" << advertisement_bytes.data()
|
||||
<< ", advertisement bytes="
|
||||
<< absl::BytesToHexString(std::string(advertisement_bytes))
|
||||
<< "(" << advertisement_bytes.size() << "),"
|
||||
<< " fast advertisement service uuid="
|
||||
<< fast_advertisement_service_uuid;
|
||||
<< ", fast advertisement service uuid="
|
||||
<< absl::BytesToHexString(fast_advertisement_service_uuid);
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
auto& peripheral = adapter_->GetPeripheral();
|
||||
peripheral.SetAdvertisementBytes(service_id, advertisement_bytes);
|
||||
@@ -159,14 +161,13 @@ bool BleMedium::StartAdvertising(
|
||||
|
||||
acceptance_thread_running_.exchange(true);
|
||||
accept_loops_runner_.Execute([&env, this, service_id]() mutable {
|
||||
if (!accept_loops_runner_.InShutdown()) {
|
||||
while (true) {
|
||||
auto client_socket =
|
||||
server_socket_->Accept(&(this->adapter_->GetPeripheral()));
|
||||
if (client_socket == nullptr) break;
|
||||
env.CallBleAcceptedConnectionCallback(*this, *(client_socket.release()),
|
||||
service_id);
|
||||
}
|
||||
while (true) {
|
||||
if (accept_loops_runner_.InShutdown()) break;
|
||||
auto client_socket =
|
||||
server_socket_->Accept(&(this->adapter_->GetPeripheral()));
|
||||
if (client_socket == nullptr) break;
|
||||
env.CallBleAcceptedConnectionCallback(*this, *(client_socket.release()),
|
||||
service_id);
|
||||
}
|
||||
acceptance_thread_running_.exchange(false);
|
||||
});
|
||||
@@ -262,11 +263,10 @@ bool BleMedium::StopAcceptingConnections(const std::string& service_id) {
|
||||
std::unique_ptr<api::BleSocket> BleMedium::Connect(
|
||||
api::BlePeripheral& remote_peripheral, const std::string& service_id,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
NEARBY_LOG(INFO,
|
||||
"G3 Ble Connect [self]: medium=%p, adapter=%p, peripheral=%p, "
|
||||
"service_id=%s",
|
||||
this, &GetAdapter(), &GetAdapter().GetPeripheral(),
|
||||
service_id.c_str());
|
||||
NEARBY_LOGS(INFO) << "G3 Ble Connect [self]: medium=" << this
|
||||
<< ", adapter=" << &GetAdapter()
|
||||
<< ", peripheral=" << &GetAdapter().GetPeripheral()
|
||||
<< ", service_id=" << service_id;
|
||||
// First, find an instance of remote medium, that exposed this peripheral.
|
||||
auto& adapter = static_cast<BlePeripheral&>(remote_peripheral).GetAdapter();
|
||||
auto* medium = static_cast<BleMedium*>(adapter.GetBleMedium());
|
||||
@@ -274,10 +274,10 @@ std::unique_ptr<api::BleSocket> BleMedium::Connect(
|
||||
if (!medium) return {}; // Can't find medium. Bail out.
|
||||
|
||||
BleServerSocket* remote_server_socket = nullptr;
|
||||
NEARBY_LOG(INFO,
|
||||
"G3 Ble Connect [peer]: medium=%p, adapter=%p, peripheral=%p, "
|
||||
"service_id=%s",
|
||||
medium, &adapter, &remote_peripheral, service_id.c_str());
|
||||
NEARBY_LOGS(INFO) << "G3 Ble Connect [peer]: medium=" << medium
|
||||
<< ", adapter=" << &adapter
|
||||
<< ", peripheral=" << &remote_peripheral
|
||||
<< ", service_id=" << service_id;
|
||||
// Then, find our server socket context in this medium.
|
||||
{
|
||||
absl::MutexLock medium_lock(&medium->mutex_);
|
||||
@@ -312,7 +312,7 @@ std::unique_ptr<api::BleSocket> BleMedium::Connect(
|
||||
return {};
|
||||
}
|
||||
|
||||
NEARBY_LOG(INFO, "G3 Ble Connect: connected: socket=%p", socket.get());
|
||||
NEARBY_LOGS(INFO) << "G3 Ble Connect: connected: socket=" << socket.get();
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ class BleMedium : public api::BleMedium {
|
||||
std::atomic_bool acceptance_thread_running_ = false;
|
||||
|
||||
// A thread pool dedicated to wait to complete the accept_loops_runner_.
|
||||
MultiThreadExecutor close_accept_loops_runner_{kMaxConcurrentAcceptLoops};
|
||||
MultiThreadExecutor close_accept_loops_runner_{1};
|
||||
|
||||
// A server socket is established when start advertising.
|
||||
std::unique_ptr<BleServerSocket> server_socket_;
|
||||
|
||||
@@ -160,6 +160,8 @@ Exception BleV2ServerSocket::DoClose() {
|
||||
BleV2Medium::BleV2Medium(api::BluetoothAdapter& adapter)
|
||||
: adapter_(static_cast<BluetoothAdapter*>(&adapter)) {
|
||||
adapter_->SetBleV2Medium(this);
|
||||
is_extended_advertisements_available_ =
|
||||
MediumEnvironment::Instance().IsBleExtendedAdvertisementsAvailable();
|
||||
|
||||
MediumEnvironment::Instance().RegisterBleV2Medium(*this, &peripheral_);
|
||||
}
|
||||
@@ -180,7 +182,7 @@ bool BleV2Medium::StartAdvertising(
|
||||
<< TxPowerLevelToName(advertise_parameters.tx_power_level)
|
||||
<< ", is_connectable=" << advertise_parameters.is_connectable;
|
||||
if (advertising_data.is_extended_advertisement &&
|
||||
!is_support_extended_advertisement_) {
|
||||
!IsExtendedAdvertisementsAvailable()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 Ble StartAdvertising does not support extended advertisement";
|
||||
return false;
|
||||
@@ -215,7 +217,7 @@ std::unique_ptr<BleV2Medium::AdvertisingSession> BleV2Medium::StartAdvertising(
|
||||
<< TxPowerLevelToName(advertise_parameters.tx_power_level)
|
||||
<< ", is_connectable=" << advertise_parameters.is_connectable;
|
||||
if (advertising_data.is_extended_advertisement &&
|
||||
!is_support_extended_advertisement_) {
|
||||
!IsExtendedAdvertisementsAvailable()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 Ble StartAdvertising does not support extended advertisement";
|
||||
return nullptr;
|
||||
@@ -326,7 +328,7 @@ std::unique_ptr<api::ble_v2::GattClient> BleV2Medium::ConnectToGattServer(
|
||||
}
|
||||
|
||||
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
|
||||
return is_support_extended_advertisement_;
|
||||
return is_extended_advertisements_available_;
|
||||
}
|
||||
|
||||
bool BleV2Medium::GetRemotePeripheral(const std::string& mac_address,
|
||||
|
||||
@@ -23,15 +23,24 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/borrowable.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/g3/socket_base.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/prng.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -323,8 +332,7 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
absl::flat_hash_set<std::pair<Uuid, std::uint32_t>>
|
||||
scanning_internal_session_ids_ ABSL_GUARDED_BY(mutex_);
|
||||
// TODO(edwinwu): Adds extended advertisement for testing.
|
||||
bool is_support_extended_advertisement_ = false;
|
||||
bool is_extended_advertisements_available_ = false;
|
||||
};
|
||||
|
||||
} // namespace g3
|
||||
|
||||
@@ -217,6 +217,16 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
<< service_uuid;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (cancellation_flag->Cancelled()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "G3 Bluetooth Connect: Has been cancelled after connected: "
|
||||
"service_uuid="
|
||||
<< service_uuid;
|
||||
socket->Close();
|
||||
return {};
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "G3 ConnectToService: connected: socket="
|
||||
<< socket.get();
|
||||
return socket;
|
||||
|
||||
@@ -70,7 +70,6 @@ void CredentialStorageImpl::SaveCredentials(
|
||||
NEARBY_LOGS(INFO) << "G3 Save Private Credentials for account: ["
|
||||
<< account_name << "], manager app ID:[" << manager_app_id
|
||||
<< "]";
|
||||
absl::MutexLock lock(&private_mutex_);
|
||||
SaveLocalCredentialsLocked(manager_app_id, account_name,
|
||||
private_credentials);
|
||||
}
|
||||
@@ -83,7 +82,6 @@ void CredentialStorageImpl::SaveCredentials(
|
||||
NEARBY_LOGS(INFO) << "G3 Save Public Credentials for account: ["
|
||||
<< account_name << "], manager app ID:[" << manager_app_id
|
||||
<< "]";
|
||||
absl::MutexLock lock(&public_mutex_);
|
||||
PublicCredentialKey key = CreatePublicCredentialKey(
|
||||
manager_app_id, account_name, public_credential_type);
|
||||
auto public_result =
|
||||
@@ -116,7 +114,6 @@ void CredentialStorageImpl::UpdateLocalCredential(
|
||||
NEARBY_LOGS(INFO) << "G3 Update Private Credential for for account: ["
|
||||
<< account_name << "], manager app ID:[" << manager_app_id
|
||||
<< "]";
|
||||
absl::MutexLock lock(&private_mutex_);
|
||||
absl::StatusOr<std::vector<LocalCredential>> credentials =
|
||||
GetLocalCredentialsLocked(CredentialSelector{
|
||||
.manager_app_id = std::string(manager_app_id),
|
||||
@@ -126,10 +123,9 @@ void CredentialStorageImpl::UpdateLocalCredential(
|
||||
NEARBY_LOGS(WARNING) << credentials.status();
|
||||
credentials = std::vector<LocalCredential>();
|
||||
}
|
||||
auto it = std::find_if(credentials->begin(), credentials->end(),
|
||||
[&](const LocalCredential& a) {
|
||||
return a.secret_id() == credential.secret_id();
|
||||
});
|
||||
auto it = std::find_if(
|
||||
credentials->begin(), credentials->end(),
|
||||
[&](const LocalCredential& a) { return a.id() == credential.id(); });
|
||||
if (it == credentials->end()) {
|
||||
credentials->push_back(std::move(credential));
|
||||
} else {
|
||||
@@ -143,7 +139,6 @@ void CredentialStorageImpl::GetLocalCredentials(
|
||||
const CredentialSelector& credential_selector,
|
||||
GetLocalCredentialsResultCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "G3 Get Private Credentials for " << credential_selector;
|
||||
absl::MutexLock lock(&private_mutex_);
|
||||
std::move(callback.credentials_fetched_cb)(
|
||||
GetLocalCredentialsLocked(credential_selector));
|
||||
}
|
||||
@@ -174,7 +169,6 @@ void CredentialStorageImpl::GetPublicCredentials(
|
||||
PublicCredentialType public_credential_type,
|
||||
GetPublicCredentialsResultCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "G3 Get Public Credentials for " << credential_selector;
|
||||
absl::MutexLock lock(&public_mutex_);
|
||||
PublicCredentialKey key = CreatePublicCredentialKey(
|
||||
credential_selector.manager_app_id, credential_selector.account_name,
|
||||
public_credential_type);
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace g3 {
|
||||
|
||||
class DeviceInfo : public api::DeviceInfo {
|
||||
public:
|
||||
std::optional<std::u16string> GetOsDeviceName() const override {
|
||||
return u"Windows";
|
||||
std::optional<std::string> GetOsDeviceName() const override {
|
||||
return "Windows";
|
||||
}
|
||||
|
||||
api::DeviceInfo::DeviceType GetDeviceType() const override {
|
||||
@@ -42,16 +42,7 @@ class DeviceInfo : public api::DeviceInfo {
|
||||
return api::DeviceInfo::OsType::kChromeOs;
|
||||
}
|
||||
|
||||
std::optional<std::u16string> GetFullName() const override {
|
||||
return u"nearby";
|
||||
}
|
||||
std::optional<std::u16string> GetGivenName() const override {
|
||||
return u"nearby";
|
||||
}
|
||||
std::optional<std::u16string> GetLastName() const override {
|
||||
return u"nearby";
|
||||
}
|
||||
std::optional<std::string> GetProfileUserName() const override {
|
||||
std::optional<std::string> GetGivenName() const override {
|
||||
return "nearby";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/g3/log_message.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
namespace nearby {
|
||||
namespace g3 {
|
||||
|
||||
namespace {
|
||||
|
||||
// This is a partial copy of base::StringAppendV for OSS compilation.
|
||||
void NearbyStringAppendV(std::string* dst, const char* format, va_list ap) {
|
||||
// Fixed size buffer 1024 should be big enough.
|
||||
static const int kSpaceLength = 1024;
|
||||
char space[kSpaceLength];
|
||||
int result = vsnprintf(space, kSpaceLength, format, ap);
|
||||
va_end(ap);
|
||||
dst->append(space, result);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
api::LogMessage::Severity g_min_log_severity = api::LogMessage::Severity::kInfo;
|
||||
|
||||
inline absl::LogSeverity ConvertSeverity(api::LogMessage::Severity severity) {
|
||||
switch (severity) {
|
||||
// api::LogMessage::Severity kVerbose and kInfo is mapped to
|
||||
// absl::LogSeverity kInfo since absl::LogSeverity doesn't have kVerbose
|
||||
// level.
|
||||
case api::LogMessage::Severity::kVerbose:
|
||||
case api::LogMessage::Severity::kInfo:
|
||||
return absl::LogSeverity::kInfo;
|
||||
case api::LogMessage::Severity::kWarning:
|
||||
return absl::LogSeverity::kWarning;
|
||||
case api::LogMessage::Severity::kError:
|
||||
return absl::LogSeverity::kError;
|
||||
case api::LogMessage::Severity::kFatal:
|
||||
return absl::LogSeverity::kFatal;
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, Severity severity)
|
||||
: log_streamer_(ConvertSeverity(severity), file, line) {}
|
||||
|
||||
LogMessage::~LogMessage() = default;
|
||||
|
||||
void LogMessage::Print(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string result;
|
||||
NearbyStringAppendV(&result, format, ap);
|
||||
log_streamer_.stream() << result;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
std::ostream& LogMessage::Stream() { return log_streamer_.stream(); }
|
||||
|
||||
} // namespace g3
|
||||
|
||||
namespace api {
|
||||
|
||||
void LogMessage::SetMinLogSeverity(Severity severity) {
|
||||
g3::g_min_log_severity = severity;
|
||||
}
|
||||
|
||||
bool LogMessage::ShouldCreateLogMessage(Severity severity) {
|
||||
return severity >= g3::g_min_log_severity;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace nearby
|
||||
@@ -15,28 +15,45 @@
|
||||
#include "internal/platform/implementation/platform.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "file/base/path.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/atomic_boolean.h"
|
||||
#include "internal/platform/implementation/atomic_reference.h"
|
||||
#include "internal/platform/implementation/ble.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/condition_variable.h"
|
||||
#include "internal/platform/implementation/count_down_latch.h"
|
||||
#include "internal/platform/implementation/credential_storage.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#include "internal/platform/implementation/http_loader.h"
|
||||
#include "internal/platform/implementation/input_file.h"
|
||||
#include "internal/platform/implementation/log_message.h"
|
||||
#include "internal/platform/implementation/mutex.h"
|
||||
#include "internal/platform/implementation/output_file.h"
|
||||
#include "internal/platform/implementation/preferences_manager.h"
|
||||
#include "internal/platform/implementation/scheduled_executor.h"
|
||||
#include "internal/platform/implementation/server_sync.h"
|
||||
#include "internal/platform/implementation/shared/count_down_latch.h"
|
||||
#include "internal/platform/implementation/submittable_executor.h"
|
||||
#include "internal/platform/implementation/timer.h"
|
||||
#include "internal/platform/implementation/wifi_direct.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/wifi_lan.h"
|
||||
#include "internal/platform/os_name.h"
|
||||
#include "internal/platform/payload_id.h"
|
||||
#include "thread/thread.h"
|
||||
#ifndef NO_WEBRTC
|
||||
#include "internal/platform/implementation/g3/webrtc.h"
|
||||
#include "internal/platform/implementation/webrtc.h"
|
||||
@@ -50,7 +67,6 @@
|
||||
#include "internal/platform/implementation/g3/condition_variable.h"
|
||||
#include "internal/platform/implementation/g3/credential_storage_impl.h"
|
||||
#include "internal/platform/implementation/g3/device_info.h"
|
||||
#include "internal/platform/implementation/g3/log_message.h"
|
||||
#include "internal/platform/implementation/g3/multi_thread_executor.h"
|
||||
#include "internal/platform/implementation/g3/mutex.h"
|
||||
#include "internal/platform/implementation/g3/preferences_manager.h"
|
||||
@@ -70,14 +86,12 @@ namespace api {
|
||||
|
||||
std::string ImplementationPlatform::GetCustomSavePath(
|
||||
const std::string& parent_folder, const std::string& file_name) {
|
||||
return file::JoinPath(parent_folder, file_name);
|
||||
return absl::StrCat(parent_folder, file_name);
|
||||
}
|
||||
|
||||
std::string ImplementationPlatform::GetDownloadPath(
|
||||
const std::string& parent_folder, const std::string& file_name) {
|
||||
std::string fullPath("/tmp");
|
||||
|
||||
return file::JoinPath("/tmp", file_name);
|
||||
return absl::StrCat("/tmp/", file_name);
|
||||
}
|
||||
|
||||
OSName ImplementationPlatform::GetCurrentOS() { return OSName::kLinux; }
|
||||
@@ -153,7 +167,7 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
|
||||
|
||||
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
|
||||
const char* file, int line, LogMessage::Severity severity) {
|
||||
return std::make_unique<g3::LogMessage>(file, line, severity);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<BluetoothClassicMedium>
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/cancelable.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
@@ -32,13 +36,14 @@ class ScheduledCancelable : public api::Cancelable {
|
||||
public:
|
||||
bool Cancel() override {
|
||||
Status expected = kNotRun;
|
||||
while (expected == kNotRun) {
|
||||
if (status_.compare_exchange_strong(expected, kCanceled)) {
|
||||
return true;
|
||||
}
|
||||
if (status_.compare_exchange_strong(expected, kCanceled)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsCanceled() const { return status_ == kCanceled; }
|
||||
|
||||
bool MarkExecuted() {
|
||||
Status expected = kNotRun;
|
||||
while (expected == kNotRun) {
|
||||
@@ -61,7 +66,7 @@ class ScheduledCancelable : public api::Cancelable {
|
||||
} // namespace
|
||||
|
||||
ScheduledExecutor::ScheduledExecutor() {
|
||||
absl::optional<FakeClock*> fake_clock =
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
if (fake_clock.has_value()) {
|
||||
name_ = absl::StrFormat("G3 scheduled executor %p", this);
|
||||
@@ -70,7 +75,7 @@ ScheduledExecutor::ScheduledExecutor() {
|
||||
}
|
||||
|
||||
ScheduledExecutor::~ScheduledExecutor() {
|
||||
absl::optional<FakeClock*> fake_clock =
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
if (fake_clock.has_value()) {
|
||||
(*fake_clock)->RemoveObserver(name_);
|
||||
@@ -86,11 +91,12 @@ std::shared_ptr<api::Cancelable> ScheduledExecutor::Schedule(
|
||||
}
|
||||
Runnable task = [this, scheduled_cancelable,
|
||||
runnable = std::move(runnable)]() mutable {
|
||||
if (!executor_.InShutdown() && scheduled_cancelable->MarkExecuted()) {
|
||||
if (!executor_.InShutdown() && !scheduled_cancelable->IsCanceled() &&
|
||||
scheduled_cancelable->MarkExecuted()) {
|
||||
runnable();
|
||||
}
|
||||
};
|
||||
absl::optional<FakeClock*> fake_clock =
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
if (fake_clock.has_value()) {
|
||||
absl::Time trigger_time = (*fake_clock)->Now() + delay;
|
||||
@@ -104,7 +110,7 @@ std::shared_ptr<api::Cancelable> ScheduledExecutor::Schedule(
|
||||
}
|
||||
|
||||
void ScheduledExecutor::RunReadyTasks() {
|
||||
absl::optional<FakeClock*> fake_clock =
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
if (executor_.InShutdown()) {
|
||||
return;
|
||||
|
||||
@@ -15,9 +15,17 @@
|
||||
#include "internal/platform/implementation/g3/webrtc.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/webrtc.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "webrtc/api/peer_connection_interface.h"
|
||||
#include "webrtc/api/scoped_refptr.h"
|
||||
#include "webrtc/api/task_queue/default_task_queue_factory.h"
|
||||
#include "webrtc/rtc_base/checks.h"
|
||||
|
||||
@@ -56,6 +64,12 @@ const std::string WebRtcMedium::GetDefaultCountryCode() { return "US"; }
|
||||
|
||||
void WebRtcMedium::CreatePeerConnection(
|
||||
webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) {
|
||||
CreatePeerConnection(std::nullopt, observer, std::move(callback));
|
||||
}
|
||||
|
||||
void WebRtcMedium::CreatePeerConnection(
|
||||
std::optional<webrtc::PeerConnectionFactoryInterface::Options> options,
|
||||
webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) {
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
if (!env.GetUseValidPeerConnection()) {
|
||||
callback(nullptr);
|
||||
@@ -75,10 +89,17 @@ void WebRtcMedium::CreatePeerConnection(
|
||||
webrtc::CreateDefaultTaskQueueFactory();
|
||||
factory_dependencies.signaling_thread = signaling_thread.release();
|
||||
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
|
||||
peer_connection_factory = webrtc::CreateModularPeerConnectionFactory(
|
||||
std::move(factory_dependencies));
|
||||
RTC_CHECK(peer_connection_factory != nullptr)
|
||||
<< "Failed to create peer connection factory";
|
||||
if (options.has_value()) {
|
||||
peer_connection_factory->SetOptions(options.value());
|
||||
}
|
||||
auto peer_connection_or_error =
|
||||
webrtc::CreateModularPeerConnectionFactory(
|
||||
std::move(factory_dependencies))
|
||||
->CreatePeerConnectionOrError(rtc_config, std::move(dependencies));
|
||||
peer_connection_factory->CreatePeerConnectionOrError(
|
||||
rtc_config, std::move(dependencies));
|
||||
RTC_CHECK(peer_connection_or_error.ok())
|
||||
<< "Failed to create peer connection";
|
||||
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#define PLATFORM_IMPL_G3_WEBRTC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/webrtc.h"
|
||||
#include "internal/platform/implementation/g3/single_thread_executor.h"
|
||||
#include "webrtc/api/peer_connection_interface.h"
|
||||
@@ -63,6 +66,13 @@ class WebRtcMedium : public api::WebRtcMedium {
|
||||
void CreatePeerConnection(webrtc::PeerConnectionObserver* observer,
|
||||
PeerConnectionCallback callback) override;
|
||||
|
||||
// Creates and returns a new webrtc::PeerConnectionInterface object via
|
||||
// |callback| with |PeerConnectionFactoryInterface::Options|.
|
||||
void CreatePeerConnection(
|
||||
std::optional<webrtc::PeerConnectionFactoryInterface::Options> options,
|
||||
webrtc::PeerConnectionObserver* observer,
|
||||
PeerConnectionCallback callback) override;
|
||||
|
||||
// Returns a signaling messenger for sending WebRTC signaling messages.
|
||||
std::unique_ptr<api::WebRtcSignalingMessenger> GetSignalingMessenger(
|
||||
absl::string_view self_id,
|
||||
|
||||
@@ -13,6 +13,18 @@
|
||||
# limitations under the License.
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "crypto",
|
||||
srcs = [
|
||||
"crypto.cc",
|
||||
],
|
||||
visibility = ["//internal/platform/implementation:__subpackages__"],
|
||||
deps = [
|
||||
"@boringssl//:crypto",
|
||||
"@com_google_absl//absl/types:span",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "posix_mutex",
|
||||
srcs = [
|
||||
@@ -45,10 +57,7 @@ cc_library(
|
||||
name = "file",
|
||||
srcs = ["file.cc"],
|
||||
hdrs = ["file.h"],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
"//internal/platform/implementation:__subpackages__",
|
||||
],
|
||||
visibility = ["//internal/platform/implementation:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:types",
|
||||
|
||||
+11
-22
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,31 +12,20 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_G3_LOG_MESSAGE_H_
|
||||
#define PLATFORM_IMPL_G3_LOG_MESSAGE_H_
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "internal/platform/implementation/log_message.h"
|
||||
#include "absl/types/span.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
namespace nearby {
|
||||
namespace g3 {
|
||||
|
||||
// See documentation in
|
||||
// cpp/platform/api/log_message.h
|
||||
class LogMessage : public api::LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line, Severity severity);
|
||||
~LogMessage() override;
|
||||
void RandBytes(void* bytes, size_t length) {
|
||||
RAND_bytes(reinterpret_cast<uint8_t*>(bytes), length);
|
||||
}
|
||||
|
||||
void Print(const char* format, ...) override;
|
||||
void RandBytes(absl::Span<uint8_t> bytes) {
|
||||
RAND_bytes(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
std::ostream& Stream() override;
|
||||
|
||||
private:
|
||||
google::LogMessage log_streamer_;
|
||||
};
|
||||
|
||||
} // namespace g3
|
||||
} // namespace nearby
|
||||
|
||||
#endif // PLATFORM_IMPL_G3_LOG_MESSAGE_H_
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "internal/platform/implementation/shared/file.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
@@ -37,7 +36,7 @@ IOFile::IOFile(const absl::string_view file_path, size_t size)
|
||||
: file_(std::string(file_path.data(), file_path.size()),
|
||||
std::ios::binary | std::ios::in | std::ios::ate),
|
||||
path_(file_path),
|
||||
total_size_(file_.tellg()) {
|
||||
total_size_(size) {
|
||||
file_.seekg(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#ifndef NO_WEBRTC
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/proto/offline_wire_formats.pb.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
@@ -60,6 +62,13 @@ class WebRtcMedium {
|
||||
virtual void CreatePeerConnection(webrtc::PeerConnectionObserver* observer,
|
||||
PeerConnectionCallback callback) = 0;
|
||||
|
||||
// Creates and returns a new webrtc::PeerConnectionInterface object via
|
||||
// |callback| with |PeerConnectionFactoryInterface::Options|.
|
||||
virtual void CreatePeerConnection(
|
||||
std::optional<webrtc::PeerConnectionFactoryInterface::Options> options,
|
||||
webrtc::PeerConnectionObserver* observer,
|
||||
PeerConnectionCallback callback) = 0;
|
||||
|
||||
// Returns a signaling messenger for sending WebRTC signaling messages.
|
||||
virtual std::unique_ptr<WebRtcSignalingMessenger> GetSignalingMessenger(
|
||||
absl::string_view self_id,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/listeners.h"
|
||||
@@ -99,10 +100,10 @@ class WifiLanMedium {
|
||||
|
||||
// Callback that is invoked when a discovered service is found or lost.
|
||||
struct DiscoveredServiceCallback {
|
||||
absl::AnyInvocable<void(NsdServiceInfo service_info)>
|
||||
service_discovered_cb = DefaultCallback<NsdServiceInfo>();
|
||||
absl::AnyInvocable<void(NsdServiceInfo service_info)> service_lost_cb =
|
||||
DefaultCallback<NsdServiceInfo>();
|
||||
absl::AnyInvocable<void(const NsdServiceInfo& service_info)>
|
||||
service_discovered_cb = DefaultCallback<const NsdServiceInfo&>();
|
||||
absl::AnyInvocable<void(const NsdServiceInfo& service_info)>
|
||||
service_lost_cb = DefaultCallback<const NsdServiceInfo&>();
|
||||
};
|
||||
|
||||
// Starts the discovery of nearby WifiLan services.
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/wifi_utils.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "absl/strings/str_split.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
// Utility function to convert channel number to frequency in MHz
|
||||
// @param channel to convert
|
||||
// @return center frequency in Mhz of the channel, return "kUnspecified" if no
|
||||
// match
|
||||
// Add band support later
|
||||
int WifiUtils::ConvertChannelToFrequencyMhz(int channel, WifiBandType band) {
|
||||
if (band == WifiBandType::kUnknown || band == WifiBandType::kBand24Ghz ||
|
||||
band == WifiBandType::kBand5Ghz) {
|
||||
if (channel == 14) {
|
||||
return 2484;
|
||||
} else if (channel >= kBand24GhzFirstChNum &&
|
||||
channel <= kBand24GhzLastChNum) {
|
||||
return ((channel - kBand24GhzFirstChNum) * 5) + kBand24GhzStartFreqMhz;
|
||||
} else if (channel >= kBand5GhzFirstChNum &&
|
||||
channel <= kBand5GhzLastChNum) {
|
||||
return ((channel - kBand5GhzFirstChNum) * 5) + kBand5GhzStartFreqMhz;
|
||||
} else {
|
||||
return kUnspecified;
|
||||
}
|
||||
}
|
||||
|
||||
if (band == WifiBandType::kBand6Ghz) {
|
||||
if (channel >= kBand6GhzFirstChNum && channel <= kBand6GhzLastChNum) {
|
||||
if (channel == 2) {
|
||||
return kBand6GhzOpClass136Ch2FreqMhz;
|
||||
}
|
||||
return ((channel - kBand6GhzFirstChNum) * 5) + kBand6GhzStartFreqMhz;
|
||||
} else {
|
||||
return kUnspecified;
|
||||
}
|
||||
}
|
||||
|
||||
if (band == WifiBandType::kBand60Ghz) {
|
||||
if (channel >= kBand60GhzFirstChNum && channel <= kBand60GhzLastChNum) {
|
||||
return ((channel - kBand60GhzFirstChNum) * 2160) + kBand60GhzStartFreqMhz;
|
||||
} else {
|
||||
return kUnspecified;
|
||||
}
|
||||
}
|
||||
|
||||
return kUnspecified;
|
||||
}
|
||||
|
||||
// Utility function to convert frequency in MHz to channel number
|
||||
// @param freqMhz frequency in MHz
|
||||
// @return channel number associated with given frequency, return "kUnspecified"
|
||||
// if no match
|
||||
int WifiUtils::ConvertFrequencyMhzToChannel(int freq_mhz) {
|
||||
// Special case
|
||||
if (freq_mhz == kBand24GhzEndFreqMhz) {
|
||||
return 14;
|
||||
} else if (freq_mhz >= kBand24GhzStartFreqMhz &&
|
||||
freq_mhz <= kBand24GhzEndFreqMhz) {
|
||||
return (freq_mhz - kBand24GhzStartFreqMhz) / 5 + kBand24GhzFirstChNum;
|
||||
} else if (freq_mhz >= kBand5GhzStartFreqMhz &&
|
||||
freq_mhz <= kBand5GhzEndFreqMhz) {
|
||||
return (freq_mhz - kBand5GhzStartFreqMhz) / 5 + kBand5GhzFirstChNum;
|
||||
} else if (freq_mhz >= kBand6GhzStartFreqMhz &&
|
||||
freq_mhz <= kBand6GhzEndFreqMhz) {
|
||||
if (freq_mhz == kBand6GhzOpClass136Ch2FreqMhz) {
|
||||
return 2;
|
||||
}
|
||||
return (freq_mhz - kBand6GhzStartFreqMhz) / 5 + kBand6GhzFirstChNum;
|
||||
} else if (freq_mhz >= kBand60GhzStartFreqMhz &&
|
||||
freq_mhz <= kBand60GhzEndFreqMhz) {
|
||||
return (freq_mhz - kBand60GhzStartFreqMhz) / 2160 + kBand60GhzFirstChNum;
|
||||
}
|
||||
|
||||
return kUnspecified;
|
||||
}
|
||||
|
||||
// Function to validate an IP address
|
||||
bool WifiUtils::ValidateIPV4(std::string ipv4) {
|
||||
int result;
|
||||
// split the string into tokens
|
||||
std::vector<absl::string_view> list = absl::StrSplit(ipv4, '.');
|
||||
|
||||
// if the token size is not equal to four
|
||||
if (list.size() != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate each token
|
||||
for (absl::string_view str : list) {
|
||||
// verify that the string is a number or not, and the numbers are in the
|
||||
// valid range
|
||||
if (!absl::SimpleAtoi(str, &result)) return false;
|
||||
if (result > 255 || result < 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string WifiUtils::GetHumanReadableIpAddress(
|
||||
absl::string_view binary_address) {
|
||||
std::vector<std::string> parts;
|
||||
for (unsigned int b : binary_address) {
|
||||
parts.push_back(absl::StrFormat("%d", b));
|
||||
}
|
||||
return absl::StrJoin(parts, ".");
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_PUBLIC_WIFI_UTILS_H_
|
||||
#define PLATFORM_PUBLIC_WIFI_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/wifi.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
using ::nearby::api::WifiBandType;
|
||||
|
||||
class WifiUtils {
|
||||
public:
|
||||
static constexpr int kUnspecified = -1;
|
||||
static constexpr int kBand24GhzFirstChNum = 1;
|
||||
static constexpr int kBand24GhzLastChNum = 14;
|
||||
static constexpr int kBand24GhzStartFreqMhz = 2412;
|
||||
static constexpr int kBand24GhzEndFreqMhz = 2484;
|
||||
static constexpr int kBand5GhzFirstChNum = 32;
|
||||
static constexpr int kBand5GhzLastChNum = 177;
|
||||
static constexpr int kBand5GhzStartFreqMhz = 5160;
|
||||
static constexpr int kBand5GhzEndFreqMhz = 5885;
|
||||
static constexpr int kBand6GhzFirstChNum = 1;
|
||||
static constexpr int kBand6GhzLastChNum = 233;
|
||||
static constexpr int kBand6GhzStartFreqMhz = 5955;
|
||||
static constexpr int kBand6GhzEndFreqMhz = 7115;
|
||||
static constexpr int kBand6GhzPscStartMhz = 5975;
|
||||
static constexpr int kBand6GhzPscStepSizeMhz = 80;
|
||||
static constexpr int kBand6GhzOpClass136Ch2FreqMhz = 5935;
|
||||
static constexpr int kBand60GhzFirstChNum = 1;
|
||||
static constexpr int kBand60GhzLastChNum = 6;
|
||||
static constexpr int kBand60GhzStartFreqMhz = 58320;
|
||||
static constexpr int kBand60GhzEndFreqMhz = 70200;
|
||||
|
||||
static int ConvertChannelToFrequencyMhz(int channel, WifiBandType band_type);
|
||||
static int ConvertFrequencyMhzToChannel(int freq_mhz);
|
||||
|
||||
static bool ValidateIPV4(std::string ipv4);
|
||||
// Converts an IP address from binary format for human readable.
|
||||
static std::string GetHumanReadableIpAddress(
|
||||
absl::string_view binary_address);
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
#endif // PLATFORM_PUBLIC_WIFI_UTILS_H_
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/wifi_utils.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace {
|
||||
|
||||
constexpr int kChan6Num_2G = 9;
|
||||
constexpr int kChan6NumFreq_2G = 2452;
|
||||
|
||||
constexpr int kChan48Num_5G = 48;
|
||||
constexpr int kChan48NumFreq_5G = 5240;
|
||||
|
||||
constexpr int kChan69Num_6G = 69;
|
||||
constexpr int kChan69NumFreq_6G = 6295;
|
||||
|
||||
constexpr int kChan4Num_60G = 4;
|
||||
constexpr int kChan4NumFreq_60G = 64800;
|
||||
|
||||
constexpr int kChan20Num_2G_NotExist = 20;
|
||||
constexpr int kChan180Num_5G_NotExist = 180;
|
||||
constexpr int kChan0Num_6G_NotExist = 0;
|
||||
constexpr int kChan30Num_60G_NotExist = 30;
|
||||
|
||||
constexpr int kFreqNotExist = 1002;
|
||||
|
||||
TEST(WifiUtilsTest, ConvertChannelToFrequency) {
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G,
|
||||
WifiBandType::kUnknown),
|
||||
kChan6NumFreq_2G);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G,
|
||||
WifiBandType::kBand24Ghz),
|
||||
kChan6NumFreq_2G);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan48Num_5G,
|
||||
WifiBandType::kBand5Ghz),
|
||||
kChan48NumFreq_5G);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan69Num_6G,
|
||||
WifiBandType::kBand6Ghz),
|
||||
kChan69NumFreq_6G);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan4Num_60G,
|
||||
WifiBandType::kBand60Ghz),
|
||||
kChan4NumFreq_60G);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan20Num_2G_NotExist,
|
||||
WifiBandType::kBand24Ghz),
|
||||
WifiUtils::kUnspecified);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan180Num_5G_NotExist,
|
||||
WifiBandType::kBand5Ghz),
|
||||
WifiUtils::kUnspecified);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan0Num_6G_NotExist,
|
||||
WifiBandType::kBand6Ghz),
|
||||
WifiUtils::kUnspecified);
|
||||
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan30Num_60G_NotExist,
|
||||
WifiBandType::kBand60Ghz),
|
||||
WifiUtils::kUnspecified);
|
||||
}
|
||||
|
||||
TEST(WifiUtilsTest, ConvertFrequencyToChannel) {
|
||||
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan6NumFreq_2G),
|
||||
kChan6Num_2G);
|
||||
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan48NumFreq_5G),
|
||||
kChan48Num_5G);
|
||||
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan69NumFreq_6G),
|
||||
kChan69Num_6G);
|
||||
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan4NumFreq_60G),
|
||||
kChan4Num_60G);
|
||||
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kFreqNotExist),
|
||||
WifiUtils::kUnspecified);
|
||||
}
|
||||
|
||||
TEST(WifiUtilsTest, Ipv4Validation) {
|
||||
EXPECT_FALSE(WifiUtils::ValidateIPV4("12.34.212.46.37"));
|
||||
EXPECT_FALSE(WifiUtils::ValidateIPV4("12.gt.212.46"));
|
||||
EXPECT_FALSE(WifiUtils::ValidateIPV4("192.168.358.46"));
|
||||
EXPECT_FALSE(WifiUtils::ValidateIPV4("192.-168.1.46"));
|
||||
EXPECT_TRUE(WifiUtils::ValidateIPV4("192.168.1.46"));
|
||||
}
|
||||
|
||||
TEST(WifiUtilsTest, GetHumanReadableIpAddress) {
|
||||
EXPECT_EQ(
|
||||
WifiUtils::GetHumanReadableIpAddress(absl::HexStringToBytes("000AFEFF")),
|
||||
"0.10.254.255");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby
|
||||
@@ -18,7 +18,6 @@ cc_library(
|
||||
name = "types",
|
||||
srcs = [
|
||||
"device_info.cc",
|
||||
"log_message.cc",
|
||||
"timer.cc",
|
||||
],
|
||||
hdrs = [
|
||||
@@ -31,30 +30,30 @@ cc_library(
|
||||
"future.h",
|
||||
"input_file.h",
|
||||
"listenable_future.h",
|
||||
"log_message.h",
|
||||
"mutex.h",
|
||||
"output_file.h",
|
||||
"preferences_manager.h",
|
||||
"scheduled_executor.h",
|
||||
"settable_future.h",
|
||||
"submittable_executor.h",
|
||||
"task_scheduler.h",
|
||||
"timer.h",
|
||||
"utils.h",
|
||||
],
|
||||
copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated"],
|
||||
defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"],
|
||||
visibility = ["//third_party/nearby/sharing/internal/impl/windows:__pkg__"],
|
||||
visibility = [
|
||||
"//sharing/internal/impl/windows:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":comm",
|
||||
"//base",
|
||||
"//base:stringprintf",
|
||||
"//internal/base:bluetooth_address",
|
||||
"//internal/base:files",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/windows/generated:types",
|
||||
"//strings:strappendv",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
@@ -102,16 +101,21 @@ cc_library(
|
||||
"wifi.h",
|
||||
"wifi_direct.h",
|
||||
"wifi_hotspot.h",
|
||||
"wifi_intel.h",
|
||||
"wifi_lan.h",
|
||||
],
|
||||
copts = ["-DNO_INTEL_PIE"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/flags:platform_flags",
|
||||
"//internal/platform/implementation:account_manager",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation:wifi_utils",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/platform/implementation/windows/generated:types",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
@@ -141,6 +145,26 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "string_utils",
|
||||
srcs = [
|
||||
"string_utils.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"string_utils.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//internal/platform:__subpackages__",
|
||||
"//location/nearby:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//internal/platform:logging",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "windows",
|
||||
srcs = [
|
||||
@@ -170,6 +194,7 @@ cc_library(
|
||||
"session_manager.cc",
|
||||
"submittable_executor.cc",
|
||||
"system_clock.cc",
|
||||
"task_scheduler.cc",
|
||||
"thread_pool.cc",
|
||||
"utils.cc",
|
||||
"webrtc.cc",
|
||||
@@ -179,6 +204,7 @@ cc_library(
|
||||
"wifi_hotspot_medium.cc",
|
||||
"wifi_hotspot_server_socket.cc",
|
||||
"wifi_hotspot_socket.cc",
|
||||
"wifi_intel.cc",
|
||||
"wifi_lan_medium.cc",
|
||||
"wifi_lan_server_socket.cc",
|
||||
"wifi_lan_socket.cc",
|
||||
@@ -186,30 +212,40 @@ cc_library(
|
||||
],
|
||||
# This is the temporary solution to solve compilation error of Win32 WFDxxx() related API.
|
||||
# WFD API is only support after _WIN32_WINNT_WIN8, but the current lexan _WIN32_WINNT is set to _WIN32_WINNT_WIN7
|
||||
copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated -D_WIN32_WINNT=_WIN32_WINNT_WIN10 -DWINVER=_WIN32_WINNT_WIN10"],
|
||||
copts = [
|
||||
"-DNO_INTEL_PIE",
|
||||
"-D_WIN32_WINNT=_WIN32_WINNT_WIN10 -DWINVER=_WIN32_WINNT_WIN10",
|
||||
"-Wno-unused-variable",
|
||||
"-Wno-unused-value",
|
||||
],
|
||||
defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"],
|
||||
visibility = [
|
||||
"//chrome/chromeos/assistant/data_migration/lib:__pkg__",
|
||||
"//connections:__subpackages__",
|
||||
"//fastpair:__subpackages__",
|
||||
"//internal/platform:__subpackages__",
|
||||
"//location/nearby:__subpackages__",
|
||||
"//presence:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":comm",
|
||||
":crypto", # build_cleaner: keep
|
||||
":string_utils",
|
||||
":types",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/account",
|
||||
"//internal/base:files",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/flags:platform_flags",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation:wifi_utils",
|
||||
"//internal/platform/implementation/shared:count_down_latch",
|
||||
"//internal/platform/implementation/shared:file",
|
||||
"//internal/platform/implementation/windows/generated:types",
|
||||
@@ -218,7 +254,6 @@ cc_library(
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/log:check",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
@@ -240,9 +275,7 @@ cc_library(
|
||||
"test_data.h",
|
||||
"test_utils.h",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:private", # Only private by automation, not intent. Owner may accept CLs adding visibility. See go/scheuklappen#explicit-private.
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"@nlohmann_json//:json",
|
||||
@@ -270,13 +303,16 @@ cc_test(
|
||||
"preferences_repository_test.cc",
|
||||
"scheduled_executor_test.cc",
|
||||
"submittable_executor_test.cc",
|
||||
"task_scheduler_test.cc",
|
||||
"thread_pool_test.cc",
|
||||
"timer_test.cc",
|
||||
"utils_test.cc",
|
||||
"webrtc_test.cc",
|
||||
"wifi_hotspot_test.cc",
|
||||
"wifi_medium_test.cc",
|
||||
],
|
||||
copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated -DCORE_ADAPTER_DLL"],
|
||||
tags = ["notap"],
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
tags = ["nozapfhahn"],
|
||||
deps = [
|
||||
":comm",
|
||||
":crypto",
|
||||
@@ -284,7 +320,7 @@ cc_test(
|
||||
":types",
|
||||
":windows",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
@@ -300,3 +336,17 @@ cc_test(
|
||||
"@nlohmann_json//:json",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "string_utils_test",
|
||||
size = "small",
|
||||
timeout = "short",
|
||||
srcs = [
|
||||
"string_utils_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":string_utils",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace windows {
|
||||
// A boolean value that may be updated atomically.
|
||||
class AtomicBoolean : public api::AtomicBoolean {
|
||||
public:
|
||||
explicit AtomicBoolean(bool value = false) : atomic_boolean_(value) {}
|
||||
~AtomicBoolean() override = default;
|
||||
|
||||
// Atomically read and return current value.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define PLATFORM_IMPL_WINDOWS_ATOMIC_REFERENCE_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#include "internal/platform/implementation/atomic_reference.h"
|
||||
|
||||
@@ -25,6 +26,7 @@ namespace windows {
|
||||
// Type that allows 32-bit atomic reads and writes.
|
||||
class AtomicUint32 : public api::AtomicUint32 {
|
||||
public:
|
||||
explicit AtomicUint32(std::uint32_t value = 0) : atomic_uint32_(value) {}
|
||||
~AtomicUint32() override = default;
|
||||
|
||||
// Atomically reads and returns stored value.
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
@@ -101,31 +102,42 @@ std::string GattCommunicationStatusToString(GattCommunicationStatus status) {
|
||||
|
||||
BleGattClient::BleGattClient(BluetoothLEDevice ble_device)
|
||||
: ble_device_(ble_device) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": GATT client is created.";
|
||||
if (ble_device_ == nullptr) {
|
||||
LOG(WARNING) << __func__ << ": ble_device is null.";
|
||||
} else {
|
||||
LOG(INFO) << __func__ << ": GATT client is created, address: "
|
||||
<< uint64_to_mac_address_string(ble_device_.BluetoothAddress());
|
||||
}
|
||||
}
|
||||
|
||||
BleGattClient::~BleGattClient() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": GATT client is released.";
|
||||
LOG(INFO) << __func__ << ": GATT client is released.";
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
const Uuid& service_uuid, const std::vector<Uuid>& characteristic_uuids) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableBleV2Gatt)) {
|
||||
auto windows_bluetooth_adapter_ = ::winrt::Windows::Devices::Bluetooth::
|
||||
BluetoothAdapter::GetDefaultAsync()
|
||||
.get();
|
||||
if (windows_bluetooth_adapter_.IsExtendedAdvertisingSupported()) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": GATT is disabled.";
|
||||
BluetoothAdapter bluetooth_adapter;
|
||||
if (bluetooth_adapter.IsExtendedAdvertisingSupported()) {
|
||||
LOG(WARNING) << __func__ << ": GATT is disabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bluetooth_adapter.IsCentralRoleSupported()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Bluetooth Hardware does not support Central "
|
||||
"Role, which is required to start GATT client.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableBleV2GattOnNonExtendedDevice)) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": GATT is disabled.";
|
||||
LOG(WARNING) << __func__ << ": GATT is disabled.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -135,13 +147,12 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
absl::StrAppend(out, std::string(uuid));
|
||||
});
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Discover service_uuid="
|
||||
<< std::string(service_uuid)
|
||||
<< " with characteristic_uuids=" << flat_characteristics;
|
||||
VLOG(1) << __func__ << ": Discover service_uuid=" << std::string(service_uuid)
|
||||
<< " with characteristic_uuids=" << flat_characteristics;
|
||||
|
||||
try {
|
||||
if (ble_device_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": BLE device is disconnected.";
|
||||
LOG(ERROR) << __func__ << ": BLE device is disconnected.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -155,23 +166,21 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
gatt_devices_services_result_ = get_gatt_services_async.GetResults();
|
||||
break;
|
||||
case winrt::Windows::Foundation::AsyncStatus::Started:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get GATT services due to timeout.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get GATT services due to timeout.";
|
||||
get_gatt_services_async.Cancel();
|
||||
return false;
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get GATT services due to unknown reasons.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get GATT services due to unknown reasons.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gatt_devices_services_result_.Status() !=
|
||||
GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get gatt service with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_devices_services_result_.Status());
|
||||
LOG(ERROR) << __func__ << ": Failed to get gatt service with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_devices_services_result_.Status());
|
||||
gatt_devices_services_result_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
@@ -185,9 +194,8 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
winrt::to_string(winrt::to_hstring(service.Uuid())));
|
||||
});
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Found GATT services=" << flat_services
|
||||
<< " from BLE device.";
|
||||
LOG(INFO) << __func__ << ": Found GATT services=" << flat_services
|
||||
<< " from BLE device.";
|
||||
|
||||
// Needs to check each service to make sure it includes all characteristic
|
||||
// uuids. Services may include duplicate service UUID, but each of them may
|
||||
@@ -196,27 +204,25 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
winrt::guid uuid = service.Uuid();
|
||||
std::string uuid_string = winrt::to_string(winrt::to_hstring(uuid));
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Found service UUID=" << uuid_string;
|
||||
VLOG(1) << __func__ << ": Found service UUID=" << uuid_string;
|
||||
if (!is_nearby_uuid_equal_to_winrt_guid(service_uuid, uuid)) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
LOG(WARNING)
|
||||
<< __func__
|
||||
<< ": Service uuid not match, continue check other services.";
|
||||
continue;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Found the discovery service UUID=" << uuid_string;
|
||||
LOG(INFO) << __func__
|
||||
<< ": Found the discovery service UUID=" << uuid_string;
|
||||
|
||||
// Try to check the characteristic uuids.
|
||||
GattCharacteristicsResult gatt_characteristics_result =
|
||||
service.GetCharacteristicsAsync(BluetoothCacheMode::Uncached).get();
|
||||
if (gatt_characteristics_result.Status() !=
|
||||
GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get characteristics with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_characteristics_result.Status());
|
||||
LOG(ERROR) << __func__ << ": Failed to get characteristics with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_characteristics_result.Status());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -227,8 +233,8 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
gatt_characteristic.Uuid())));
|
||||
});
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Found GATT characteristics="
|
||||
<< flat_characteristics;
|
||||
VLOG(1) << __func__
|
||||
<< ": Found GATT characteristics=" << flat_characteristics;
|
||||
|
||||
bool found_all = true;
|
||||
|
||||
@@ -246,8 +252,8 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
}
|
||||
}
|
||||
if (found == false) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Cannot find characteristic: "
|
||||
<< std::string(characteristic_uuid);
|
||||
LOG(WARNING) << __func__ << ": Cannot find characteristic: "
|
||||
<< std::string(characteristic_uuid);
|
||||
found_all = false;
|
||||
break;
|
||||
}
|
||||
@@ -258,21 +264,18 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
}
|
||||
|
||||
// found all characteristics.
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Found all characteristics.";
|
||||
VLOG(1) << __func__ << ": Found all characteristics.";
|
||||
return true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to find service and all characteristics.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to find service and all characteristics.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get GATT services. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to get GATT services. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get GATT services. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to get GATT services. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -281,17 +284,16 @@ bool BleGattClient::DiscoverServiceAndCharacteristics(
|
||||
absl::optional<api::ble_v2::GattCharacteristic>
|
||||
BleGattClient::GetCharacteristic(const Uuid& service_uuid,
|
||||
const Uuid& characteristic_uuid) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Stared to get characteristic UUID="
|
||||
<< std::string(characteristic_uuid)
|
||||
<< " in service UUID=" << std::string(service_uuid);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__ << ": Stared to get characteristic UUID="
|
||||
<< std::string(characteristic_uuid)
|
||||
<< " in service UUID=" << std::string(service_uuid);
|
||||
try {
|
||||
std::optional<GattCharacteristic> gatt_characteristic =
|
||||
GetNativeCharacteristic(service_uuid, characteristic_uuid);
|
||||
|
||||
if (!gatt_characteristic.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get native GATT characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get native GATT characteristic.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
@@ -329,18 +331,17 @@ BleGattClient::GetCharacteristic(const Uuid& service_uuid,
|
||||
native_characteristic_map_[result].native_characteristic =
|
||||
gatt_characteristic;
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Return Characteristic. uuid="
|
||||
<< std::string(characteristic_uuid);
|
||||
VLOG(1) << __func__ << ": Return Characteristic. uuid="
|
||||
<< std::string(characteristic_uuid);
|
||||
|
||||
return result;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to get GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
|
||||
return absl::nullopt;
|
||||
@@ -348,33 +349,33 @@ BleGattClient::GetCharacteristic(const Uuid& service_uuid,
|
||||
|
||||
absl::optional<std::string> BleGattClient::ReadCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Read characteristic="
|
||||
<< std::string(characteristic.uuid);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__
|
||||
<< ": Read characteristic=" << std::string(characteristic.uuid);
|
||||
try {
|
||||
std::optional<GattCharacteristic> gatt_characteristic =
|
||||
GetNativeCharacteristic(characteristic.service_uuid,
|
||||
characteristic.uuid);
|
||||
|
||||
if (!gatt_characteristic.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get native GATT characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get native GATT characteristic.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
GattReadResult result =
|
||||
gatt_characteristic->ReadValueAsync(BluetoothCacheMode::Uncached).get();
|
||||
if (result.Status() != GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to read GATT characteristic with error: "
|
||||
<< GattCommunicationStatusToString(result.Status());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to read GATT characteristic with error: "
|
||||
<< GattCommunicationStatusToString(result.Status());
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
IBuffer buffer = result.Value();
|
||||
int size = buffer.Length();
|
||||
if (size == 0) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": No characteristic value.";
|
||||
return absl::nullopt;
|
||||
VLOG(1) << __func__ << ": No characteristic value.";
|
||||
return "";
|
||||
}
|
||||
|
||||
DataReader data_reader = DataReader::FromBuffer(buffer);
|
||||
@@ -384,18 +385,17 @@ absl::optional<std::string> BleGattClient::ReadCharacteristic(
|
||||
data.push_back(static_cast<char>(data_reader.ReadByte()));
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Got characteristic value length=" << data.size();
|
||||
VLOG(1) << __func__ << ": Got characteristic value length=" << data.size();
|
||||
|
||||
return data;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to read GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to read GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to read GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to read GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
|
||||
return absl::nullopt;
|
||||
@@ -404,16 +404,15 @@ absl::optional<std::string> BleGattClient::ReadCharacteristic(
|
||||
bool BleGattClient::WriteCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
absl::string_view value, api::ble_v2::GattClient::WriteType write_type) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": write characteristic: "
|
||||
<< std::string(characteristic.uuid);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__
|
||||
<< ": write characteristic: " << std::string(characteristic.uuid);
|
||||
try {
|
||||
std::optional<GattCharacteristic> gatt_characteristic =
|
||||
native_characteristic_map_[characteristic].native_characteristic;
|
||||
|
||||
if (!gatt_characteristic.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get native GATT characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get native GATT characteristic.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -430,27 +429,25 @@ bool BleGattClient::WriteCharacteristic(
|
||||
gatt_characteristic->WriteValueAsync(buffer, write_option).get();
|
||||
|
||||
if (status != GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to write data to GATT characteristic: "
|
||||
<< std::string(characteristic.uuid) << "with error: "
|
||||
<< GattCommunicationStatusToString(status);
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to write data to GATT characteristic: "
|
||||
<< std::string(characteristic.uuid)
|
||||
<< "with error: " << GattCommunicationStatusToString(status);
|
||||
return false;
|
||||
} else {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Write data to GATT characteristic: "
|
||||
<< std::string(characteristic.uuid)
|
||||
<< ", bytes count: " << value.size();
|
||||
VLOG(1) << __func__ << ": Write data to GATT characteristic: "
|
||||
<< std::string(characteristic.uuid)
|
||||
<< ", bytes count: " << value.size();
|
||||
return true;
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to write GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to write GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to write GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to write GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -459,8 +456,8 @@ bool BleGattClient::SetCharacteristicSubscription(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool enable,
|
||||
absl::AnyInvocable<void(absl::string_view value)>
|
||||
on_characteristic_changed_cb) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Started to set Characteristic Subscription.";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__ << ": Started to set Characteristic Subscription.";
|
||||
GattClientCharacteristicConfigurationDescriptorValue gcccd_value =
|
||||
GattClientCharacteristicConfigurationDescriptorValue::None;
|
||||
if ((characteristic.property & Property::kNotify) != Property::kNone) {
|
||||
@@ -470,22 +467,18 @@ bool BleGattClient::SetCharacteristicSubscription(
|
||||
gcccd_value =
|
||||
GattClientCharacteristicConfigurationDescriptorValue::Indicate;
|
||||
} else {
|
||||
NEARBY_LOGS(WARNING) << "Characeristic: "
|
||||
<< std::string(characteristic.uuid)
|
||||
<< " supports neither notifications nor indications.";
|
||||
LOG(WARNING) << "Characeristic: " << std::string(characteristic.uuid)
|
||||
<< " supports neither notifications nor indications.";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<GattCharacteristic> gatt_characteristic;
|
||||
{
|
||||
absl::MutexLock lock(&mutex_);
|
||||
gatt_characteristic =
|
||||
native_characteristic_map_[characteristic].native_characteristic;
|
||||
}
|
||||
|
||||
gatt_characteristic =
|
||||
native_characteristic_map_[characteristic].native_characteristic;
|
||||
|
||||
if (!gatt_characteristic.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get native GATT characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get native GATT characteristic.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -498,7 +491,6 @@ bool BleGattClient::SetCharacteristicSubscription(
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&mutex_);
|
||||
// Set value changed handler
|
||||
try {
|
||||
if (enable) {
|
||||
@@ -513,27 +505,23 @@ bool BleGattClient::SetCharacteristicSubscription(
|
||||
});
|
||||
|
||||
if (!native_characteristic_map_[characteristic].notification_token) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to add value change handler.";
|
||||
LOG(ERROR) << __func__ << ": Failed to add value change handler.";
|
||||
return false;
|
||||
}
|
||||
} else if (native_characteristic_map_[characteristic].notification_token) {
|
||||
gatt_characteristic->ValueChanged(std::exchange(
|
||||
native_characteristic_map_[characteristic].notification_token, {}));
|
||||
}
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Successfully set Characteristic Subscription.";
|
||||
LOG(ERROR) << __func__ << ": Successfully set Characteristic Subscription.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set Characteristic Subscription."
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to set Characteristic Subscription."
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set Characteristic Subscription."
|
||||
" WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to set Characteristic Subscription."
|
||||
" WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -541,38 +529,36 @@ bool BleGattClient::SetCharacteristicSubscription(
|
||||
void BleGattClient::Disconnect() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
try {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Disconnect is called.";
|
||||
VLOG(1) << __func__ << ": Disconnect is called.";
|
||||
if (ble_device_ != nullptr) {
|
||||
ble_device_.Close();
|
||||
ble_device_ = nullptr;
|
||||
}
|
||||
native_characteristic_map_.clear();
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to disconnect GATT device. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to disconnect GATT device. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to disconnect GATT device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to disconnect GATT device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<GattCharacteristic> BleGattClient::GetNativeCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Stared to get native characteristic UUID="
|
||||
<< std::string(characteristic_uuid)
|
||||
<< " in service UUID=" << std::string(service_uuid);
|
||||
VLOG(1) << __func__ << ": Stared to get native characteristic UUID="
|
||||
<< std::string(characteristic_uuid)
|
||||
<< " in service UUID=" << std::string(service_uuid);
|
||||
|
||||
try {
|
||||
if (ble_device_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": BLE device is disconnected.";
|
||||
LOG(ERROR) << __func__ << ": BLE device is disconnected.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
if (gatt_devices_services_result_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No available GATT services.";
|
||||
LOG(ERROR) << __func__ << ": No available GATT services.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
@@ -582,10 +568,10 @@ std::optional<GattCharacteristic> BleGattClient::GetNativeCharacteristic(
|
||||
service.GetCharacteristicsAsync(BluetoothCacheMode::Cached).get();
|
||||
if (gatt_characteristics_result.Status() !=
|
||||
GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get characteristics with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_characteristics_result.Status());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get characteristics with error: "
|
||||
<< GattCommunicationStatusToString(
|
||||
gatt_characteristics_result.Status());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -593,9 +579,8 @@ std::optional<GattCharacteristic> BleGattClient::GetNativeCharacteristic(
|
||||
gatt_characteristics_result.Characteristics()) {
|
||||
if (is_nearby_uuid_equal_to_winrt_guid(characteristic_uuid,
|
||||
characteristic.Uuid())) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< __func__ << ": Return native Characteristic. uuid="
|
||||
<< std::string(characteristic_uuid);
|
||||
VLOG(1) << __func__ << ": Return native Characteristic. uuid="
|
||||
<< std::string(characteristic_uuid);
|
||||
|
||||
return characteristic;
|
||||
}
|
||||
@@ -603,13 +588,13 @@ std::optional<GattCharacteristic> BleGattClient::GetNativeCharacteristic(
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get native characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get native characteristic.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get native GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get native GATT characteristic. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
LOG(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get native GATT characteristic. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
@@ -621,9 +606,8 @@ std::optional<GattCharacteristic> BleGattClient::GetNativeCharacteristic(
|
||||
bool BleGattClient::WriteCharacteristicConfigurationDescriptor(
|
||||
GattCharacteristic& characteristic,
|
||||
GattClientCharacteristicConfigurationDescriptorValue value) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< __func__
|
||||
<< ": Stared to write characteristic configuration descriptor";
|
||||
VLOG(1) << __func__
|
||||
<< ": Stared to write characteristic configuration descriptor";
|
||||
|
||||
try {
|
||||
GattCommunicationStatus status =
|
||||
@@ -631,23 +615,23 @@ bool BleGattClient::WriteCharacteristicConfigurationDescriptor(
|
||||
.WriteClientCharacteristicConfigurationDescriptorAsync(value)
|
||||
.get();
|
||||
if (status == GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Successfully write client characteristic "
|
||||
"configuration descriptor";
|
||||
VLOG(1) << __func__
|
||||
<< ": Successfully write client characteristic "
|
||||
"configuration descriptor";
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to write client characteristic "
|
||||
"configuration descriptor with error: "
|
||||
<< GattCommunicationStatusToString(status);
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to write client characteristic "
|
||||
"configuration descriptor with error: "
|
||||
<< GattCommunicationStatusToString(status);
|
||||
} catch (std::exception exception) {
|
||||
// This usually happens when a device reports that it support notify, but
|
||||
// it actually doesn't.
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to write client characteristic "
|
||||
"configuration descriptor";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to write client characteristic "
|
||||
"configuration descriptor";
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
LOG(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to write client characteristic configuration descriptor."
|
||||
" WinRT exception: "
|
||||
@@ -659,7 +643,7 @@ bool BleGattClient::WriteCharacteristicConfigurationDescriptor(
|
||||
void BleGattClient::OnCharacteristicValueChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
GattValueChangedEventArgs args) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Gatt Characteristic value changed.";
|
||||
VLOG(1) << __func__ << ": Gatt Characteristic value changed.";
|
||||
IBuffer buffer = args.CharacteristicValue();
|
||||
int size = buffer.Length();
|
||||
DataReader data_reader = DataReader::FromBuffer(buffer);
|
||||
@@ -668,8 +652,7 @@ void BleGattClient::OnCharacteristicValueChanged(
|
||||
for (int i = 0; i < size; ++i) {
|
||||
data.push_back(static_cast<char>(data_reader.ReadByte()));
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Got characteristic value length= " << data.size();
|
||||
VLOG(1) << __func__ << ": Got characteristic value length= " << data.size();
|
||||
|
||||
absl::AnyInvocable<void(absl::string_view value)>
|
||||
on_characteristic_changed_cb;
|
||||
@@ -678,8 +661,7 @@ void BleGattClient::OnCharacteristicValueChanged(
|
||||
if (!native_characteristic_map_.contains(characteristic) ||
|
||||
!native_characteristic_map_[characteristic]
|
||||
.on_characteristic_changed_cb) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": No registered callback for characteristic.";
|
||||
LOG(INFO) << __func__ << ": No registered callback for characteristic.";
|
||||
return;
|
||||
}
|
||||
on_characteristic_changed_cb =
|
||||
|
||||
@@ -23,10 +23,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "winrt/base.h"
|
||||
@@ -42,25 +47,29 @@ class BleGattClient : public api::ble_v2::GattClient {
|
||||
|
||||
bool DiscoverServiceAndCharacteristics(
|
||||
const Uuid& service_uuid,
|
||||
const std::vector<Uuid>& characteristic_uuids) override;
|
||||
const std::vector<Uuid>& characteristic_uuids) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
absl::optional<api::ble_v2::GattCharacteristic> GetCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid) override;
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
absl::optional<std::string> ReadCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic) override;
|
||||
const api::ble_v2::GattCharacteristic& characteristic) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool WriteCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
absl::string_view value,
|
||||
api::ble_v2::GattClient::WriteType write_type) override;
|
||||
api::ble_v2::GattClient::WriteType write_type) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool SetCharacteristicSubscription(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool enable,
|
||||
absl::AnyInvocable<void(absl::string_view value)>
|
||||
on_characteristic_changed_cb) override;
|
||||
on_characteristic_changed_cb) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void Disconnect() override;
|
||||
void Disconnect() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
// Used to save native data related to the GATT characteristic.
|
||||
@@ -75,13 +84,15 @@ class BleGattClient : public api::ble_v2::GattClient {
|
||||
std::optional<::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattCharacteristic>
|
||||
GetNativeCharacteristic(const Uuid& service_uuid,
|
||||
const Uuid& characteristic_uuid);
|
||||
const Uuid& characteristic_uuid)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
bool WriteCharacteristicConfigurationDescriptor(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattCharacteristic& characteristic,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattClientCharacteristicConfigurationDescriptorValue value);
|
||||
GattClientCharacteristicConfigurationDescriptorValue value)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
void OnCharacteristicValueChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
@@ -90,9 +101,11 @@ class BleGattClient : public api::ble_v2::GattClient {
|
||||
|
||||
absl::Mutex mutex_;
|
||||
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothLEDevice ble_device_;
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothLEDevice ble_device_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattDeviceServicesResult gatt_devices_services_result_ = nullptr;
|
||||
GattDeviceServicesResult gatt_devices_services_result_
|
||||
ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
|
||||
absl::flat_hash_map<api::ble_v2::GattCharacteristic, GattCharacteristicData>
|
||||
native_characteristic_map_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "internal/platform/implementation/windows/ble_gatt_server.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -25,15 +26,21 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/Windows.Storage.Streams.h"
|
||||
#include "winrt/base.h"
|
||||
@@ -81,6 +88,9 @@ using ::winrt::Windows::Storage::Streams::DataWriter;
|
||||
using Permission = api::ble_v2::GattCharacteristic::Permission;
|
||||
using Property = api::ble_v2::GattCharacteristic::Property;
|
||||
|
||||
constexpr absl::Duration kGattServerTimeout = absl::Milliseconds(500);
|
||||
constexpr int kGattServerCheckIntervalInMills = 50;
|
||||
|
||||
std::string ConvertGattStatusToString(
|
||||
GattServiceProviderAdvertisementStatus status) {
|
||||
switch (status) {
|
||||
@@ -106,20 +116,22 @@ BleGattServer::BleGattServer(api::BluetoothAdapter* adapter,
|
||||
api::ble_v2::ServerGattConnectionCallback callback)
|
||||
: adapter_(dynamic_cast<BluetoothAdapter*>(adapter)),
|
||||
peripheral_(adapter_->GetMacAddress()),
|
||||
gatt_connection_callback_(std::move(callback)) {}
|
||||
gatt_connection_callback_(std::move(callback)) {
|
||||
DCHECK(adapter_ != nullptr);
|
||||
}
|
||||
|
||||
absl::optional<api::ble_v2::GattCharacteristic>
|
||||
BleGattServer::CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": create characteristic, service_uuid: "
|
||||
<< std::string(service_uuid) << ", characteristic_uuid: "
|
||||
<< std::string(characteristic_uuid);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
LOG(INFO) << __func__ << ": create characteristic, service_uuid: "
|
||||
<< std::string(service_uuid)
|
||||
<< ", characteristic_uuid: " << std::string(characteristic_uuid);
|
||||
|
||||
if (!service_uuid_.IsEmpty() && service_uuid_ != service_uuid) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Only support one GATT service for now.";
|
||||
LOG(ERROR) << __func__ << ": Only support one GATT service for now.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
@@ -142,18 +154,18 @@ BleGattServer::CreateCharacteristic(
|
||||
bool BleGattServer::UpdateCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const nearby::ByteArray& value) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": update characteristic: "
|
||||
<< std::string(characteristic.uuid);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
LOG(INFO) << __func__
|
||||
<< ": update characteristic: " << std::string(characteristic.uuid);
|
||||
|
||||
if (characteristic.service_uuid != service_uuid_) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Cannot found the GATT service.";
|
||||
LOG(ERROR) << __func__ << ": Cannot found the GATT service.";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& it : gatt_characteristic_datas_) {
|
||||
if (it.gatt_characteristic.uuid == characteristic.uuid) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Found the characteristic to update.";
|
||||
VLOG(1) << __func__ << ": Found the characteristic to update.";
|
||||
it.data = value;
|
||||
|
||||
// If it is in running, notify the value changed.
|
||||
@@ -165,8 +177,7 @@ bool BleGattServer::UpdateCharacteristic(
|
||||
is_indicate_characteristic = true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Notify characteristic value updated.";
|
||||
LOG(INFO) << __func__ << ": Notify characteristic value updated.";
|
||||
if (is_indicate_characteristic) {
|
||||
NotifyValueChanged(it.gatt_characteristic);
|
||||
}
|
||||
@@ -176,7 +187,7 @@ bool BleGattServer::UpdateCharacteristic(
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to update the characteristic.";
|
||||
LOG(ERROR) << __func__ << ": Failed to update the characteristic.";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -184,45 +195,75 @@ bool BleGattServer::UpdateCharacteristic(
|
||||
absl::Status BleGattServer::NotifyCharacteristicChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
|
||||
const ByteArray& new_value) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
// Currently, the method is not hooked up at platform layer.
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Notify characteristic="
|
||||
<< std::string(characteristic.uuid) << " changed.";
|
||||
VLOG(1) << __func__
|
||||
<< ": Notify characteristic=" << std::string(characteristic.uuid)
|
||||
<< " changed.";
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void BleGattServer::Stop() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to stop GATT server.";
|
||||
try {
|
||||
if (gatt_service_provider_ == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": GATT server already stopped.";
|
||||
return;
|
||||
}
|
||||
absl::AnyInvocable<void()> close_notifier = nullptr;
|
||||
{
|
||||
absl::MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__ << ": Start to stop GATT server.";
|
||||
if (gatt_service_provider_ != nullptr) {
|
||||
try {
|
||||
if (is_advertising_) {
|
||||
gatt_service_provider_.StopAdvertising();
|
||||
}
|
||||
|
||||
if (is_advertising_) {
|
||||
gatt_service_provider_.StopAdvertising();
|
||||
gatt_characteristic_datas_.clear();
|
||||
service_uuid_ = Uuid();
|
||||
gatt_service_provider_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
} else {
|
||||
LOG(WARNING) << __func__ << ": no GATT server is running.";
|
||||
}
|
||||
close_notifier = std::move(close_notifier_);
|
||||
}
|
||||
|
||||
gatt_characteristic_datas_.clear();
|
||||
service_uuid_ = Uuid();
|
||||
gatt_service_provider_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
if (close_notifier != nullptr) {
|
||||
close_notifier();
|
||||
}
|
||||
}
|
||||
|
||||
bool BleGattServer::InitializeGattServer() {
|
||||
try {
|
||||
// Create and advertise GATT service.
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Create GATT service service_uuid="
|
||||
<< std::string(service_uuid_);
|
||||
VLOG(1) << __func__ << ": Create GATT service service_uuid="
|
||||
<< std::string(service_uuid_);
|
||||
|
||||
if (adapter_ == nullptr || !adapter_->IsEnabled()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Bluetooth adapter is disabled.";
|
||||
if (adapter_ == nullptr) {
|
||||
LOG(ERROR) << __func__ << ": Bluetooth adapter is absent.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!adapter_->IsEnabled()) {
|
||||
LOG(ERROR) << __func__ << ": Bluetooth adapter is disabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!adapter_->IsLowEnergySupported()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Bluetooth adapter does not support BLE, which "
|
||||
"is needed to start GATT server.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!adapter_->IsPeripheralRoleSupported()) {
|
||||
LOG(ERROR)
|
||||
<< __func__
|
||||
<< ": Bluetooth Hardware does not support Peripheral Role, which is "
|
||||
"required to start GATT server.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -231,9 +272,8 @@ bool BleGattServer::InitializeGattServer() {
|
||||
GattServiceProvider::CreateAsync(service_uuid).get();
|
||||
|
||||
if (service_provider_result.Error() != BluetoothError::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to create GATT service. Error: "
|
||||
<< static_cast<int>(service_provider_result.Error());
|
||||
LOG(ERROR) << __func__ << ": Failed to create GATT service. Error: "
|
||||
<< static_cast<int>(service_provider_result.Error());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -242,7 +282,7 @@ bool BleGattServer::InitializeGattServer() {
|
||||
service_provider_advertisement_changed_token_ =
|
||||
gatt_service_provider_.AdvertisementStatusChanged(
|
||||
{this, &BleGattServer::ServiceProvider_AdvertisementStatusChanged});
|
||||
NEARBY_LOGS(INFO) << __func__ << ": GATT service created.";
|
||||
LOG(INFO) << __func__ << ": GATT service created.";
|
||||
|
||||
// Create GATT characteristics.
|
||||
for (auto& characteristic_data : gatt_characteristic_datas_) {
|
||||
@@ -276,12 +316,11 @@ bool BleGattServer::InitializeGattServer() {
|
||||
is_notify_supported = true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": GATT characteristic properties: read="
|
||||
<< is_read_supported
|
||||
<< ",write=" << is_write_supported
|
||||
<< ",indicate=" << is_indicate_supported
|
||||
<< ",notify=" << is_notify_supported;
|
||||
VLOG(1) << __func__
|
||||
<< ": GATT characteristic properties: read=" << is_read_supported
|
||||
<< ",write=" << is_write_supported
|
||||
<< ",indicate=" << is_indicate_supported
|
||||
<< ",notify=" << is_notify_supported;
|
||||
|
||||
gatt_characteristic_parameters.CharacteristicProperties(properties);
|
||||
gatt_characteristic_parameters.WriteProtectionLevel(
|
||||
@@ -290,10 +329,8 @@ bool BleGattServer::InitializeGattServer() {
|
||||
winrt::guid characteristic_uuid = nearby_uuid_to_winrt_guid(
|
||||
characteristic_data.gatt_characteristic.uuid);
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Create characteristic characteristic_uuid="
|
||||
<< winrt::to_string(
|
||||
winrt::to_hstring(characteristic_uuid));
|
||||
VLOG(1) << __func__ << ": Create characteristic characteristic_uuid="
|
||||
<< winrt::to_string(winrt::to_hstring(characteristic_uuid));
|
||||
|
||||
GattLocalCharacteristicResult result =
|
||||
gatt_service_provider_.Service()
|
||||
@@ -302,9 +339,9 @@ bool BleGattServer::InitializeGattServer() {
|
||||
.get();
|
||||
|
||||
if (result.Error() != BluetoothError::Success) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to create GATT characteristic. Error: "
|
||||
<< static_cast<int>(result.Error());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to create GATT characteristic. Error: "
|
||||
<< static_cast<int>(result.Error());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -312,9 +349,8 @@ bool BleGattServer::InitializeGattServer() {
|
||||
|
||||
::winrt::guid local_characteristic_guid =
|
||||
characteristic_data.local_characteristic.Uuid();
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Local GATT characteristic. uuid: "
|
||||
<< winrt::to_string(
|
||||
winrt::to_hstring(local_characteristic_guid));
|
||||
VLOG(1) << __func__ << ": Local GATT characteristic. uuid: "
|
||||
<< winrt::to_string(winrt::to_hstring(local_characteristic_guid));
|
||||
|
||||
// Setup gatt local characteristic events.
|
||||
if (is_read_supported) {
|
||||
@@ -339,15 +375,15 @@ bool BleGattServer::InitializeGattServer() {
|
||||
|
||||
is_gatt_server_inited_ = true;
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": GATT service is initalized.";
|
||||
LOG(INFO) << __func__ << ": GATT service is initalized.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
@@ -361,21 +397,31 @@ bool BleGattServer::InitializeGattServer() {
|
||||
|
||||
bool BleGattServer::StartAdvertisement(const ByteArray& service_data,
|
||||
bool is_connectable) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": service_data="
|
||||
<< absl::BytesToHexString(service_data.AsStringView())
|
||||
<< ", is_connectable=" << is_connectable;
|
||||
VLOG(1) << __func__ << ": service_data="
|
||||
<< absl::BytesToHexString(service_data.AsStringView())
|
||||
<< ", is_connectable=" << is_connectable;
|
||||
|
||||
if (is_advertising_) {
|
||||
NEARBY_LOGS(ERROR) << ": GATT server is already in advertising.";
|
||||
LOG(ERROR) << ": GATT server is already in advertising.";
|
||||
return false;
|
||||
}
|
||||
|
||||
is_advertising_ = true;
|
||||
|
||||
if (!is_gatt_server_inited_ && !InitializeGattServer()) {
|
||||
NEARBY_LOGS(ERROR) << ":Failed to initalize GATT service.";
|
||||
is_advertising_ = false;
|
||||
LOG(ERROR) << ":Failed to initalize GATT service.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gatt_service_provider_ == nullptr) {
|
||||
LOG(WARNING) << __func__ << ": no GATT server is running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gatt_service_provider_.AdvertisementStatus() ==
|
||||
GattServiceProviderAdvertisementStatus::Started) {
|
||||
LOG(WARNING) << __func__ << ": GATT server is already in advertising.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -392,69 +438,96 @@ bool BleGattServer::StartAdvertisement(const ByteArray& service_data,
|
||||
advertisement_parameters.ServiceData(data_writer.DetachBuffer());
|
||||
|
||||
gatt_service_provider_.StartAdvertising(advertisement_parameters);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": GATT server started.";
|
||||
|
||||
// Wait for the advertising to start.
|
||||
int wait_milliseconds = 0;
|
||||
while (gatt_service_provider_.AdvertisementStatus() !=
|
||||
GattServiceProviderAdvertisementStatus::Started) {
|
||||
absl::SleepFor(absl::Milliseconds(kGattServerCheckIntervalInMills));
|
||||
wait_milliseconds += kGattServerCheckIntervalInMills;
|
||||
if (absl::Milliseconds(wait_milliseconds) > kGattServerTimeout) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to start GATT advertising due to timeout.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
is_advertising_ = true;
|
||||
LOG(INFO) << __func__ << ": GATT server started.";
|
||||
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
|
||||
is_advertising_ = false;
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to advertise GATT server.";
|
||||
LOG(ERROR) << __func__ << ": Failed to advertise GATT server.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BleGattServer::StopAdvertisement() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": stop advertisement.";
|
||||
LOG(INFO) << __func__ << ": stop advertisement.";
|
||||
|
||||
if (!is_advertising_) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": no GATT advertisement.";
|
||||
LOG(WARNING) << __func__ << ": no GATT advertisement.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gatt_service_provider_ == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": no GATT server is running.";
|
||||
LOG(WARNING) << __func__ << ": no GATT server is running.";
|
||||
is_advertising_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gatt_service_provider_.AdvertisementStatus() ==
|
||||
GattServiceProviderAdvertisementStatus ::Stopped) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": no GATT advertisement is running.";
|
||||
LOG(WARNING) << __func__ << ": no GATT advertisement is running.";
|
||||
is_advertising_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
gatt_service_provider_.StopAdvertising();
|
||||
|
||||
// Don't wait for the advertising to stop, because the advertisement status
|
||||
// cannot back to stopped. Based on the observation, the advertisement
|
||||
// status is stopped after the stop advertising is called.
|
||||
|
||||
is_advertising_ = false;
|
||||
NEARBY_LOGS(INFO) << __func__ << ": GATT server stopped.";
|
||||
LOG(INFO) << __func__ << ": GATT server stopped.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BleGattServer::SetCloseNotifier(absl::AnyInvocable<void()> notifier) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
close_notifier_ = std::move(notifier);
|
||||
}
|
||||
|
||||
::winrt::fire_and_forget BleGattServer::Characteristic_ReadRequestedAsync(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattReadRequestedEventArgs args) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Read characteristic. uuid: "
|
||||
<< winrt::to_string(winrt::to_hstring(
|
||||
gatt_local_characteristic.Uuid()));
|
||||
LOG(INFO) << __func__ << ": Read characteristic. uuid: "
|
||||
<< winrt::to_string(
|
||||
winrt::to_hstring(gatt_local_characteristic.Uuid()));
|
||||
|
||||
auto deferral = args.GetDeferral();
|
||||
|
||||
@@ -464,15 +537,15 @@ bool BleGattServer::StopAdvertisement() {
|
||||
FindGattCharacteristicData(gatt_local_characteristic);
|
||||
|
||||
if (characteristic_data == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< ::winrt::to_string(::winrt::to_hstring(
|
||||
gatt_local_characteristic.Uuid()));
|
||||
LOG(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< ::winrt::to_string(
|
||||
::winrt::to_hstring(gatt_local_characteristic.Uuid()));
|
||||
return {};
|
||||
}
|
||||
|
||||
GattReadRequest request = args.GetRequestAsync().get();
|
||||
if (request == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get GATT read request.";
|
||||
LOG(ERROR) << __func__ << ": Failed to get GATT read request.";
|
||||
deferral.Complete();
|
||||
return {};
|
||||
}
|
||||
@@ -485,20 +558,20 @@ bool BleGattServer::StopAdvertisement() {
|
||||
request.RespondWithValue(buffer);
|
||||
deferral.Complete();
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Sent data to remote device.";
|
||||
VLOG(1) << __func__ << ": Sent data to remote device.";
|
||||
return {};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
|
||||
deferral.Complete();
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to send data to remote device.";
|
||||
LOG(ERROR) << __func__ << ": Failed to send data to remote device.";
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -507,7 +580,7 @@ bool BleGattServer::StopAdvertisement() {
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattWriteRequestedEventArgs args) {
|
||||
// In Nearby Connctions, don't support write charaterisctics right now.
|
||||
// In Nearby Connections, don't support write characteristics right now.
|
||||
throw std::logic_error("Not implemented.");
|
||||
}
|
||||
|
||||
@@ -515,10 +588,9 @@ void BleGattServer::Characteristic_SubscribedClientsChanged(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Foundation::IInspectable const& args) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Subscribed clients changed. characteristic="
|
||||
<< ::winrt::to_string(::winrt::to_hstring(
|
||||
gatt_local_characteristic.Uuid()));
|
||||
LOG(INFO) << __func__ << ": Subscribed clients changed. characteristic="
|
||||
<< ::winrt::to_string(
|
||||
::winrt::to_hstring(gatt_local_characteristic.Uuid()));
|
||||
|
||||
try {
|
||||
std::vector<api::ble_v2::GattCharacteristic>
|
||||
@@ -530,9 +602,9 @@ void BleGattServer::Characteristic_SubscribedClientsChanged(
|
||||
FindGattCharacteristicData(gatt_local_characteristic);
|
||||
|
||||
if (characteristic_data == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< ::winrt::to_string(::winrt::to_hstring(
|
||||
gatt_local_characteristic.Uuid()));
|
||||
LOG(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< ::winrt::to_string(
|
||||
::winrt::to_hstring(gatt_local_characteristic.Uuid()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -588,12 +660,12 @@ void BleGattServer::Characteristic_SubscribedClientsChanged(
|
||||
subscribed_characteristic);
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,8 +674,9 @@ void BleGattServer::ServiceProvider_AdvertisementStatusChanged(
|
||||
GattServiceProvider const& sender,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattServiceProviderAdvertisementStatusChangedEventArgs const& args) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Advertisement status changed. status="
|
||||
<< ConvertGattStatusToString(args.Status());
|
||||
LOG(INFO) << __func__ << ": Advertisement status changed. status="
|
||||
<< ConvertGattStatusToString(args.Status())
|
||||
<< ", error=" << static_cast<int>(args.Error());
|
||||
}
|
||||
|
||||
void BleGattServer::NotifyValueChanged(
|
||||
@@ -613,8 +686,8 @@ void BleGattServer::NotifyValueChanged(
|
||||
FindGattCharacteristicData(gatt_characteristic);
|
||||
|
||||
if (characteristic_data == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< std::string(gatt_characteristic.uuid);
|
||||
LOG(ERROR) << __func__ << ": Failed to find characteristic="
|
||||
<< std::string(gatt_characteristic.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -634,19 +707,19 @@ void BleGattServer::NotifyValueChanged(
|
||||
|
||||
for (const auto& result : results) {
|
||||
if (result.Status() != GattCommunicationStatus::Success) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to notify value change. remote device id="
|
||||
<< ::winrt::to_string(
|
||||
result.SubscribedClient().Session().DeviceId().Id());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to notify value change. remote device id="
|
||||
<< ::winrt::to_string(
|
||||
result.SubscribedClient().Session().DeviceId().Id());
|
||||
}
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,20 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/ble_v2_peripheral.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
@@ -37,26 +44,32 @@ namespace windows {
|
||||
|
||||
class BleGattServer : public api::ble_v2::GattServer {
|
||||
public:
|
||||
// Make sure the adapter parameter is not null.
|
||||
BleGattServer(api::BluetoothAdapter* adapter,
|
||||
api::ble_v2::ServerGattConnectionCallback callback);
|
||||
~BleGattServer() override = default;
|
||||
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
api::ble_v2::GattCharacteristic::Permission permission,
|
||||
api::ble_v2::GattCharacteristic::Property property) override;
|
||||
api::ble_v2::GattCharacteristic::Property property) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool UpdateCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const nearby::ByteArray& value) override;
|
||||
const nearby::ByteArray& value) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
absl::Status NotifyCharacteristicChanged(
|
||||
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
|
||||
const ByteArray& new_value) override;
|
||||
const ByteArray& new_value) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void Stop() override;
|
||||
void Stop() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool StartAdvertisement(const ByteArray& service_data, bool is_connectable);
|
||||
bool StopAdvertisement();
|
||||
bool StartAdvertisement(const ByteArray& service_data, bool is_connectable)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopAdvertisement() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void SetCloseNotifier(absl::AnyInvocable<void()> notifier)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
api::ble_v2::BlePeripheral& GetBlePeripheral() override {
|
||||
return peripheral_;
|
||||
@@ -78,51 +91,65 @@ class BleGattServer : public api::ble_v2::GattServer {
|
||||
::winrt::event_token subscribed_clients_changed_token{};
|
||||
};
|
||||
|
||||
bool InitializeGattServer();
|
||||
bool InitializeGattServer() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void NotifyValueChanged(
|
||||
const api::ble_v2::GattCharacteristic& gatt_characteristic);
|
||||
const api::ble_v2::GattCharacteristic& gatt_characteristic)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
GattCharacteristicData* FindGattCharacteristicData(
|
||||
const ::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic& gatt_local_characteristic);
|
||||
GattLocalCharacteristic& gatt_local_characteristic)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
GattCharacteristicData* FindGattCharacteristicData(
|
||||
const api::ble_v2::GattCharacteristic& gatt_characteristic);
|
||||
const api::ble_v2::GattCharacteristic& gatt_characteristic)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
::winrt::fire_and_forget Characteristic_ReadRequestedAsync(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattReadRequestedEventArgs args);
|
||||
GattReadRequestedEventArgs args)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
::winrt::fire_and_forget Characteristic_WriteRequestedAsync(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattWriteRequestedEventArgs args);
|
||||
GattWriteRequestedEventArgs args)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void Characteristic_SubscribedClientsChanged(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattLocalCharacteristic const& gatt_local_characteristic,
|
||||
::winrt::Windows::Foundation::IInspectable const& args);
|
||||
::winrt::Windows::Foundation::IInspectable const& args)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
void ServiceProvider_AdvertisementStatusChanged(
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattServiceProvider const& sender,
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattServiceProviderAdvertisementStatusChangedEventArgs const& args);
|
||||
GattServiceProviderAdvertisementStatusChangedEventArgs const& args)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
BluetoothAdapter* adapter_ = nullptr;
|
||||
absl::Mutex mutex_;
|
||||
|
||||
BluetoothAdapter* const adapter_ = nullptr;
|
||||
BleV2Peripheral peripheral_;
|
||||
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattServiceProvider gatt_service_provider_ = nullptr;
|
||||
|
||||
Uuid service_uuid_;
|
||||
std::vector<GattCharacteristicData> gatt_characteristic_datas_;
|
||||
|
||||
api::ble_v2::ServerGattConnectionCallback gatt_connection_callback_{};
|
||||
|
||||
::winrt::event_token service_provider_advertisement_changed_token_{};
|
||||
bool is_advertising_ = false;
|
||||
bool is_gatt_server_inited_ = false;
|
||||
::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
|
||||
GattServiceProvider gatt_service_provider_ ABSL_GUARDED_BY(mutex_) =
|
||||
nullptr;
|
||||
|
||||
absl::AnyInvocable<void()> close_notifier_ ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
|
||||
Uuid service_uuid_ ABSL_GUARDED_BY(mutex_);
|
||||
std::vector<GattCharacteristicData> gatt_characteristic_datas_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
bool is_advertising_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool is_gatt_server_inited_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
|
||||
::winrt::event_token service_provider_advertisement_changed_token_
|
||||
ABSL_GUARDED_BY(mutex_) = {};
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/ble_gatt_server.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
|
||||
@@ -44,6 +47,23 @@ TEST(BleV2GattServer, DISABLED_Stop) {
|
||||
blev2_gatt_server.Stop();
|
||||
}
|
||||
|
||||
TEST(BleV2GattServer, DISABLED_StopNotifierIsCalled) {
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleGattServer blev2_gatt_server(&bluetoothAdapter, {});
|
||||
bool is_close_notifier_called = false;
|
||||
absl::Notification notification;
|
||||
std::function<void()> notifier = [&is_close_notifier_called,
|
||||
¬ification]() {
|
||||
is_close_notifier_called = true;
|
||||
notification.Notify();
|
||||
};
|
||||
blev2_gatt_server.SetCloseNotifier(std::move(notifier));
|
||||
|
||||
blev2_gatt_server.Stop();
|
||||
notification.WaitForNotificationWithTimeout(absl::Seconds(1));
|
||||
EXPECT_TRUE(is_close_notifier_called);
|
||||
}
|
||||
|
||||
TEST(BleV2GattServer, DISABLED_CreateCharacteristic) {
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleGattServer blev2_gatt_server(&bluetoothAdapter, {});
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "internal/platform/implementation/windows/ble_medium.h"
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <future> // NOLINT
|
||||
#include <list>
|
||||
@@ -26,7 +27,9 @@
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/ble_peripheral.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
@@ -146,22 +149,20 @@ bool BleMedium::StartAdvertising(
|
||||
const std::string& fast_advertisement_service_uuid) {
|
||||
try {
|
||||
if (!adapter_->IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << "BLE cannot start advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
LOG(WARNING) << "BLE cannot start advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Windows Ble StartAdvertising: service_id=" << service_id
|
||||
<< ", advertisement bytes= 0x"
|
||||
<< absl::BytesToHexString(advertisement_bytes.AsStringView()) << "("
|
||||
<< advertisement_bytes.size() << "),"
|
||||
<< " fast advertisement service uuid= 0x"
|
||||
<< absl::BytesToHexString(fast_advertisement_service_uuid);
|
||||
LOG(INFO) << "Windows Ble StartAdvertising: service_id=" << service_id
|
||||
<< ", advertisement bytes= 0x"
|
||||
<< absl::BytesToHexString(advertisement_bytes.AsStringView())
|
||||
<< "(" << advertisement_bytes.size() << "),"
|
||||
<< " fast advertisement service uuid= 0x"
|
||||
<< absl::BytesToHexString(fast_advertisement_service_uuid);
|
||||
|
||||
if (is_publisher_started_) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "BLE cannot start to advertise again when it is running.";
|
||||
LOG(WARNING) << "BLE cannot start to advertise again when it is running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -205,8 +206,8 @@ bool BleMedium::StartAdvertising(
|
||||
publisher_.UseExtendedAdvertisement(false);
|
||||
} else {
|
||||
// otherwise no-op
|
||||
NEARBY_LOGS(INFO) << "Everyone Mode unavailable for hardware that does "
|
||||
"not support Extended Advertising.";
|
||||
LOG(INFO) << "Everyone Mode unavailable for hardware that does "
|
||||
"not support Extended Advertising.";
|
||||
publisher_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
@@ -217,21 +218,21 @@ bool BleMedium::StartAdvertising(
|
||||
publisher_.Start();
|
||||
|
||||
is_publisher_started_ = true;
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartAdvertising started.";
|
||||
LOG(INFO) << "Windows Ble StartAdvertising started.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception to start BLE advertising: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to start BLE advertising: " << exception.what();
|
||||
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception to start BLE advertising: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to start BLE advertising: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -239,16 +240,15 @@ bool BleMedium::StartAdvertising(
|
||||
bool BleMedium::StopAdvertising(const std::string& service_id) {
|
||||
try {
|
||||
if (!adapter_->IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << "BLE cannot stop advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
LOG(WARNING) << "BLE cannot stop advertising because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopAdvertising: service_id="
|
||||
<< service_id;
|
||||
LOG(INFO) << "Windows Ble StopAdvertising: service_id=" << service_id;
|
||||
|
||||
if (!is_publisher_started_) {
|
||||
NEARBY_LOGS(WARNING) << "BLE advertising is not running.";
|
||||
LOG(WARNING) << "BLE advertising is not running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -266,18 +266,18 @@ bool BleMedium::StopAdvertising(const std::string& service_id) {
|
||||
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception to stop BLE advertising: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to stop BLE advertising: " << exception.what();
|
||||
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception to stop BLE advertising: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to stop BLE advertising: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -288,16 +288,15 @@ bool BleMedium::StartScanning(
|
||||
DiscoveredPeripheralCallback callback) {
|
||||
try {
|
||||
if (!adapter_->IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << "BLE cannot start scanning because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
LOG(WARNING) << "BLE cannot start scanning because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning: service_id=" << service_id;
|
||||
LOG(INFO) << "Windows Ble StartScanning: service_id=" << service_id;
|
||||
|
||||
if (is_watcher_started_) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "BLE cannot start to scan again when it is running.";
|
||||
LOG(WARNING) << "BLE cannot start to scan again when it is running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -327,21 +326,20 @@ bool BleMedium::StartScanning(
|
||||
|
||||
is_watcher_started_ = true;
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning started.";
|
||||
LOG(INFO) << "Windows Ble StartScanning started.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception to start BLE scanning: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to start BLE scanning: " << exception.what();
|
||||
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception to start BLE scanning: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": Exception to start BLE scanning: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -349,15 +347,15 @@ bool BleMedium::StartScanning(
|
||||
bool BleMedium::StopScanning(const std::string& service_id) {
|
||||
try {
|
||||
if (!adapter_->IsEnabled()) {
|
||||
NEARBY_LOGS(WARNING) << "BLE cannot stop scanning because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
LOG(WARNING) << "BLE cannot stop scanning because the "
|
||||
"bluetooth adapter is not enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopScanning: service_id=" << service_id;
|
||||
LOG(INFO) << "Windows Ble StopScanning: service_id=" << service_id;
|
||||
|
||||
if (!is_watcher_started_) {
|
||||
NEARBY_LOGS(WARNING) << "BLE scanning is not running.";
|
||||
LOG(WARNING) << "BLE scanning is not running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -368,37 +366,35 @@ bool BleMedium::StopScanning(const std::string& service_id) {
|
||||
// stopping to finish.
|
||||
is_watcher_started_ = false;
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Windows Ble stoped scanning successfully for service_id="
|
||||
<< service_id;
|
||||
LOG(ERROR) << "Windows Ble stoped scanning successfully for service_id="
|
||||
<< service_id;
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception to stop BLE scanning: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception to stop BLE scanning: " << exception.what();
|
||||
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception to stop BLE scanning: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": Exception to stop BLE scanning: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BleMedium::StartAcceptingConnections(const std::string& service_id,
|
||||
AcceptedConnectionCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartAcceptingConnections: service_id="
|
||||
<< service_id;
|
||||
LOG(INFO) << "Windows Ble StartAcceptingConnections: service_id="
|
||||
<< service_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleMedium::StopAcceptingConnections(const std::string& service_id) {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopAcceptingConnections: service_id="
|
||||
<< service_id;
|
||||
LOG(INFO) << "Windows Ble StopAcceptingConnections: service_id="
|
||||
<< service_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -406,15 +402,15 @@ std::unique_ptr<api::BleSocket> BleMedium::Connect(
|
||||
api::BlePeripheral& remote_peripheral, const std::string& service_id,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
if (cancellation_flag->Cancelled()) {
|
||||
NEARBY_LOGS(ERROR) << "Windows BLE Connect: Has been cancelled: "
|
||||
"service_id="
|
||||
<< service_id;
|
||||
LOG(ERROR) << "Windows BLE Connect: Has been cancelled: "
|
||||
"service_id="
|
||||
<< service_id;
|
||||
return {};
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Windows Ble Connect: Cannot connect over BLE socket. "
|
||||
"service_id="
|
||||
<< service_id;
|
||||
LOG(ERROR) << "Windows Ble Connect: Cannot connect over BLE socket. "
|
||||
"service_id="
|
||||
<< service_id;
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -424,75 +420,73 @@ void BleMedium::PublisherHandler(
|
||||
// This method is called when publisher's status is changed.
|
||||
switch (args.Status()) {
|
||||
case BluetoothLEAdvertisementPublisherStatus::Created:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium created to advertise.";
|
||||
LOG(INFO) << "Nearby BLE Medium created to advertise.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Started:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium started to advertise.";
|
||||
LOG(INFO) << "Nearby BLE Medium started to advertise.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Stopping:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium is stopping.";
|
||||
LOG(INFO) << "Nearby BLE Medium is stopping.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Waiting:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium is waiting.";
|
||||
LOG(INFO) << "Nearby BLE Medium is waiting.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Stopped:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium stopped to advertise.";
|
||||
LOG(INFO) << "Nearby BLE Medium stopped to advertise.";
|
||||
break;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Aborted:
|
||||
switch (args.Error()) {
|
||||
case BluetoothError::Success:
|
||||
if (publisher_.Status() ==
|
||||
BluetoothLEAdvertisementPublisherStatus::Started) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium start advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
LOG(ERROR) << "Nearby BLE Medium start advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
}
|
||||
if (publisher_.Status() ==
|
||||
BluetoothLEAdvertisementPublisherStatus::Stopped) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stop advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stop advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"unknown errors.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"unknown errors.";
|
||||
}
|
||||
break;
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"radio not available.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"radio not available.";
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"resource in use.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"resource in use.";
|
||||
break;
|
||||
case BluetoothError::DeviceNotConnected:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"remote device is not connected.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"remote device is not connected.";
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by policy.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by policy.";
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by user.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by user.";
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"hardware not supported.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"hardware not supported.";
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"transport not supported.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"transport not supported.";
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"consent required.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"consent required.";
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
default:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"unknown errors.";
|
||||
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"unknown errors.";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -502,7 +496,7 @@ void BleMedium::PublisherHandler(
|
||||
|
||||
// The publisher is stopped. Clean up the running publisher
|
||||
if (publisher_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium cleaned the publisher.";
|
||||
LOG(ERROR) << "Nearby BLE Medium cleaned the publisher.";
|
||||
publisher_.StatusChanged(publisher_token_);
|
||||
publisher_ = nullptr;
|
||||
is_publisher_started_ = false;
|
||||
@@ -516,47 +510,42 @@ void BleMedium::WatcherHandler(
|
||||
// information on the reason.
|
||||
switch (args.Error()) {
|
||||
case BluetoothError::Success:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan successfully.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan successfully.";
|
||||
break;
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR)
|
||||
LOG(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to radio not available.";
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to resource in use.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to resource in use.";
|
||||
break;
|
||||
case BluetoothError::DeviceNotConnected:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"remote device is not connected.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"remote device is not connected.";
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR)
|
||||
LOG(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to disabled by policy.";
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to disabled by user.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to disabled by user.";
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"hardware not supported.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"hardware not supported.";
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"transport not supported.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"transport not supported.";
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to consent required.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to consent required.";
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
break;
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -564,7 +553,7 @@ void BleMedium::WatcherHandler(
|
||||
// The BLE V1 interface doesn't have an API to return the error to the upper
|
||||
// layer.
|
||||
if (watcher_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium cleaned the watcher.";
|
||||
LOG(ERROR) << "Nearby BLE Medium cleaned the watcher.";
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
watcher_ = nullptr;
|
||||
@@ -600,11 +589,10 @@ void BleMedium::AdvertisementReceivedHandler(
|
||||
|
||||
ByteArray advertisement_data(data);
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << "Nearby BLE Medium Advertisement discovered. "
|
||||
"0x16 Service data: advertisement bytes= 0x"
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_data.AsStringView())
|
||||
<< "(" << advertisement_data.size() << ")";
|
||||
VLOG(1) << "Nearby BLE Medium Advertisement discovered. "
|
||||
"0x16 Service data: advertisement bytes= 0x"
|
||||
<< absl::BytesToHexString(advertisement_data.AsStringView())
|
||||
<< "(" << advertisement_data.size() << ")";
|
||||
|
||||
std::string peripheral_name =
|
||||
uint64_to_mac_address_string(args.BluetoothAddress());
|
||||
@@ -616,7 +604,7 @@ void BleMedium::AdvertisementReceivedHandler(
|
||||
if (peripheral_map_.contains(peripheral_name)) {
|
||||
if (peripheral_map_[peripheral_name]->GetAdvertisementBytes(
|
||||
service_id_) != advertisement_data) {
|
||||
NEARBY_LOGS(INFO) << "BLE reports lost device: " << peripheral_name;
|
||||
LOG(INFO) << "BLE reports lost device: " << peripheral_name;
|
||||
|
||||
// Lost the device first and then the report discovered the
|
||||
// device.
|
||||
@@ -644,15 +632,13 @@ void BleMedium::AdvertisementReceivedHandler(
|
||||
|
||||
// Received Fast Advertisement packet
|
||||
if (unconsumed_buffer_length <= 27) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Sending Fast Advertisement packet for processing.";
|
||||
LOG(INFO) << "Sending Fast Advertisement packet for processing.";
|
||||
advertisement_received_callback_.peripheral_discovered_cb(
|
||||
/*ble_peripheral*/ *peripheral_ptr, /*service_id*/ service_id_,
|
||||
/*is_fast_advertisement*/ true);
|
||||
} else {
|
||||
// Received Extended Advertising packet
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Sending Extended Advertising packet for processing.";
|
||||
LOG(INFO) << "Sending Extended Advertising packet for processing.";
|
||||
advertisement_received_callback_.peripheral_discovered_cb(
|
||||
/*ble_peripheral*/ *peripheral_ptr, /*service_id*/ service_id_,
|
||||
/*is_fast_advertisement*/ false);
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
#include "internal/platform/implementation/windows/ble_socket.h"
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/windows/ble_peripheral.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,18 +15,24 @@
|
||||
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_V2_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_V2_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/ble_gatt_server.h"
|
||||
#include "internal/platform/implementation/windows/ble_v2_peripheral.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.Advertisement.h"
|
||||
|
||||
@@ -42,51 +48,59 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
// Returns true once the Ble advertising has been initiated.
|
||||
bool StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters) override;
|
||||
bool StopAdvertising() override;
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
std::unique_ptr<AdvertisingSession> StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters,
|
||||
AdvertisingCallback callback) override;
|
||||
AdvertisingCallback callback) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool StartScanning(const Uuid& service_uuid,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) override;
|
||||
bool StopScanning() override;
|
||||
ScanCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopScanning() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<ScanningSession> StartScanning(
|
||||
const Uuid& service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanningCallback callback) override;
|
||||
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
|
||||
api::ble_v2::ServerGattConnectionCallback callback) override;
|
||||
api::ble_v2::ServerGattConnectionCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) override;
|
||||
api::ble_v2::ClientGattConnectionCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::BleServerSocket> OpenServerSocket(
|
||||
const std::string& service_id) override;
|
||||
const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::BleSocket> Connect(
|
||||
const std::string& service_id, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BlePeripheral& remote_peripheral,
|
||||
CancellationFlag* cancellation_flag) override;
|
||||
CancellationFlag* cancellation_flag) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool IsExtendedAdvertisementsAvailable() override;
|
||||
|
||||
bool GetRemotePeripheral(const std::string& mac_address,
|
||||
GetRemotePeripheralCallback callback) override;
|
||||
GetRemotePeripheralCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
|
||||
GetRemotePeripheralCallback callback) override;
|
||||
GetRemotePeripheralCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
bool StartBleAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters);
|
||||
bool StopBleAdvertising();
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool StopBleAdvertising() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
bool StartGattAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters);
|
||||
bool StopGattAdvertising();
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool StopGattAdvertising() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
void PublisherHandler(
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
@@ -111,50 +125,53 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args);
|
||||
|
||||
uint64_t GenerateSessionId();
|
||||
uint64_t GenerateSessionId() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
// Returns nullptr if `address` is invalid.
|
||||
BleV2Peripheral* GetOrCreatePeripheral(absl::string_view address);
|
||||
BleV2Peripheral* GetOrCreatePeripheral(absl::string_view address)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
// Returns nullptr if `id` does not match a known peripheral.
|
||||
BleV2Peripheral* GetPeripheral(BleV2Peripheral::UniqueId id);
|
||||
BleV2Peripheral* GetPeripheral(BleV2Peripheral::UniqueId id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
void RemoveExpiredPeripherals()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(peripheral_map_mutex_);
|
||||
void RemoveExpiredPeripherals() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
BluetoothAdapter* adapter_;
|
||||
absl::Mutex mutex_;
|
||||
|
||||
BluetoothAdapter* const adapter_;
|
||||
Uuid service_uuid_;
|
||||
api::ble_v2::TxPowerLevel tx_power_level_;
|
||||
ScanCallback scan_callback_;
|
||||
|
||||
absl::Mutex map_mutex_;
|
||||
// std::map<Uuid, std::map<uint64_t, ScanningCallback>>
|
||||
absl::flat_hash_map<Uuid, absl::flat_hash_map<uint64_t, ScanningCallback>>
|
||||
service_uuid_to_session_map_ ABSL_GUARDED_BY(map_mutex_);
|
||||
service_uuid_to_session_map_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// WinRT objects
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher_ = nullptr;
|
||||
BluetoothLEAdvertisementPublisher publisher_ ABSL_GUARDED_BY(mutex_) =
|
||||
nullptr;
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher_ = nullptr;
|
||||
BluetoothLEAdvertisementWatcher watcher_ ABSL_GUARDED_BY(mutex_) =
|
||||
nullptr;
|
||||
|
||||
bool is_ble_publisher_started_ = false;
|
||||
bool is_gatt_publisher_started_ = false;
|
||||
bool is_watcher_started_ = false;
|
||||
bool is_ble_publisher_started_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool is_gatt_publisher_started_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool is_watcher_started_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
|
||||
::winrt::event_token publisher_token_;
|
||||
::winrt::event_token watcher_token_;
|
||||
::winrt::event_token advertisement_received_token_;
|
||||
::winrt::event_token publisher_token_ ABSL_GUARDED_BY(mutex_);
|
||||
::winrt::event_token watcher_token_ ABSL_GUARDED_BY(mutex_);
|
||||
::winrt::event_token advertisement_received_token_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
BleGattServer* ble_gatt_server_ = nullptr;
|
||||
// Map to protect the pointer for BlePeripheral because
|
||||
// DiscoveredPeripheralCallback only keeps the pointer to the object
|
||||
absl::Mutex peripheral_map_mutex_;
|
||||
struct PeripheralInfo {
|
||||
absl::Time last_access_time;
|
||||
std::unique_ptr<BleV2Peripheral> peripheral;
|
||||
};
|
||||
absl::flat_hash_map<BleV2Peripheral::UniqueId, PeripheralInfo> peripheral_map_
|
||||
ABSL_GUARDED_BY(peripheral_map_mutex_);
|
||||
absl::Time cleanup_time_ ABSL_GUARDED_BY(peripheral_map_mutex_) = absl::Now();
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
absl::Time cleanup_time_ ABSL_GUARDED_BY(mutex_) = absl::Now();
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -35,7 +35,7 @@ BleV2Peripheral::BleV2Peripheral(absl::string_view address) {
|
||||
bool BleV2Peripheral::SetAddress(absl::string_view address) {
|
||||
// The address must be in format "00:B0:D0:63:C2:26".
|
||||
if (address.size() != kMacAddressLength) {
|
||||
NEARBY_LOGS(ERROR) << ": Invalid MAC address length.";
|
||||
LOG(ERROR) << ": Invalid MAC address length.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ bool BleV2Peripheral::SetAddress(absl::string_view address) {
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << ": Invalid MAC address format.";
|
||||
LOG(ERROR) << ": Invalid MAC address format.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/ble_v2_socket.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
@@ -37,7 +38,7 @@ BleV2ServerSocket::BleV2ServerSocket(api::BluetoothAdapter* adapter)
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleSocket> BleV2ServerSocket::Accept() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Accept is called.";
|
||||
LOG(INFO) << __func__ << ": Accept is called.";
|
||||
|
||||
while (!closed_ && pending_sockets_.empty()) {
|
||||
cond_.Wait(&mutex_);
|
||||
@@ -47,14 +48,14 @@ std::unique_ptr<api::ble_v2::BleSocket> BleV2ServerSocket::Accept() {
|
||||
BleV2Socket ble_socket = pending_sockets_.front();
|
||||
pending_sockets_.pop_front();
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Accepted a remote connection.";
|
||||
LOG(INFO) << __func__ << ": Accepted a remote connection.";
|
||||
return std::make_unique<BleV2Socket>(ble_socket);
|
||||
}
|
||||
|
||||
Exception BleV2ServerSocket::Close() {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close is called.";
|
||||
LOG(INFO) << __func__ << ": Close is called.";
|
||||
|
||||
if (closed_) {
|
||||
return {Exception::kSuccess};
|
||||
@@ -68,7 +69,7 @@ Exception BleV2ServerSocket::Close() {
|
||||
|
||||
bool BleV2ServerSocket::Bind() {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": GATT socket started.";
|
||||
LOG(ERROR) << __func__ << ": GATT socket started.";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "internal/platform/implementation/windows/ble_v2_socket.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
@@ -22,8 +23,11 @@
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -40,38 +44,38 @@ api::ble_v2::BlePeripheral* BleV2Socket::GetRemotePeripheral() {
|
||||
|
||||
bool BleV2Socket::Connect(api::ble_v2::BlePeripheral* ble_peripheral) {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Connect to BLE peripheral="
|
||||
<< ble_peripheral->GetAddress();
|
||||
VLOG(1) << __func__
|
||||
<< ": Connect to BLE peripheral=" << ble_peripheral->GetAddress();
|
||||
return false;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BleV2Socket::BleInputStream::Read(std::int64_t size) {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Read data size=" << size;
|
||||
VLOG(1) << __func__ << ": Read data size=" << size;
|
||||
return ExceptionOr<ByteArray>(Exception::kIo);
|
||||
}
|
||||
|
||||
Exception BleV2Socket::BleInputStream::Close() {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Close BLE input stream.";
|
||||
VLOG(1) << __func__ << ": Close BLE input stream.";
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BleV2Socket::BleOutputStream::Write(const ByteArray& data) {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Write data size=" << data.size();
|
||||
VLOG(1) << __func__ << ": Write data size=" << data.size();
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
Exception BleV2Socket::BleOutputStream::Flush() {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Flush is called.";
|
||||
LOG(INFO) << __func__ << ": Flush is called.";
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BleV2Socket::BleOutputStream::Close() {
|
||||
// TODO(b/271031645): implement BLE socket using weave
|
||||
NEARBY_LOGS(INFO) << __func__ << ": close is called.";
|
||||
LOG(INFO) << __func__ << ": close is called.";
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -32,12 +32,17 @@
|
||||
#include <stdio.h>
|
||||
#include <usbiodef.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "third_party/json/src/json.hpp"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/implementation/platform.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
@@ -85,8 +90,7 @@ BluetoothAdapter::BluetoothAdapter() : windows_bluetooth_adapter_(nullptr) {
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothAdapter::GetDefaultAsync()
|
||||
.get();
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": No Bluetooth adapter on this device.";
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
} else {
|
||||
// Gets the radio represented by this Bluetooth adapter.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.getradioasync?view=winrt-20348
|
||||
@@ -94,20 +98,20 @@ BluetoothAdapter::BluetoothAdapter() : windows_bluetooth_adapter_(nullptr) {
|
||||
windows_bluetooth_adapter_.GetRadioAsync().get();
|
||||
}
|
||||
} catch (const winrt::hresult_error &error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronously sets the status of the BluetoothAdapter to 'status', and
|
||||
// returns true if the operation was a success.
|
||||
bool BluetoothAdapter::SetStatus(Status status) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Set Bluetooth radio status to "
|
||||
<< (status == Status::kEnabled ? "On" : "Off");
|
||||
LOG(ERROR) << __func__ << ": Set Bluetooth radio status to "
|
||||
<< (status == Status::kEnabled ? "On" : "Off");
|
||||
if (windows_bluetooth_radio_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No Bluetooth radio on this device.";
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth radio on this device.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,25 +120,23 @@ bool BluetoothAdapter::SetStatus(Status status) {
|
||||
if (status == Status::kDisabled &&
|
||||
(radio_state == RadioState::Unknown || radio_state == RadioState::Off ||
|
||||
radio_state == RadioState::Disabled)) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": Skip set radio status kDisabled due to requested state is "
|
||||
"already kDisabled.";
|
||||
LOG(INFO) << __func__
|
||||
<< ": Skip set radio status kDisabled due to requested state is "
|
||||
"already kDisabled.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (status == Status::kEnabled && radio_state == RadioState::On) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": Skip set radio status kEnabled due to requested state is "
|
||||
"already kEnabled.";
|
||||
LOG(INFO) << __func__
|
||||
<< ": Skip set radio status kEnabled due to requested state is "
|
||||
"already kEnabled.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!FeatureFlags::GetInstance().GetFlags().enable_set_radio_state) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Attempt to set the radio state while "
|
||||
"FeatureFlags::enable_set_radio_state is false.";
|
||||
LOG(INFO) << __func__
|
||||
<< ": Attempt to set the radio state while "
|
||||
"FeatureFlags::enable_set_radio_state is false.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -148,22 +150,19 @@ bool BluetoothAdapter::SetStatus(Status status) {
|
||||
windows_bluetooth_radio_.SetStateAsync(RadioState::On).get();
|
||||
}
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set Bluetooth radio state to "
|
||||
<< (status == Status::kDisabled ? "kDisabled."
|
||||
: "kEnabled.")
|
||||
<< "Exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to set Bluetooth radio state to "
|
||||
<< (status == Status::kDisabled ? "kDisabled." : "kEnabled.")
|
||||
<< "Exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Successfully set the radio state to "
|
||||
<< (status == Status::kDisabled ? "kDisabled."
|
||||
: "kEnabled.");
|
||||
LOG(INFO) << __func__ << ": Successfully set the radio state to "
|
||||
<< (status == Status::kDisabled ? "kDisabled." : "kEnabled.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -171,7 +170,7 @@ bool BluetoothAdapter::SetStatus(Status status) {
|
||||
// Status::Value::kEnabled.
|
||||
bool BluetoothAdapter::IsEnabled() const {
|
||||
if (windows_bluetooth_radio_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No Bluetooth radio on this device.";
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth radio on this device.";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -179,14 +178,14 @@ bool BluetoothAdapter::IsEnabled() const {
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio.state?view=winrt-20348
|
||||
return windows_bluetooth_radio_.State() == RadioState::On;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -195,7 +194,7 @@ bool BluetoothAdapter::IsEnabled() const {
|
||||
// Advertising
|
||||
bool BluetoothAdapter::IsExtendedAdvertisingSupported() const {
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -204,14 +203,83 @@ bool BluetoothAdapter::IsExtendedAdvertisingSupported() const {
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.isextendedadvertisingsupported?view=winrt-22621
|
||||
return windows_bluetooth_adapter_.IsExtendedAdvertisingSupported();
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE Central Role
|
||||
bool BluetoothAdapter::IsCentralRoleSupported() const {
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// Indicates whether the adapter supports the BLE Central Role
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.iscentralrolesupported?view=winrt-22621
|
||||
return windows_bluetooth_adapter_.IsCentralRoleSupported();
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE Peripheral Role
|
||||
bool BluetoothAdapter::IsPeripheralRoleSupported() const {
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// Indicates whether the adapter supports the BLE Peripheral Role
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.isperipheralrolesupported?view=winrt-22621
|
||||
return windows_bluetooth_adapter_.IsPeripheralRoleSupported();
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE
|
||||
bool BluetoothAdapter::IsLowEnergySupported() const {
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// Indicates whether the adapter supports BLE
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.islowenergysupported?view=winrt-22621
|
||||
return windows_bluetooth_adapter_.IsLowEnergySupported();
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -248,13 +316,13 @@ void BluetoothAdapter::RestoreRadioNameIfNecessary() {
|
||||
auto settings_file =
|
||||
nearby::api::ImplementationPlatform::CreateInputFile(full_path, 0);
|
||||
if (settings_file == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create input file.";
|
||||
LOG(ERROR) << __func__ << ": Failed to create input file.";
|
||||
return;
|
||||
}
|
||||
|
||||
auto total_size = settings_file->GetTotalSize();
|
||||
if (total_size == 0) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": No data for local settings.";
|
||||
LOG(WARNING) << __func__ << ": No data for local settings.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -264,7 +332,7 @@ void BluetoothAdapter::RestoreRadioNameIfNecessary() {
|
||||
settings_file->Close();
|
||||
|
||||
if (!raw_local_settings.ok()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to read data file.";
|
||||
LOG(ERROR) << __func__ << ": Failed to read data file.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,12 +340,11 @@ void BluetoothAdapter::RestoreRadioNameIfNecessary() {
|
||||
json::parse(raw_local_settings.GetResult().data(), nullptr, false);
|
||||
|
||||
if (local_settings.is_discarded()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Invalid local settings data.";
|
||||
LOG(ERROR) << __func__ << ": Invalid local settings data.";
|
||||
return;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": loaded settings: " << local_settings.dump();
|
||||
VLOG(1) << __func__ << ": loaded settings: " << local_settings.dump();
|
||||
|
||||
LocalSettings settings = local_settings.get<LocalSettings>();
|
||||
|
||||
@@ -286,10 +353,10 @@ void BluetoothAdapter::RestoreRadioNameIfNecessary() {
|
||||
/* persist= */ true);
|
||||
}
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,9 +364,8 @@ void BluetoothAdapter::StoreRadioNames(absl::string_view original_radio_name,
|
||||
absl::string_view nearby_radio_name) {
|
||||
try {
|
||||
if (original_radio_name.empty() || nearby_radio_name.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ":Failed to save radio names due to invalid parameters.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ":Failed to save radio names due to invalid parameters.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,7 +377,7 @@ void BluetoothAdapter::StoreRadioNames(absl::string_view original_radio_name,
|
||||
nearby::api::ImplementationPlatform::CreateOutputFile(full_path);
|
||||
|
||||
if (settings_file == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create output file.";
|
||||
LOG(ERROR) << __func__ << ": Failed to create output file.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -320,18 +386,18 @@ void BluetoothAdapter::StoreRadioNames(absl::string_view original_radio_name,
|
||||
|
||||
json encoded_local_settings;
|
||||
to_json(encoded_local_settings, local_settings);
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": saved settings: "
|
||||
<< encoded_local_settings.dump();
|
||||
VLOG(1) << __func__
|
||||
<< ": saved settings: " << encoded_local_settings.dump();
|
||||
|
||||
ByteArray data(encoded_local_settings.dump());
|
||||
|
||||
settings_file->Write(data);
|
||||
settings_file->Close();
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,20 +408,22 @@ std::string BluetoothAdapter::GetName() const {
|
||||
return *device_name_;
|
||||
}
|
||||
|
||||
char *_instance_id = GetGenericBluetoothAdapterInstanceID();
|
||||
if (_instance_id == nullptr) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
std::optional<std::string> adapter_instance_id =
|
||||
GetGenericBluetoothAdapterInstanceID();
|
||||
if (!adapter_instance_id.has_value()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string instance_id(_instance_id);
|
||||
std::string instance_id = *adapter_instance_id;
|
||||
|
||||
// Change radio module local name in registry
|
||||
HKEY hKey;
|
||||
|
||||
// Retrieve the size required
|
||||
size_t registry_query_size = absl::SNPrintF(nullptr, // output
|
||||
char empty[0];
|
||||
size_t registry_query_size = absl::SNPrintF(empty, // output
|
||||
0, // size
|
||||
REGISTRY_QUERY_FORMAT, // format
|
||||
instance_id.c_str()); // args
|
||||
@@ -410,18 +478,18 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
StoreRadioNames(GetName(), name);
|
||||
}
|
||||
if (name.size() > 248 * sizeof(char)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set name for bluetooth adapter because "
|
||||
"the name exceeded the 248 bytes limit for Windows.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to set name for bluetooth adapter because "
|
||||
"the name exceeded the 248 bytes limit for Windows.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name.size() > kAndroidDiscoverableBluetoothNameMaxLength * sizeof(char)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set name for bluetooth adapter because "
|
||||
"Android cannot discover Windows bluetooth device "
|
||||
"name that exceeded the 37 bytes limit (11 "
|
||||
"characters in EndpointInfo).";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to set name for bluetooth adapter because "
|
||||
"Android cannot discover Windows bluetooth device "
|
||||
"name that exceeded the 37 bytes limit (11 "
|
||||
"characters in EndpointInfo).";
|
||||
device_name_ = std::string(name);
|
||||
return true;
|
||||
}
|
||||
@@ -429,19 +497,22 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
device_name_ = std::nullopt;
|
||||
|
||||
if (registry_bluetooth_adapter_name_ == name) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Tried to set name for bluetooth adapter to the "
|
||||
"same name again.";
|
||||
LOG(INFO) << __func__
|
||||
<< ": Tried to set name for bluetooth adapter to the "
|
||||
"same name again.";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string instance_id(GetGenericBluetoothAdapterInstanceID());
|
||||
std::optional<std::string> adapter_instance_id =
|
||||
GetGenericBluetoothAdapterInstanceID();
|
||||
|
||||
if (instance_id.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
if (!adapter_instance_id.has_value()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string instance_id = *adapter_instance_id;
|
||||
// defined in usbiodef.h
|
||||
const GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
|
||||
|
||||
@@ -461,7 +532,7 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
StringFromGUID2(guid, guid_ole_str, guid_ole_str_size);
|
||||
|
||||
if (conversionResult == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to convert guid to string";
|
||||
LOG(ERROR) << __func__ << ": Failed to convert guid to string";
|
||||
return false;
|
||||
}
|
||||
std::string guid_str;
|
||||
@@ -523,9 +594,9 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
// Convert the P&P instance id, to one that CreateFileA expects
|
||||
find_and_replace(instance_id_modified.data(), "\\", "#");
|
||||
|
||||
size_t file_name_size =
|
||||
absl::SNPrintF(nullptr, 0, "\\\\.\\%s#%s", instance_id_modified.c_str(),
|
||||
guid_str.c_str());
|
||||
char empty[0];
|
||||
size_t file_name_size = absl::SNPrintF(
|
||||
empty, 0, "\\\\.\\%s#%s", instance_id_modified.c_str(), guid_str.c_str());
|
||||
|
||||
std::string file_name;
|
||||
file_name.reserve(file_name_size + 1);
|
||||
@@ -552,15 +623,15 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
// access right. This parameter can be NULL.
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to open device. Error code: "
|
||||
<< GetLastError();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to open device. Error code: " << GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change radio module local name in registry
|
||||
HKEY hKey;
|
||||
size_t buffer_size =
|
||||
absl::SNPrintF(nullptr, 0, REGISTRY_QUERY_FORMAT, instance_id);
|
||||
absl::SNPrintF(empty, 0, REGISTRY_QUERY_FORMAT, instance_id);
|
||||
|
||||
std::string local_name_key;
|
||||
local_name_key.reserve(buffer_size + 1);
|
||||
@@ -582,9 +653,8 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
// key.
|
||||
|
||||
if (status != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to open registry key. Error code: "
|
||||
<< status;
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to open registry key. Error code: " << status;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -610,9 +680,8 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
}
|
||||
|
||||
if (status != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set/delete registry key. Error code: "
|
||||
<< status;
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to set/delete registry key. Error code: " << status;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -642,10 +711,9 @@ bool BluetoothAdapter::SetName(absl::string_view name, bool persist) {
|
||||
&bytes, // A pointer to a variable that receives the size of the
|
||||
// data stored in the output buffer, in bytes.
|
||||
NULL)) { // A pointer to an OVERLAPPED structure.
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to update radio module local name. Error code: "
|
||||
<< GetLastError();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to update radio module local name. Error code: "
|
||||
<< GetLastError();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -679,8 +747,8 @@ void BluetoothAdapter::process_error() {
|
||||
break;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to convert guid to string "
|
||||
<< errorResult << " Error code:" << errorMessageID;
|
||||
LOG(ERROR) << __func__ << ": Failed to convert guid to string " << errorResult
|
||||
<< " Error code:" << errorMessageID;
|
||||
}
|
||||
|
||||
void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||
@@ -697,7 +765,8 @@ void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||
memcpy(source, s.c_str(), s.size());
|
||||
}
|
||||
|
||||
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) const {
|
||||
std::optional<std::string>
|
||||
BluetoothAdapter::GetGenericBluetoothAdapterInstanceID() const {
|
||||
unsigned i;
|
||||
CONFIGRET r;
|
||||
HDEVINFO hDevInfo;
|
||||
@@ -713,9 +782,9 @@ char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) const {
|
||||
SetupDiGetClassDevsA(&GUID_DEVCLASS_BLUETOOTH, NULL, NULL, DIGCF_PRESENT);
|
||||
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not find BluetoothDevice on this machine";
|
||||
return NULL;
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Could not find BluetoothDevice on this machine";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Get first Generic Bluetooth Adapter InstanceID
|
||||
@@ -741,34 +810,34 @@ char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) const {
|
||||
// computer's USB ports.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/bluetooth/bluetooth-host-radio-support
|
||||
if (strncmp("USB", deviceInstanceID, 3) == 0) {
|
||||
return deviceInstanceID;
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return std::string(deviceInstanceID);
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get the generic bluetooth adapter id";
|
||||
|
||||
return NULL;
|
||||
LOG(ERROR) << __func__ << ": Failed to get the generic bluetooth adapter id";
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Returns BT MAC address assigned to this adapter.
|
||||
std::string BluetoothAdapter::GetMacAddress() const {
|
||||
if (windows_bluetooth_adapter_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
LOG(ERROR) << __func__ << ": No Bluetooth adapter on this device.";
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return uint64_to_mac_address_string(
|
||||
windows_bluetooth_adapter_.BluetoothAddress());
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
LOG(ERROR) << __func__ << ": exception:" << exception.what();
|
||||
return "";
|
||||
} catch (const winrt::hresult_error &ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": exception:" << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
return "";
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": unknown error.";
|
||||
LOG(ERROR) << __func__ << ": unknown error.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -794,9 +863,8 @@ std::string BluetoothAdapter::GetNameFromRegistry(PHKEY hKey) const {
|
||||
// size of the buffer pointed to by the lpData
|
||||
// parameter, in bytes.
|
||||
if (status != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get the required size of the local name buffer";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get the required size of the local name buffer";
|
||||
return "";
|
||||
}
|
||||
unsigned char *local_name = new unsigned char[local_name_size];
|
||||
@@ -834,7 +902,7 @@ std::string BluetoothAdapter::GetNameFromComputerName() const {
|
||||
return std::string(computer_name);
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get any computer name";
|
||||
LOG(ERROR) << __func__ << ": Failed to get any computer name";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ using WindowsBluetoothAdapter =
|
||||
|
||||
// Represents a radio device on the system.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio?view=winrt-20348
|
||||
using winrt::Windows::Devices::Radios::IRadio;
|
||||
using winrt::Windows::Devices::Radios::Radio;
|
||||
|
||||
// Enumeration that describes possible radio states.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radiostate?view=winrt-20348
|
||||
@@ -98,6 +98,16 @@ class BluetoothAdapter : public api::BluetoothAdapter {
|
||||
// Returns true if the Bluetooth hardware supports Bluetooth 5.0 Extended
|
||||
// Advertising
|
||||
bool IsExtendedAdvertisingSupported() const;
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE Central Role
|
||||
bool IsCentralRoleSupported() const;
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE Peripheral Role
|
||||
bool IsPeripheralRoleSupported() const;
|
||||
|
||||
// Returns true if the Bluetooth hardware supports BLE
|
||||
bool IsLowEnergySupported() const;
|
||||
|
||||
void RestoreRadioNameIfNecessary();
|
||||
|
||||
private:
|
||||
@@ -105,11 +115,11 @@ class BluetoothAdapter : public api::BluetoothAdapter {
|
||||
void StoreRadioNames(absl::string_view original_radio_name,
|
||||
absl::string_view nearby_radio_name);
|
||||
|
||||
WindowsBluetoothAdapter windows_bluetooth_adapter_;
|
||||
WindowsBluetoothAdapter windows_bluetooth_adapter_ = nullptr;
|
||||
std::string registry_bluetooth_adapter_name_;
|
||||
|
||||
IRadio windows_bluetooth_radio_;
|
||||
char *GetGenericBluetoothAdapterInstanceID() const;
|
||||
Radio windows_bluetooth_radio_ = nullptr;
|
||||
std::optional<std::string> GetGenericBluetoothAdapterInstanceID() const;
|
||||
void find_and_replace(char *source, const char *strFind,
|
||||
const char *strReplace) const;
|
||||
ScanMode scan_mode_ = ScanMode::kNone;
|
||||
|
||||
@@ -183,6 +183,21 @@ TEST(BluetoothAdapter, DISABLED_IsExtendedAdvertisingSupported) {
|
||||
EXPECT_TRUE(bluetooth_adapter.IsExtendedAdvertisingSupported());
|
||||
}
|
||||
|
||||
TEST(BluetoothAdapter, DISABLED_IsCentralRoleSupported) {
|
||||
BluetoothAdapter bluetooth_adapter;
|
||||
EXPECT_TRUE(bluetooth_adapter.IsCentralRoleSupported());
|
||||
}
|
||||
|
||||
TEST(BluetoothAdapter, DISABLED_IsPeripheralRoleSupported) {
|
||||
BluetoothAdapter bluetooth_adapter;
|
||||
EXPECT_TRUE(bluetooth_adapter.IsPeripheralRoleSupported());
|
||||
}
|
||||
|
||||
TEST(BluetoothAdapter, DISABLED_IsLowEnergySupported) {
|
||||
BluetoothAdapter bluetooth_adapter;
|
||||
EXPECT_TRUE(bluetooth_adapter.IsLowEnergySupported());
|
||||
}
|
||||
|
||||
TEST(BluetoothAdapter, DISABLED_GetNameFromComputerName) {
|
||||
BluetoothAdapter bluetooth_adapter;
|
||||
EXPECT_TRUE(!bluetooth_adapter.GetNameFromComputerName().empty());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
#include <winstring.h>
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <codecvt>
|
||||
#include <exception>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
@@ -34,9 +39,11 @@
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
constexpr int kBluetoothTimeoutInSeconds = 10;
|
||||
|
||||
using ::winrt::Windows::Foundation::TimeSpan;
|
||||
|
||||
constexpr int kBluetoothTimeoutInSeconds = 10;
|
||||
constexpr int kCheckBluetoothServiceMaxTimes = 3;
|
||||
constexpr absl::Duration kCheckBluetoothServiceInterval = absl::Seconds(1);
|
||||
} // namespace
|
||||
|
||||
BluetoothDevice::~BluetoothDevice() {}
|
||||
@@ -71,10 +78,16 @@ std::string BluetoothDevice::GetMacAddress() const { return mac_address_; }
|
||||
|
||||
// Checks cache first, will check uncached if no result.
|
||||
RfcommDeviceService BluetoothDevice::GetRfcommServiceForIdAsync(
|
||||
const RfcommServiceId serviceId) {
|
||||
RfcommServiceId serviceId) {
|
||||
if (nearby::NearbyFlags::GetInstance().GetBoolFlag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableNewBluetoothRefactor)) {
|
||||
return GetRfcommServiceForIdWithRetryAsync(serviceId);
|
||||
}
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Get RF services for service id:"
|
||||
<< winrt::to_string(serviceId.AsString());
|
||||
LOG(INFO) << __func__ << ": Get RF services for service id:"
|
||||
<< winrt::to_string(serviceId.AsString());
|
||||
|
||||
RfcommDeviceServicesResult rfcomm_device_services = nullptr;
|
||||
// Try to get service from un cached mode.
|
||||
@@ -88,13 +101,12 @@ RfcommDeviceService BluetoothDevice::GetRfcommServiceForIdAsync(
|
||||
rfcomm_device_services = rfcomm_device_services_async.GetResults();
|
||||
break;
|
||||
case winrt::Windows::Foundation::AsyncStatus::Started:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get RfcommDeviceService due to timeout.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get RfcommDeviceService due to timeout.";
|
||||
rfcomm_device_services_async.Cancel();
|
||||
return nullptr;
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
LOG(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get RfcommDeviceService due to unknown reasons.";
|
||||
return nullptr;
|
||||
@@ -102,35 +114,106 @@ RfcommDeviceService BluetoothDevice::GetRfcommServiceForIdAsync(
|
||||
|
||||
if (rfcomm_device_services != nullptr &&
|
||||
rfcomm_device_services.Services().Size() > 0) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Get "
|
||||
<< rfcomm_device_services.Services().Size()
|
||||
<< " services without cache.";
|
||||
LOG(INFO) << __func__ << ": Get "
|
||||
<< rfcomm_device_services.Services().Size()
|
||||
<< " services without cache.";
|
||||
// found the matched service.
|
||||
for (auto rfcomm_device_service : rfcomm_device_services.Services()) {
|
||||
if (rfcomm_device_service.Device() != nullptr &&
|
||||
winrt::to_string(rfcomm_device_service.Device().DeviceId()) ==
|
||||
id_) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__ << ": Found service from no-cache mode.";
|
||||
LOG(INFO) << __func__ << ": Found service from no-cache mode.";
|
||||
return rfcomm_device_service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get RfcommDeviceService due to no any services.";
|
||||
return nullptr;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get RfcommDeviceService: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get RfcommDeviceService: " << exception.what();
|
||||
return nullptr;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": RfcommDeviceService: " << ex.code()
|
||||
<< ", error message: " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": RfcommDeviceService: " << ex.code()
|
||||
<< ", error message: " << winrt::to_string(ex.message());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks cache first, will check uncached if no result.
|
||||
RfcommDeviceService BluetoothDevice::GetRfcommServiceForIdWithRetryAsync(
|
||||
RfcommServiceId serviceId) {
|
||||
int check_service_count = 0;
|
||||
while (check_service_count < kCheckBluetoothServiceMaxTimes) {
|
||||
try {
|
||||
LOG(INFO) << __func__ << ": Get RF services for service id:"
|
||||
<< winrt::to_string(serviceId.AsString());
|
||||
|
||||
RfcommDeviceServicesResult rfcomm_device_services = nullptr;
|
||||
// Try to get service from un cached mode.
|
||||
auto rfcomm_device_services_async =
|
||||
windows_bluetooth_device_.GetRfcommServicesForIdAsync(
|
||||
serviceId, BluetoothCacheMode::Uncached);
|
||||
|
||||
switch (rfcomm_device_services_async.wait_for(
|
||||
TimeSpan(std::chrono::seconds(kBluetoothTimeoutInSeconds)))) {
|
||||
case winrt::Windows::Foundation::AsyncStatus::Completed:
|
||||
rfcomm_device_services = rfcomm_device_services_async.GetResults();
|
||||
break;
|
||||
case winrt::Windows::Foundation::AsyncStatus::Started:
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get RfcommDeviceService due to timeout.";
|
||||
rfcomm_device_services_async.Cancel();
|
||||
return nullptr;
|
||||
default:
|
||||
LOG(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to get RfcommDeviceService due to unknown reasons.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (rfcomm_device_services != nullptr &&
|
||||
rfcomm_device_services.Services().Size() > 0) {
|
||||
LOG(INFO) << __func__ << ": Get "
|
||||
<< rfcomm_device_services.Services().Size()
|
||||
<< " services without cache.";
|
||||
// found the matched service.
|
||||
for (auto rfcomm_device_service : rfcomm_device_services.Services()) {
|
||||
if (rfcomm_device_service.Device() != nullptr &&
|
||||
winrt::to_string(rfcomm_device_service.Device().DeviceId()) ==
|
||||
id_) {
|
||||
LOG(INFO) << __func__ << ": Found service from no-cache mode.";
|
||||
return rfcomm_device_service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++check_service_count;
|
||||
absl::SleepFor(kCheckBluetoothServiceInterval);
|
||||
LOG(ERROR) << __func__ << ": No any services at " << check_service_count
|
||||
<< "th check.";
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get RfcommDeviceService: " << exception.what();
|
||||
return nullptr;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
LOG(ERROR) << __func__ << ": RfcommDeviceService: " << ex.code()
|
||||
<< ", error message: " << winrt::to_string(ex.message());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(ERROR) << __func__ << ": Failed to get RfcommDeviceService.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -77,10 +77,12 @@ class BluetoothDevice : public api::BluetoothDevice {
|
||||
void SetName(std::string name) { name_ = name; }
|
||||
|
||||
RfcommDeviceService GetRfcommServiceForIdAsync(
|
||||
const winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId
|
||||
serviceId);
|
||||
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId serviceId);
|
||||
|
||||
private:
|
||||
RfcommDeviceService GetRfcommServiceForIdWithRetryAsync(
|
||||
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId serviceId);
|
||||
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice windows_bluetooth_device_;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -14,11 +14,9 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_medium.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <codecvt>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
@@ -31,6 +29,8 @@
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
@@ -49,12 +49,31 @@
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
using winrt::Windows::Foundation::IInspectable;
|
||||
using winrt::Windows::Foundation::Collections::IMapView;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceAccessInformation;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceInformation;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceInformationKind;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceInformationUpdate;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceWatcher;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
using ::winrt::Windows::Foundation::IInspectable;
|
||||
using ::winrt::Windows::Foundation::Collections::IMapView;
|
||||
using ::winrt::Windows::Storage::Streams::DataReader;
|
||||
using ::winrt::Windows::Storage::Streams::DataWriter;
|
||||
using ::winrt::Windows::Storage::Streams::UnicodeEncoding;
|
||||
|
||||
// Used to cntrol the dump output for device information. It is only for debug
|
||||
// Used to control the dump output for device information. It is only for debug
|
||||
// purpose.
|
||||
constexpr bool kEnableDumpDeviceInfomation = false;
|
||||
// The maximum length of Bluetooth device name Android can discover.
|
||||
constexpr int kAndroidDiscoverableBluetoothNameMaxLength = 37; // bytes
|
||||
// Used to select bluetooth devices.
|
||||
constexpr wchar_t kBluetoothSelector[] =
|
||||
L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}"
|
||||
L"\"";
|
||||
|
||||
void DumpDeviceInformation(
|
||||
const IMapView<winrt::hstring, IInspectable>& properties) {
|
||||
@@ -68,31 +87,29 @@ void DumpDeviceInformation(
|
||||
|
||||
for (const auto& property : properties) {
|
||||
if (property.Key() == L"System.ItemNameDisplay") {
|
||||
NEARBY_LOGS(INFO) << "System.ItemNameDisplay: "
|
||||
<< InspectableReader::ReadString(property.Value());
|
||||
LOG(INFO) << "System.ItemNameDisplay: "
|
||||
<< InspectableReader::ReadString(property.Value());
|
||||
} else if (property.Key() == L"System.Devices.Aep.CanPair") {
|
||||
NEARBY_LOGS(INFO) << "System.Devices.Aep.CanPair: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
LOG(INFO) << "System.Devices.Aep.CanPair: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
} else if (property.Key() == L"System.Devices.Aep.IsPaired") {
|
||||
NEARBY_LOGS(INFO) << "System.Devices.Aep.IsPaired: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
LOG(INFO) << "System.Devices.Aep.IsPaired: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
} else if (property.Key() == L"System.Devices.Aep.IsPresent") {
|
||||
NEARBY_LOGS(INFO) << "System.Devices.Aep.IsPresent: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
LOG(INFO) << "System.Devices.Aep.IsPresent: "
|
||||
<< InspectableReader::ReadBoolean(property.Value());
|
||||
} else if (property.Key() == L"System.Devices.Aep.DeviceAddress") {
|
||||
NEARBY_LOGS(INFO) << "System.Devices.Aep.DeviceAddress: "
|
||||
<< InspectableReader::ReadString(property.Value());
|
||||
LOG(INFO) << "System.Devices.Aep.DeviceAddress: "
|
||||
<< InspectableReader::ReadString(property.Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
constexpr uint8_t kAndroidDiscoverableBluetoothNameMaxLength = 37; // bytes
|
||||
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(
|
||||
api::BluetoothAdapter& bluetoothAdapter)
|
||||
: bluetooth_adapter_(dynamic_cast<BluetoothAdapter&>(bluetoothAdapter)) {
|
||||
api::BluetoothAdapter& bluetooth_adapter)
|
||||
: bluetooth_adapter_(dynamic_cast<BluetoothAdapter&>(bluetooth_adapter)) {
|
||||
InitializeDeviceWatcher();
|
||||
bluetooth_adapter_.RestoreRadioNameIfNecessary();
|
||||
|
||||
@@ -103,17 +120,16 @@ BluetoothClassicMedium::BluetoothClassicMedium(
|
||||
BluetoothClassicMedium::~BluetoothClassicMedium() {}
|
||||
|
||||
void BluetoothClassicMedium::OnScanModeChanged(
|
||||
BluetoothAdapter::ScanMode scanMode) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": OnScanModeChanged is called with scanMode: "
|
||||
<< static_cast<int>(scanMode);
|
||||
BluetoothAdapter::ScanMode scan_mode) {
|
||||
LOG(INFO) << __func__ << ": OnScanModeChanged is called with scanMode: "
|
||||
<< static_cast<int>(scan_mode);
|
||||
|
||||
if (scanMode == scan_mode_) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": No change of scan mode.";
|
||||
if (scan_mode == scan_mode_) {
|
||||
LOG(INFO) << __func__ << ": No change of scan mode.";
|
||||
return;
|
||||
}
|
||||
|
||||
scan_mode_ = scanMode;
|
||||
scan_mode_ = scan_mode;
|
||||
bool radio_discoverable =
|
||||
scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
@@ -125,12 +141,12 @@ void BluetoothClassicMedium::OnScanModeChanged(
|
||||
}
|
||||
|
||||
if (is_radio_discoverable_ == radio_discoverable) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": No change of radio discovery.";
|
||||
LOG(INFO) << __func__ << ": No change of radio discovery.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (rfcomm_provider_ == nullptr) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": No advertising.";
|
||||
LOG(WARNING) << __func__ << ": No advertising.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -141,23 +157,22 @@ void BluetoothClassicMedium::OnScanModeChanged(
|
||||
is_radio_discoverable_ = radio_discoverable;
|
||||
return;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": OnScanModeChanged exception: " << exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": OnScanModeChanged exception: " << exception.what();
|
||||
return;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": OnScanModeChanged exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": OnScanModeChanged exception: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
return;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback) {
|
||||
NEARBY_LOGS(INFO) << "StartDiscovery is called.";
|
||||
LOG(INFO) << "StartDiscovery is called.";
|
||||
|
||||
bool result = false;
|
||||
discovery_callback_ = std::move(discovery_callback);
|
||||
@@ -170,7 +185,7 @@ bool BluetoothClassicMedium::StartDiscovery(
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
NEARBY_LOGS(INFO) << "StopDiscovery is called.";
|
||||
LOG(INFO) << "StopDiscovery is called.";
|
||||
|
||||
bool result = false;
|
||||
|
||||
@@ -184,14 +199,14 @@ bool BluetoothClassicMedium::StopDiscovery() {
|
||||
void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
try {
|
||||
// create watcher
|
||||
const winrt::param::iterable<winrt::hstring> RequestedProperties =
|
||||
const winrt::param::iterable<winrt::hstring> requested_properties =
|
||||
winrt::single_threaded_vector<winrt::hstring>(
|
||||
{winrt::to_hstring("System.Devices.Aep.IsPresent"),
|
||||
winrt::to_hstring("System.Devices.Aep.DeviceAddress")});
|
||||
|
||||
device_watcher_ = DeviceInformation::CreateWatcher(
|
||||
BLUETOOTH_SELECTOR, // aqsFilter
|
||||
RequestedProperties, // additionalProperties
|
||||
kBluetoothSelector, // aqsFilter
|
||||
requested_properties, // additionalProperties
|
||||
DeviceInformationKind::AssociationEndpoint); // kind
|
||||
|
||||
// An app must subscribe to all of the added, removed, and updated events
|
||||
@@ -217,14 +232,14 @@ void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
device_watcher_.Removed(
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Removed});
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": InitializeDeviceWatcher exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": InitializeDeviceWatcher exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": InitializeDeviceWatcher exception: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": InitializeDeviceWatcher exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,9 +247,9 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << "ConnectToService is called.";
|
||||
LOG(INFO) << "ConnectToService is called.";
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid not specified.";
|
||||
LOG(ERROR) << __func__ << ": service_uuid not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -246,83 +261,51 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
// Must check for valid pattern as the guid constructor will throw on an
|
||||
// invalid format
|
||||
if (!std::regex_match(service_uuid, pattern)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": invalid service_uuid: " << service_uuid;
|
||||
LOG(ERROR) << __func__ << ": invalid service_uuid: " << service_uuid;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::guid service(service_uuid);
|
||||
|
||||
if (cancellation_flag == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": cancellation_flag not specified.";
|
||||
LOG(ERROR) << __func__ << ": cancellation_flag not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
remote_device_to_connect_ =
|
||||
std::make_unique<BluetoothDevice>(remote_device.GetMacAddress());
|
||||
auto remote_device_to_connect_ = dynamic_cast<BluetoothDevice*>(
|
||||
GetRemoteDevice(remote_device.GetMacAddress()));
|
||||
|
||||
// First try, check if the remote device that we want to request connection
|
||||
// to has already been discovered by the Bluetooth Classic Device Watcher
|
||||
// beforehand inside the discovered_devices_by_id_ map
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
|
||||
it = discovered_devices_by_id_.find(
|
||||
winrt::to_hstring(remote_device_to_connect_->GetId()));
|
||||
|
||||
std::unique_ptr<BluetoothDevice> device = nullptr;
|
||||
BluetoothDevice* current_device = nullptr;
|
||||
|
||||
if (it != discovered_devices_by_id_.end()) {
|
||||
current_device = it->second.get();
|
||||
} else {
|
||||
// The remote device was not discovered by the Bluetooth Classic Device
|
||||
// Watcher beforehand.
|
||||
// Second try, request Windows to scan for nearby
|
||||
// bluetooth devices that has this static mac address again in this
|
||||
// instance
|
||||
auto remote_bluetooth_device_from_mac_address =
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::
|
||||
FromBluetoothAddressAsync(
|
||||
mac_address_string_to_uint64(remote_device.GetMacAddress()))
|
||||
.get();
|
||||
if (remote_bluetooth_device_from_mac_address == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Windows failed to get remote bluetooth device "
|
||||
"from static mac address.";
|
||||
return nullptr;
|
||||
}
|
||||
device = std::make_unique<BluetoothDevice>(
|
||||
remote_bluetooth_device_from_mac_address);
|
||||
current_device = device.get();
|
||||
}
|
||||
|
||||
if (current_device == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get current device.";
|
||||
if (remote_device_to_connect_ == nullptr ||
|
||||
remote_device_to_connect_->GetId().empty()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get remote device from MAC address.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::hstring device_id = winrt::to_hstring(current_device->GetId());
|
||||
winrt::hstring device_id =
|
||||
winrt::to_hstring(remote_device_to_connect_->GetId());
|
||||
|
||||
if (!HaveAccess(device_id)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to gain access to device: "
|
||||
<< winrt::to_string(device_id);
|
||||
LOG(ERROR) << __func__ << ": Failed to gain access to device: "
|
||||
<< winrt::to_string(device_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RfcommDeviceService requested_service(
|
||||
GetRequestedService(current_device, service));
|
||||
GetRequestedService(remote_device_to_connect_, service));
|
||||
|
||||
if (!FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.skip_service_discovery_before_connecting_to_rfcomm &&
|
||||
!CheckSdp(requested_service)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Invalid SDP.";
|
||||
LOG(ERROR) << __func__ << ": Invalid SDP.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto rfcomm_socket = std::make_unique<BluetoothSocket>();
|
||||
|
||||
if (cancellation_flag->Cancelled()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
LOG(INFO)
|
||||
<< __func__
|
||||
<< ": Bluetooth Classic socket connection cancelled for device: "
|
||||
<< winrt::to_string(device_id) << ", service: " << service_uuid;
|
||||
@@ -342,25 +325,25 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception connecting bluetooth async: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception connecting bluetooth async: "
|
||||
<< exception.what();
|
||||
return nullptr;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception connecting bluetooth async, error code: "
|
||||
<< ex.code()
|
||||
<< ", error message: " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception connecting bluetooth async, error code: "
|
||||
<< ex.code()
|
||||
<< ", error message: " << winrt::to_string(ex.message());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
api::BluetoothDevice& remote_device) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to createPairing with device: "
|
||||
<< remote_device.GetMacAddress();
|
||||
VLOG(1) << __func__ << ": Start to createPairing with device: "
|
||||
<< remote_device.GetMacAddress();
|
||||
try {
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice bluetooth_device =
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::
|
||||
@@ -374,18 +357,15 @@ std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
return std::make_unique<BluetoothPairing>(bluetooth_device,
|
||||
custom_pairing);
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to get DeviceInformationCustomPairing.";
|
||||
VLOG(1) << __func__ << ": Failed to get DeviceInformationCustomPairing.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << " : Failed to create pairing. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << " : Failed to create pairing. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to create pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to create pairing. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -420,39 +400,39 @@ bool BluetoothClassicMedium::HaveAccess(winrt::hstring device_id) {
|
||||
|
||||
RfcommDeviceService BluetoothClassicMedium::GetRequestedService(
|
||||
BluetoothDevice* device, winrt::guid service) {
|
||||
RfcommServiceId rfcommServiceId = RfcommServiceId::FromUuid(service);
|
||||
return device->GetRfcommServiceForIdAsync(rfcommServiceId);
|
||||
RfcommServiceId rfcomm_service_id = RfcommServiceId::FromUuid(service);
|
||||
return device->GetRfcommServiceForIdAsync(rfcomm_service_id);
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requested_service) {
|
||||
// Do various checks of the SDP record to make sure you are talking to a
|
||||
// device that actually supports the Bluetooth Rfcomm Service
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.getsdprawattributesasync?view=winrt-20348
|
||||
try {
|
||||
if (requestedService == nullptr) {
|
||||
if (requested_service == nullptr) {
|
||||
LOG(WARNING) << __func__ << ": Request service is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attributes = requestedService.GetSdpRawAttributesAsync().get();
|
||||
auto attributes = requested_service.GetSdpRawAttributesAsync().get();
|
||||
if (!attributes.HasKey(Constants::SdpServiceNameAttributeId)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Missing SdpServiceNameAttributeId.";
|
||||
LOG(ERROR) << __func__ << ": Missing SdpServiceNameAttributeId.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attributeReader = DataReader::FromBuffer(
|
||||
auto attribute_reader = DataReader::FromBuffer(
|
||||
attributes.Lookup(Constants::SdpServiceNameAttributeId));
|
||||
|
||||
auto attributeType = attributeReader.ReadByte();
|
||||
auto attribute_type = attribute_reader.ReadByte();
|
||||
|
||||
if (attributeType != Constants::SdpServiceNameAttributeType) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Missing SdpServiceNameAttributeType.";
|
||||
if (attribute_type != Constants::SdpServiceNameAttributeType) {
|
||||
LOG(ERROR) << __func__ << ": Missing SdpServiceNameAttributeType.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to get SDP information.";
|
||||
LOG(ERROR) << "Failed to get SDP information.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -469,15 +449,15 @@ bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
std::unique_ptr<api::BluetoothServerSocket>
|
||||
BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) {
|
||||
NEARBY_LOGS(INFO) << "ListenForService is called with service name: "
|
||||
<< service_name << ".";
|
||||
LOG(INFO) << "ListenForService is called with service name: " << service_name
|
||||
<< ".";
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid was empty.";
|
||||
LOG(ERROR) << __func__ << ": service_uuid was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (service_name.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_name was empty.";
|
||||
LOG(ERROR) << __func__ << ": service_name was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -486,15 +466,14 @@ BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
|
||||
scan_mode_ = bluetooth_adapter_.GetScanMode();
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": scan_mode: " << static_cast<int>(scan_mode_);
|
||||
LOG(INFO) << __func__ << ": scan_mode: " << static_cast<int>(scan_mode_);
|
||||
bool radio_discoverable =
|
||||
scan_mode_ == BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
bool result = StartAdvertising(radio_discoverable);
|
||||
|
||||
if (!result) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to start listening.";
|
||||
LOG(ERROR) << __func__ << ": Failed to start listening.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -503,19 +482,34 @@ BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
|
||||
api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
return new BluetoothDevice(mac_address);
|
||||
auto it = mac_address_to_bluetooth_device_map_.find(mac_address);
|
||||
|
||||
if (it == mac_address_to_bluetooth_device_map_.end()) {
|
||||
LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address
|
||||
<< " is not in list. create it";
|
||||
auto bluetooth_device = std::make_unique<BluetoothDevice>(mac_address);
|
||||
|
||||
mac_address_to_bluetooth_device_map_[mac_address] =
|
||||
std::move(bluetooth_device);
|
||||
return mac_address_to_bluetooth_device_map_[mac_address].get();
|
||||
}
|
||||
|
||||
LOG(INFO) << __func__ << ": Bluetooth device " << mac_address
|
||||
<< " is in cache";
|
||||
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartScanning() {
|
||||
if (!IsWatcherStarted()) {
|
||||
if (device_watcher_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to start scanning due to no available watcher.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to start scanning due to no available watcher.";
|
||||
return false;
|
||||
}
|
||||
|
||||
discovered_devices_by_id_.clear();
|
||||
mac_address_to_bluetooth_device_map_.clear();
|
||||
removed_bluetooth_devices_map_.clear();
|
||||
|
||||
// The Start method can only be called when the DeviceWatcher is in the
|
||||
// Created, Stopped or Aborted state.
|
||||
@@ -530,9 +524,8 @@ bool BluetoothClassicMedium::StartScanning() {
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to start scanning when watcher already started.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Attempted to start scanning when watcher already started.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -541,16 +534,15 @@ bool BluetoothClassicMedium::StopScanning() {
|
||||
device_watcher_.Stop();
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to stop scanning when watcher already stopped.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Attempted to stop scanning when watcher already stopped.";
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
DeviceWatcher sender, DeviceInformation deviceInfo) {
|
||||
NEARBY_LOGS(INFO) << "Device added " << winrt::to_string(deviceInfo.Id());
|
||||
IMapView<winrt::hstring, IInspectable> properties = deviceInfo.Properties();
|
||||
DeviceWatcher sender, DeviceInformation device_info) {
|
||||
LOG(INFO) << "Device added " << winrt::to_string(device_info.Id());
|
||||
IMapView<winrt::hstring, IInspectable> properties = device_info.Properties();
|
||||
DumpDeviceInformation(properties);
|
||||
|
||||
if (!IsWatcherStarted()) {
|
||||
@@ -559,85 +551,93 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
|
||||
// If device no item name, ignore it.
|
||||
if (!properties.HasKey(L"System.ItemNameDisplay")) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " due to no name.";
|
||||
LOG(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(device_info.Id()) << " due to no name.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
if (properties.Lookup(L"System.ItemNameDisplay") == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " due to empty name.";
|
||||
LOG(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(device_info.Id()) << " due to empty name.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
// If device doesn't support pair, ignore it.
|
||||
if (!properties.HasKey(L"System.Devices.Aep.CanPair")) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " due to no pair property.";
|
||||
LOG(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(device_info.Id())
|
||||
<< " due to no pair property.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
if (!InspectableReader::ReadBoolean(
|
||||
properties.Lookup(L"System.Devices.Aep.CanPair"))) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " due to not support pair.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
// Create an iterator for the internal list
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
|
||||
it = discovered_devices_by_id_.find(deviceInfo.Id());
|
||||
|
||||
// Add to our internal list if necessary
|
||||
if (it != discovered_devices_by_id_.end()) {
|
||||
// We're already tracking this one
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " is alreay added.";
|
||||
LOG(WARNING) << __func__ << ": Ignore the Bluetooth device "
|
||||
<< winrt::to_string(device_info.Id())
|
||||
<< " due to not support pair.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
// Create a bluetooth device out of this id
|
||||
auto bluetoothDevice =
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
deviceInfo.Id())
|
||||
auto native_bluetooth_device =
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
device_info.Id())
|
||||
.get();
|
||||
auto bluetoothDeviceP = std::make_unique<BluetoothDevice>(bluetoothDevice);
|
||||
|
||||
discovered_devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDeviceP);
|
||||
std::string mac_address =
|
||||
uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress());
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Notifying bluetooth device added";
|
||||
// Create an iterator for the internal list
|
||||
auto it = mac_address_to_bluetooth_device_map_.find(mac_address);
|
||||
|
||||
// Add to our internal list if necessary
|
||||
if (it != mac_address_to_bluetooth_device_map_.end()) {
|
||||
// We're already tracking this one
|
||||
LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address
|
||||
<< " is alreay added.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
auto bluetooth_device =
|
||||
std::make_unique<BluetoothDevice>(native_bluetooth_device);
|
||||
|
||||
mac_address_to_bluetooth_device_map_[mac_address] =
|
||||
std::move(bluetooth_device);
|
||||
|
||||
LOG(INFO) << __func__ << ": Notifying bluetooth device " << mac_address
|
||||
<< " added";
|
||||
if (discovery_callback_.device_discovered_cb != nullptr) {
|
||||
discovery_callback_.device_discovered_cb(
|
||||
*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
*mac_address_to_bluetooth_device_map_[mac_address]);
|
||||
}
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceAdded(*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
observer->DeviceAdded(*mac_address_to_bluetooth_device_map_[mac_address]);
|
||||
}
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
auto it = discovered_devices_by_id_.find(deviceInfoUpdate.Id());
|
||||
DeviceWatcher sender, DeviceInformationUpdate device_update_info) {
|
||||
auto native_bluetooth_device =
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
device_update_info.Id())
|
||||
.get();
|
||||
std::string mac_address =
|
||||
uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress());
|
||||
|
||||
if (it == discovered_devices_by_id_.end()) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Bluetooth device "
|
||||
<< winrt::to_string(deviceInfoUpdate.Id())
|
||||
<< " is not in list.";
|
||||
auto it = mac_address_to_bluetooth_device_map_.find(mac_address);
|
||||
|
||||
if (it == mac_address_to_bluetooth_device_map_.end()) {
|
||||
LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address
|
||||
<< " is not in list.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Device updated name: "
|
||||
<< discovered_devices_by_id_[deviceInfoUpdate.Id()]->GetName() << " ("
|
||||
<< winrt::to_string(deviceInfoUpdate.Id()) << ")";
|
||||
LOG(INFO) << "Device updated name: "
|
||||
<< mac_address_to_bluetooth_device_map_[mac_address]->GetName()
|
||||
<< " (" << mac_address << ")";
|
||||
IMapView<winrt::hstring, IInspectable> properties =
|
||||
deviceInfoUpdate.Properties();
|
||||
device_update_info.Properties();
|
||||
DumpDeviceInformation(properties);
|
||||
|
||||
if (!IsWatcherStarted()) {
|
||||
@@ -652,17 +652,15 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
properties.Lookup(L"System.ItemNameDisplay"));
|
||||
|
||||
if (it->second->GetName() == new_device_name) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Device name is same as old name, ignore the update.";
|
||||
LOG(INFO) << "Device name is same as old name, ignore the update.";
|
||||
} else {
|
||||
it->second->SetName(new_device_name);
|
||||
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Updated device name:"
|
||||
<< discovered_devices_by_id_[deviceInfoUpdate.Id()]->GetName();
|
||||
LOG(INFO) << "Updated device name:"
|
||||
<< mac_address_to_bluetooth_device_map_[mac_address]->GetName();
|
||||
|
||||
discovery_callback_.device_name_changed_cb(
|
||||
*discovered_devices_by_id_[deviceInfoUpdate.Id()]);
|
||||
*mac_address_to_bluetooth_device_map_[mac_address]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,12 +668,13 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
if (properties.HasKey(L"System.Devices.Aep.IsPaired")) {
|
||||
bool new_paired_status = InspectableReader::ReadBoolean(
|
||||
properties.Lookup(L"System.Devices.Aep.IsPaired"));
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Notifying device paired changed: " << std::boolalpha
|
||||
<< new_paired_status;
|
||||
LOG(INFO) << __func__
|
||||
<< ": Notifying device paired changed: " << std::boolalpha
|
||||
<< new_paired_status;
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DevicePairedChanged(
|
||||
*discovered_devices_by_id_[deviceInfoUpdate.Id()], new_paired_status);
|
||||
*mac_address_to_bluetooth_device_map_[mac_address],
|
||||
new_paired_status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,35 +682,47 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
|
||||
auto it = discovered_devices_by_id_.find(deviceInfo.Id());
|
||||
DeviceWatcher sender, DeviceInformationUpdate device_update_info) {
|
||||
auto native_bluetooth_device =
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
device_update_info.Id())
|
||||
.get();
|
||||
|
||||
if (it == discovered_devices_by_id_.end()) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Bluetooth device "
|
||||
<< winrt::to_string(deviceInfo.Id())
|
||||
<< " is not in list.";
|
||||
if (native_bluetooth_device == nullptr) {
|
||||
LOG(WARNING) << __func__ << ": cannot get native bluetooth device.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Device removed "
|
||||
<< discovered_devices_by_id_[deviceInfo.Id()]->GetName()
|
||||
<< " (" << winrt::to_string(deviceInfo.Id()) << ")";
|
||||
std::string mac_address =
|
||||
uint64_to_mac_address_string(native_bluetooth_device.BluetoothAddress());
|
||||
auto it = mac_address_to_bluetooth_device_map_.find(mac_address);
|
||||
|
||||
if (it == mac_address_to_bluetooth_device_map_.end()) {
|
||||
LOG(WARNING) << __func__ << ": Bluetooth device " << mac_address
|
||||
<< " is not in list.";
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Device removed "
|
||||
<< mac_address_to_bluetooth_device_map_[mac_address]->GetName()
|
||||
<< " (" << mac_address << ")";
|
||||
|
||||
if (!IsWatcherStarted()) {
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Notifying bluetooth device removed";
|
||||
LOG(INFO) << __func__ << ": Notifying bluetooth device removed";
|
||||
if (discovery_callback_.device_lost_cb != nullptr) {
|
||||
discovery_callback_.device_lost_cb(
|
||||
*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
*mac_address_to_bluetooth_device_map_[mac_address]);
|
||||
}
|
||||
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceRemoved(*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
observer->DeviceRemoved(*mac_address_to_bluetooth_device_map_[mac_address]);
|
||||
}
|
||||
|
||||
discovered_devices_by_id_.erase(deviceInfo.Id());
|
||||
auto node = mac_address_to_bluetooth_device_map_.extract(mac_address);
|
||||
removed_bluetooth_devices_map_[mac_address] = std::move(node.mapped());
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
@@ -738,23 +749,23 @@ bool BluetoothClassicMedium::IsWatcherRunning() {
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": StartAdvertising is called with radio_discoverable: "
|
||||
<< radio_discoverable << ".";
|
||||
LOG(INFO) << __func__
|
||||
<< ": StartAdvertising is called with radio_discoverable: "
|
||||
<< radio_discoverable << ".";
|
||||
|
||||
try {
|
||||
if (rfcomm_provider_ != nullptr &&
|
||||
is_radio_discoverable_ == radio_discoverable) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": Ignore StartAdvertising due to no change to "
|
||||
"current advertising.";
|
||||
LOG(WARNING) << __func__
|
||||
<< ": Ignore StartAdvertising due to no change to "
|
||||
"current advertising.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rfcomm_provider_ != nullptr && !StopAdvertising()) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": Failed to StartAdvertising due to cannot stop "
|
||||
"running advertising.";
|
||||
LOG(WARNING) << __func__
|
||||
<< ": Failed to StartAdvertising due to cannot stop "
|
||||
"running advertising.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -769,9 +780,8 @@ bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
raw_server_socket_ = server_socket_.get();
|
||||
|
||||
if (!server_socket_->listen()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to StartAdvertising due to cannot start socket.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to StartAdvertising due to cannot start socket.";
|
||||
server_socket_->Close();
|
||||
server_socket_ = nullptr;
|
||||
rfcomm_provider_ = nullptr;
|
||||
@@ -788,13 +798,13 @@ bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
radio_discoverable);
|
||||
is_radio_discoverable_ = radio_discoverable;
|
||||
|
||||
NEARBY_LOGS(INFO) << ": StartListening completed successfully.";
|
||||
LOG(INFO) << ": StartListening completed successfully.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception setting up for listen: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Exception setting up for listen: " << exception.what();
|
||||
|
||||
if (server_socket_ != nullptr) {
|
||||
server_socket_->Close();
|
||||
@@ -807,9 +817,8 @@ bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Exception setting up for listen: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": Exception setting up for listen: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
if (server_socket_ != nullptr) {
|
||||
server_socket_->Close();
|
||||
server_socket_ = nullptr;
|
||||
@@ -821,7 +830,7 @@ bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
if (server_socket_ != nullptr) {
|
||||
server_socket_->Close();
|
||||
server_socket_ = nullptr;
|
||||
@@ -836,12 +845,12 @@ bool BluetoothClassicMedium::StartAdvertising(bool radio_discoverable) {
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopAdvertising() {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": StopAdvertising is called";
|
||||
LOG(INFO) << __func__ << ": StopAdvertising is called";
|
||||
|
||||
try {
|
||||
if (rfcomm_provider_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Ignore StopAdvertising due to no advertising.";
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Ignore StopAdvertising due to no advertising.";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -850,19 +859,18 @@ bool BluetoothClassicMedium::StopAdvertising() {
|
||||
raw_server_socket_ = nullptr;
|
||||
server_socket_ = nullptr;
|
||||
|
||||
NEARBY_LOGS(INFO) << ": StopAdvertising completed successfully.";
|
||||
LOG(INFO) << ": StopAdvertising completed successfully.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": StopAdvertising exception: " << exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": StopAdvertising exception: " << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": StopAdvertising exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
LOG(ERROR) << __func__ << ": StopAdvertising exception: " << ex.code()
|
||||
<< ": " << winrt::to_string(ex.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -870,26 +878,25 @@ bool BluetoothClassicMedium::StopAdvertising() {
|
||||
bool BluetoothClassicMedium::InitializeServiceSdpAttributes(
|
||||
RfcommServiceProvider rfcomm_provider, std::string service_name) {
|
||||
try {
|
||||
auto sdpWriter = DataWriter();
|
||||
auto sdp_writer = DataWriter();
|
||||
|
||||
// Write the Service Name Attribute.
|
||||
sdpWriter.WriteByte(Constants::SdpServiceNameAttributeType);
|
||||
sdp_writer.WriteByte(Constants::SdpServiceNameAttributeType);
|
||||
|
||||
// The length of the UTF-8 encoded Service Name SDP Attribute.
|
||||
sdpWriter.WriteByte(service_name.size());
|
||||
sdp_writer.WriteByte(service_name.size());
|
||||
|
||||
// The UTF-8 encoded Service Name value.
|
||||
sdpWriter.UnicodeEncoding(UnicodeEncoding::Utf8);
|
||||
sdpWriter.WriteString(winrt::to_hstring(service_name));
|
||||
sdp_writer.UnicodeEncoding(UnicodeEncoding::Utf8);
|
||||
sdp_writer.WriteString(winrt::to_hstring(service_name));
|
||||
|
||||
// Set the SDP Attribute on the RFCOMM Service Provider.
|
||||
rfcomm_provider.SdpRawAttributes().Insert(
|
||||
Constants::SdpServiceNameAttributeId, sdpWriter.DetachBuffer());
|
||||
Constants::SdpServiceNameAttributeId, sdp_writer.DetachBuffer());
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to InitializeServiceSdpAttributes.";
|
||||
LOG(ERROR) << __func__ << ": Failed to InitializeServiceSdpAttributes.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,11 +15,15 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
@@ -32,76 +36,11 @@
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Represents a device. This class allows access to well-known device properties
|
||||
// as well as additional properties specified during device enumeration.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformation;
|
||||
|
||||
// Represents the kind of DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationkind?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationKind;
|
||||
|
||||
// Contains updated properties for a DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationupdate?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationUpdate;
|
||||
|
||||
// Enumerates devices dynamically, so that the app receives notifications if
|
||||
// devices are added, removed, or changed after the initial enumeration is
|
||||
// complete.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcher;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Specifies the type of character encoding for a stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.unicodeencoding?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::UnicodeEncoding;
|
||||
|
||||
// Describes the state of a DeviceWatcher object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcherstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
|
||||
// Represents an instance of a service on a Bluetooth basic rate device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService;
|
||||
|
||||
// Indicates the status of the access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||
|
||||
// Contains the information about access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessInformation;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Represents an instance of a local RFCOMM service.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceprovider?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Bluetooth protocol ID = \"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids
|
||||
#define BLUETOOTH_SELECTOR \
|
||||
L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\""
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
explicit BluetoothClassicMedium(api::BluetoothAdapter& bluetoothAdapter);
|
||||
|
||||
explicit BluetoothClassicMedium(api::BluetoothAdapter& bluetooth_adapter);
|
||||
~BluetoothClassicMedium() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
|
||||
@@ -166,56 +105,67 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
bool StopScanning();
|
||||
bool StartAdvertising(bool radio_discoverable);
|
||||
bool StopAdvertising();
|
||||
bool InitializeServiceSdpAttributes(RfcommServiceProvider rfcomm_provider,
|
||||
std::string service_name);
|
||||
bool InitializeServiceSdpAttributes(
|
||||
::winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider
|
||||
rfcomm_provider,
|
||||
std::string service_name);
|
||||
bool IsWatcherStarted();
|
||||
bool IsWatcherRunning();
|
||||
void InitializeDeviceWatcher();
|
||||
void OnScanModeChanged(BluetoothAdapter::ScanMode scanMode);
|
||||
void OnScanModeChanged(BluetoothAdapter::ScanMode scan_mode);
|
||||
|
||||
// This is for a coroutine whose return type is winrt::fire_and_forget, which
|
||||
// handles async operations which don't have any dependencies.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/fire-and-forget
|
||||
winrt::fire_and_forget DeviceWatcher_Added(DeviceWatcher sender,
|
||||
DeviceInformation deviceInfo);
|
||||
winrt::fire_and_forget DeviceWatcher_Added(
|
||||
::winrt::Windows::Devices::Enumeration::DeviceWatcher sender,
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformation device_info);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
::winrt::Windows::Devices::Enumeration::DeviceWatcher sender,
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformationUpdate
|
||||
device_update_info);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
::winrt::Windows::Devices::Enumeration::DeviceWatcher sender,
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformationUpdate
|
||||
device_update_info);
|
||||
|
||||
// Check to make sure we can connect if we try
|
||||
bool HaveAccess(winrt::hstring deviceId);
|
||||
bool HaveAccess(::winrt::hstring device_id);
|
||||
|
||||
// Get the service requested
|
||||
RfcommDeviceService GetRequestedService(BluetoothDevice* device,
|
||||
winrt::guid service);
|
||||
::winrt::guid service);
|
||||
|
||||
// Check to see that the device actually handles the requested service
|
||||
bool CheckSdp(RfcommDeviceService requestedService);
|
||||
bool CheckSdp(RfcommDeviceService requested_service);
|
||||
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback_;
|
||||
|
||||
DeviceWatcher device_watcher_ = nullptr;
|
||||
::winrt::Windows::Devices::Enumeration::DeviceWatcher device_watcher_ =
|
||||
nullptr;
|
||||
|
||||
std::unique_ptr<BluetoothSocket> bluetooth_socket_;
|
||||
|
||||
std::string service_name_;
|
||||
std::string service_uuid_;
|
||||
|
||||
// hstring is the only type of string winrt understands.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>
|
||||
discovered_devices_by_id_;
|
||||
// Map MAC address to bluetooth device.
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<BluetoothDevice>>
|
||||
mac_address_to_bluetooth_device_map_;
|
||||
|
||||
// Track removed devices.
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<BluetoothDevice>>
|
||||
removed_bluetooth_devices_map_;
|
||||
|
||||
BluetoothAdapter& bluetooth_adapter_;
|
||||
|
||||
BluetoothAdapter::ScanMode scan_mode_ = BluetoothAdapter::ScanMode::kUnknown;
|
||||
std::unique_ptr<BluetoothDevice> remote_device_to_connect_;
|
||||
|
||||
// Used for advertising.
|
||||
RfcommServiceProvider rfcomm_provider_ = nullptr;
|
||||
::winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider
|
||||
rfcomm_provider_ = nullptr;
|
||||
std::unique_ptr<BluetoothServerSocket> server_socket_ = nullptr;
|
||||
BluetoothServerSocket* raw_server_socket_ = nullptr;
|
||||
bool is_radio_discoverable_ = false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -20,12 +20,24 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_socket.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
using ::winrt::Windows::Networking::Sockets::SocketProtectionLevel;
|
||||
using ::winrt::Windows::Networking::Sockets::SocketQualityOfService;
|
||||
using ::winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
using ::winrt::Windows::Networking::Sockets::StreamSocketListener;
|
||||
using ::winrt::Windows::Networking::Sockets::
|
||||
StreamSocketListenerConnectionReceivedEventArgs;
|
||||
} // namespace
|
||||
|
||||
BluetoothServerSocket::BluetoothServerSocket(absl::string_view service_name)
|
||||
: service_name_(service_name) {}
|
||||
@@ -40,7 +52,7 @@ BluetoothServerSocket::~BluetoothServerSocket() { Close(); }
|
||||
// Once error is reported, it is permanent, and ServerSocket has to be closed.
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Accept is called.";
|
||||
LOG(INFO) << __func__ << ": Accept is called.";
|
||||
|
||||
while (!closed_ && pending_sockets_.empty()) {
|
||||
cond_.Wait(&mutex_);
|
||||
@@ -50,7 +62,7 @@ std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
|
||||
StreamSocket bluetooth_socket = pending_sockets_.front();
|
||||
pending_sockets_.pop_front();
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Accepted a remote connection.";
|
||||
LOG(INFO) << __func__ << ": Accepted a remote connection.";
|
||||
return std::make_unique<BluetoothSocket>(bluetooth_socket);
|
||||
}
|
||||
|
||||
@@ -63,7 +75,7 @@ void BluetoothServerSocket::SetCloseNotifier(
|
||||
Exception BluetoothServerSocket::Close() {
|
||||
try {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close is called.";
|
||||
LOG(INFO) << __func__ << ": Close is called.";
|
||||
|
||||
if (closed_) {
|
||||
return {Exception::kSuccess};
|
||||
@@ -87,23 +99,23 @@ Exception BluetoothServerSocket::Close() {
|
||||
close_notifier_();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close completed succesfully.";
|
||||
LOG(INFO) << __func__ << ": Close completed succesfully.";
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
@@ -129,12 +141,12 @@ bool BluetoothServerSocket::listen() {
|
||||
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -144,7 +156,7 @@ bool BluetoothServerSocket::listen() {
|
||||
StreamSocketListener listener,
|
||||
StreamSocketListenerConnectionReceivedEventArgs const& args) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Received connection.";
|
||||
LOG(INFO) << __func__ << ": Received connection.";
|
||||
|
||||
if (closed_) {
|
||||
return ::winrt::fire_and_forget{};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_socket.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/base.h"
|
||||
@@ -30,28 +31,9 @@
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Supports listening for an incoming network connection using Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistener?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::StreamSocketListener;
|
||||
|
||||
// Provides data for a ConnectionReceived event on a StreamSocketListener
|
||||
// object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistenerconnectionreceivedeventargs?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::
|
||||
StreamSocketListenerConnectionReceivedEventArgs;
|
||||
|
||||
// Specifies the quality of service for a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketqualityofservice?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::SocketQualityOfService;
|
||||
|
||||
// Specifies the level of encryption to use on a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel?view=winrt-22000
|
||||
using winrt::Windows::Networking::Sockets::SocketProtectionLevel;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html.
|
||||
class BluetoothServerSocket : public api::BluetoothServerSocket {
|
||||
public:
|
||||
BluetoothServerSocket(absl::string_view service_name);
|
||||
explicit BluetoothServerSocket(absl::string_view service_name);
|
||||
|
||||
~BluetoothServerSocket() override;
|
||||
|
||||
@@ -77,24 +59,28 @@ class BluetoothServerSocket : public api::BluetoothServerSocket {
|
||||
|
||||
bool listen();
|
||||
|
||||
const StreamSocketListener& stream_socket_listener() const {
|
||||
const ::winrt::Windows::Networking::Sockets::StreamSocketListener&
|
||||
stream_socket_listener() const {
|
||||
return stream_socket_listener_;
|
||||
}
|
||||
|
||||
private:
|
||||
// The listener is accepting incoming connections
|
||||
::winrt::fire_and_forget Listener_ConnectionReceived(
|
||||
StreamSocketListener listener,
|
||||
StreamSocketListenerConnectionReceivedEventArgs const& args);
|
||||
::winrt::Windows::Networking::Sockets::StreamSocketListener listener,
|
||||
::winrt::Windows::Networking::Sockets::
|
||||
StreamSocketListenerConnectionReceivedEventArgs const& args);
|
||||
|
||||
// Retrieves IP addresses from local machine
|
||||
std::vector<std::string> GetIpAddresses() const;
|
||||
|
||||
mutable absl::Mutex mutex_;
|
||||
absl::CondVar cond_;
|
||||
std::deque<StreamSocket> pending_sockets_ ABSL_GUARDED_BY(mutex_);
|
||||
StreamSocketListener stream_socket_listener_{nullptr};
|
||||
winrt::event_token listener_event_token_{};
|
||||
std::deque<::winrt::Windows::Networking::Sockets::StreamSocket>
|
||||
pending_sockets_ ABSL_GUARDED_BY(mutex_);
|
||||
::winrt::Windows::Networking::Sockets::StreamSocketListener
|
||||
stream_socket_listener_{nullptr};
|
||||
::winrt::event_token listener_event_token_{};
|
||||
|
||||
// Close notifier
|
||||
absl::AnyInvocable<void()> close_notifier_ = nullptr;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_socket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -21,32 +22,46 @@
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/base.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "winrt/Windows.Networking.Sockets.h"
|
||||
#include "winrt/base.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
using ::winrt::Windows::Devices::Bluetooth::BluetoothConnectionStatus;
|
||||
using ::winrt::Windows::Networking::HostName;
|
||||
using ::winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
using ::winrt::Windows::Storage::Streams::Buffer;
|
||||
using ::winrt::Windows::Storage::Streams::IInputStream;
|
||||
using ::winrt::Windows::Storage::Streams::InputStreamOptions;
|
||||
using ::winrt::Windows::Storage::Streams::IOutputStream;
|
||||
|
||||
constexpr int kMaxConnectRetryCount = 3;
|
||||
constexpr absl::Duration kConnectInterval = absl::Seconds(3);
|
||||
} // namespace
|
||||
|
||||
BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
|
||||
: windows_socket_(streamSocket) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Initialize bluetooth socket.";
|
||||
BluetoothSocket::BluetoothSocket(StreamSocket stream_socket)
|
||||
: windows_socket_(stream_socket) {
|
||||
LOG(INFO) << __func__ << ": Initialize bluetooth socket.";
|
||||
native_bluetooth_device_ =
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
windows_socket_.Information().RemoteHostName())
|
||||
.get();
|
||||
if (FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.enable_bluetooth_connection_status_track) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Flag enable_bluetooth_connection_status_track is enabled.";
|
||||
LOG(INFO) << "Flag enable_bluetooth_connection_status_track is enabled.";
|
||||
connection_status_changed_token_ =
|
||||
native_bluetooth_device_.ConnectionStatusChanged(
|
||||
{this, &BluetoothSocket::Listener_ConnectionStatusChanged});
|
||||
@@ -78,7 +93,7 @@ OutputStream& BluetoothSocket::GetOutputStream() { return output_stream_; }
|
||||
// After this call object should be treated as not connected.
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception BluetoothSocket::Close() {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close bluetooth socket.";
|
||||
LOG(INFO) << __func__ << ": Close bluetooth socket.";
|
||||
|
||||
// The Close method aborts any pending operations and releases all unmanaged
|
||||
// resources associated with the StreamSocket object, including the Input and
|
||||
@@ -103,14 +118,14 @@ Exception BluetoothSocket::Close() {
|
||||
is_bluetooth_socket_closed_ = true;
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
@@ -125,26 +140,37 @@ api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() {
|
||||
// Starts an asynchronous operation on a StreamSocket object to connect to a
|
||||
// remote network destination specified by a remote hostname and a remote
|
||||
// service name.
|
||||
bool BluetoothSocket::Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": start to connect to bluetooth service:"
|
||||
<< winrt::to_string(connectionServiceName);
|
||||
bool BluetoothSocket::Connect(HostName connection_host_name,
|
||||
::winrt::hstring connection_service_name) {
|
||||
LOG(INFO) << __func__ << ": start to connect to bluetooth service:"
|
||||
<< winrt::to_string(connection_service_name);
|
||||
|
||||
connect_called_count_ = 0;
|
||||
while (connect_called_count_ < kMaxConnectRetryCount) {
|
||||
connect_called_count_ += 1;
|
||||
if (nearby::NearbyFlags::GetInstance().GetBoolFlag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableNewBluetoothRefactor)) {
|
||||
bool connect_result =
|
||||
InternalConnect(connectionHostName, connectionServiceName);
|
||||
InternalConnect(connection_host_name, connection_service_name);
|
||||
if (connect_result) {
|
||||
return connect_result;
|
||||
}
|
||||
} else {
|
||||
int connect_called_count = 0;
|
||||
while (connect_called_count < kMaxConnectRetryCount) {
|
||||
connect_called_count += 1;
|
||||
bool connect_result =
|
||||
InternalConnect(connection_host_name, connection_service_name);
|
||||
if (connect_result) {
|
||||
return connect_result;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Failed to connect bluetooth at the "
|
||||
<< connect_called_count_ << "th call.";
|
||||
LOG(WARNING) << __func__ << ": Failed to connect bluetooth at the "
|
||||
<< connect_called_count << "th call.";
|
||||
|
||||
absl::SleepFor(kConnectInterval);
|
||||
absl::SleepFor(kConnectInterval);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(WARNING) << __func__ << ": Failed to connect bluetooth";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,14 +183,13 @@ ExceptionOr<ByteArray> BluetoothSocket::BluetoothInputStream::Read(
|
||||
std::int64_t size) {
|
||||
try {
|
||||
if (size <= 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Invalid transmit packet size: " << size;
|
||||
LOG(ERROR) << __func__ << ": Invalid transmit packet size: " << size;
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
if (size > read_buffer_.Capacity()) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": resize receive buffer to packet size: " << size;
|
||||
LOG(WARNING) << __func__
|
||||
<< ": resize receive buffer to packet size: " << size;
|
||||
read_buffer_ = Buffer(size);
|
||||
}
|
||||
|
||||
@@ -176,27 +201,27 @@ ExceptionOr<ByteArray> BluetoothSocket::BluetoothInputStream::Read(
|
||||
.get();
|
||||
|
||||
if (ibuffer.Length() != size) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Got " << ibuffer.Length()
|
||||
<< " bytes of total " << size << " bytes.";
|
||||
LOG(WARNING) << __func__ << ": Got " << ibuffer.Length()
|
||||
<< " bytes of total " << size << " bytes.";
|
||||
}
|
||||
|
||||
ByteArray data((char*)ibuffer.data(), ibuffer.Length());
|
||||
return ExceptionOr(data);
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothInputStream::Close() {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close bluetooth input stream.";
|
||||
LOG(INFO) << __func__ << ": Close bluetooth input stream.";
|
||||
|
||||
try {
|
||||
if (winrt_input_stream_ != nullptr) {
|
||||
@@ -204,14 +229,14 @@ Exception BluetoothSocket::BluetoothInputStream::Close() {
|
||||
}
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
@@ -224,9 +249,8 @@ BluetoothSocket::BluetoothOutputStream::BluetoothOutputStream(
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Write(const ByteArray& data) {
|
||||
try {
|
||||
if (data.size() > write_buffer_.Capacity()) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": resize write buffer to packet size: "
|
||||
<< data.size();
|
||||
LOG(WARNING) << __func__
|
||||
<< ": resize write buffer to packet size: " << data.size();
|
||||
write_buffer_ = Buffer(data.size());
|
||||
}
|
||||
|
||||
@@ -237,14 +261,14 @@ Exception BluetoothSocket::BluetoothOutputStream::Write(const ByteArray& data) {
|
||||
winrt_output_stream_.WriteAsync(write_buffer_).get();
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
@@ -258,59 +282,56 @@ Exception BluetoothSocket::BluetoothOutputStream::Flush() {
|
||||
winrt_output_stream_.FlushAsync().get();
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Close() {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close bluetooth output stream.";
|
||||
LOG(INFO) << __func__ << ": Close bluetooth output stream.";
|
||||
try {
|
||||
if (winrt_output_stream_ != nullptr) {
|
||||
winrt_output_stream_.Close();
|
||||
}
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothSocket::InternalConnect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName) {
|
||||
bool BluetoothSocket::InternalConnect(HostName connection_host_name,
|
||||
winrt::hstring connection_service_name) {
|
||||
try {
|
||||
if (connectionHostName == nullptr || connectionServiceName.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Bluetooth socket connection failed. Attempting to "
|
||||
"connect to empty HostName/MAC address or ServiceName.";
|
||||
if (connection_host_name == nullptr || connection_service_name.empty()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Bluetooth socket connection failed. Attempting to "
|
||||
"connect to empty HostName/MAC address or ServiceName.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Bluetooth socket connection to host name:"
|
||||
<< winrt::to_string(connectionHostName.DisplayName())
|
||||
<< ", service name:"
|
||||
<< winrt::to_string(connectionServiceName);
|
||||
LOG(INFO) << __func__ << ": Bluetooth socket connection to host name:"
|
||||
<< winrt::to_string(connection_host_name.DisplayName())
|
||||
<< ", service name:" << winrt::to_string(connection_service_name);
|
||||
|
||||
windows_socket_ = winrt::Windows::Networking::Sockets::StreamSocket();
|
||||
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.connectasync?view=winrt-20348
|
||||
windows_socket_.ConnectAsync(connectionHostName, connectionServiceName)
|
||||
windows_socket_.ConnectAsync(connection_host_name, connection_service_name)
|
||||
.get();
|
||||
|
||||
auto info = windows_socket_.Information();
|
||||
@@ -324,8 +345,7 @@ bool BluetoothSocket::InternalConnect(HostName connectionHostName,
|
||||
if (FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.enable_bluetooth_connection_status_track) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Flag enable_bluetooth_connection_status_track is enabled.";
|
||||
LOG(INFO) << "Flag enable_bluetooth_connection_status_track is enabled.";
|
||||
connection_status_changed_token_ =
|
||||
native_bluetooth_device_.ConnectionStatusChanged(
|
||||
{this, &BluetoothSocket::Listener_ConnectionStatusChanged});
|
||||
@@ -337,19 +357,18 @@ bool BluetoothSocket::InternalConnect(HostName connectionHostName,
|
||||
input_stream_ = BluetoothInputStream(windows_socket_.InputStream());
|
||||
output_stream_ = BluetoothOutputStream(windows_socket_.OutputStream());
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Bluetooth socket successfully connected to "
|
||||
<< bluetooth_device_->GetName();
|
||||
LOG(INFO) << __func__ << ": Bluetooth socket successfully connected to "
|
||||
<< bluetooth_device_->GetName();
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return false;
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -362,12 +381,10 @@ winrt::fire_and_forget BluetoothSocket::Listener_ConnectionStatusChanged(
|
||||
// Based on the test, the args are empty, so cannot provide more information
|
||||
// on the status change.
|
||||
BluetoothConnectionStatus connection_status = device.ConnectionStatus();
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": Bluetooth connection status changed to:"
|
||||
<< ((connection_status ==
|
||||
BluetoothConnectionStatus::Connected)
|
||||
? "Connected"
|
||||
: "Disconnected");
|
||||
LOG(WARNING) << __func__ << ": Bluetooth connection status changed to:"
|
||||
<< ((connection_status == BluetoothConnectionStatus::Connected)
|
||||
? "Connected"
|
||||
: "Disconnected");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,60 +15,29 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
#include "winrt/Windows.Networking.Sockets.h"
|
||||
#include "winrt/Windows.Storage.Streams.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Storage.Streams.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Provides data for a hostname or an IP address.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.hostname?view=winrt-20348
|
||||
using winrt::Windows::Networking::HostName;
|
||||
|
||||
// Supports network communication using a stream socket over Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::IStreamSocket;
|
||||
using winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
|
||||
// Provides a default implementation of the IBuffer interface and its related
|
||||
// interfaces.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.buffer?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::Buffer;
|
||||
|
||||
// Represents a sequential stream of bytes to be read.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.iinputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IInputStream;
|
||||
|
||||
// Represents a sequential stream of bytes to be written.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.ioutputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IOutputStream;
|
||||
|
||||
// Specifies the read options for an input stream.
|
||||
// This enumeration has a FlagsAttribute attribute that allows a bitwise
|
||||
// combination of its member values.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.inputstreamoptions?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::InputStreamOptions;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Represents an asynchronous action.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncAction;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html.
|
||||
class BluetoothSocket : public api::BluetoothSocket {
|
||||
public:
|
||||
BluetoothSocket();
|
||||
|
||||
explicit BluetoothSocket(StreamSocket streamSocket);
|
||||
|
||||
explicit BluetoothSocket(
|
||||
::winrt::Windows::Networking::Sockets::StreamSocket stream_socket);
|
||||
~BluetoothSocket() override;
|
||||
|
||||
// NOTE:
|
||||
@@ -95,28 +64,32 @@ class BluetoothSocket : public api::BluetoothSocket {
|
||||
|
||||
// Connect asynchronously to the target remote device
|
||||
// Returns true if successful, false otherwise
|
||||
bool Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName);
|
||||
bool Connect(::winrt::Windows::Networking::HostName connection_host_name,
|
||||
::winrt::hstring connection_service_name);
|
||||
|
||||
private:
|
||||
static constexpr int kInitialTransmitPacketSize = 4096;
|
||||
|
||||
class BluetoothInputStream : public InputStream {
|
||||
public:
|
||||
explicit BluetoothInputStream(IInputStream stream);
|
||||
explicit BluetoothInputStream(
|
||||
::winrt::Windows::Storage::Streams::IInputStream stream);
|
||||
~BluetoothInputStream() override = default;
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IInputStream winrt_input_stream_{nullptr};
|
||||
Buffer read_buffer_{kInitialTransmitPacketSize};
|
||||
::winrt::Windows::Storage::Streams::IInputStream winrt_input_stream_{
|
||||
nullptr};
|
||||
::winrt::Windows::Storage::Streams::Buffer read_buffer_{
|
||||
kInitialTransmitPacketSize};
|
||||
};
|
||||
|
||||
class BluetoothOutputStream : public OutputStream {
|
||||
public:
|
||||
explicit BluetoothOutputStream(IOutputStream stream);
|
||||
explicit BluetoothOutputStream(
|
||||
::winrt::Windows::Storage::Streams::IOutputStream stream);
|
||||
~BluetoothOutputStream() override = default;
|
||||
|
||||
Exception Write(const ByteArray& data) override;
|
||||
@@ -125,26 +98,28 @@ class BluetoothSocket : public api::BluetoothSocket {
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IOutputStream winrt_output_stream_{nullptr};
|
||||
Buffer write_buffer_{kInitialTransmitPacketSize};
|
||||
::winrt::Windows::Storage::Streams::IOutputStream winrt_output_stream_{
|
||||
nullptr};
|
||||
::winrt::Windows::Storage::Streams::Buffer write_buffer_{
|
||||
kInitialTransmitPacketSize};
|
||||
};
|
||||
|
||||
bool InternalConnect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName);
|
||||
bool InternalConnect(
|
||||
::winrt::Windows::Networking::HostName connection_host_name,
|
||||
::winrt::hstring connection_service_name);
|
||||
|
||||
winrt::fire_and_forget Listener_ConnectionStatusChanged(
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice device,
|
||||
winrt::Windows::Foundation::IInspectable const& args);
|
||||
::winrt::fire_and_forget Listener_ConnectionStatusChanged(
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice device,
|
||||
::winrt::Windows::Foundation::IInspectable const& args);
|
||||
|
||||
StreamSocket windows_socket_{nullptr};
|
||||
::winrt::Windows::Networking::Sockets::StreamSocket windows_socket_{nullptr};
|
||||
bool is_bluetooth_socket_closed_ = false;
|
||||
BluetoothInputStream input_stream_{nullptr};
|
||||
BluetoothOutputStream output_stream_{nullptr};
|
||||
std::unique_ptr<BluetoothDevice> bluetooth_device_ = nullptr;
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice native_bluetooth_device_{
|
||||
nullptr};
|
||||
winrt::event_token connection_status_changed_token_{};
|
||||
int connect_called_count_ = 0;
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice
|
||||
native_bluetooth_device_{nullptr};
|
||||
::winrt::event_token connection_status_changed_token_{};
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
@@ -54,8 +53,7 @@ BluetoothPairing::BluetoothPairing(
|
||||
BluetoothDevice bluetooth_device,
|
||||
DeviceInformationCustomPairing custom_pairing)
|
||||
: bluetooth_device_(bluetooth_device), custom_pairing_(custom_pairing) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": BluetoothPairing is created for device.";
|
||||
VLOG(1) << __func__ << ": BluetoothPairing is created for device.";
|
||||
}
|
||||
|
||||
BluetoothPairing::~BluetoothPairing() {
|
||||
@@ -64,19 +62,17 @@ BluetoothPairing::~BluetoothPairing() {
|
||||
std::exchange(pairing_requested_token_, {}));
|
||||
}
|
||||
CancelPairing();
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": BluetoothPairing is destroyed for device.";
|
||||
VLOG(1) << __func__ << ": BluetoothPairing is destroyed for device.";
|
||||
}
|
||||
|
||||
bool BluetoothPairing::InitiatePairing(
|
||||
api::BluetoothPairingCallback pairing_cb) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to initiate pairing process.";
|
||||
VLOG(1) << __func__ << ": Start to initiate pairing process.";
|
||||
try {
|
||||
pairing_requested_token_ = custom_pairing_.PairingRequested(
|
||||
{this, &BluetoothPairing::OnPairingRequested});
|
||||
if (!pairing_requested_token_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< " Failed to registered pairing callback.";
|
||||
VLOG(1) << __func__ << " Failed to registered pairing callback.";
|
||||
return false;
|
||||
}
|
||||
pairing_callback_ = std::move(pairing_cb);
|
||||
@@ -91,35 +87,32 @@ bool BluetoothPairing::InitiatePairing(
|
||||
OnPair(pairing_result);
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to initiate pairing. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to initiate pairing. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to initiate pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to initiate pairing. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::FinishPairing(
|
||||
std::optional<absl::string_view> pin_code) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Start to finish pairing.";
|
||||
VLOG(1) << __func__ << "Start to finish pairing.";
|
||||
try {
|
||||
if (!pairing_requested_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No pairing requested.";
|
||||
VLOG(1) << __func__ << "No pairing requested.";
|
||||
return false;
|
||||
}
|
||||
if (!pairing_deferral_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No ongoing pairing process.";
|
||||
VLOG(1) << __func__ << "No ongoing pairing process.";
|
||||
return false;
|
||||
}
|
||||
if (expecting_pin_code_) {
|
||||
if (!pin_code.has_value()) {
|
||||
NEARBY_LOGS(INFO) << __func__ << " Failed to get pin code";
|
||||
LOG(INFO) << __func__ << " Failed to get pin code";
|
||||
return false;
|
||||
}
|
||||
expecting_pin_code_ = false;
|
||||
@@ -129,28 +122,25 @@ bool BluetoothPairing::FinishPairing(
|
||||
pairing_requested_.Accept();
|
||||
}
|
||||
pairing_deferral_.Complete();
|
||||
NEARBY_LOGS(VERBOSE) << "Successfully finished pairing.";
|
||||
VLOG(1) << "Successfully finished pairing.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to finish pairing. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to finish pairing. exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to finish pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to finish pairing. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::CancelPairing() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< " Start to cancel ongoing pairing process.";
|
||||
VLOG(1) << __func__ << " Start to cancel ongoing pairing process.";
|
||||
try {
|
||||
if (!pairing_deferral_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No ongoing pairing process.";
|
||||
VLOG(1) << __func__ << "No ongoing pairing process.";
|
||||
return true;
|
||||
}
|
||||
// There is no way to explicitly cancel an in-progress pairing on Windows as
|
||||
@@ -161,48 +151,44 @@ bool BluetoothPairing::CancelPairing() {
|
||||
// deferral is completed, will know that cancellation was the actual result.
|
||||
was_cancelled_ = true;
|
||||
pairing_deferral_.Close();
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Canceled ongoing pairing process.";
|
||||
VLOG(1) << __func__ << "Canceled ongoing pairing process.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to cancel ongoing pairing "
|
||||
<< "process. exception: " << exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to cancel ongoing pairing "
|
||||
<< "process. exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to cancel ongoing pairing process. "
|
||||
<< "WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to cancel ongoing pairing process. "
|
||||
<< "WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::Unpair() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to unpair with remote device.";
|
||||
VLOG(1) << __func__ << ": Start to unpair with remote device.";
|
||||
try {
|
||||
if (!IsPaired()) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << " : Remote device Was not paired.";
|
||||
VLOG(1) << __func__ << " : Remote device Was not paired.";
|
||||
return true;
|
||||
}
|
||||
DeviceUnpairingResult unpairing_result =
|
||||
bluetooth_device_.DeviceInformation().Pairing().UnpairAsync().get();
|
||||
if (unpairing_result.Status() == DeviceUnpairingResultStatus::Unpaired) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Unpaired with remote device.";
|
||||
VLOG(1) << __func__ << ": Unpaired with remote device.";
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to unpaired with remote device.";
|
||||
VLOG(1) << __func__ << ": Failed to unpaired with remote device.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to unpaired with device. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__ << ": Failed to unpaired with device. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to unpaired with device. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to unpaired with device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -210,18 +196,17 @@ bool BluetoothPairing::Unpair() {
|
||||
bool BluetoothPairing::IsPaired() {
|
||||
try {
|
||||
bool is_paired = bluetooth_device_.DeviceInformation().Pairing().IsPaired();
|
||||
NEARBY_LOGS(INFO) << __func__ << (is_paired ? " True" : " False");
|
||||
LOG(INFO) << __func__ << (is_paired ? " True" : " False");
|
||||
return is_paired;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get IsPaired. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get IsPaired. exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get IsPaired. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get IsPaired. WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -229,7 +214,7 @@ bool BluetoothPairing::IsPaired() {
|
||||
void BluetoothPairing::OnPairingRequested(
|
||||
DeviceInformationCustomPairing custom_pairing,
|
||||
DevicePairingRequestedEventArgs pairing_requested) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Requested to pair.";
|
||||
VLOG(1) << __func__ << "Requested to pair.";
|
||||
try {
|
||||
DevicePairingKinds pairing_kind = pairing_requested.PairingKind();
|
||||
pairing_requested_ = pairing_requested;
|
||||
@@ -237,40 +222,38 @@ void BluetoothPairing::OnPairingRequested(
|
||||
api::PairingParams params;
|
||||
switch (pairing_kind) {
|
||||
case DevicePairingKinds::ProvidePin:
|
||||
NEARBY_LOGS(INFO) << __func__ << "DevicePairingKind: RequestPinCode.";
|
||||
LOG(INFO) << __func__ << "DevicePairingKind: RequestPinCode.";
|
||||
expecting_pin_code_ = true;
|
||||
params.pairing_type = PairingType::kRequestPin;
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
case DevicePairingKinds::ConfirmOnly:
|
||||
NEARBY_LOGS(INFO) << __func__ << "DevicePairingKind: ConfirmOnly.";
|
||||
LOG(INFO) << __func__ << "DevicePairingKind: ConfirmOnly.";
|
||||
params.pairing_type = PairingType::kConsent;
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
case DevicePairingKinds::ConfirmPinMatch:
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "DevicePairingKind: Confirm Pin Match.";
|
||||
LOG(INFO) << __func__ << "DevicePairingKind: Confirm Pin Match.";
|
||||
params.pairing_type = PairingType::kConfirmPasskey;
|
||||
params.passkey = winrt::to_string(pairing_requested.Pin());
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
default:
|
||||
params.pairing_type = PairingType::kUnknown;
|
||||
NEARBY_LOGS(INFO) << __func__ << "Unsupported DevicePairingKind:"
|
||||
<< static_cast<int>(pairing_kind);
|
||||
LOG(INFO) << __func__ << "Unsupported DevicePairingKind:"
|
||||
<< static_cast<int>(pairing_kind);
|
||||
break;
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to request to pair with device. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to request to pair with device. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to request to pair with device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to request to pair with device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
}
|
||||
@@ -278,8 +261,8 @@ void BluetoothPairing::OnPairingRequested(
|
||||
void BluetoothPairing::OnPair(DevicePairingResult& pairing_result) {
|
||||
try {
|
||||
DevicePairingResultStatus status = pairing_result.Status();
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "Pairing Result Status: " << static_cast<int>(status);
|
||||
LOG(INFO) << __func__
|
||||
<< "Pairing Result Status: " << static_cast<int>(status);
|
||||
if (was_cancelled_ &&
|
||||
status == DevicePairingResultStatus::RejectedByHandler) {
|
||||
// See comment in CancelPairing() for explanation of why was_cancelled_
|
||||
@@ -289,53 +272,52 @@ void BluetoothPairing::OnPair(DevicePairingResult& pairing_result) {
|
||||
switch (status) {
|
||||
case DevicePairingResultStatus::AlreadyPaired:
|
||||
case DevicePairingResultStatus::Paired:
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Paired.";
|
||||
LOG(ERROR) << __func__ << "Pairing Result Status: Paired.";
|
||||
pairing_callback_.on_paired_cb();
|
||||
return;
|
||||
case DevicePairingResultStatus::PairingCanceled:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Pairing Canceled.";
|
||||
LOG(ERROR) << __func__ << "Pairing Result Status: Pairing Canceled.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthCanceled);
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationFailure:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Failure.";
|
||||
LOG(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Failure.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthFailed);
|
||||
return;
|
||||
case DevicePairingResultStatus::ConnectionRejected:
|
||||
case DevicePairingResultStatus::RejectedByHandler:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Rejected.";
|
||||
LOG(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Rejected.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthRejected);
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationTimeout:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Timeout.";
|
||||
LOG(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Timeout.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthTimeout);
|
||||
return;
|
||||
case DevicePairingResultStatus::Failed:
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
LOG(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
return;
|
||||
case DevicePairingResultStatus::OperationAlreadyInProgress:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Operation In Progress.";
|
||||
LOG(ERROR) << __func__
|
||||
<< "Pairing Result Status: Operation In Progress.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kRepeatedAttempts);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
LOG(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get Pairing Result Status. exception: "
|
||||
<< exception.what();
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Failed to get Pairing Result Status. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get Pairing Result Status."
|
||||
<< " WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
LOG(ERROR) << __func__ << ": Failed to get Pairing Result Status."
|
||||
<< " WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
}
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
}
|
||||
|
||||
@@ -18,19 +18,16 @@
|
||||
#include <windows.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <filesystem> // NOLINT
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/base/bluetooth_address.h"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#include "internal/platform/implementation/windows/session_manager.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/base.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
@@ -56,25 +53,25 @@ constexpr char logs_relative_path[] = "Google\\Nearby\\Sharing\\Logs";
|
||||
constexpr char crash_dumps_relative_path[] =
|
||||
"Google\\Nearby\\Sharing\\CrashDumps";
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetOsDeviceName() const {
|
||||
std::optional<std::string> DeviceInfo::GetOsDeviceName() const {
|
||||
DWORD size = 0;
|
||||
|
||||
// Get length of the computer name.
|
||||
if (!GetComputerNameExW(ComputerNameDnsHostname, nullptr, &size)) {
|
||||
if (GetLastError() != ERROR_MORE_DATA) {
|
||||
NEARBY_LOGS(ERROR) << ": Failed to get device name size, error:"
|
||||
<< GetLastError();
|
||||
LOG(ERROR) << ": Failed to get device name size, error:"
|
||||
<< GetLastError();
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR device_name[size];
|
||||
if (GetComputerNameExW(ComputerNameDnsHostname, device_name, &size)) {
|
||||
std::wstring wide_name(device_name);
|
||||
return std::u16string(wide_name.begin(), wide_name.end());
|
||||
std::wstring device_name(size, L' ');
|
||||
if (GetComputerNameExW(ComputerNameDnsHostname, device_name.data(), &size)) {
|
||||
winrt::hstring device_name_str(device_name);
|
||||
return winrt::to_string(device_name_str);
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << ": Failed to get device name, error:" << GetLastError();
|
||||
LOG(ERROR) << ": Failed to get device name, error:" << GetLastError();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -87,7 +84,7 @@ api::DeviceInfo::OsType DeviceInfo::GetOsType() const {
|
||||
return api::DeviceInfo::OsType::kWindows;
|
||||
}
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetFullName() const {
|
||||
std::optional<std::string> DeviceInfo::GetGivenName() const {
|
||||
// FindAllAsync finds all users that are using this app. When we "Switch User"
|
||||
// on Desktop,FindAllAsync() will still return the current user instead of all
|
||||
// of them because the users who are switched out are not using the apps of
|
||||
@@ -100,52 +97,7 @@ std::optional<std::u16string> DeviceInfo::GetFullName() const {
|
||||
UserAuthenticationStatus::LocallyAuthenticated)
|
||||
.get();
|
||||
if (users == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error retrieving locally authenticated user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// On Windows Desktop apps, the first Windows.System.User instance
|
||||
// returned in the IVectorView is always the current user.
|
||||
// https://github.com/microsoft/Windows-task-snippets/blob/master/tasks/User-info.md
|
||||
User current_user = users.GetAt(0);
|
||||
|
||||
// Retrieve the human-readable properties for the current user
|
||||
IAsyncOperation<IInspectable> full_name_obj_async =
|
||||
current_user.GetPropertyAsync(KnownUserProperties::DisplayName());
|
||||
IInspectable full_name_obj = full_name_obj_async.get();
|
||||
if (full_name_obj == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Error retrieving full name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
winrt::hstring full_name = full_name_obj.as<winrt::hstring>();
|
||||
std::wstring wstr(full_name);
|
||||
std::u16string u16str(wstr.begin(), wstr.end());
|
||||
|
||||
if (u16str.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Error unboxing string value for full name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return u16str;
|
||||
}
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetGivenName() const {
|
||||
// FindAllAsync finds all users that are using this app. When we "Switch User"
|
||||
// on Desktop,FindAllAsync() will still return the current user instead of all
|
||||
// of them because the users who are switched out are not using the apps of
|
||||
// the user who is switched in, so FindAllAsync() will not find them. (Under
|
||||
// the UWP application model, each process runs under its own user account.
|
||||
// That user account is different from the user account of the logged-in user.
|
||||
// Processes aren't owned by the logged-in user for purposes of isolation.)
|
||||
IVectorView<User> users =
|
||||
User::FindAllAsync(UserType::LocalUser,
|
||||
UserAuthenticationStatus::LocallyAuthenticated)
|
||||
.get();
|
||||
if (users == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error retrieving locally authenticated user.";
|
||||
LOG(ERROR) << __func__ << ": Error retrieving locally authenticated user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -159,109 +111,19 @@ std::optional<std::u16string> DeviceInfo::GetGivenName() const {
|
||||
current_user.GetPropertyAsync(KnownUserProperties::FirstName());
|
||||
IInspectable given_name_obj = given_name_obj_async.get();
|
||||
if (given_name_obj == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Error retrieving first name of user.";
|
||||
LOG(ERROR) << __func__ << ": Error retrieving first name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
winrt::hstring given_name = given_name_obj.as<winrt::hstring>();
|
||||
std::wstring wstr(given_name);
|
||||
std::u16string u16str(wstr.begin(), wstr.end());
|
||||
std::string given_name_str = winrt::to_string(given_name);
|
||||
|
||||
if (u16str.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Error unboxing string value for first name of user.";
|
||||
if (given_name_str.empty()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Error unboxing string value for first name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return u16str;
|
||||
}
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetLastName() const {
|
||||
// FindAllAsync finds all users that are using this app. When we "Switch User"
|
||||
// on Desktop,FindAllAsync() will still return the current user instead of all
|
||||
// of them because the users who are switched out are not using the apps of
|
||||
// the user who is switched in, so FindAllAsync() will not find them. (Under
|
||||
// the UWP application model, each process runs under its own user account.
|
||||
// That user account is different from the user account of the logged-in user.
|
||||
// Processes aren't owned by the logged-in user for purposes of isolation.)
|
||||
IVectorView<User> users =
|
||||
User::FindAllAsync(UserType::LocalUser,
|
||||
UserAuthenticationStatus::LocallyAuthenticated)
|
||||
.get();
|
||||
if (users == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error retrieving locally authenticated user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// On Windows Desktop apps, the first Windows.System.User instance
|
||||
// returned in the IVectorView is always the current user.
|
||||
// https://github.com/microsoft/Windows-task-snippets/blob/master/tasks/User-info.md
|
||||
User current_user = users.GetAt(0);
|
||||
|
||||
// Retrieve the human-readable properties for the current user
|
||||
IAsyncOperation<IInspectable> last_name_obj_async =
|
||||
current_user.GetPropertyAsync(KnownUserProperties::LastName());
|
||||
IInspectable last_name_obj = last_name_obj_async.get();
|
||||
if (last_name_obj == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Error retrieving last name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
winrt::hstring last_name = last_name_obj.as<winrt::hstring>();
|
||||
std::wstring wstr(last_name);
|
||||
std::u16string u16str(wstr.begin(), wstr.end());
|
||||
|
||||
if (u16str.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Error unboxing string value for last name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return u16str;
|
||||
}
|
||||
|
||||
std::optional<std::string> DeviceInfo::GetProfileUserName() const {
|
||||
// FindAllAsync finds all users that are using this app. When we "Switch User"
|
||||
// on Desktop,FindAllAsync() will still return the current user instead of all
|
||||
// of them because the users who are switched out are not using the apps of
|
||||
// the user who is switched in, so FindAllAsync() will not find them. (Under
|
||||
// the UWP application model, each process runs under its own user account.
|
||||
// That user account is different from the user account of the logged-in user.
|
||||
// Processes aren't owned by the logged-in user for purposes of isolation.)
|
||||
IVectorView<User> users =
|
||||
User::FindAllAsync(UserType::LocalUser,
|
||||
UserAuthenticationStatus::LocallyAuthenticated)
|
||||
.get();
|
||||
if (users == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error retrieving locally authenticated user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// On Windows Desktop apps, the first Windows.System.User instance
|
||||
// returned in the IVectorView is always the current user.
|
||||
// https://github.com/microsoft/Windows-task-snippets/blob/master/tasks/User-info.md
|
||||
User current_user = users.GetAt(0);
|
||||
|
||||
// Retrieve the human-readable properties for the current user
|
||||
IAsyncOperation<IInspectable> account_name_obj_async =
|
||||
current_user.GetPropertyAsync(KnownUserProperties::AccountName());
|
||||
IInspectable account_name_obj = account_name_obj_async.get();
|
||||
if (account_name_obj == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Error retrieving account name of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
winrt::hstring account_name = account_name_obj.as<winrt::hstring>();
|
||||
std::string account_name_string = winrt::to_string(account_name);
|
||||
|
||||
if (account_name_string.empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Error unboxing string value for profile username of user.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return account_name_string;
|
||||
return given_name_str;
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> DeviceInfo::GetDownloadPath() const {
|
||||
@@ -307,7 +169,7 @@ std::optional<std::filesystem::path> DeviceInfo::GetCommonAppDataPath() const {
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> DeviceInfo::GetTemporaryPath() const {
|
||||
return std::filesystem::temp_directory_path();
|
||||
return nearby::sharing::GetTemporaryDirectory();
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> DeviceInfo::GetLogPath() const {
|
||||
|
||||
@@ -31,13 +31,10 @@ class DeviceInfo : public api::DeviceInfo {
|
||||
public:
|
||||
~DeviceInfo() override = default;
|
||||
|
||||
std::optional<std::u16string> GetOsDeviceName() const override;
|
||||
std::optional<std::string> GetOsDeviceName() const override;
|
||||
api::DeviceInfo::DeviceType GetDeviceType() const override;
|
||||
api::DeviceInfo::OsType GetOsType() const override;
|
||||
std::optional<std::u16string> GetFullName() const override;
|
||||
std::optional<std::u16string> GetGivenName() const override;
|
||||
std::optional<std::u16string> GetLastName() const override;
|
||||
std::optional<std::string> GetProfileUserName() const override;
|
||||
std::optional<std::string> GetGivenName() const override;
|
||||
|
||||
std::optional<std::filesystem::path> GetDownloadPath() const override;
|
||||
std::optional<std::filesystem::path> GetLocalAppDataPath() const override;
|
||||
|
||||
@@ -14,11 +14,8 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/device_info.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -37,21 +34,10 @@ TEST(DeviceInfo, GetOsType) {
|
||||
EXPECT_EQ(DeviceInfo().GetOsType(), api::DeviceInfo::OsType::kWindows);
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_GetFullName) {
|
||||
EXPECT_TRUE(DeviceInfo().GetFullName().has_value());
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_GetGivenName) {
|
||||
EXPECT_TRUE(DeviceInfo().GetGivenName().has_value());
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_GetLastName) {
|
||||
EXPECT_TRUE(DeviceInfo().GetLastName().has_value());
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_GetProfileUserName) {
|
||||
EXPECT_TRUE(DeviceInfo().GetProfileUserName().has_value());
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_GetLocalAppDataPath) {
|
||||
EXPECT_TRUE(DeviceInfo().GetLocalAppDataPath().has_value());
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
#include "internal/platform/implementation/windows/executor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -32,13 +34,13 @@ Executor::Executor(int32_t max_concurrency)
|
||||
|
||||
void Executor::Execute(Runnable&& runnable) {
|
||||
if (shut_down_) {
|
||||
NEARBY_LOGS(VERBOSE) << "Warning: " << __func__
|
||||
<< ": Attempt to execute on a shut down pool.";
|
||||
VLOG(1) << "Warning: " << __func__
|
||||
<< ": Attempt to execute on a shut down pool.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (runnable == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Runnable was null.";
|
||||
LOG(ERROR) << __func__ << ": Runnable was null.";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,45 +14,54 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/file.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/implementation/windows/string_utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// InputFile
|
||||
std::unique_ptr<IOFile> IOFile::CreateInputFile(
|
||||
const absl::string_view file_path, size_t size) {
|
||||
std::unique_ptr<IOFile> IOFile::CreateInputFile(absl::string_view file_path,
|
||||
size_t size) {
|
||||
return absl::WrapUnique(new IOFile(file_path, size));
|
||||
}
|
||||
|
||||
IOFile::IOFile(const absl::string_view file_path, size_t size)
|
||||
: path_(file_path) {
|
||||
IOFile::IOFile(absl::string_view file_path, size_t size) : path_(file_path) {
|
||||
// Always open input file path as wide string on Windows platform.
|
||||
std::wstring wide_path = string_to_wstring(std::string(file_path));
|
||||
std::wstring wide_path = string_utils::StringToWideString(
|
||||
std::string(file_path));
|
||||
file_.open(wide_path, std::ios::binary | std::ios::in | std::ios::ate);
|
||||
|
||||
total_size_ = file_.tellg();
|
||||
if (total_size_ == -1) {
|
||||
// Unsure why it consistently returns -1 when the file size exceeds 2GB. If
|
||||
// obtaining the file size through tellg fails, use the size provided
|
||||
// in the parameters.
|
||||
total_size_ = size;
|
||||
}
|
||||
|
||||
file_.seekg(0);
|
||||
}
|
||||
|
||||
std::unique_ptr<IOFile> IOFile::CreateOutputFile(const absl::string_view path) {
|
||||
std::unique_ptr<IOFile> IOFile::CreateOutputFile(absl::string_view path) {
|
||||
return std::unique_ptr<IOFile>(new IOFile(path));
|
||||
}
|
||||
|
||||
IOFile::IOFile(const absl::string_view file_path)
|
||||
IOFile::IOFile(absl::string_view file_path)
|
||||
: file_(), path_(file_path), total_size_(0) {
|
||||
// Always open input file path as wide string on Windows platform.
|
||||
std::wstring wide_path = string_to_wstring(path_);
|
||||
std::wstring wide_path =
|
||||
string_utils::StringToWideString(path_);
|
||||
file_.open(wide_path, std::ios::binary | std::ios::out);
|
||||
}
|
||||
|
||||
@@ -66,20 +75,22 @@ ExceptionOr<ByteArray> IOFile::Read(std::int64_t size) {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
|
||||
if (file_.peek() == EOF) {
|
||||
if (file_.eof()) {
|
||||
return ExceptionOr<ByteArray>{ByteArray{}};
|
||||
}
|
||||
|
||||
ByteArray bytes(size);
|
||||
std::unique_ptr<char[]> read_bytes{new char[size]};
|
||||
file_.read(read_bytes.get(), static_cast<ptrdiff_t>(size));
|
||||
if (buffer_.size() < size) {
|
||||
buffer_.resize(size);
|
||||
}
|
||||
|
||||
file_.read(buffer_.data(), static_cast<ptrdiff_t>(size));
|
||||
auto num_bytes_read = file_.gcount();
|
||||
if (num_bytes_read == 0) {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
return ExceptionOr<ByteArray>(ByteArray(read_bytes.get(), num_bytes_read));
|
||||
return ExceptionOr<ByteArray>(ByteArray(buffer_.data(), num_bytes_read));
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << "Fail to read";
|
||||
LOG(ERROR) << "Fail to read";
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
}
|
||||
@@ -105,7 +116,7 @@ Exception IOFile::Write(const ByteArray& data) {
|
||||
file_.flush();
|
||||
return {file_.good() ? Exception::kSuccess : Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << "Fail to write";
|
||||
LOG(ERROR) << "Fail to write";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_FILE_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_FILE_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/input_file.h"
|
||||
#include "internal/platform/implementation/output_file.h"
|
||||
@@ -30,10 +32,10 @@ namespace windows {
|
||||
|
||||
class IOFile final : public api::InputFile, public api::OutputFile {
|
||||
public:
|
||||
static std::unique_ptr<IOFile> CreateInputFile(
|
||||
const absl::string_view file_path, size_t size);
|
||||
static std::unique_ptr<IOFile> CreateInputFile(absl::string_view file_path,
|
||||
size_t size);
|
||||
|
||||
static std::unique_ptr<IOFile> CreateOutputFile(const absl::string_view path);
|
||||
static std::unique_ptr<IOFile> CreateOutputFile(absl::string_view path);
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
|
||||
@@ -46,11 +48,12 @@ class IOFile final : public api::InputFile, public api::OutputFile {
|
||||
Exception Flush() override;
|
||||
|
||||
private:
|
||||
explicit IOFile(const absl::string_view file_path, size_t size);
|
||||
explicit IOFile(const absl::string_view file_path);
|
||||
explicit IOFile(absl::string_view file_path, size_t size);
|
||||
explicit IOFile(absl::string_view file_path);
|
||||
|
||||
std::fstream file_;
|
||||
std::string path_;
|
||||
std::string buffer_;
|
||||
std::int64_t total_size_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Google LLC
|
||||
// Copyright 2022-2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/file_path.h"
|
||||
|
||||
// clang-format off
|
||||
#include <windows.h>
|
||||
#include <winver.h>
|
||||
#include <PathCch.h>
|
||||
@@ -22,28 +23,36 @@
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <wchar.h>
|
||||
// clang-format on
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/implementation/windows/string_utils.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
const wchar_t* kUpOneLevel = L"/..";
|
||||
const wchar_t* kUpOneLevel = L"..";
|
||||
constexpr wchar_t kDot = L'.';
|
||||
constexpr wchar_t kPathDelimiter = L'/';
|
||||
constexpr wchar_t kReplacementChar = L'_';
|
||||
constexpr wchar_t kForwardSlash = L'/';
|
||||
constexpr wchar_t kBackSlash = L'\\';
|
||||
|
||||
wchar_t const* kForbiddenPathNames[] = {
|
||||
constexpr std::wstring_view kForbiddenPathNames[] = {
|
||||
L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4",
|
||||
L"COM5", L"COM6", L"COM7", L"COM8", L"COM9", L"LPT1", L"LPT2", L"LPT3",
|
||||
L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9"};
|
||||
@@ -51,12 +60,14 @@ wchar_t const* kForbiddenPathNames[] = {
|
||||
std::wstring FilePath::GetCustomSavePath(std::wstring parent_folder,
|
||||
std::wstring file_name) {
|
||||
std::wstring path;
|
||||
SanitizeFileName(file_name);
|
||||
path += parent_folder + kPathDelimiter + file_name;
|
||||
return CreateOutputFileWithRename(path);
|
||||
}
|
||||
|
||||
std::wstring FilePath::GetDownloadPath(std::wstring parent_folder,
|
||||
std::wstring file_name) {
|
||||
SanitizeFileName(file_name);
|
||||
return CreateOutputFileWithRename(
|
||||
GetDownloadPathInternal(parent_folder, file_name));
|
||||
}
|
||||
@@ -167,8 +178,8 @@ std::wstring FilePath::CreateOutputFileWithRename(std::wstring path) {
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
NEARBY_LOGS(INFO) << "Renamed " << wstring_to_string(path) << " to "
|
||||
<< wstring_to_string(target);
|
||||
LOG(INFO) << "Renamed " << string_utils::WideStringToString(path) << " to "
|
||||
<< string_utils::WideStringToString(target);
|
||||
}
|
||||
|
||||
// The above leaves the file open, so close it.
|
||||
@@ -198,23 +209,30 @@ std::wstring FilePath::MutateForbiddenPathElements(std::wstring& str) {
|
||||
if (lastToken.length() > 0) path_elements.push_back(lastToken);
|
||||
|
||||
std::wstring processed_path;
|
||||
absl::Span<const std::wstring_view> forbidden(kForbiddenPathNames);
|
||||
|
||||
for (auto& path_element : path_elements) {
|
||||
auto tmp_path_element = path_element;
|
||||
|
||||
if (tmp_path_element.size() == 1 && tmp_path_element[0] == kDot) {
|
||||
// Change the dot path name to an underscore.
|
||||
tmp_path_element[0] = kReplacementChar;
|
||||
LOG(INFO) << "Renamed path element "
|
||||
<< string_utils::WideStringToString(path_element) << " to "
|
||||
<< string_utils::WideStringToString(tmp_path_element);
|
||||
path_element[0] = kReplacementChar;
|
||||
}
|
||||
|
||||
std::transform(tmp_path_element.begin(), tmp_path_element.end(),
|
||||
tmp_path_element.begin(),
|
||||
[](wchar_t c) { return std::toupper(c); });
|
||||
|
||||
std::vector<std::wstring> forbidden(std::begin(kForbiddenPathNames),
|
||||
std::end(kForbiddenPathNames));
|
||||
|
||||
while (std::find(forbidden.begin(), forbidden.end(), tmp_path_element) !=
|
||||
forbidden.end()) {
|
||||
tmp_path_element.insert(tmp_path_element.begin(), kReplacementChar);
|
||||
NEARBY_LOGS(INFO) << "Renamed path element "
|
||||
<< wstring_to_string(path_element) << " to "
|
||||
<< wstring_to_string(tmp_path_element);
|
||||
LOG(INFO) << "Renamed path element "
|
||||
<< string_utils::WideStringToString(path_element) << " to "
|
||||
<< string_utils::WideStringToString(tmp_path_element);
|
||||
path_element.insert(path_element.begin(), kReplacementChar);
|
||||
}
|
||||
|
||||
@@ -227,16 +245,15 @@ std::wstring FilePath::MutateForbiddenPathElements(std::wstring& str) {
|
||||
return processed_path;
|
||||
}
|
||||
|
||||
void FilePath::SanitizePath(std::wstring& path) {
|
||||
size_t pos = std::wstring::npos;
|
||||
// Search for the substring in string in a loop until nothing is found
|
||||
while ((pos = path.find(kUpOneLevel)) != std::string::npos) {
|
||||
// If found then erase it from string
|
||||
path.erase(pos, wcslen(kUpOneLevel));
|
||||
void FilePath::SanitizeFileName(std::wstring& file_name) {
|
||||
if (!file_name.empty() && file_name[file_name.size() - 1] == kDot) {
|
||||
// Change the last dot to an underscore.
|
||||
file_name[file_name.size() - 1] = kReplacementChar;
|
||||
}
|
||||
}
|
||||
|
||||
void FilePath::SanitizePath(std::wstring& path) {
|
||||
path = MutateForbiddenPathElements(path);
|
||||
|
||||
ReplaceInvalidCharacters(path);
|
||||
}
|
||||
|
||||
@@ -249,16 +266,22 @@ void FilePath::ReplaceInvalidCharacters(std::wstring& path) {
|
||||
for (; it != path.end(); it++) {
|
||||
// If 0 < character < 32, it's illegal, replace it
|
||||
if (*it > 0 && *it < 32) {
|
||||
NEARBY_LOGS(INFO) << "In path " << wstring_to_string(path)
|
||||
<< " replaced \'" << std::string(1, *it) << "\' with \'"
|
||||
<< std::string(1, kReplacementChar);
|
||||
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
|
||||
<< " replaced \'" << std::string(1, *it) << "\' with \'"
|
||||
<< std::string(1, kReplacementChar);
|
||||
*it = kReplacementChar;
|
||||
}
|
||||
if (*it == 0) { // character is null
|
||||
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
|
||||
<< " replaced \'NULL\' with \'"
|
||||
<< std::string(1, kReplacementChar) << "\'";
|
||||
*it = kReplacementChar;
|
||||
}
|
||||
for (auto illegal_character : kIllegalFileCharacters) {
|
||||
if (*it == illegal_character) {
|
||||
NEARBY_LOGS(INFO) << "In path " << wstring_to_string(path)
|
||||
<< " replaced \'" << std::string(1, *it)
|
||||
<< "\' with \'" << std::string(1, kReplacementChar);
|
||||
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
|
||||
<< " replaced \'" << std::string(1, *it) << "\' with \'"
|
||||
<< std::string(1, kReplacementChar);
|
||||
*it = kReplacementChar;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class FilePath {
|
||||
static std::wstring MutateForbiddenPathElements(std::wstring& str);
|
||||
static std::wstring GetDownloadPathInternal(std::wstring parent_folder,
|
||||
std::wstring file_name);
|
||||
static void SanitizeFileName(std::wstring& file_name);
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@@ -39,6 +38,7 @@ const wchar_t* kFileName(L"increment_file_test.txt");
|
||||
const wchar_t* kFirstIterationFileName(L"/increment_file_test (1).txt");
|
||||
const wchar_t* kSecondIterationFileName(L"/increment_file_test (2).txt");
|
||||
const wchar_t* kThirdIterationFileName(L"/increment_file_test (3).txt");
|
||||
const wchar_t* kFileNameWithNullReplaced(L"/increment_file_test.txt_.txt");
|
||||
const wchar_t* kNoDotsFileName(L"incrementfiletesttxt");
|
||||
const wchar_t* kOneIterationNoDotsFileName(L"/incrementfiletesttxt (1)");
|
||||
const wchar_t* kMultipleDotsFileName(L"increment.file.test.txt");
|
||||
@@ -52,6 +52,8 @@ const wchar_t* kLongEscapeMixedSlash(L"../test\\..\\../test");
|
||||
const wchar_t* kLongEscapeEndingEscape(L"../test/../../test/..");
|
||||
const wchar_t* kLongEscapeEndingEscapeWithSlash(
|
||||
L"../test/../../test/../../../");
|
||||
const wchar_t* kFileNameWithThreeDots(L"...");
|
||||
const wchar_t* kFileNameWithFrontTwoDots(L"..file.name.txt");
|
||||
} // namespace
|
||||
|
||||
// Can't run on google 3, I presume the SHGetKnownFolderPath
|
||||
@@ -124,71 +126,6 @@ FolderArgumentsShouldReturnBaseDownloadPath) {
|
||||
EXPECT_EQ(actual, default_download_path_);
|
||||
} // NOLINT false lint error here
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithAttemptToEscape\
|
||||
UsersDownloadFolderShouldReturnDownloadPathNotEscapingUsersDownloadFolder) {
|
||||
std::wstring parent_folder(kImmediateEscape);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithMultiple\
|
||||
AttemptsToEscapeUsersDownloadFolderWithBackslashShouldReturnDownloadPath\
|
||||
NotEscapingUsersDownloadFolder) {
|
||||
std::wstring parent_folder(kLongEscapeBackSlash);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_ + kTwoLevelFolder);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithMultiple\
|
||||
AttemptsToEscapeUsersDownloadFolderShouldReturnDownloadPathNotEscapingUsers\
|
||||
DownloadFolder) {
|
||||
std::wstring parent_folder(kLongEscapeSlash);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_ + kTwoLevelFolder);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithMultiple\
|
||||
AttemptsToEscapeUsersDownloadFolderWithMixedSlashShouldReturnDownloadPath\
|
||||
NotEscapingUsersDownloadFolder) {
|
||||
std::wstring parent_folder(kLongEscapeMixedSlash);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_ + kTwoLevelFolder);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithMultiple\
|
||||
AttemptsToEscapeUsersDownloadFolderWithEndingEscapeShouldReturnDownload\
|
||||
PathNotEscapingUsersDownloadFolder) {
|
||||
std::wstring parent_folder(kLongEscapeEndingEscape);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_ + kTwoLevelFolder);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithMultiple\
|
||||
AttemptsToEscapeUsersDownloadFolderWithEndingSlashShouldReturnDownloadPathNot\
|
||||
EscapingUsersDownloadFolder) {
|
||||
std::wstring parent_folder(kLongEscapeEndingEscapeWithSlash);
|
||||
std::wstring file_name(L"");
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, default_download_path_ + kTwoLevelFolder);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithSlashFileName\
|
||||
ArgumentsShouldReturnBaseDownloadPath) {
|
||||
std::wstring parent_folder(L"");
|
||||
@@ -852,5 +789,88 @@ AHoleBetweenRenamedFiles) {
|
||||
input_file.open(output_file3_path, std::ifstream::binary | std::ifstream::in);
|
||||
ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithFileName\
|
||||
FileNameTwoDotsFrontShouldReturnBaseDownloadPathWithFileNameTwoDotsFront) {
|
||||
std::wstring parent_folder(L"");
|
||||
std::wstring file_name(kFileNameWithFrontTwoDots);
|
||||
|
||||
std::wstringstream path(L"");
|
||||
path << default_download_path_ << L"/" << file_name;
|
||||
|
||||
std::wstring expected = path.str();
|
||||
|
||||
auto actual = FilePath::GetDownloadPath(parent_folder, file_name);
|
||||
EXPECT_EQ(actual, expected);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithFileName\
|
||||
FileNameThreeDotsShouldReturnBaseDownloadPathWithUnderscore) {
|
||||
std::wstring parent_folder(L"");
|
||||
std::wstring file_name(kFileNameWithThreeDots);
|
||||
|
||||
std::wstringstream path(L"");
|
||||
path << default_download_path_ << L"/.._";
|
||||
|
||||
std::wstring expected = path.str();
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, expected);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPath_FileExistsReturns\
|
||||
FileWithIncrementedNameWithNull) {
|
||||
std::wstring file_name(kFileName);
|
||||
int size = file_name.size();
|
||||
file_name.append(L"1.txt");
|
||||
file_name[size] = L'\x00';
|
||||
std::wstring renamed_file_name(kFileNameWithNullReplaced);
|
||||
std::wstring parent_folder(L"");
|
||||
|
||||
std::wstring output_file_path(default_download_path_);
|
||||
output_file_path.append(L"/");
|
||||
output_file_path.append(file_name);
|
||||
|
||||
std::wstring expected(default_download_path_);
|
||||
expected += renamed_file_name;
|
||||
|
||||
std::wifstream input_file;
|
||||
std::wofstream output_file;
|
||||
|
||||
output_file.open(output_file_path,
|
||||
std::ofstream::binary | std::ofstream::out);
|
||||
|
||||
ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit);
|
||||
|
||||
output_file.close();
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, expected);
|
||||
|
||||
// Remove the file and check that it is removed
|
||||
// File 1
|
||||
_wremove(output_file_path.c_str());
|
||||
|
||||
input_file.open(output_file_path, std::ifstream::binary | std::ifstream::in);
|
||||
|
||||
ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit);
|
||||
}
|
||||
|
||||
TEST_F(FilePathTests, GetDownloadPathWithFileName\
|
||||
ParentFolderWithADotShouldBeReplaceedWithUnderscore) {
|
||||
std::wstring parent_folder(L"test/./folder/");
|
||||
std::wstring file_name(kFileName);
|
||||
|
||||
std::wstringstream path(L"");
|
||||
path << default_download_path_ << L"/test/_/folder" << L"/" << kFileName;
|
||||
|
||||
std::wstring expected = path.str();
|
||||
|
||||
auto actual(FilePath::GetDownloadPath(parent_folder, file_name));
|
||||
|
||||
EXPECT_EQ(actual, expected);
|
||||
}
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -15,10 +15,13 @@ licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "types",
|
||||
hdrs = glob(["**/*.h"]),
|
||||
includes = ["."],
|
||||
linkopts = [
|
||||
"wininet.lib",
|
||||
"advapi32.lib",
|
||||
"bcrypt.lib",
|
||||
"cfgmgr32.lib",
|
||||
"comdlg32.lib",
|
||||
"gdi32.lib",
|
||||
"kernel32.lib",
|
||||
@@ -38,12 +41,11 @@ cc_library(
|
||||
"wlanapi.lib",
|
||||
"shlwapi.lib",
|
||||
],
|
||||
textual_hdrs = glob(["**/*.h"]),
|
||||
visibility = [
|
||||
"//fastpair:__subpackages__",
|
||||
"//internal:__subpackages__",
|
||||
"//internal/platform/implementation/windows:__subpackages__",
|
||||
"//location/nearby/cpp/sharing/implementation/internal:__subpackages__",
|
||||
"//third_party/nearby/sharing:__subpackages__",
|
||||
"//location/nearby/apps/better_together/plugins:__subpackages__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/http_loader.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -202,8 +204,8 @@ absl::Status HttpLoader::ConnectWebServer() {
|
||||
0); /*Flags*/
|
||||
|
||||
if (internet_handle_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to open internet with error "
|
||||
<< GetLastError() << ".";
|
||||
LOG(ERROR) << "Failed to open internet with error " << GetLastError()
|
||||
<< ".";
|
||||
return absl::FailedPreconditionError(absl::StrCat(GetLastError()));
|
||||
}
|
||||
|
||||
@@ -217,8 +219,8 @@ absl::Status HttpLoader::ConnectWebServer() {
|
||||
0); /*Context*/
|
||||
|
||||
if (connect_handle_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to connect remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
LOG(ERROR) << "Failed to connect remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
InternetCloseHandle(internet_handle_);
|
||||
return absl::FailedPreconditionError(absl::StrCat(GetLastError()));
|
||||
}
|
||||
@@ -242,9 +244,8 @@ absl::Status HttpLoader::SendRequest() {
|
||||
0);
|
||||
|
||||
if (request_handle_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to open request to remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
LOG(ERROR) << "Failed to open request to remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
InternetCloseHandle(internet_handle_);
|
||||
InternetCloseHandle(connect_handle_);
|
||||
|
||||
@@ -284,9 +285,8 @@ absl::Status HttpLoader::SendRequest() {
|
||||
data_size); /*Data size*/
|
||||
|
||||
if (result == FALSE) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to send request to remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
LOG(ERROR) << "Failed to send request to remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
InternetCloseHandle(request_handle_);
|
||||
InternetCloseHandle(connect_handle_);
|
||||
InternetCloseHandle(internet_handle_);
|
||||
@@ -334,9 +334,8 @@ absl::StatusOr<WebResponse> HttpLoader::ProcessResponse() {
|
||||
web_response.body.append(buffer, read_size);
|
||||
}
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to read response from remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
LOG(ERROR) << "Failed to read response from remote web server with error "
|
||||
<< GetLastError() << ".";
|
||||
InternetCloseHandle(request_handle_);
|
||||
InternetCloseHandle(connect_handle_);
|
||||
InternetCloseHandle(internet_handle_);
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/windows/log_message.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "strings/strappendv.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
api::LogMessage::Severity min_log_severity_ = api::LogMessage::Severity::kInfo;
|
||||
|
||||
inline absl::LogSeverity ConvertSeverity(api::LogMessage::Severity severity) {
|
||||
switch (severity) {
|
||||
// api::LogMessage::Severity kVerbose and kInfo is mapped to
|
||||
// absl::LogSeverity kInfo since absl::LogSeverity doesn't have kVerbose
|
||||
// level.
|
||||
case api::LogMessage::Severity::kVerbose:
|
||||
case api::LogMessage::Severity::kInfo:
|
||||
return absl::LogSeverity::kInfo;
|
||||
case api::LogMessage::Severity::kWarning:
|
||||
return absl::LogSeverity::kWarning;
|
||||
case api::LogMessage::Severity::kError:
|
||||
return absl::LogSeverity::kError;
|
||||
case api::LogMessage::Severity::kFatal:
|
||||
return absl::LogSeverity::kFatal;
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, Severity severity)
|
||||
: log_streamer_(ConvertSeverity(severity), file, line) {}
|
||||
|
||||
LogMessage::~LogMessage() = default;
|
||||
|
||||
void LogMessage::Print(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string result;
|
||||
strings::StrAppendV(&result, format, ap);
|
||||
log_streamer_.stream() << result;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
std::ostream& LogMessage::Stream() { return log_streamer_.stream(); }
|
||||
|
||||
} // namespace windows
|
||||
|
||||
namespace api {
|
||||
|
||||
void LogMessage::SetMinLogSeverity(Severity severity) {
|
||||
windows::min_log_severity_ = severity;
|
||||
}
|
||||
|
||||
bool LogMessage::ShouldCreateLogMessage(Severity severity) {
|
||||
return severity >= windows::min_log_severity_;
|
||||
}
|
||||
} // namespace api
|
||||
} // namespace nearby
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "internal/platform/implementation/log_message.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// See documentation in
|
||||
// cpp/platform/api/log_message.h
|
||||
class LogMessage : public api::LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line, Severity severity);
|
||||
~LogMessage() override;
|
||||
|
||||
void Print(const char* format, ...) override;
|
||||
|
||||
std::ostream& Stream() override;
|
||||
|
||||
private:
|
||||
google::LogMessage log_streamer_;
|
||||
static api::LogMessage::Severity min_log_severity_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_
|
||||
@@ -14,12 +14,9 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_MUTEX_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_MUTEX_H_
|
||||
#include <stdio.h>
|
||||
#include <synchapi.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/mutex.h"
|
||||
|
||||
@@ -59,7 +56,7 @@ class ABSL_LOCKABLE Mutex : public api::Mutex {
|
||||
std::recursive_mutex& GetRecursiveMutex() { return recursive_mutex_; }
|
||||
|
||||
private:
|
||||
friend class ConditionVariable;
|
||||
friend class ::nearby::ConditionVariable;
|
||||
absl::Mutex mutex_;
|
||||
std::recursive_mutex recursive_mutex_; // The actual mutex allocation
|
||||
Mode mode_;
|
||||
|
||||
@@ -27,44 +27,57 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/atomic_boolean.h"
|
||||
#include "internal/platform/implementation/atomic_reference.h"
|
||||
#include "internal/platform/implementation/ble.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/condition_variable.h"
|
||||
#include "internal/platform/implementation/count_down_latch.h"
|
||||
#include "internal/platform/implementation/credential_storage.h"
|
||||
#include "internal/platform/implementation/http_loader.h"
|
||||
#include "internal/platform/implementation/input_file.h"
|
||||
#include "internal/platform/implementation/mutex.h"
|
||||
#include "internal/platform/implementation/output_file.h"
|
||||
#include "internal/platform/implementation/scheduled_executor.h"
|
||||
#include "internal/platform/implementation/server_sync.h"
|
||||
#include "internal/platform/implementation/shared/count_down_latch.h"
|
||||
#include "internal/platform/implementation/submittable_executor.h"
|
||||
#include "internal/platform/implementation/wifi.h"
|
||||
#include "internal/platform/implementation/wifi_lan.h"
|
||||
#include "internal/platform/implementation/windows/atomic_boolean.h"
|
||||
#include "internal/platform/implementation/windows/atomic_reference.h"
|
||||
#include "internal/platform/implementation/windows/ble.h"
|
||||
#include "internal/platform/implementation/windows/ble_medium.h"
|
||||
#include "internal/platform/implementation/windows/ble_v2.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_medium.h"
|
||||
#include "internal/platform/implementation/windows/condition_variable.h"
|
||||
#include "internal/platform/implementation/windows/device_info.h"
|
||||
#include "internal/platform/implementation/windows/executor.h"
|
||||
#include "internal/platform/implementation/windows/file.h"
|
||||
#include "internal/platform/implementation/windows/file_path.h"
|
||||
#include "internal/platform/implementation/windows/future.h"
|
||||
#include "internal/platform/implementation/windows/http_loader.h"
|
||||
#include "internal/platform/implementation/windows/listenable_future.h"
|
||||
#include "internal/platform/implementation/windows/log_message.h"
|
||||
#include "internal/platform/implementation/windows/mutex.h"
|
||||
#include "internal/platform/implementation/windows/preferences_manager.h"
|
||||
#include "internal/platform/implementation/windows/scheduled_executor.h"
|
||||
#include "internal/platform/implementation/windows/server_sync.h"
|
||||
#include "internal/platform/implementation/windows/settable_future.h"
|
||||
#include "internal/platform/implementation/windows/string_utils.h"
|
||||
#include "internal/platform/implementation/windows/submittable_executor.h"
|
||||
#include "internal/platform/implementation/windows/timer.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/implementation/windows/webrtc.h"
|
||||
#include "internal/platform/implementation/windows/wifi.h"
|
||||
#include "internal/platform/implementation/windows/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/windows/wifi_lan.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/os_name.h"
|
||||
#include "internal/platform/payload_id.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace api {
|
||||
@@ -102,28 +115,28 @@ std::string GetApplicationName(DWORD pid) {
|
||||
|
||||
std::string ImplementationPlatform::GetCustomSavePath(
|
||||
const std::string& parent_folder, const std::string& file_name) {
|
||||
auto parent = windows::string_to_wstring(parent_folder);
|
||||
auto file = windows::string_to_wstring(file_name);
|
||||
auto parent = windows::string_utils::StringToWideString(parent_folder);
|
||||
auto file = windows::string_utils::StringToWideString(file_name);
|
||||
|
||||
return windows::wstring_to_string(
|
||||
return windows::string_utils::WideStringToString(
|
||||
windows::FilePath::GetCustomSavePath(parent, file));
|
||||
}
|
||||
|
||||
std::string ImplementationPlatform::GetDownloadPath(
|
||||
const std::string& parent_folder, const std::string& file_name) {
|
||||
auto parent = windows::string_to_wstring(std::string(parent_folder));
|
||||
auto file = windows::string_to_wstring(std::string(file_name));
|
||||
auto parent = windows::string_utils::StringToWideString(parent_folder);
|
||||
auto file = windows::string_utils::StringToWideString(file_name);
|
||||
|
||||
return windows::wstring_to_string(
|
||||
return windows::string_utils::WideStringToString(
|
||||
windows::FilePath::GetDownloadPath(parent, file));
|
||||
}
|
||||
|
||||
std::string ImplementationPlatform::GetDownloadPath(
|
||||
const std::string& file_name) {
|
||||
std::wstring fake_parent_path;
|
||||
auto file = windows::string_to_wstring(std::string(file_name));
|
||||
auto file = windows::string_utils::StringToWideString(file_name);
|
||||
|
||||
return windows::wstring_to_string(
|
||||
return windows::string_utils::WideStringToString(
|
||||
windows::FilePath::GetDownloadPath(fake_parent_path, file));
|
||||
}
|
||||
|
||||
@@ -166,29 +179,29 @@ OSName ImplementationPlatform::GetCurrentOS() { return OSName::kWindows; }
|
||||
|
||||
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(
|
||||
bool initial_value) {
|
||||
return absl::make_unique<windows::AtomicBoolean>();
|
||||
return std::make_unique<windows::AtomicBoolean>(initial_value);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicUint32> ImplementationPlatform::CreateAtomicUint32(
|
||||
std::uint32_t value) {
|
||||
return absl::make_unique<windows::AtomicUint32>();
|
||||
return std::make_unique<windows::AtomicUint32>(value);
|
||||
}
|
||||
|
||||
std::unique_ptr<CountDownLatch> ImplementationPlatform::CreateCountDownLatch(
|
||||
std::int32_t count) {
|
||||
return absl::make_unique<shared::CountDownLatch>(count);
|
||||
return std::make_unique<shared::CountDownLatch>(count);
|
||||
}
|
||||
|
||||
#pragma push_macro("CreateMutex")
|
||||
#undef CreateMutex
|
||||
std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) {
|
||||
return absl::make_unique<windows::Mutex>(mode);
|
||||
return std::make_unique<windows::Mutex>(mode);
|
||||
}
|
||||
#pragma pop_macro("CreateMutex")
|
||||
|
||||
std::unique_ptr<ConditionVariable>
|
||||
ImplementationPlatform::CreateConditionVariable(Mutex* mutex) {
|
||||
return absl::make_unique<windows::ConditionVariable>(mutex);
|
||||
return std::make_unique<windows::ConditionVariable>(mutex);
|
||||
}
|
||||
|
||||
ABSL_DEPRECATED("This interface will be deleted in the near future.")
|
||||
@@ -217,8 +230,8 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
|
||||
const std::string& file_path) {
|
||||
std::string path(file_path);
|
||||
|
||||
auto folder_path =
|
||||
windows::string_to_wstring(path.substr(0, path.find_last_of('/')));
|
||||
auto folder_path = windows::string_utils::StringToWideString(
|
||||
path.substr(0, path.find_last_of('/')));
|
||||
// Verifies that a path is a valid directory.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathisdirectoryw
|
||||
if (!PathIsDirectoryW(folder_path.data())) {
|
||||
@@ -232,42 +245,36 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
|
||||
return windows::IOFile::CreateOutputFile(file_path);
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
|
||||
const char* file, int line, LogMessage::Severity severity) {
|
||||
return absl::make_unique<windows::LogMessage>(file, line, severity);
|
||||
}
|
||||
|
||||
std::unique_ptr<SubmittableExecutor>
|
||||
ImplementationPlatform::CreateSingleThreadExecutor() {
|
||||
return absl::make_unique<windows::SubmittableExecutor>();
|
||||
return std::make_unique<windows::SubmittableExecutor>();
|
||||
}
|
||||
|
||||
std::unique_ptr<SubmittableExecutor>
|
||||
ImplementationPlatform::CreateMultiThreadExecutor(
|
||||
std::int32_t max_concurrency) {
|
||||
return absl::make_unique<windows::SubmittableExecutor>(max_concurrency);
|
||||
return std::make_unique<windows::SubmittableExecutor>(max_concurrency);
|
||||
}
|
||||
|
||||
std::unique_ptr<ScheduledExecutor>
|
||||
ImplementationPlatform::CreateScheduledExecutor() {
|
||||
return absl::make_unique<windows::ScheduledExecutor>();
|
||||
return std::make_unique<windows::ScheduledExecutor>();
|
||||
}
|
||||
|
||||
std::unique_ptr<BluetoothAdapter>
|
||||
ImplementationPlatform::CreateBluetoothAdapter() {
|
||||
return absl::make_unique<windows::BluetoothAdapter>();
|
||||
return std::make_unique<windows::BluetoothAdapter>();
|
||||
}
|
||||
|
||||
std::unique_ptr<BluetoothClassicMedium>
|
||||
ImplementationPlatform::CreateBluetoothClassicMedium(
|
||||
nearby::api::BluetoothAdapter& adapter) {
|
||||
return absl::make_unique<windows::BluetoothClassicMedium>(adapter);
|
||||
return std::make_unique<windows::BluetoothClassicMedium>(adapter);
|
||||
}
|
||||
|
||||
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
|
||||
BluetoothAdapter& adapter) {
|
||||
return absl::make_unique<windows::BleMedium>(adapter);
|
||||
return std::make_unique<windows::BleMedium>(adapter);
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
@@ -276,6 +283,11 @@ ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {
|
||||
return std::make_unique<windows::BleV2Medium>(adapter);
|
||||
}
|
||||
|
||||
std::unique_ptr<api::CredentialStorage>
|
||||
ImplementationPlatform::CreateCredentialStorage() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<ServerSyncMedium>
|
||||
ImplementationPlatform::CreateServerSyncMedium() {
|
||||
@@ -288,7 +300,7 @@ std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() {
|
||||
}
|
||||
|
||||
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
|
||||
return absl::make_unique<windows::WifiLanMedium>();
|
||||
return std::make_unique<windows::WifiLanMedium>();
|
||||
}
|
||||
|
||||
std::unique_ptr<WifiHotspotMedium>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/preferences_manager.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem> // NOLINT(build/c++17)
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -21,9 +22,16 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "nlohmann/json_fwd.hpp"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/platform/implementation/platform.h"
|
||||
#include "internal/platform/implementation/preferences_manager.h"
|
||||
#include "internal/platform/implementation/windows/preferences_repository.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
@@ -39,7 +47,8 @@ PreferencesManager::PreferencesManager(absl::string_view file_path)
|
||||
nearby::api::ImplementationPlatform::CreateDeviceInfo()
|
||||
->GetLocalAppDataPath();
|
||||
if (!path.has_value()) {
|
||||
path = std::filesystem::temp_directory_path();
|
||||
path = nearby::sharing::GetTemporaryDirectory().value_or(
|
||||
nearby::sharing::CurrentDirectory());
|
||||
}
|
||||
|
||||
std::filesystem::path full_path = *path / std::string(file_path);
|
||||
@@ -187,7 +196,7 @@ void PreferencesManager::Remove(absl::string_view key) {
|
||||
// Writes data to storage.
|
||||
bool PreferencesManager::Commit() {
|
||||
if (!preferences_repository_->SavePreferences(value_)) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to save preference." << std::endl;
|
||||
LOG(ERROR) << "Failed to save preference." << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -195,8 +204,8 @@ bool PreferencesManager::Commit() {
|
||||
|
||||
bool PreferencesManager::SetValue(absl::string_view key, const json& value) {
|
||||
if (!value_.is_object()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
LOG(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
value_ = json::object();
|
||||
}
|
||||
|
||||
@@ -212,8 +221,8 @@ template <typename T>
|
||||
T PreferencesManager::GetValue(absl::string_view key,
|
||||
const T& default_value) const {
|
||||
if (!value_.is_object()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
LOG(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@@ -228,8 +237,8 @@ template <typename T>
|
||||
bool PreferencesManager::SetArrayValue(absl::string_view key,
|
||||
absl::Span<const T> value) {
|
||||
if (!value_.is_object()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
LOG(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
value_ = json::object();
|
||||
}
|
||||
|
||||
@@ -252,8 +261,8 @@ std::vector<T> PreferencesManager::GetArrayValue(
|
||||
std::vector<T> result;
|
||||
|
||||
if (!value_.is_object()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
LOG(ERROR) << "Preferences is no longer an object! value_="
|
||||
<< value_.dump(4);
|
||||
|
||||
for (const T& value : default_value) {
|
||||
result.push_back(value);
|
||||
|
||||
@@ -41,26 +41,23 @@ constexpr absl::Duration kTimeOut = absl::Milliseconds(200);
|
||||
constexpr char kPreferencesFilePath[] = "Google/Nearby/Sharing";
|
||||
} // namespace
|
||||
|
||||
|
||||
TEST(PreferencesManager, CorruptedConfigFile) {
|
||||
std::filesystem::path settingsPath =
|
||||
std::filesystem::temp_directory_path();
|
||||
std::filesystem::path settingsPath = std::filesystem::temp_directory_path();
|
||||
std::ofstream output_stream{settingsPath / "preferences.json"};
|
||||
output_stream << "CORRUPTED" << std::endl;
|
||||
|
||||
NEARBY_LOGS(INFO) << "Loading preferences from: " << settingsPath.string();
|
||||
LOG(INFO) << "Loading preferences from: " << settingsPath.string();
|
||||
EXPECT_EQ(PreferencesManager(settingsPath.string()).GetInteger("data", 100),
|
||||
100);
|
||||
}
|
||||
|
||||
TEST(PreferencesManager, ValidConfigFile) {
|
||||
std::filesystem::path settingsPath =
|
||||
std::filesystem::temp_directory_path();
|
||||
std::filesystem::path settingsPath = std::filesystem::temp_directory_path();
|
||||
std::ofstream output_stream{settingsPath / "preferences.json"};
|
||||
output_stream << "{\"data\":8, \"name\": \"Valid\"}" << std::endl;
|
||||
output_stream.close();
|
||||
|
||||
NEARBY_LOGS(INFO) << "Loading preferences from: " << settingsPath.string();
|
||||
LOG(INFO) << "Loading preferences from: " << settingsPath.string();
|
||||
EXPECT_EQ(PreferencesManager(settingsPath.string()).GetInteger("data", 100),
|
||||
8);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "nlohmann/json_fwd.hpp"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -40,8 +42,8 @@ json PreferencesRepository::LoadPreferences() {
|
||||
// The top level root should be an object, if it's not then something went
|
||||
// wrong or the file was corrupted.
|
||||
if (!preferences.value().is_object()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences loaded was not a valid object: "
|
||||
<< preferences.value().dump(4);
|
||||
LOG(ERROR) << "Preferences loaded was not a valid object: "
|
||||
<< preferences.value().dump(4);
|
||||
|
||||
return json::object();
|
||||
}
|
||||
@@ -49,17 +51,17 @@ json PreferencesRepository::LoadPreferences() {
|
||||
return preferences.value();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Could not load preferences file, trying backup.";
|
||||
LOG(ERROR) << "Could not load preferences file, trying backup.";
|
||||
|
||||
// In the future we should switch to using a transaction log or another
|
||||
// stable method which doesn't pose a risk of losing settings
|
||||
preferences = RestoreFromBackup();
|
||||
if (preferences.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << "Successfully recovered from backup.";
|
||||
LOG(ERROR) << "Successfully recovered from backup.";
|
||||
return preferences.value();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Failed to load preferences file from back up.";
|
||||
LOG(ERROR) << "Failed to load preferences file from back up.";
|
||||
|
||||
return json::object();
|
||||
}
|
||||
@@ -68,9 +70,9 @@ bool PreferencesRepository::SavePreferences(json preferences) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
try {
|
||||
std::filesystem::path path = path_;
|
||||
if (!std::filesystem::exists(path) &&
|
||||
!std::filesystem::create_directories(path)) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to create preferences path.";
|
||||
if (!nearby::sharing::FileExists(path) &&
|
||||
!nearby::sharing::CreateDirectories(path)) {
|
||||
LOG(ERROR) << "Failed to create preferences path.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -78,30 +80,32 @@ bool PreferencesRepository::SavePreferences(json preferences) {
|
||||
std::filesystem::path full_name_backup = path / kPreferencesBackupFileName;
|
||||
|
||||
// Create a backup without moving the bytes on disk
|
||||
if (std::filesystem::exists(full_name)) {
|
||||
NEARBY_LOGS(INFO) << "Making backup of preferences file.";
|
||||
std::filesystem::rename(full_name, full_name_backup);
|
||||
if (nearby::sharing::FileExists(full_name)) {
|
||||
LOG(INFO) << "Making backup of preferences file.";
|
||||
if (!nearby::sharing::Rename(full_name, full_name_backup)) {
|
||||
LOG(ERROR) << "Failed to rename preferences backup file.";
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream preferences_file(full_name.c_str());
|
||||
std::ofstream preferences_file(full_name);
|
||||
preferences_file << preferences;
|
||||
preferences_file.close();
|
||||
|
||||
// Make sure the file wasn't saved in a corrupted state
|
||||
if (!AttemptLoad().has_value()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences saved to disk in corrupted state. "
|
||||
"Restoring from backup.";
|
||||
LOG(ERROR) << "Preferences saved to disk in corrupted state. "
|
||||
"Restoring from backup.";
|
||||
|
||||
if (!RestoreFromBackup().has_value()) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to restore preferences file.";
|
||||
LOG(ERROR) << "Failed to restore preferences file.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to save preferences file: " << e.what();
|
||||
LOG(ERROR) << "Failed to save preferences file: " << e.what();
|
||||
return false;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,12 +115,13 @@ bool PreferencesRepository::SavePreferences(json preferences) {
|
||||
std::optional<json> PreferencesRepository::AttemptLoad() {
|
||||
std::filesystem::path path = path_;
|
||||
std::filesystem::path full_name = path / kPreferencesFileName;
|
||||
if (!std::filesystem::exists(path) || !std::filesystem::exists(full_name)) {
|
||||
if (!nearby::sharing::DirectoryExists(path) ||
|
||||
!nearby::sharing::FileExists(full_name)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
try {
|
||||
std::ifstream preferences_file(full_name.c_str());
|
||||
std::ifstream preferences_file(full_name);
|
||||
if (!preferences_file.good()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -125,16 +130,16 @@ std::optional<json> PreferencesRepository::AttemptLoad() {
|
||||
preferences_file.close();
|
||||
|
||||
if (preferences.is_discarded()) {
|
||||
NEARBY_LOGS(ERROR) << "Preferences file corrupted.";
|
||||
LOG(ERROR) << "Preferences file corrupted.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return preferences;
|
||||
} catch (const std::exception& e) {
|
||||
NEARBY_LOGS(ERROR) << "Exception while loading preferences: " << e.what();
|
||||
LOG(ERROR) << "Exception while loading preferences: " << e.what();
|
||||
return std::nullopt;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exception.";
|
||||
LOG(ERROR) << __func__ << ": Unknown exception.";
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
@@ -144,15 +149,16 @@ std::optional<json> PreferencesRepository::RestoreFromBackup() {
|
||||
std::filesystem::path full_name = path / kPreferencesFileName;
|
||||
std::filesystem::path full_name_backup = path / kPreferencesBackupFileName;
|
||||
|
||||
if (!std::filesystem::exists(full_name_backup)) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "Backup requested but no backup preferences file found.";
|
||||
if (!nearby::sharing::FileExists(full_name_backup)) {
|
||||
LOG(WARNING) << "Backup requested but no backup preferences file found.";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::filesystem::rename(full_name_backup, full_name);
|
||||
if (!nearby::sharing::Rename(full_name_backup, full_name)) {
|
||||
LOG(ERROR) << "Failed to rename preferences backup file.";
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Attempting load from backup preferences.";
|
||||
LOG(INFO) << "Attempting load from backup preferences.";
|
||||
return AttemptLoad();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,19 +16,25 @@
|
||||
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/cancelable.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
ScheduledExecutor::ScheduledExecutor()
|
||||
: executor_(std::make_unique<nearby::windows::Executor>()),
|
||||
shut_down_(false) {}
|
||||
shut_down_(false),
|
||||
use_task_scheduler_(NearbyFlags::GetInstance().GetBoolFlag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableTaskScheduler)) {}
|
||||
|
||||
// Cancelable is kept both in the executor context, and in the caller context.
|
||||
// We want Cancelable to live until both caller and executor are done with it.
|
||||
@@ -36,30 +42,44 @@ ScheduledExecutor::ScheduledExecutor()
|
||||
// using std:shared_ptr<> instead of std::unique_ptr<>.
|
||||
std::shared_ptr<api::Cancelable> ScheduledExecutor::Schedule(
|
||||
Runnable&& runnable, absl::Duration duration) {
|
||||
if (shut_down_) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Attempt to Schedule on a shut down executor.";
|
||||
if (use_task_scheduler_) {
|
||||
if (shut_down_) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Attempt to Schedule on a shut down executor.";
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
return task_scheduler_.Schedule(std::move(runnable), duration);
|
||||
} else {
|
||||
if (shut_down_) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": Attempt to Schedule on a shut down executor.";
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Cleans completed tasks
|
||||
auto it = scheduled_tasks_.begin();
|
||||
while (it != scheduled_tasks_.end()) {
|
||||
if ((*it)->IsDone()) {
|
||||
it = scheduled_tasks_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ScheduledTask> task =
|
||||
std::make_shared<ScheduledTask>(std::move(runnable), duration);
|
||||
|
||||
scheduled_tasks_.push_back(task);
|
||||
executor_->Execute([task]() { task->Start(); });
|
||||
return task;
|
||||
}
|
||||
|
||||
// Cleans completed tasks
|
||||
std::remove_if(
|
||||
scheduled_tasks_.begin(), scheduled_tasks_.end(),
|
||||
[](std::shared_ptr<ScheduledTask>& task) { return task->IsDone(); });
|
||||
|
||||
std::shared_ptr<ScheduledTask> task =
|
||||
std::make_shared<ScheduledTask>(std::move(runnable), duration);
|
||||
|
||||
scheduled_tasks_.push_back(task);
|
||||
executor_->Execute([task]() { task->Start(); });
|
||||
return task;
|
||||
}
|
||||
|
||||
void ScheduledExecutor::Execute(Runnable&& runnable) {
|
||||
if (shut_down_) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Attempt to Execute on a shut down executor.";
|
||||
LOG(ERROR) << __func__ << ": Attempt to Execute on a shut down executor.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,18 +87,26 @@ void ScheduledExecutor::Execute(Runnable&& runnable) {
|
||||
}
|
||||
|
||||
void ScheduledExecutor::Shutdown() {
|
||||
if (!shut_down_) {
|
||||
shut_down_ = true;
|
||||
for (auto& task : scheduled_tasks_) {
|
||||
task->Cancel();
|
||||
if (use_task_scheduler_) {
|
||||
if (!shut_down_) {
|
||||
shut_down_ = true;
|
||||
executor_->Shutdown();
|
||||
task_scheduler_.Shutdown();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!shut_down_) {
|
||||
shut_down_ = true;
|
||||
for (auto& task : scheduled_tasks_) {
|
||||
task->Cancel();
|
||||
}
|
||||
|
||||
scheduled_tasks_.clear();
|
||||
executor_->Shutdown();
|
||||
return;
|
||||
scheduled_tasks_.clear();
|
||||
executor_->Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Attempt to Shutdown on a shut down executor.";
|
||||
LOG(ERROR) << __func__ << ": Attempt to Shutdown on a shut down executor.";
|
||||
}
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/synchronization/notification.h"
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "internal/platform/implementation/cancelable.h"
|
||||
#include "internal/platform/implementation/scheduled_executor.h"
|
||||
#include "internal/platform/implementation/windows/executor.h"
|
||||
#include "internal/platform/implementation/windows/task_scheduler.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -49,7 +51,7 @@ class ScheduledExecutor : public api::ScheduledExecutor {
|
||||
std::shared_ptr<api::Cancelable> Schedule(Runnable&& runnable,
|
||||
absl::Duration duration) override;
|
||||
|
||||
// Executes the runnable task immedately.
|
||||
// Executes the runnable task immediately.
|
||||
void Execute(Runnable&& runnable) override;
|
||||
|
||||
// Shutdowns the executor, all scheduled task will be cancelled.
|
||||
@@ -94,6 +96,9 @@ class ScheduledExecutor : public api::ScheduledExecutor {
|
||||
std::unique_ptr<nearby::windows::Executor> executor_ = nullptr;
|
||||
std::vector<std::shared_ptr<ScheduledTask>> scheduled_tasks_;
|
||||
std::atomic_bool shut_down_ = false;
|
||||
|
||||
const bool use_task_scheduler_;
|
||||
TaskScheduler task_scheduler_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/scheduled_executor.h"
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -21,13 +22,31 @@
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/windows/test_data.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
|
||||
TEST(ScheduledExecutorTests, ExecuteSucceeds) {
|
||||
constexpr absl::Duration kWaitTimeout = absl::Milliseconds(2000);
|
||||
|
||||
class ScheduledExecutorTest : public ::testing::TestWithParam<bool> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableTaskScheduler,
|
||||
GetParam());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
NearbyFlags::GetInstance().ResetOverridedValues();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(ScheduledExecutorTest, ExecuteSucceeds) {
|
||||
absl::Notification notification;
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
@@ -47,8 +66,7 @@ TEST(ScheduledExecutorTests, ExecuteSucceeds) {
|
||||
notification.Notify();
|
||||
});
|
||||
|
||||
ASSERT_TRUE(
|
||||
notification.WaitForNotificationWithTimeout(absl::Milliseconds(200)));
|
||||
ASSERT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout));
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
@@ -61,7 +79,7 @@ TEST(ScheduledExecutorTests, ExecuteSucceeds) {
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, ScheduleSucceeds) {
|
||||
TEST_P(ScheduledExecutorTest, ScheduleSucceeds) {
|
||||
absl::Notification notification;
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
@@ -88,8 +106,7 @@ TEST(ScheduledExecutorTests, ScheduleSucceeds) {
|
||||
},
|
||||
absl::Milliseconds(50));
|
||||
|
||||
ASSERT_TRUE(
|
||||
notification.WaitForNotificationWithTimeout(absl::Milliseconds(200)));
|
||||
ASSERT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout));
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
@@ -99,7 +116,7 @@ TEST(ScheduledExecutorTests, ScheduleSucceeds) {
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelSucceeds) {
|
||||
TEST_P(ScheduledExecutorTest, CancelSucceeds) {
|
||||
absl::Notification notification;
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
@@ -123,8 +140,7 @@ TEST(ScheduledExecutorTests, CancelSucceeds) {
|
||||
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
EXPECT_FALSE(
|
||||
notification.WaitForNotificationWithTimeout(absl::Milliseconds(2000)));
|
||||
EXPECT_FALSE(notification.WaitForNotificationWithTimeout(kWaitTimeout));
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
@@ -136,7 +152,7 @@ TEST(ScheduledExecutorTests, CancelSucceeds) {
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
|
||||
TEST_P(ScheduledExecutorTest, CancelAfterStartedFails) {
|
||||
absl::Notification notification;
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
@@ -158,11 +174,10 @@ TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
|
||||
},
|
||||
absl::Milliseconds(100));
|
||||
|
||||
absl::SleepFor(absl::Milliseconds(200));
|
||||
absl::SleepFor(absl::Milliseconds(500));
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
ASSERT_TRUE(
|
||||
notification.WaitForNotificationWithTimeout(absl::Milliseconds(2000)));
|
||||
ASSERT_TRUE(notification.WaitForNotificationWithTimeout(kWaitTimeout));
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
@@ -174,6 +189,9 @@ TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ScheduledExecutorTaskSchedulerFlagTest,
|
||||
ScheduledExecutorTest, testing::Bool());
|
||||
|
||||
} // namespace
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "absl/base/const_init.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/implementation/windows/submittable_executor.h"
|
||||
@@ -91,7 +92,7 @@ bool SessionManager::RegisterSessionListener(
|
||||
absl::string_view listener_name,
|
||||
absl::AnyInvocable<void(SessionState)> callback) {
|
||||
absl::MutexLock lock(&session_mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Registering listener: " << listener_name;
|
||||
LOG(INFO) << __func__ << ": Registering listener: " << listener_name;
|
||||
|
||||
// Create session thread if no running thread.
|
||||
if (session_thread_ == nullptr) {
|
||||
@@ -114,38 +115,36 @@ bool SessionManager::RegisterSessionListener(
|
||||
|
||||
session_callbacks_->emplace(listener_name, std::move(callback));
|
||||
listeners_.emplace(listener_name);
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is registered.";
|
||||
LOG(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is registered.";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionManager::UnregisterSessionListener(
|
||||
absl::string_view listener_name) {
|
||||
absl::MutexLock lock(&session_mutex_);
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Unregistering listener: " << listener_name;
|
||||
LOG(INFO) << __func__ << ": Unregistering listener: " << listener_name;
|
||||
if (session_thread_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No running listener.";
|
||||
LOG(ERROR) << __func__ << ": No running listener.";
|
||||
return false;
|
||||
}
|
||||
if (!session_callbacks_->contains(listener_name) ||
|
||||
!listeners_.contains(listener_name)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": No listener with name:" << listener_name;
|
||||
LOG(ERROR) << __func__ << ": No listener with name:" << listener_name;
|
||||
return false;
|
||||
}
|
||||
session_callbacks_->erase(listener_name);
|
||||
listeners_.erase(listener_name);
|
||||
|
||||
if (!session_callbacks_->empty()) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is unregistered.";
|
||||
LOG(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is unregistered.";
|
||||
return true;
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is unregistered.";
|
||||
LOG(INFO) << __func__ << ": Session listener: " << listener_name
|
||||
<< " is unregistered.";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -178,8 +177,7 @@ bool SessionManager::PreventSleep() const {
|
||||
EXECUTION_STATE execution_state =
|
||||
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
|
||||
if (execution_state == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set execution state of the thread.";
|
||||
LOG(ERROR) << __func__ << ": Failed to set execution state of the thread.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -188,16 +186,15 @@ bool SessionManager::PreventSleep() const {
|
||||
bool SessionManager::AllowSleep() const {
|
||||
EXECUTION_STATE execution_state = SetThreadExecutionState(ES_CONTINUOUS);
|
||||
if (execution_state == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set execution state of the thread.";
|
||||
LOG(ERROR) << __func__ << ": Failed to set execution state of the thread.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionManager::NotifySessionState(SessionState state) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Notifying session state: " << static_cast<int>(state);
|
||||
LOG(INFO) << __func__
|
||||
<< ": Notifying session state: " << static_cast<int>(state);
|
||||
if (state == SessionManager::SessionState::kLock) {
|
||||
absl::MutexLock lock(&session_mutex_);
|
||||
for (auto& it : *SessionManager::session_callbacks_) {
|
||||
@@ -214,19 +211,18 @@ void SessionManager::NotifySessionState(SessionState state) {
|
||||
void SessionManager::StartSession(absl::Notification& notification) {
|
||||
session_hwnd_ = CreateNearbyWindow();
|
||||
if (session_hwnd_ == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create session Window.";
|
||||
LOG(ERROR) << __func__ << ": Failed to create session Window.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WTSRegisterSessionNotification(session_hwnd_, NOTIFY_FOR_THIS_SESSION)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ":Failed to register session notification.";
|
||||
LOG(ERROR) << __func__ << ":Failed to register session notification.";
|
||||
return;
|
||||
}
|
||||
|
||||
notification.Notify();
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Session thread started.";
|
||||
LOG(INFO) << __func__ << ": Session thread started.";
|
||||
|
||||
// Main message loop
|
||||
MSG msg = {};
|
||||
@@ -237,17 +233,16 @@ void SessionManager::StartSession(absl::Notification& notification) {
|
||||
}
|
||||
|
||||
if (!WTSUnRegisterSessionNotification(session_hwnd_)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to register session notification.";
|
||||
LOG(ERROR) << __func__ << ": Failed to register session notification.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UnregisterClassA(/*lpClassName=*/kMessageWindowClass,
|
||||
/*hInstance=*/(HINSTANCE)GetModuleHandle(nullptr))) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to unregister window class.";
|
||||
LOG(ERROR) << __func__ << ": Failed to unregister window class.";
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Completed Message loop.";
|
||||
LOG(INFO) << __func__ << ": Completed Message loop.";
|
||||
}
|
||||
|
||||
void SessionManager::StopSession() {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/windows/string_utils.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby::windows::string_utils {
|
||||
|
||||
// Converts std::string to wstring
|
||||
std::wstring StringToWideString(std::string str) {
|
||||
if (str.empty()) {
|
||||
return L"";
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
|
||||
int output_length =
|
||||
MultiByteToWideChar(/*CodePage=*/CP_UTF8,
|
||||
/*dwFlags=*/0,
|
||||
/*lpMultiByteStr=*/str.c_str(),
|
||||
/*cbMultiByte=*/static_cast<int>(str.length()),
|
||||
/*lpWideCharStr=*/nullptr,
|
||||
/*cchWideChar=*/0);
|
||||
if (output_length == 0) {
|
||||
return L"";
|
||||
}
|
||||
std::wstring output(output_length, L'\0');
|
||||
int result = MultiByteToWideChar(
|
||||
/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpMultiByteStr=*/str.c_str(),
|
||||
/*cbMultiByte=*/static_cast<int>(str.length()),
|
||||
/*lpWideCharStr=*/&output[0],
|
||||
/*cchWideChar=*/output_length);
|
||||
if (result == 0) {
|
||||
LOG(INFO) << "Error converting String to Wstring. Error code: "
|
||||
<< GetLastError();
|
||||
return L"";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Converts wstring to std::string
|
||||
std::string WideStringToString(std::wstring wstr) {
|
||||
if (wstr.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string output;
|
||||
size_t start = 0;
|
||||
size_t index = 0;
|
||||
|
||||
// Iterate over the wstring buffer, chop it into wchar chunks and convert them
|
||||
// one-by-one
|
||||
do {
|
||||
index = wstr.find(L'\0', start);
|
||||
if (index == std::wstring::npos) index = wstr.length();
|
||||
if (start <= wstr.length()) {
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
|
||||
int size =
|
||||
WideCharToMultiByte(/*CodePage=*/CP_UTF8,
|
||||
/*dwFlags=*/WC_ERR_INVALID_CHARS,
|
||||
/*lpWideCharStr=*/&wstr[start],
|
||||
/*cchWideChar=*/static_cast<int>(index - start),
|
||||
/*lpMultiByteStr=*/nullptr,
|
||||
/*cbMultiByte=*/0,
|
||||
/*lpDefaultChar=*/nullptr,
|
||||
/*lpUsedDefaultChar=*/nullptr);
|
||||
if (size == 0) {
|
||||
return "";
|
||||
}
|
||||
std::string converted_chunk = std::string(size, '\0');
|
||||
int result = WideCharToMultiByte(
|
||||
/*CodePage=*/CP_UTF8, /*dwFlags=*/WC_ERR_INVALID_CHARS,
|
||||
/*lpWideCharStr=*/&wstr[start],
|
||||
/*cchWideChar=*/static_cast<int>(index - start),
|
||||
/*lpMultiByteStr=*/&converted_chunk[0],
|
||||
/*cbMultiByte=*/static_cast<int>(converted_chunk.size()),
|
||||
/*lpDefaultChar=*/nullptr,
|
||||
/*lpUsedDefaultChar=*/nullptr);
|
||||
if (result == 0) {
|
||||
LOG(INFO) << "Error converting Wstring to String. Error code: "
|
||||
<< GetLastError();
|
||||
return "";
|
||||
}
|
||||
output.append(converted_chunk);
|
||||
// Append '\0' to handle the case of {wstring \0 wstring \0 wstring} ->
|
||||
// {string \0 string \0 string}
|
||||
if (index < wstr.length()) {
|
||||
LOG(INFO) << "Appending a null byte to string";
|
||||
output.append(1, '\0');
|
||||
}
|
||||
}
|
||||
start = index + 1;
|
||||
} while (index != std::wstring::npos && start < wstr.length());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace nearby::windows::string_utils
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace nearby::windows::string_utils {
|
||||
|
||||
// Converts UTF-8 encoded string to wstring
|
||||
std::wstring StringToWideString(std::string str);
|
||||
// Converts wstring to UTF-8 encoded string
|
||||
std::string WideStringToString(std::wstring wstr);
|
||||
|
||||
} // namespace nearby::windows::string_utils
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user