mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Merge branch 'sync-upstream'
bringing main up to speed with upstream
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
build --action_env=BAZEL_CXXOPTS=-"std=c++20" --repo_env=BAZEL_CONLYOPTS="-std=gnu17"
|
||||
build --action_env=CC=/usr/bin/clang
|
||||
build --action_env=CXX=/usr/bin/clang++
|
||||
build --check_visibility=false --spawn_strategy=standalone --verbose_failures
|
||||
build --cxxopt=-std=c++20
|
||||
build --cxxopt='-fvisibility-inlines-hidden'
|
||||
build --host_cxxopt=-std=c++20
|
||||
# Definition of --config=memcheck
|
||||
build:memcheck --strip=never --test_timeout=3600
|
||||
common --enable_bzlmod
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# Copyright 2026 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,25 +12,18 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
|
||||
licenses(["notice"])
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
proto_library(
|
||||
name = "sharing_log_proto",
|
||||
srcs = [
|
||||
"nearby_sharing_log.proto",
|
||||
],
|
||||
deps = [
|
||||
"//proto:sharing_enums_proto",
|
||||
"@com_google_protobuf//:duration_proto",
|
||||
],
|
||||
licenses(["notice"])
|
||||
|
||||
bool_flag(
|
||||
name = "enable_webrtc",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
cc_proto_library(
|
||||
name = "sharing_log_cc_proto",
|
||||
deps = [":sharing_log_proto"],
|
||||
config_setting(
|
||||
name = "webrtc_enabled",
|
||||
flag_values = {":enable_webrtc": "True"},
|
||||
)
|
||||
+2
-1
@@ -190,10 +190,11 @@ cmake(
|
||||
"CMAKE_C_STANDARD": "17",
|
||||
"CMAKE_C_STANDARD_REQUIRED": "ON",
|
||||
"CMAKE_C_EXTENSIONS": "ON",
|
||||
"CMAKE_INSTALL_LIBDIR": "lib",
|
||||
},
|
||||
env = {
|
||||
# CMake still needs pkg-config to pass its internal configuration checks for systemd
|
||||
"PKG_CONFIG_PATH": "/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig",
|
||||
"PKG_CONFIG_PATH": "/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig",
|
||||
},
|
||||
# Link the systemd dependency you defined in your WORKSPACE
|
||||
deps = ["@libsystemd//:libsystemd"],
|
||||
|
||||
+20
-32
@@ -92,7 +92,7 @@ let package = Package(
|
||||
.target(
|
||||
name: "protobuf-utf8",
|
||||
dependencies: [
|
||||
.product(name: "abseil", package: "abseil-cpp-SwiftPM"),
|
||||
.product(name: "abseil", package: "abseil-cpp-SwiftPM")
|
||||
],
|
||||
path: "third_party/protobuf/third_party/utf8_range",
|
||||
sources: [
|
||||
@@ -102,13 +102,13 @@ let package = Package(
|
||||
],
|
||||
publicHeadersPath: ".",
|
||||
cSettings: [
|
||||
.headerSearchPath("./"),
|
||||
.headerSearchPath("./")
|
||||
],
|
||||
),
|
||||
.target(
|
||||
name: "protobuf",
|
||||
dependencies: [
|
||||
"protobuf-utf8",
|
||||
"protobuf-utf8"
|
||||
],
|
||||
path: "third_party/protobuf/src",
|
||||
exclude: [
|
||||
@@ -282,11 +282,11 @@ let package = Package(
|
||||
"google/protobuf/io/zero_copy_sink_test.cc",
|
||||
],
|
||||
sources: [
|
||||
"google/protobuf",
|
||||
"google/protobuf"
|
||||
],
|
||||
publicHeadersPath: ".",
|
||||
cSettings: [
|
||||
.headerSearchPath("./"),
|
||||
.headerSearchPath("./")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
@@ -321,7 +321,6 @@ let package = Package(
|
||||
"connections/implementation/flags/BUILD",
|
||||
"connections/implementation/mediums/advertisements/BUILD",
|
||||
"connections/implementation/mediums/ble/BUILD",
|
||||
"connections/implementation/mediums/multiplex/BUILD",
|
||||
"connections/implementation/mediums/BUILD",
|
||||
"connections/implementation/BUILD",
|
||||
"connections/implementation/fuzzers",
|
||||
@@ -346,7 +345,6 @@ let package = Package(
|
||||
"internal/platform/implementation/apple/Mediums/WiFiCommon/BUILD",
|
||||
"internal/platform/implementation/BUILD",
|
||||
"internal/platform/BUILD",
|
||||
"internal/analytics/BUILD",
|
||||
"internal/flags/BUILD",
|
||||
"internal/network/BUILD",
|
||||
"internal/rpc/BUILD",
|
||||
@@ -369,17 +367,12 @@ let package = Package(
|
||||
"connections/implementation/payload_manager_test.cc",
|
||||
"connections/implementation/offline_frames_validator_test.cc",
|
||||
"connections/implementation/service_controller_router_test.cc",
|
||||
"connections/implementation/awdl_bwu_handler_test.cc",
|
||||
"connections/implementation/bluetooth_bwu_test.cc",
|
||||
"connections/implementation/wifi_direct_bwu_test.cc",
|
||||
"connections/implementation/wifi_hotspot_bwu_test.cc",
|
||||
"connections/implementation/wifi_lan_bwu_handler_test.cc",
|
||||
"connections/implementation/analytics/analytics_recorder_test.cc",
|
||||
"connections/implementation/analytics/throughput_recorder_test.cc",
|
||||
"connections/implementation/analytics/analytics_recorder_impl_test.cc",
|
||||
"connections/implementation/mediums/advertisements/data_element_test.cc",
|
||||
"connections/implementation/mediums/advertisements/dct_advertisement_test.cc",
|
||||
"connections/implementation/mediums/advertisements/advertisement_util_test.cc",
|
||||
"connections/implementation/mediums/awdl_test.cc",
|
||||
"connections/implementation/mediums/awdl_bwu_handler_test.cc",
|
||||
"connections/implementation/mediums/ble_test.cc",
|
||||
"connections/implementation/mediums/ble/bloom_filter_test.cc",
|
||||
"connections/implementation/mediums/ble/ble_l2cap_packet_test.cc",
|
||||
@@ -392,18 +385,19 @@ let package = Package(
|
||||
"connections/implementation/mediums/ble/discovered_peripheral_tracker_test.cc",
|
||||
"connections/implementation/mediums/ble/instant_on_lost_advertisement_test.cc",
|
||||
"connections/implementation/mediums/ble/instant_on_lost_manager_test.cc",
|
||||
"connections/implementation/mediums/multiplex/multiplex_frames_test.cc",
|
||||
"connections/implementation/mediums/multiplex/multiplex_socket_test.cc",
|
||||
"connections/implementation/mediums/multiplex/multiplex_output_stream_test.cc",
|
||||
"connections/implementation/mediums/webrtc_peer_id_test.cc",
|
||||
"connections/implementation/mediums/wifi_lan_test.cc",
|
||||
"connections/implementation/mediums/bluetooth_classic_test.cc",
|
||||
"connections/implementation/mediums/ble_test.cc",
|
||||
"connections/implementation/mediums/webrtc_test.cc",
|
||||
"connections/implementation/mediums/lost_entity_tracker_test.cc",
|
||||
"connections/implementation/mediums/bluetooth_bwu_handler_test.cc",
|
||||
"connections/implementation/mediums/bluetooth_classic_test.cc",
|
||||
"connections/implementation/mediums/bluetooth_radio_test.cc",
|
||||
"connections/implementation/mediums/lost_entity_tracker_test.cc",
|
||||
"connections/implementation/mediums/webrtc_peer_id_test.cc",
|
||||
"connections/implementation/mediums/webrtc_test.cc",
|
||||
"connections/implementation/mediums/wifi_direct_bwu_handler_test.cc",
|
||||
"connections/implementation/mediums/wifi_direct_test.cc",
|
||||
"connections/implementation/mediums/wifi_hotspot_bwu_handler_test.cc",
|
||||
"connections/implementation/mediums/wifi_hotspot_test.cc",
|
||||
"connections/implementation/mediums/wifi_lan_bwu_handler_test.cc",
|
||||
"connections/implementation/mediums/wifi_lan_test.cc",
|
||||
"connections/implementation/mediums/wifi_test.cc",
|
||||
"connections/implementation/endpoint_channel_manager_test.cc",
|
||||
"connections/implementation/bwu_manager_test.cc",
|
||||
@@ -438,13 +432,13 @@ let package = Package(
|
||||
"internal/encoding/base85_test.cc",
|
||||
"internal/data/leveldb_data_set_test.cc",
|
||||
"internal/flags/nearby_flags_test.cc",
|
||||
"internal/proto/analytics/connections_log_test.cc",
|
||||
"internal/platform/feature_flags_test.cc",
|
||||
"internal/platform/file_test.cc",
|
||||
"internal/platform/cancelable_alarm_test.cc",
|
||||
"internal/platform/crypto_test.cc",
|
||||
"internal/platform/byte_array_test.cc",
|
||||
"internal/platform/credential_storage_impl_test.cc",
|
||||
"internal/platform/implementation/device_info_test.cc",
|
||||
"internal/platform/implementation/g3/awdl_test.cc",
|
||||
"internal/platform/implementation/g3/ble_test.cc",
|
||||
"internal/platform/input_stream_test.cc",
|
||||
@@ -479,6 +473,7 @@ let package = Package(
|
||||
"internal/platform/implementation/apple/mutex_test.cc",
|
||||
"internal/platform/implementation/apple/atomic_boolean_test.cc",
|
||||
"internal/platform/implementation/apple/atomic_uint32_test.cc",
|
||||
"internal/platform/implementation/apple/webrtc_platform.mm",
|
||||
"internal/platform/implementation/shared/file_test.cc",
|
||||
"internal/platform/implementation/wifi_utils_test.cc",
|
||||
"internal/platform/atomic_boolean_test.cc",
|
||||
@@ -501,7 +496,6 @@ let package = Package(
|
||||
"internal/network/http_client_impl_test.cc",
|
||||
"internal/network/http_status_code_test.cc",
|
||||
"internal/test/fake_clock_test.cc",
|
||||
"internal/test/fake_webrtc.cc",
|
||||
"internal/test/fake_timer_test.cc",
|
||||
"internal/test/fake_device_info_test.cc",
|
||||
"internal/test/fake_task_runner_test.cc",
|
||||
@@ -523,16 +517,9 @@ let package = Package(
|
||||
"proto",
|
||||
"internal/data/leveldb_data_set_test.proto",
|
||||
// webrtc
|
||||
"connections/implementation/webrtc_bwu_handler.cc",
|
||||
"connections/implementation/webrtc_endpoint_channel.cc",
|
||||
"connections/implementation/mediums/webrtc.cc",
|
||||
"connections/implementation/mediums/webrtc_peer_id.cc",
|
||||
"connections/implementation/mediums/webrtc",
|
||||
"internal/platform/tachyon_express_signaling_messenger.cc",
|
||||
"internal/platform/tachyon_express_signaling_messenger.h",
|
||||
"internal/platform/implementation/apple/webrtc.h",
|
||||
"internal/platform/implementation/apple/webrtc.mm",
|
||||
// This breaks the build, but seems to work fine without it?
|
||||
// Only used in tests
|
||||
"internal/platform/medium_environment.cc",
|
||||
],
|
||||
sources: [
|
||||
@@ -565,6 +552,7 @@ let package = Package(
|
||||
.headerSearchPath("./"),
|
||||
.headerSearchPath("compiled_proto/"),
|
||||
.define("NO_WEBRTC"),
|
||||
.define("NC_OSS_BUILD"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
|
||||
@@ -562,6 +562,9 @@ inline constexpr BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCred
|
||||
pin_(
|
||||
&::google::protobuf::internal::fixed_address_empty_string,
|
||||
::_pbi::ConstantInitialized()),
|
||||
device_name_(
|
||||
&::google::protobuf::internal::fixed_address_empty_string,
|
||||
::_pbi::ConstantInitialized()),
|
||||
port_{0},
|
||||
frequency_{0} {}
|
||||
|
||||
@@ -2056,44 +2059,47 @@ bool AutoReconnectFrame_EventType_Parse(::absl::string_view name, AutoReconnectF
|
||||
return success;
|
||||
}
|
||||
PROTOBUF_CONSTINIT const uint32_t MediumMetadata_WifiDirectAuthType_internal_data_[] = {
|
||||
196608u, 0u, };
|
||||
262144u, 0u, };
|
||||
static ::google::protobuf::internal::ExplicitlyConstructed<::std::string>
|
||||
MediumMetadata_WifiDirectAuthType_strings[3] = {};
|
||||
MediumMetadata_WifiDirectAuthType_strings[4] = {};
|
||||
|
||||
static const char MediumMetadata_WifiDirectAuthType_names[] = {
|
||||
"WIFI_DIRECT_TYPE_UNKNOWN"
|
||||
"WIFI_DIRECT_WITH_DEVICE_NAME"
|
||||
"WIFI_DIRECT_WITH_PASSWORD"
|
||||
"WIFI_DIRECT_WITH_PIN"
|
||||
};
|
||||
|
||||
static const ::google::protobuf::internal::EnumEntry MediumMetadata_WifiDirectAuthType_entries[] = {
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[0], 24}, 0},
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[24], 25}, 1},
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[49], 20}, 2},
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[24], 28}, 3},
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[52], 25}, 1},
|
||||
{{&MediumMetadata_WifiDirectAuthType_names[77], 20}, 2},
|
||||
};
|
||||
|
||||
static const int MediumMetadata_WifiDirectAuthType_entries_by_number[] = {
|
||||
0, // 0 -> WIFI_DIRECT_TYPE_UNKNOWN
|
||||
1, // 1 -> WIFI_DIRECT_WITH_PASSWORD
|
||||
2, // 2 -> WIFI_DIRECT_WITH_PIN
|
||||
2, // 1 -> WIFI_DIRECT_WITH_PASSWORD
|
||||
3, // 2 -> WIFI_DIRECT_WITH_PIN
|
||||
1, // 3 -> WIFI_DIRECT_WITH_DEVICE_NAME
|
||||
};
|
||||
|
||||
const ::std::string& MediumMetadata_WifiDirectAuthType_Name(MediumMetadata_WifiDirectAuthType value) {
|
||||
static const bool kDummy = ::google::protobuf::internal::InitializeEnumStrings(
|
||||
MediumMetadata_WifiDirectAuthType_entries, MediumMetadata_WifiDirectAuthType_entries_by_number, 3,
|
||||
MediumMetadata_WifiDirectAuthType_entries, MediumMetadata_WifiDirectAuthType_entries_by_number, 4,
|
||||
MediumMetadata_WifiDirectAuthType_strings);
|
||||
(void)kDummy;
|
||||
|
||||
int idx = ::google::protobuf::internal::LookUpEnumName(MediumMetadata_WifiDirectAuthType_entries,
|
||||
MediumMetadata_WifiDirectAuthType_entries_by_number,
|
||||
3, value);
|
||||
4, value);
|
||||
return idx == -1 ? ::google::protobuf::internal::GetEmptyString() : MediumMetadata_WifiDirectAuthType_strings[idx].get();
|
||||
}
|
||||
|
||||
bool MediumMetadata_WifiDirectAuthType_Parse(::absl::string_view name, MediumMetadata_WifiDirectAuthType* PROTOBUF_NONNULL value) {
|
||||
int int_value;
|
||||
bool success = ::google::protobuf::internal::LookUpEnumValue(
|
||||
MediumMetadata_WifiDirectAuthType_entries, 3, name, &int_value);
|
||||
MediumMetadata_WifiDirectAuthType_entries, 4, name, &int_value);
|
||||
if (success) {
|
||||
*value = static_cast<MediumMetadata_WifiDirectAuthType>(int_value);
|
||||
}
|
||||
@@ -7696,7 +7702,8 @@ PROTOBUF_NDEBUG_INLINE BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
gateway_(arena, from.gateway_, _i_give_permission_to_break_this_code_default_gateway_),
|
||||
ip_v6_address_(arena, from.ip_v6_address_),
|
||||
service_name_(arena, from.service_name_),
|
||||
pin_(arena, from.pin_) {}
|
||||
pin_(arena, from.pin_),
|
||||
device_name_(arena, from.device_name_) {}
|
||||
|
||||
BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials(
|
||||
::google::protobuf::Arena* PROTOBUF_NULLABLE arena,
|
||||
@@ -7730,7 +7737,8 @@ PROTOBUF_NDEBUG_INLINE BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
gateway_(arena, Impl_::_i_give_permission_to_break_this_code_default_gateway_),
|
||||
ip_v6_address_(arena),
|
||||
service_name_(arena),
|
||||
pin_(arena) {}
|
||||
pin_(arena),
|
||||
device_name_(arena) {}
|
||||
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) {
|
||||
new (&_impl_) Impl_(internal_visibility(), arena);
|
||||
@@ -7758,6 +7766,7 @@ inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentia
|
||||
this_._impl_.ip_v6_address_.Destroy();
|
||||
this_._impl_.service_name_.Destroy();
|
||||
this_._impl_.pin_.Destroy();
|
||||
this_._impl_.device_name_.Destroy();
|
||||
this_._impl_.~Impl_();
|
||||
}
|
||||
|
||||
@@ -7801,16 +7810,16 @@ BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::GetClass
|
||||
return BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials_class_data_.base();
|
||||
}
|
||||
PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
|
||||
const ::_pbi::TcParseTable<3, 8, 0, 0, 2>
|
||||
const ::_pbi::TcParseTable<4, 9, 0, 0, 2>
|
||||
BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_table_ = {
|
||||
{
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_._has_bits_),
|
||||
0, // no _extensions_
|
||||
8, 56, // max_field_number, fast_idx_mask
|
||||
9, 120, // max_field_number, fast_idx_mask
|
||||
offsetof(decltype(_table_), field_lookup_table),
|
||||
4294967040, // skipmap
|
||||
4294966784, // skipmap
|
||||
offsetof(decltype(_table_), field_entries),
|
||||
8, // num_field_entries
|
||||
9, // num_field_entries
|
||||
0, // num_aux_entries
|
||||
offsetof(decltype(_table_), field_names), // no aux_entries
|
||||
BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials_class_data_.base(),
|
||||
@@ -7820,10 +7829,7 @@ BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_table_
|
||||
::_pbi::TcParser::GetTable<::location::nearby::connections::BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials>(), // to_prefetch
|
||||
#endif // PROTOBUF_PREFETCH_PARSE_TABLE
|
||||
}, {{
|
||||
// optional string pin = 8;
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{66, 5, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.pin_)}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
// optional string ssid = 1;
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{10, 0, 0,
|
||||
@@ -7834,11 +7840,11 @@ BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_table_
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.password_)}},
|
||||
// optional int32 port = 3;
|
||||
{::_pbi::TcParser::FastV32S1,
|
||||
{24, 6, 0,
|
||||
{24, 7, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.port_)}},
|
||||
// optional int32 frequency = 4;
|
||||
{::_pbi::TcParser::FastV32S1,
|
||||
{32, 7, 0,
|
||||
{32, 8, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.frequency_)}},
|
||||
// optional string gateway = 5 [default = "0.0.0.0"];
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
@@ -7848,10 +7854,24 @@ BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_table_
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{50, 3, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.ip_v6_address_)}},
|
||||
// optional string service_name = 7;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{58, 4, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.service_name_)}},
|
||||
// optional string pin = 8;
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{66, 5, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.pin_)}},
|
||||
// optional string device_name = 9;
|
||||
{::_pbi::TcParser::FastBS1,
|
||||
{74, 6, 0,
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.device_name_)}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
}}, {{
|
||||
65535, 65535
|
||||
}}, {{
|
||||
@@ -7860,17 +7880,19 @@ BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_table_
|
||||
// optional string password = 2;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.password_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
// optional int32 port = 3;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.port_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.port_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
|
||||
// optional int32 frequency = 4;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.frequency_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.frequency_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
|
||||
// optional string gateway = 5 [default = "0.0.0.0"];
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.gateway_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
// optional bytes ip_v6_address = 6;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.ip_v6_address_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
// optional string service_name = 7;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.service_name_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
// optional string pin = 8;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.pin_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
// optional string device_name = 9;
|
||||
{PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.device_name_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
|
||||
}},
|
||||
// no aux_entries
|
||||
{{
|
||||
@@ -7884,7 +7906,7 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
(void) cached_has_bits;
|
||||
|
||||
cached_has_bits = _impl_._has_bits_[0];
|
||||
if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) {
|
||||
if (BatchCheckHasBit(cached_has_bits, 0x0000007fU)) {
|
||||
if (CheckHasBit(cached_has_bits, 0x00000001U)) {
|
||||
_impl_.ssid_.ClearNonDefaultToEmpty();
|
||||
}
|
||||
@@ -7903,12 +7925,12 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
if (CheckHasBit(cached_has_bits, 0x00000020U)) {
|
||||
_impl_.pin_.ClearNonDefaultToEmpty();
|
||||
}
|
||||
if (CheckHasBit(cached_has_bits, 0x00000040U)) {
|
||||
_impl_.device_name_.ClearNonDefaultToEmpty();
|
||||
}
|
||||
}
|
||||
if (BatchCheckHasBit(cached_has_bits, 0x000000c0U)) {
|
||||
::memset(&_impl_.port_, 0, static_cast<::size_t>(
|
||||
reinterpret_cast<char*>(&_impl_.frequency_) -
|
||||
reinterpret_cast<char*>(&_impl_.port_)) + sizeof(_impl_.frequency_));
|
||||
}
|
||||
_impl_.port_ = 0;
|
||||
_impl_.frequency_ = 0;
|
||||
_impl_._has_bits_.Clear();
|
||||
_internal_metadata_.Clear<::std::string>();
|
||||
}
|
||||
@@ -7945,14 +7967,14 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
}
|
||||
|
||||
// optional int32 port = 3;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000040U)) {
|
||||
if (CheckHasBit(cached_has_bits, 0x00000080U)) {
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32ToArrayWithField<3>(
|
||||
stream, this_._internal_port(), target);
|
||||
}
|
||||
|
||||
// optional int32 frequency = 4;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000080U)) {
|
||||
if (CheckHasBit(cached_has_bits, 0x00000100U)) {
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32ToArrayWithField<4>(
|
||||
stream, this_._internal_frequency(), target);
|
||||
@@ -7970,7 +7992,7 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
target = stream->WriteBytesMaybeAliased(6, _s, target);
|
||||
}
|
||||
|
||||
// optional string service_name = 7;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
if (CheckHasBit(cached_has_bits, 0x00000010U)) {
|
||||
const ::std::string& _s = this_._internal_service_name();
|
||||
target = stream->WriteStringMaybeAliased(7, _s, target);
|
||||
@@ -7982,6 +8004,12 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
target = stream->WriteStringMaybeAliased(8, _s, target);
|
||||
}
|
||||
|
||||
// optional string device_name = 9;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000040U)) {
|
||||
const ::std::string& _s = this_._internal_device_name();
|
||||
target = stream->WriteStringMaybeAliased(9, _s, target);
|
||||
}
|
||||
|
||||
if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) {
|
||||
target = stream->WriteRaw(
|
||||
this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).data(),
|
||||
@@ -8028,7 +8056,7 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize(
|
||||
this_._internal_ip_v6_address());
|
||||
}
|
||||
// optional string service_name = 7;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
if (CheckHasBit(cached_has_bits, 0x00000010U)) {
|
||||
total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this_._internal_service_name());
|
||||
@@ -8038,13 +8066,20 @@ PROTOBUF_NOINLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDire
|
||||
total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this_._internal_pin());
|
||||
}
|
||||
// optional int32 port = 3;
|
||||
// optional string device_name = 9;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000040U)) {
|
||||
total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this_._internal_device_name());
|
||||
}
|
||||
// optional int32 port = 3;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000080U)) {
|
||||
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
|
||||
this_._internal_port());
|
||||
}
|
||||
}
|
||||
{
|
||||
// optional int32 frequency = 4;
|
||||
if (CheckHasBit(cached_has_bits, 0x00000080U)) {
|
||||
if (CheckHasBit(cached_has_bits, 0x00000100U)) {
|
||||
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
|
||||
this_._internal_frequency());
|
||||
}
|
||||
@@ -8090,12 +8125,15 @@ void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::Mer
|
||||
_this->_internal_set_pin(from._internal_pin());
|
||||
}
|
||||
if (CheckHasBit(cached_has_bits, 0x00000040U)) {
|
||||
_this->_impl_.port_ = from._impl_.port_;
|
||||
_this->_internal_set_device_name(from._internal_device_name());
|
||||
}
|
||||
if (CheckHasBit(cached_has_bits, 0x00000080U)) {
|
||||
_this->_impl_.frequency_ = from._impl_.frequency_;
|
||||
_this->_impl_.port_ = from._impl_.port_;
|
||||
}
|
||||
}
|
||||
if (CheckHasBit(cached_has_bits, 0x00000100U)) {
|
||||
_this->_impl_.frequency_ = from._impl_.frequency_;
|
||||
}
|
||||
_this->_impl_._has_bits_[0] |= cached_has_bits;
|
||||
_this->_internal_metadata_.MergeFrom<::std::string>(
|
||||
from._internal_metadata_);
|
||||
@@ -8121,6 +8159,7 @@ void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::Int
|
||||
::_pbi::ArenaStringPtr::InternalSwap(&_impl_.ip_v6_address_, &other->_impl_.ip_v6_address_, arena);
|
||||
::_pbi::ArenaStringPtr::InternalSwap(&_impl_.service_name_, &other->_impl_.service_name_, arena);
|
||||
::_pbi::ArenaStringPtr::InternalSwap(&_impl_.pin_, &other->_impl_.pin_, arena);
|
||||
::_pbi::ArenaStringPtr::InternalSwap(&_impl_.device_name_, &other->_impl_.device_name_, arena);
|
||||
::google::protobuf::internal::memswap<
|
||||
PROTOBUF_FIELD_OFFSET(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials, _impl_.frequency_)
|
||||
+ sizeof(BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_impl_.frequency_)
|
||||
@@ -13302,7 +13341,7 @@ MediumMetadata::_table_ = {
|
||||
PROTOBUF_FIELD_OFFSET(MediumMetadata, _impl_.medium_role_)}},
|
||||
// repeated .location.nearby.connections.MediumMetadata.WifiDirectAuthType supported_wifi_direct_auth_types = 13 [packed = true];
|
||||
{::_pbi::TcParser::FastEr0P1,
|
||||
{106, 0, 2,
|
||||
{106, 0, 3,
|
||||
PROTOBUF_FIELD_OFFSET(MediumMetadata, _impl_.supported_wifi_direct_auth_types_)}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
{::_pbi::TcParser::MiniParse, {}},
|
||||
@@ -13343,7 +13382,7 @@ MediumMetadata::_table_ = {
|
||||
{::_pbi::TcParser::GetTable<::location::nearby::connections::WifiAwareUsableChannels>()},
|
||||
{::_pbi::TcParser::GetTable<::location::nearby::connections::WifiHotspotStaUsableChannels>()},
|
||||
{::_pbi::TcParser::GetTable<::location::nearby::connections::MediumRole>()},
|
||||
{0, 2},
|
||||
{0, 3},
|
||||
}},
|
||||
{{
|
||||
}},
|
||||
|
||||
@@ -722,18 +722,19 @@ bool AutoReconnectFrame_EventType_Parse(
|
||||
enum MediumMetadata_WifiDirectAuthType : int {
|
||||
MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_TYPE_UNKNOWN = 0,
|
||||
MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PASSWORD = 1,
|
||||
MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PIN = 2,
|
||||
MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PIN [[deprecated]] = 2,
|
||||
MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_DEVICE_NAME = 3,
|
||||
};
|
||||
|
||||
extern const uint32_t MediumMetadata_WifiDirectAuthType_internal_data_[];
|
||||
inline constexpr MediumMetadata_WifiDirectAuthType MediumMetadata_WifiDirectAuthType_WifiDirectAuthType_MIN =
|
||||
static_cast<MediumMetadata_WifiDirectAuthType>(0);
|
||||
inline constexpr MediumMetadata_WifiDirectAuthType MediumMetadata_WifiDirectAuthType_WifiDirectAuthType_MAX =
|
||||
static_cast<MediumMetadata_WifiDirectAuthType>(2);
|
||||
static_cast<MediumMetadata_WifiDirectAuthType>(3);
|
||||
inline bool MediumMetadata_WifiDirectAuthType_IsValid(int value) {
|
||||
return 0 <= value && value <= 2;
|
||||
return 0 <= value && value <= 3;
|
||||
}
|
||||
inline constexpr int MediumMetadata_WifiDirectAuthType_WifiDirectAuthType_ARRAYSIZE = 2 + 1;
|
||||
inline constexpr int MediumMetadata_WifiDirectAuthType_WifiDirectAuthType_ARRAYSIZE = 3 + 1;
|
||||
const ::std::string& MediumMetadata_WifiDirectAuthType_Name(MediumMetadata_WifiDirectAuthType value);
|
||||
template <typename T>
|
||||
const ::std::string& MediumMetadata_WifiDirectAuthType_Name(T value) {
|
||||
@@ -4914,6 +4915,7 @@ class BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials fin
|
||||
kIpV6AddressFieldNumber = 6,
|
||||
kServiceNameFieldNumber = 7,
|
||||
kPinFieldNumber = 8,
|
||||
kDeviceNameFieldNumber = 9,
|
||||
kPortFieldNumber = 3,
|
||||
kFrequencyFieldNumber = 4,
|
||||
};
|
||||
@@ -4981,15 +4983,15 @@ class BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials fin
|
||||
::std::string* PROTOBUF_NONNULL _internal_mutable_ip_v6_address();
|
||||
|
||||
public:
|
||||
// optional string service_name = 7;
|
||||
bool has_service_name() const;
|
||||
void clear_service_name() ;
|
||||
const ::std::string& service_name() const;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
[[deprecated]] bool has_service_name() const;
|
||||
[[deprecated]] void clear_service_name() ;
|
||||
[[deprecated]] const ::std::string& service_name() const;
|
||||
template <typename Arg_ = const ::std::string&, typename... Args_>
|
||||
void set_service_name(Arg_&& arg, Args_... args);
|
||||
::std::string* PROTOBUF_NONNULL mutable_service_name();
|
||||
[[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_service_name();
|
||||
void set_allocated_service_name(::std::string* PROTOBUF_NULLABLE value);
|
||||
[[deprecated]] void set_service_name(Arg_&& arg, Args_... args);
|
||||
[[deprecated]] ::std::string* PROTOBUF_NONNULL mutable_service_name();
|
||||
[[deprecated]] [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_service_name();
|
||||
[[deprecated]] void set_allocated_service_name(::std::string* PROTOBUF_NULLABLE value);
|
||||
|
||||
private:
|
||||
const ::std::string& _internal_service_name() const;
|
||||
@@ -5012,6 +5014,22 @@ class BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials fin
|
||||
PROTOBUF_ALWAYS_INLINE void _internal_set_pin(const ::std::string& value);
|
||||
::std::string* PROTOBUF_NONNULL _internal_mutable_pin();
|
||||
|
||||
public:
|
||||
// optional string device_name = 9;
|
||||
bool has_device_name() const;
|
||||
void clear_device_name() ;
|
||||
const ::std::string& device_name() const;
|
||||
template <typename Arg_ = const ::std::string&, typename... Args_>
|
||||
void set_device_name(Arg_&& arg, Args_... args);
|
||||
::std::string* PROTOBUF_NONNULL mutable_device_name();
|
||||
[[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_device_name();
|
||||
void set_allocated_device_name(::std::string* PROTOBUF_NULLABLE value);
|
||||
|
||||
private:
|
||||
const ::std::string& _internal_device_name() const;
|
||||
PROTOBUF_ALWAYS_INLINE void _internal_set_device_name(const ::std::string& value);
|
||||
::std::string* PROTOBUF_NONNULL _internal_mutable_device_name();
|
||||
|
||||
public:
|
||||
// optional int32 port = 3;
|
||||
bool has_port() const;
|
||||
@@ -5039,7 +5057,7 @@ class BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials fin
|
||||
private:
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<3, 8,
|
||||
static const ::google::protobuf::internal::TcParseTable<4, 9,
|
||||
0, 0,
|
||||
2>
|
||||
_table_;
|
||||
@@ -5068,6 +5086,7 @@ class BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials fin
|
||||
::google::protobuf::internal::ArenaStringPtr ip_v6_address_;
|
||||
::google::protobuf::internal::ArenaStringPtr service_name_;
|
||||
::google::protobuf::internal::ArenaStringPtr pin_;
|
||||
::google::protobuf::internal::ArenaStringPtr device_name_;
|
||||
::int32_t port_;
|
||||
::int32_t frequency_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
@@ -7679,7 +7698,8 @@ class MediumMetadata final : public ::google::protobuf::MessageLite
|
||||
using WifiDirectAuthType = MediumMetadata_WifiDirectAuthType;
|
||||
static constexpr WifiDirectAuthType WIFI_DIRECT_TYPE_UNKNOWN = MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_TYPE_UNKNOWN;
|
||||
static constexpr WifiDirectAuthType WIFI_DIRECT_WITH_PASSWORD = MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PASSWORD;
|
||||
static constexpr WifiDirectAuthType WIFI_DIRECT_WITH_PIN = MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PIN;
|
||||
[[deprecated]] static constexpr WifiDirectAuthType WIFI_DIRECT_WITH_PIN = MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_PIN;
|
||||
static constexpr WifiDirectAuthType WIFI_DIRECT_WITH_DEVICE_NAME = MediumMetadata_WifiDirectAuthType_WIFI_DIRECT_WITH_DEVICE_NAME;
|
||||
static inline bool WifiDirectAuthType_IsValid(int value) {
|
||||
return MediumMetadata_WifiDirectAuthType_IsValid(value);
|
||||
}
|
||||
@@ -15574,14 +15594,14 @@ inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentia
|
||||
|
||||
// optional int32 port = 3;
|
||||
inline bool BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::has_port() const {
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U);
|
||||
return value;
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::clear_port() {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
_impl_.port_ = 0;
|
||||
ClearHasBit(_impl_._has_bits_[0],
|
||||
0x00000040U);
|
||||
0x00000080U);
|
||||
}
|
||||
inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::port() const {
|
||||
// @@protoc_insertion_point(field_get:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.port)
|
||||
@@ -15589,7 +15609,7 @@ inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCred
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::set_port(::int32_t value) {
|
||||
_internal_set_port(value);
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000080U);
|
||||
// @@protoc_insertion_point(field_set:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.port)
|
||||
}
|
||||
inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_internal_port() const {
|
||||
@@ -15603,14 +15623,14 @@ inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentia
|
||||
|
||||
// optional int32 frequency = 4;
|
||||
inline bool BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::has_frequency() const {
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U);
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U);
|
||||
return value;
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::clear_frequency() {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
_impl_.frequency_ = 0;
|
||||
ClearHasBit(_impl_._has_bits_[0],
|
||||
0x00000080U);
|
||||
0x00000100U);
|
||||
}
|
||||
inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::frequency() const {
|
||||
// @@protoc_insertion_point(field_get:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.frequency)
|
||||
@@ -15618,7 +15638,7 @@ inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCred
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::set_frequency(::int32_t value) {
|
||||
_internal_set_frequency(value);
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000080U);
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000100U);
|
||||
// @@protoc_insertion_point(field_set:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.frequency)
|
||||
}
|
||||
inline ::int32_t BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_internal_frequency() const {
|
||||
@@ -15764,7 +15784,7 @@ inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentia
|
||||
// @@protoc_insertion_point(field_set_allocated:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.ip_v6_address)
|
||||
}
|
||||
|
||||
// optional string service_name = 7;
|
||||
// optional string service_name = 7 [deprecated = true];
|
||||
inline bool BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::has_service_name() const {
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000010U);
|
||||
return value;
|
||||
@@ -15833,6 +15853,75 @@ inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentia
|
||||
// @@protoc_insertion_point(field_set_allocated:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.service_name)
|
||||
}
|
||||
|
||||
// optional string device_name = 9;
|
||||
inline bool BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::has_device_name() const {
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
return value;
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::clear_device_name() {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
_impl_.device_name_.ClearToEmpty();
|
||||
ClearHasBit(_impl_._has_bits_[0],
|
||||
0x00000040U);
|
||||
}
|
||||
inline const ::std::string& BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::device_name() const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_get:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.device_name)
|
||||
return _internal_device_name();
|
||||
}
|
||||
template <typename Arg_, typename... Args_>
|
||||
PROTOBUF_ALWAYS_INLINE void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::set_device_name(Arg_&& arg, Args_... args) {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
_impl_.device_name_.Set(static_cast<Arg_&&>(arg), args..., GetArena());
|
||||
// @@protoc_insertion_point(field_set:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.device_name)
|
||||
}
|
||||
inline ::std::string* PROTOBUF_NONNULL BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::mutable_device_name()
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
::std::string* _s = _internal_mutable_device_name();
|
||||
// @@protoc_insertion_point(field_mutable:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.device_name)
|
||||
return _s;
|
||||
}
|
||||
inline const ::std::string& BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_internal_device_name() const {
|
||||
::google::protobuf::internal::TSanRead(&_impl_);
|
||||
return _impl_.device_name_.Get();
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_internal_set_device_name(const ::std::string& value) {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
_impl_.device_name_.Set(value, GetArena());
|
||||
}
|
||||
inline ::std::string* PROTOBUF_NONNULL BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::_internal_mutable_device_name() {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
return _impl_.device_name_.Mutable( GetArena());
|
||||
}
|
||||
inline ::std::string* PROTOBUF_NULLABLE BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::release_device_name() {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
// @@protoc_insertion_point(field_release:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.device_name)
|
||||
if (!CheckHasBit(_impl_._has_bits_[0], 0x00000040U)) {
|
||||
return nullptr;
|
||||
}
|
||||
ClearHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
auto* released = _impl_.device_name_.Release();
|
||||
if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) {
|
||||
_impl_.device_name_.Set("", GetArena());
|
||||
}
|
||||
return released;
|
||||
}
|
||||
inline void BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::set_allocated_device_name(::std::string* PROTOBUF_NULLABLE value) {
|
||||
::google::protobuf::internal::TSanWrite(&_impl_);
|
||||
if (value != nullptr) {
|
||||
SetHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
} else {
|
||||
ClearHasBit(_impl_._has_bits_[0], 0x00000040U);
|
||||
}
|
||||
_impl_.device_name_.SetAllocated(value, GetArena());
|
||||
if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.device_name_.IsDefault()) {
|
||||
_impl_.device_name_.Set("", GetArena());
|
||||
}
|
||||
// @@protoc_insertion_point(field_set_allocated:location.nearby.connections.BandwidthUpgradeNegotiationFrame.UpgradePathInfo.WifiDirectCredentials.device_name)
|
||||
}
|
||||
|
||||
// optional string pin = 8;
|
||||
inline bool BandwidthUpgradeNegotiationFrame_UpgradePathInfo_WifiDirectCredentials::has_pin() const {
|
||||
bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -324,18 +324,19 @@ bool Medium_Parse(
|
||||
enum WifiDirectAuthType : int {
|
||||
WIFI_DIRECT_TYPE_UNKNOWN = 0,
|
||||
WIFI_DIRECT_WITH_PASSWORD = 1,
|
||||
WIFI_DIRECT_WITH_PIN = 2,
|
||||
WIFI_DIRECT_WITH_PIN [[deprecated]] = 2,
|
||||
WIFI_DIRECT_WITH_DEVICE_NAME = 3,
|
||||
};
|
||||
|
||||
extern const uint32_t WifiDirectAuthType_internal_data_[];
|
||||
inline constexpr WifiDirectAuthType WifiDirectAuthType_MIN =
|
||||
static_cast<WifiDirectAuthType>(0);
|
||||
inline constexpr WifiDirectAuthType WifiDirectAuthType_MAX =
|
||||
static_cast<WifiDirectAuthType>(2);
|
||||
static_cast<WifiDirectAuthType>(3);
|
||||
inline bool WifiDirectAuthType_IsValid(int value) {
|
||||
return 0 <= value && value <= 2;
|
||||
return 0 <= value && value <= 3;
|
||||
}
|
||||
inline constexpr int WifiDirectAuthType_ARRAYSIZE = 2 + 1;
|
||||
inline constexpr int WifiDirectAuthType_ARRAYSIZE = 3 + 1;
|
||||
const ::std::string& WifiDirectAuthType_Name(WifiDirectAuthType value);
|
||||
template <typename T>
|
||||
const ::std::string& WifiDirectAuthType_Name(T value) {
|
||||
@@ -1272,17 +1273,54 @@ enum OperationResultCode : int {
|
||||
DCT_ERROR_SERVICE_CANCELLED = 5022,
|
||||
DCT_ERROR_UNVERIFIED_INTEGRITY = 5023,
|
||||
DCT_ERROR_HTTP_SERVER_CLOSED = 5024,
|
||||
DCT_ERROR_CHECKIN_FAILURE = 5025,
|
||||
DCT_ERROR_REMOTE_ATTESTATION_TIMEOUT = 5026,
|
||||
DCT_ERROR_REMOTE_ATTESTATION_NULL_PACKET = 5027,
|
||||
DCT_ERROR_REMOTE_ATTESTATION_STATUS_NOT_AVAILABLE = 5028,
|
||||
DCT_ERROR_REMOTE_ATTESTATION_HASH_TOO_SHORT = 5029,
|
||||
DCT_ERROR_REMOTE_ATTESTATION_APPLE_INTEGRITY_UNAVAILABLE = 5030,
|
||||
DCT_ERROR_LOCAL_ATTESTATION_PLAY_INTEGRITY_UNAVAILABLE = 5031,
|
||||
DCT_ERROR_LOCAL_ATTESTATION_TIMEOUT = 5032,
|
||||
DCT_ERROR_PARALLEL_ATTESTATION_TIMEOUT = 5033,
|
||||
DCT_ERROR_REMOTE_MDNS_DISCOVERY_TIMEOUT = 5034,
|
||||
DCT_ERROR_REMOTE_MDNS_REGISTER_SERVICE = 5035,
|
||||
DCT_ERROR_REMOTE_REQUEST_FAILED = 5036,
|
||||
DCT_ERROR_REMOTE_RESPONSE_FAILED = 5037,
|
||||
DCT_ERROR_REMOTE_CONTROL_MESSAGE_EXCHANGE = 5038,
|
||||
DCT_ERROR_REMOTE_CAPABILITY_MISMATCH = 5039,
|
||||
DCT_ERROR_REMOTE_HIGH_SPEED_MEDIUM_UNAVAILABLE = 5040,
|
||||
DCT_ERROR_REMOTE_WIFI_DISABLED = 5041,
|
||||
DCT_ERROR_REMOTE_WIFI_DISCONNECTED = 5042,
|
||||
DCT_ERROR_REMOTE_WIFI_CREDENTIAL_TRANSFER = 5043,
|
||||
DCT_ERROR_REMOTE_WIFI_INTERNET_CONNECTION = 5044,
|
||||
DCT_ERROR_REMOTE_UPGRADE_HIGH_SPEED_MEDIUM_FAILED = 5045,
|
||||
DCT_ERROR_REMOTE_USER_CANCELLED = 5046,
|
||||
DCT_ERROR_REMOTE_SERVICE_CANCELLED = 5047,
|
||||
DCT_ERROR_REMOTE_UNVERIFIED_INTEGRITY = 5048,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_LOW_SPEED = 5049,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_CONNECTION = 5050,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_USB_NOT_PLUGGED = 5051,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_USB_NOT_HOST = 5052,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_MDNS_DISCOVERY_NOT_STARTED = 5053,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_NO_MEDIUM = 5054,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_USB_NETWORK_NOT_STARTED = 5055,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_MEDIUM_NEGOTIATION = 5056,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_HOST_NOT_STARTED = 5057,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_HOST_NETWORK_NOT_AVAILABLE = 5058,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_NO_INCOMING_HTTP_CONNECTION = 5059,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_USB_NO_CONNECTED_DEVICE = 5060,
|
||||
DCT_ERROR_UPGRADE_HIGH_SPEED_MEDIUM_FAILED_INTERRUPTED = 5061,
|
||||
};
|
||||
|
||||
extern const uint32_t OperationResultCode_internal_data_[];
|
||||
inline constexpr OperationResultCode OperationResultCode_MIN =
|
||||
static_cast<OperationResultCode>(0);
|
||||
inline constexpr OperationResultCode OperationResultCode_MAX =
|
||||
static_cast<OperationResultCode>(5024);
|
||||
static_cast<OperationResultCode>(5061);
|
||||
inline bool OperationResultCode_IsValid(int value) {
|
||||
return ::google::protobuf::internal::ValidateEnum(value, OperationResultCode_internal_data_);
|
||||
}
|
||||
inline constexpr int OperationResultCode_ARRAYSIZE = 5024 + 1;
|
||||
inline constexpr int OperationResultCode_ARRAYSIZE = 5061 + 1;
|
||||
const ::std::string& OperationResultCode_Name(OperationResultCode value);
|
||||
template <typename T>
|
||||
const ::std::string& OperationResultCode_Name(T value) {
|
||||
|
||||
+6
-3
@@ -44,9 +44,11 @@ cc_library(
|
||||
],
|
||||
deps = [
|
||||
":core_types",
|
||||
"//connections/implementation:client_proxy",
|
||||
"//connections/implementation:internal",
|
||||
"//connections/implementation:service_id_constants",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/analytics:event_logger",
|
||||
"//internal/interop:device",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
@@ -95,15 +97,15 @@ cc_library(
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//internal/interop:authentication_status",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mac_address",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:util",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/random",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -124,6 +126,7 @@ cc_test(
|
||||
"//connections/implementation:internal_test",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
|
||||
+7
-4
@@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("@rules_apple//apple:apple.bzl", "apple_static_xcframework")
|
||||
load("@rules_apple//apple:apple_xcframework.bzl", "apple_static_xcframework")
|
||||
load("@rules_apple//apple:macos.bzl", "macos_dylib")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("//third_party/cpptoolchains/portable_llvm/build_defs:windows.bzl", "windows")
|
||||
@@ -51,16 +51,18 @@ cc_library(
|
||||
":nc_types",
|
||||
"//connections:core",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics:analytics_recorder_impl",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/analytics:event_logger",
|
||||
"//internal/flags:flag_reader",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mac_address",
|
||||
"//internal/platform:types",
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//sharing/proto/analytics:sharing_log_cc_proto",
|
||||
"//location/nearby/analytics/cpp/logging:event_logger",
|
||||
"//location/nearby/analytics/cpp/proto:connections_log_cc_proto",
|
||||
"//location/nearby/analytics/cpp/proto:sharing_log_cc_proto",
|
||||
"@com_google_absl//absl/base:no_destructor",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
@@ -73,6 +75,7 @@ cc_library(
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
alwayslink = True,
|
||||
)
|
||||
|
||||
# iOS only.
|
||||
|
||||
+29
-5
@@ -20,10 +20,16 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(NC_OSS_BUILD)
|
||||
#include "location/nearby/analytics/cpp/logging/event_logger.h"
|
||||
#include "location/nearby/analytics/cpp/proto/connections_log.pb.h"
|
||||
#include "location/nearby/analytics/cpp/proto/nearby_sharing_log.pb.h"
|
||||
#endif // !defined(NC_OSS_BUILD)
|
||||
#include "absl/base/no_destructor.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
@@ -34,6 +40,9 @@
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/core.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#if !defined(NC_OSS_BUILD)
|
||||
#include "connections/implementation/analytics/analytics_recorder_impl.h"
|
||||
#endif // !defined(NC_OSS_BUILD)
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "connections/out_of_band_connection_metadata.h"
|
||||
@@ -41,7 +50,6 @@
|
||||
#include "connections/payload.h"
|
||||
#include "connections/status.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "internal/analytics/event_logger.h"
|
||||
#include "internal/flags/flag.h"
|
||||
#include "internal/flags/flag_reader.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
@@ -49,8 +57,6 @@
|
||||
#include "internal/platform/file.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "sharing/proto/analytics/nearby_sharing_log.pb.h"
|
||||
#if TARGET_OS_IOS
|
||||
#include "internal/platform/implementation/apple/nearby_logger.h"
|
||||
#endif // TARGET_OS_IOS
|
||||
@@ -118,6 +124,7 @@ class FlagReaderWrapper : public nearby::flags::FlagReader {
|
||||
NC_PHENOTYPE_FLAG_READER phenotype_flag_reader_;
|
||||
};
|
||||
|
||||
#if !defined(NC_OSS_BUILD)
|
||||
// This is a bridging class between the C API and the C++ EventLogger interface.
|
||||
class NcEventLogger : public ::nearby::analytics::EventLogger {
|
||||
public:
|
||||
@@ -145,6 +152,10 @@ class NcEventLogger : public ::nearby::analytics::EventLogger {
|
||||
private:
|
||||
const NC_EVENT_LOGGER* event_logger_;
|
||||
};
|
||||
#else // !defined(NC_OSS_BUILD)
|
||||
class NcEventLogger;
|
||||
#endif // !defined(NC_OSS_BUILD)
|
||||
|
||||
} // namespace
|
||||
|
||||
typedef struct NcContext {
|
||||
@@ -244,6 +255,7 @@ NcContext* GetContext(NC_INSTANCE instance) {
|
||||
return cpp_connection_request_info;
|
||||
}
|
||||
|
||||
#if !defined(NC_OSS_BUILD)
|
||||
NC_INSTANCE NcCreateService() {
|
||||
return NcCreateServiceWithEventLogger(nullptr);
|
||||
}
|
||||
@@ -259,12 +271,24 @@ NcCreateServiceWithEventLogger(const NC_EVENT_LOGGER* event_logger) {
|
||||
nc_context.router = new ::nearby::connections::ServiceControllerRouter();
|
||||
nc_context.event_logger =
|
||||
event_logger == nullptr ? nullptr : new NcEventLogger(event_logger);
|
||||
nc_context.core = new ::nearby::connections::Core(nc_context.event_logger,
|
||||
nc_context.router);
|
||||
nc_context.core = new ::nearby::connections::Core(
|
||||
std::make_unique<::nearby::analytics::AnalyticsRecorderImpl>(
|
||||
nc_context.event_logger),
|
||||
nc_context.router);
|
||||
|
||||
kNcContextMap->insert({nc_context.core, nc_context});
|
||||
return nc_context.core;
|
||||
}
|
||||
#else // !defined(NC_OSS_BUILD)
|
||||
NC_INSTANCE NcCreateService() {
|
||||
NcContext nc_context;
|
||||
nc_context.router = new ::nearby::connections::ServiceControllerRouter();
|
||||
nc_context.core = new ::nearby::connections::Core(nc_context.router);
|
||||
|
||||
kNcContextMap->insert({nc_context.core, nc_context});
|
||||
return nc_context.core;
|
||||
}
|
||||
#endif // !defined(NC_OSS_BUILD)
|
||||
|
||||
void NcCloseService(NC_INSTANCE instance) {
|
||||
NcContext* nc_context = GetContext(instance);
|
||||
|
||||
@@ -27,11 +27,13 @@ extern "C" {
|
||||
// Creates a new Nearby Connections service.
|
||||
NC_API NC_INSTANCE NcCreateService();
|
||||
|
||||
#if !defined(NC_OSS_BUILD)
|
||||
// Creates a new Nearby Connections service with an event logger.
|
||||
// The passed-in |event_logger| must remain valid until NcCloseService() is
|
||||
// called.
|
||||
NC_API NC_INSTANCE
|
||||
NcCreateServiceWithEventLogger(const NC_EVENT_LOGGER* event_logger);
|
||||
#endif // !defined(NC_OSS_BUILD)
|
||||
|
||||
// Closes a Nearby Connections service.
|
||||
NC_API void NcCloseService(NC_INSTANCE instance);
|
||||
|
||||
+3
-3
@@ -25,6 +25,7 @@
|
||||
#include "connections/advertising_options.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/service_controller_router.h"
|
||||
#include "connections/listeners.h"
|
||||
@@ -37,7 +38,6 @@
|
||||
#include "connections/v3/discovery_options.h"
|
||||
#include "connections/v3/listeners.h"
|
||||
#include "connections/v3/listening_result.h"
|
||||
#include "internal/analytics/event_logger.h"
|
||||
#include "internal/interop/device.h"
|
||||
#include "internal/interop/device_provider.h"
|
||||
|
||||
@@ -49,9 +49,9 @@ class Core {
|
||||
public:
|
||||
explicit Core(ServiceControllerRouter* router);
|
||||
// Client needs to call this constructor if analytics logger is needed.
|
||||
Core(::nearby::analytics::EventLogger* event_logger,
|
||||
Core(std::unique_ptr<analytics::AnalyticsRecorder> analytics_recorder,
|
||||
ServiceControllerRouter* router)
|
||||
: client_(event_logger), router_(router) {}
|
||||
: client_(std::move(analytics_recorder)), router_(router) {}
|
||||
~Core();
|
||||
Core(Core&&);
|
||||
Core& operator=(Core&&);
|
||||
|
||||
+168
-109
@@ -49,30 +49,143 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "service_id_constants",
|
||||
hdrs = ["service_id_constants.h"],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "bwu_handler",
|
||||
srcs = ["base_bwu_handler.cc"],
|
||||
hdrs = [
|
||||
"base_bwu_handler.h",
|
||||
"bwu_handler.h",
|
||||
],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":service_id_constants",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "offline_frames",
|
||||
srcs = [
|
||||
"offline_frames.cc",
|
||||
"offline_frames_validator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"internal_payload.h",
|
||||
"offline_frames.h",
|
||||
"offline_frames_validator.h",
|
||||
],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mac_address",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "client_proxy",
|
||||
srcs = ["client_proxy.cc"],
|
||||
hdrs = ["client_proxy.h"],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/mediums/advertisements:dct_advertisement",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/base:file_path",
|
||||
"//internal/base:files",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/interop:device",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mac_address",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/random",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:span",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "endpoint_channel",
|
||||
srcs = [
|
||||
"base_endpoint_channel.cc",
|
||||
"endpoint_channel_manager.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"base_endpoint_channel.h",
|
||||
"endpoint_channel.h",
|
||||
"endpoint_channel_manager.h",
|
||||
],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation:types",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_ukey2//:ukey2",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "internal",
|
||||
srcs = [
|
||||
"awdl_bwu_handler.cc",
|
||||
"awdl_endpoint_channel.cc",
|
||||
"base_bwu_handler.cc",
|
||||
"base_endpoint_channel.cc",
|
||||
"base_pcp_handler.cc",
|
||||
"ble_endpoint_channel.cc",
|
||||
"ble_l2cap_endpoint_channel.cc",
|
||||
"bluetooth_bwu_handler.cc",
|
||||
"bluetooth_device_name.cc",
|
||||
"bluetooth_endpoint_channel.cc",
|
||||
"bwu_manager.cc",
|
||||
"client_proxy.cc",
|
||||
"connections_authentication_transport.cc",
|
||||
"encryption_runner.cc",
|
||||
"endpoint_channel_manager.cc",
|
||||
"endpoint_manager.cc",
|
||||
"injected_bluetooth_device_store.cc",
|
||||
"internal_payload.cc",
|
||||
"internal_payload_factory.cc",
|
||||
"offline_frames.cc",
|
||||
"offline_frames_validator.cc",
|
||||
"offline_service_controller.cc",
|
||||
"p2p_cluster_pcp_handler.cc",
|
||||
"p2p_point_to_point_pcp_handler.cc",
|
||||
@@ -80,41 +193,17 @@ cc_library(
|
||||
"payload_manager.cc",
|
||||
"pcp_manager.cc",
|
||||
"service_controller_router.cc",
|
||||
"webrtc_bwu_handler.cc",
|
||||
"webrtc_bwu_handler_stub.cc",
|
||||
"webrtc_endpoint_channel.cc",
|
||||
"wifi_direct_bwu_handler.cc",
|
||||
"wifi_direct_endpoint_channel.cc",
|
||||
"wifi_hotspot_bwu_handler.cc",
|
||||
"wifi_hotspot_endpoint_channel.cc",
|
||||
"wifi_lan_bwu_handler.cc",
|
||||
"wifi_lan_endpoint_channel.cc",
|
||||
"wifi_lan_service_info.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"awdl_bwu_handler.h",
|
||||
"awdl_endpoint_channel.h",
|
||||
"base_bwu_handler.h",
|
||||
"base_endpoint_channel.h",
|
||||
"base_pcp_handler.h",
|
||||
"ble_endpoint_channel.h",
|
||||
"ble_l2cap_endpoint_channel.h",
|
||||
"bluetooth_bwu_handler.h",
|
||||
"bluetooth_device_name.h",
|
||||
"bluetooth_endpoint_channel.h",
|
||||
"bwu_handler.h",
|
||||
"bwu_manager.h",
|
||||
"client_proxy.h",
|
||||
"connections_authentication_transport.h",
|
||||
"encryption_runner.h",
|
||||
"endpoint_channel.h",
|
||||
"endpoint_channel_manager.h",
|
||||
"endpoint_manager.h",
|
||||
"injected_bluetooth_device_store.h",
|
||||
"internal_payload.h",
|
||||
"internal_payload_factory.h",
|
||||
"offline_frames.h",
|
||||
"offline_frames_validator.h",
|
||||
"offline_service_controller.h",
|
||||
"p2p_cluster_pcp_handler.h",
|
||||
"p2p_point_to_point_pcp_handler.h",
|
||||
@@ -124,49 +213,37 @@ cc_library(
|
||||
"pcp_manager.h",
|
||||
"service_controller.h",
|
||||
"service_controller_router.h",
|
||||
"service_id_constants.h",
|
||||
"webrtc_bwu_handler.h",
|
||||
"webrtc_bwu_handler_stub.h",
|
||||
"webrtc_endpoint_channel.h",
|
||||
"wifi_direct_bwu_handler.h",
|
||||
"wifi_direct_endpoint_channel.h",
|
||||
"wifi_hotspot_bwu_handler.h",
|
||||
"wifi_hotspot_endpoint_channel.h",
|
||||
"wifi_lan_bwu_handler.h",
|
||||
"wifi_lan_endpoint_channel.h",
|
||||
"wifi_lan_service_info.h",
|
||||
],
|
||||
copts = [
|
||||
"-DCORE_ADAPTER_DLL",
|
||||
"-DNO_WEBRTC",
|
||||
],
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
visibility = [
|
||||
"//chrome/chromeos/assistant/data_migration/lib:__pkg__",
|
||||
"//connections:__pkg__",
|
||||
"//connections:partners",
|
||||
"//connections/implementation/fuzzers:__pkg__",
|
||||
"//connections/implementation/mediums/multiplex:__pkg__",
|
||||
"//sharing:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":ble_advertisement",
|
||||
":bwu_handler",
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":offline_frames",
|
||||
":service_id_constants",
|
||||
":types",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/mediums",
|
||||
"//connections/implementation/mediums:utils",
|
||||
"//connections/implementation/mediums:webrtc_utils",
|
||||
"//connections/implementation/mediums:webrtc",
|
||||
"//connections/implementation/mediums:webrtc_peer_id",
|
||||
"//connections/implementation/mediums/advertisements:dct_advertisement",
|
||||
"//connections/implementation/mediums/advertisements:util",
|
||||
"//connections/implementation/mediums/ble:ble_advertisement_header",
|
||||
"//connections/implementation/mediums/ble:ble_socket",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/analytics:event_logger",
|
||||
"//internal/base:file_path",
|
||||
"//internal/base:files",
|
||||
"//internal/base:masker",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/interop:authentication_status",
|
||||
"//internal/interop:authentication_transport_interface",
|
||||
@@ -175,7 +252,6 @@ cc_library(
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:connection_info",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mac_address",
|
||||
"//internal/platform:types",
|
||||
@@ -184,7 +260,6 @@ cc_library(
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation:wifi_utils",
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:btree",
|
||||
@@ -192,7 +267,6 @@ cc_library(
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/functional:bind_front",
|
||||
"@com_google_absl//absl/random",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
@@ -214,6 +288,7 @@ cc_library(
|
||||
"fake_bwu_handler.h",
|
||||
"fake_endpoint_channel.h",
|
||||
"mock_device.h",
|
||||
"mock_endpoint_channel.h",
|
||||
"mock_service_controller.h",
|
||||
"mock_service_controller_router.h",
|
||||
"offline_simulation_user.h",
|
||||
@@ -223,7 +298,11 @@ cc_library(
|
||||
"//connections:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":bwu_handler",
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
@@ -246,38 +325,30 @@ cc_library(
|
||||
cc_test(
|
||||
name = "bwu_test",
|
||||
srcs = [
|
||||
"awdl_bwu_handler_test.cc",
|
||||
"base_bwu_handler_test.cc",
|
||||
"bluetooth_bwu_test.cc",
|
||||
"bwu_manager_test.cc",
|
||||
"wifi_direct_bwu_test.cc",
|
||||
"wifi_hotspot_bwu_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":bwu_handler",
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":internal_test",
|
||||
":offline_frames",
|
||||
":service_id_constants",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/mediums",
|
||||
"//internal/analytics:mock_event_logger",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mock_platform",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/flags:platform_flags",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform", # build_cleaner: keep
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@@ -286,6 +357,7 @@ cc_test(
|
||||
name = "pcp_manager_test",
|
||||
srcs = ["pcp_manager_test.cc"],
|
||||
deps = [
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":internal_test",
|
||||
"//connections:core_types",
|
||||
@@ -311,17 +383,20 @@ cc_test(
|
||||
],
|
||||
shard_count = 8,
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":internal_test",
|
||||
":offline_frames",
|
||||
":types",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/analytics:mock_analytics_recorder",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/mediums",
|
||||
"//connections/implementation/mediums:webrtc_utils",
|
||||
"//connections/implementation/mediums:webrtc_peer_id",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/analytics:mock_event_logger",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/interop:authentication_status",
|
||||
"//internal/interop:authentication_transport_interface",
|
||||
@@ -332,7 +407,6 @@ cc_test(
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
@@ -369,7 +443,7 @@ cc_test(
|
||||
name = "offline_frames_test",
|
||||
srcs = ["offline_frames_validator_test.cc"],
|
||||
deps = [
|
||||
":internal",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
@@ -389,12 +463,11 @@ cc_test(
|
||||
"client_proxy_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
"//base:casts",
|
||||
":client_proxy",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics:mock_analytics_recorder",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/v3:v3_types",
|
||||
"//internal/analytics:mock_event_logger",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/interop:device",
|
||||
"//internal/platform:base",
|
||||
@@ -418,6 +491,8 @@ cc_test(
|
||||
"encryption_runner_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
"//connections/implementation/analytics",
|
||||
"//internal/platform:base",
|
||||
@@ -439,9 +514,12 @@ cc_test(
|
||||
"endpoint_manager_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":internal_test",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
@@ -466,14 +544,17 @@ cc_test(
|
||||
"endpoint_channel_manager_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":endpoint_channel",
|
||||
":internal",
|
||||
":offline_frames",
|
||||
"//connections/implementation/analytics",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings",
|
||||
@@ -491,13 +572,11 @@ cc_test(
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
"//connections/implementation/analytics",
|
||||
":internal_test",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@@ -510,8 +589,8 @@ cc_test(
|
||||
deps = [
|
||||
":internal",
|
||||
":internal_test",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/analytics",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:test_util",
|
||||
@@ -532,6 +611,7 @@ cc_test(
|
||||
"service_controller_router_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":client_proxy",
|
||||
":internal",
|
||||
":internal_test",
|
||||
"//connections:core_types",
|
||||
@@ -582,9 +662,11 @@ cc_test(
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
":offline_frames",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
@@ -593,26 +675,3 @@ cc_test(
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "wifi_lan_bwu_handler_test",
|
||||
srcs = [
|
||||
"wifi_lan_bwu_handler_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/mediums",
|
||||
"//internal/analytics:mock_event_logger",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:mock_platform",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:platform_impl",
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -20,59 +20,92 @@ cc_library(
|
||||
name = "analytics",
|
||||
srcs = [
|
||||
"analytics_recorder.cc",
|
||||
"throughput_recorder.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"advertising_metadata_params.h",
|
||||
"analytics_recorder.h",
|
||||
"connection_attempt_metadata_params.h",
|
||||
"discovery_metadata_params.h",
|
||||
"packet_meta_data.h",
|
||||
"throughput_recorder.h",
|
||||
"operation_result_with_medium.h",
|
||||
],
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
"//connections:core_types",
|
||||
"//internal/analytics:event_logger",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "analytics_recorder_impl",
|
||||
srcs = [
|
||||
"analytics_recorder_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"analytics_recorder_impl.h",
|
||||
],
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
visibility = [
|
||||
"//connections/c:__pkg__",
|
||||
"//sharing:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":analytics",
|
||||
"//connections:core_types",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//location/nearby/analytics/cpp/logging:event_logger",
|
||||
"//location/nearby/analytics/cpp/proto:connections_log_cc_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/algorithm:container",
|
||||
"@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/meta:type_traits",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_protobuf//:protobuf_lite",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "mock_analytics_recorder",
|
||||
testonly = True,
|
||||
hdrs = [
|
||||
"mock_analytics_recorder.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = ["//connections:__subpackages__"],
|
||||
deps = [
|
||||
":analytics",
|
||||
"//connections:core_types",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_for_library_testonly",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "analytics_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"analytics_recorder_test.cc",
|
||||
"throughput_recorder_test.cc",
|
||||
"analytics_recorder_impl_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":analytics",
|
||||
":analytics_recorder_impl",
|
||||
"//connections:core_types",
|
||||
"//internal/analytics:mock_event_logger",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:error_code_recorder",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"//internal/proto/analytics:connections_log_cc_proto",
|
||||
"//internal/test",
|
||||
"//location/nearby/analytics/cpp/logging:mock_event_logger",
|
||||
"//location/nearby/analytics/cpp/proto:connections_log_cc_proto",
|
||||
"//net/proto2/contrib/parse_proto:parse_text_proto",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
@@ -26,8 +26,7 @@ struct AdvertisingMetadataParams {
|
||||
bool is_extended_advertisement_supported = false;
|
||||
int connected_ap_frequency = 0;
|
||||
bool is_nfc_available = false;
|
||||
std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>
|
||||
std::vector<nearby::analytics::OperationResultWithMedium>
|
||||
operation_result_with_mediums = {};
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,118 +18,98 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/advertising_metadata_params.h"
|
||||
#include "connections/implementation/analytics/connection_attempt_metadata_params.h"
|
||||
#include "connections/implementation/analytics/discovery_metadata_params.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
#include "connections/payload_type.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "internal/analytics/event_logger.h"
|
||||
#include "internal/platform/error_code_params.h"
|
||||
#include "internal/platform/implementation/system_clock.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
namespace nearby::analytics {
|
||||
|
||||
enum class SafeDisconnectionResult {
|
||||
kUnknown = 0,
|
||||
kSafeDisconnection = 1,
|
||||
kUnsafeDisconnection = 2,
|
||||
};
|
||||
|
||||
class AnalyticsRecorder {
|
||||
public:
|
||||
explicit AnalyticsRecorder(::nearby::analytics::EventLogger* event_logger);
|
||||
virtual ~AnalyticsRecorder();
|
||||
AnalyticsRecorder() = default;
|
||||
virtual ~AnalyticsRecorder() = default;
|
||||
|
||||
// Advertising phase
|
||||
void OnStartAdvertising(
|
||||
virtual void OnStartAdvertising(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>& mediums,
|
||||
AdvertisingMetadataParams* advertising_metadata_params)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnStopAdvertising() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
AdvertisingMetadataParams* advertising_metadata_params) = 0;
|
||||
virtual void OnStopAdvertising() = 0;
|
||||
|
||||
// In case the client calls the {@link BasePcp#updateAdvertisingOptions()}
|
||||
// multiple times, adds one index value to group the mediums results within
|
||||
// the same UpdateAdvertisingOptions call, this API is to return the largest
|
||||
// index value in current_advertising_phase.
|
||||
int GetNextAdvertisingUpdateIndex() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual int GetNextAdvertisingUpdateIndex() = 0;
|
||||
|
||||
// Connection listening
|
||||
void OnStartedIncomingConnectionListening(connections::Strategy strategy)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnStoppedIncomingConnectionListening() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual void OnStartedIncomingConnectionListening(
|
||||
connections::Strategy strategy) = 0;
|
||||
virtual void OnStoppedIncomingConnectionListening() = 0;
|
||||
|
||||
// Discovery phase
|
||||
void OnStartDiscovery(
|
||||
virtual void OnStartDiscovery(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>& mediums,
|
||||
DiscoveryMetadataParams* discovery_metadata_params)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnStopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
DiscoveryMetadataParams* discovery_metadata_params) = 0;
|
||||
virtual void OnStopDiscovery() = 0;
|
||||
|
||||
// In case the client calls the {@link BasePcp#updateDiscoveryOptions()}
|
||||
// multiple times, adds one index value to group the medium results within the
|
||||
// same UpdateDiscoveryOptions call, this
|
||||
// API is to return the latest index value in current_discovery_phase.
|
||||
int GetNextDiscoveryUpdateIndex() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnEndpointFound(location::nearby::proto::connections::Medium medium)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual int GetNextDiscoveryUpdateIndex() = 0;
|
||||
virtual void OnEndpointFound(
|
||||
location::nearby::proto::connections::Medium medium) = 0;
|
||||
|
||||
// Connection request
|
||||
void OnRequestConnection(const connections::Strategy& strategy,
|
||||
const std::string& endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual void OnRequestConnection(const connections::Strategy& strategy,
|
||||
const std::string& endpoint_id) = 0;
|
||||
|
||||
void OnConnectionRequestReceived(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnConnectionRequestSent(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnRemoteEndpointAccepted(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnLocalEndpointAccepted(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnRemoteEndpointRejected(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnLocalEndpointRejected(const std::string& remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual void OnConnectionRequestReceived(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
virtual void OnConnectionRequestSent(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
virtual void OnRemoteEndpointAccepted(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
virtual void OnLocalEndpointAccepted(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
virtual void OnRemoteEndpointRejected(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
virtual void OnLocalEndpointRejected(
|
||||
const std::string& remote_endpoint_id) = 0;
|
||||
|
||||
// Connection attempt
|
||||
// Records an attempt with meta data at establishing an incoming physical
|
||||
// connection.
|
||||
void OnIncomingConnectionAttempt(
|
||||
virtual void OnIncomingConnectionAttempt(
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
// Records an attempt with meta data at establishing an outgoing physical
|
||||
// connection.
|
||||
void OnOutgoingConnectionAttempt(
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params) = 0;
|
||||
virtual void OnOutgoingConnectionAttempt(
|
||||
const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params) = 0;
|
||||
|
||||
static std::unique_ptr<AdvertisingMetadataParams>
|
||||
BuildAdvertisingMetadataParams(
|
||||
bool is_extended_advertisement_supported = false,
|
||||
int connected_ap_frequency = 0, bool is_nfc_available = false,
|
||||
const std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>&
|
||||
const std::vector<OperationResultWithMedium>&
|
||||
operation_result_with_mediums = {});
|
||||
static std::unique_ptr<DiscoveryMetadataParams> BuildDiscoveryMetadataParams(
|
||||
bool is_extended_advertisement_supported = false,
|
||||
int connected_ap_frequency = 0, bool is_nfc_available = false,
|
||||
const std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>&
|
||||
const std::vector<OperationResultWithMedium>&
|
||||
operation_result_with_mediums = {});
|
||||
|
||||
static std::unique_ptr<ConnectionAttemptMetadataParams>
|
||||
@@ -147,363 +127,78 @@ class AnalyticsRecorder {
|
||||
GetChannelIoErrorResultCodeFromMedium(
|
||||
location::nearby::proto::connections::Medium medium);
|
||||
|
||||
// Connection establishedSafeDisconnectionResult
|
||||
void OnConnectionEstablished(
|
||||
// Connection established
|
||||
virtual void OnConnectionEstablished(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
const std::string& connection_token) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnConnectionClosed(
|
||||
const std::string& connection_token) = 0;
|
||||
virtual void OnConnectionClosed(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
SafeDisconnectionResult result) = 0;
|
||||
|
||||
// Payload
|
||||
void OnIncomingPayloadStarted(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
connections::PayloadType type,
|
||||
std::int64_t total_size_bytes)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnPayloadChunkReceived(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnIncomingPayloadDone(
|
||||
virtual void OnIncomingPayloadStarted(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
connections::PayloadType type,
|
||||
std::int64_t total_size_bytes) = 0;
|
||||
virtual void OnPayloadChunkReceived(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes) = 0;
|
||||
virtual void OnIncomingPayloadDone(
|
||||
const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnOutgoingPayloadStarted(const std::vector<std::string>& endpoint_ids,
|
||||
std::int64_t payload_id,
|
||||
connections::PayloadType type,
|
||||
std::int64_t total_size_bytes)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnPayloadChunkSent(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnOutgoingPayloadDone(
|
||||
operation_result_code) = 0;
|
||||
virtual void OnOutgoingPayloadStarted(
|
||||
const std::vector<std::string>& endpoint_ids, std::int64_t payload_id,
|
||||
connections::PayloadType type, std::int64_t total_size_bytes) = 0;
|
||||
virtual void OnPayloadChunkSent(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes) = 0;
|
||||
virtual void OnOutgoingPayloadDone(
|
||||
const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
operation_result_code) = 0;
|
||||
|
||||
// BandwidthUpgrade
|
||||
void OnBandwidthUpgradeStarted(
|
||||
virtual void OnBandwidthUpgradeStarted(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium from_medium,
|
||||
location::nearby::proto::connections::Medium to_medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptDirection
|
||||
direction,
|
||||
const std::string& connection_token) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id,
|
||||
int num_interfaces,
|
||||
int num_ipv6_only_interfaces)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnBandwidthUpgradeError(
|
||||
const std::string& connection_token) = 0;
|
||||
virtual void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id,
|
||||
int num_interfaces,
|
||||
int num_ipv6_only_interfaces) = 0;
|
||||
virtual void OnBandwidthUpgradeError(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::BandwidthUpgradeResult result,
|
||||
location::nearby::proto::connections::BandwidthUpgradeErrorStage
|
||||
error_stage,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnBandwidthUpgradeSuccess(const std::string& endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
operation_result_code) = 0;
|
||||
virtual void OnBandwidthUpgradeSuccess(const std::string& endpoint_id) = 0;
|
||||
|
||||
// Error Code
|
||||
void OnErrorCode(const ErrorCodeParams& params);
|
||||
virtual void OnErrorCode(const ErrorCodeParams& params) = 0;
|
||||
|
||||
// Log the start client session event with start client session logging
|
||||
// resources setup (e.g. client_session_, started_client_session_time_)
|
||||
void LogStartSession() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual void LogStartSession() = 0;
|
||||
virtual void LogSession() = 0;
|
||||
|
||||
// Invokes event_logger_.Log() at the end of life of client. Log action is
|
||||
// called in a separate thread to allow synchronous potentially lengthy
|
||||
// execution.
|
||||
void LogSession() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual bool IsSessionLogged() = 0;
|
||||
|
||||
bool IsSessionLogged();
|
||||
|
||||
location::nearby::proto::connections::OperationResultCategory
|
||||
virtual location::nearby::proto::connections::OperationResultCategory
|
||||
GetOperationResultCategory(
|
||||
location::nearby::proto::connections::OperationResultCode result_code);
|
||||
|
||||
// Waits until all logs are sent to the backend.
|
||||
// For testing only.
|
||||
void Sync();
|
||||
|
||||
private:
|
||||
// Tracks the chunks and duration of a Payload on a particular medium.
|
||||
class PendingPayload {
|
||||
public:
|
||||
PendingPayload(location::nearby::proto::connections::PayloadType type,
|
||||
std::int64_t total_size_bytes)
|
||||
: PendingPayload(type, total_size_bytes,
|
||||
location::nearby::proto::connections::
|
||||
OperationResultCode::DETAIL_UNKNOWN) {}
|
||||
PendingPayload(location::nearby::proto::connections::PayloadType type,
|
||||
std::int64_t total_size_bytes,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code)
|
||||
: start_time_(SystemClock::ElapsedRealtime()),
|
||||
type_(type),
|
||||
total_size_bytes_(total_size_bytes),
|
||||
num_bytes_transferred_(0),
|
||||
num_chunks_(0),
|
||||
operation_result_code_(operation_result_code) {}
|
||||
~PendingPayload() = default;
|
||||
|
||||
void AddChunk(std::int64_t chunk_size_bytes);
|
||||
|
||||
location::nearby::analytics::proto::ConnectionsLog::Payload GetProtoPayload(
|
||||
location::nearby::proto::connections::PayloadStatus status);
|
||||
|
||||
location::nearby::proto::connections::PayloadType type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
std::int64_t total_size_bytes() const { return total_size_bytes_; }
|
||||
|
||||
void SetOperationResultCode(
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) {
|
||||
operation_result_code_ = operation_result_code;
|
||||
}
|
||||
|
||||
private:
|
||||
absl::Time start_time_;
|
||||
location::nearby::proto::connections::PayloadType type_;
|
||||
std::int64_t total_size_bytes_;
|
||||
std::int64_t num_bytes_transferred_;
|
||||
int num_chunks_;
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code_ = location::nearby::proto::connections::
|
||||
OperationResultCode::DETAIL_UNKNOWN;
|
||||
};
|
||||
|
||||
class LogicalConnection {
|
||||
public:
|
||||
LogicalConnection(
|
||||
location::nearby::proto::connections::Medium initial_medium,
|
||||
const std::string& connection_token) {
|
||||
PhysicalConnectionEstablished(initial_medium, connection_token);
|
||||
}
|
||||
LogicalConnection(const LogicalConnection&) = delete;
|
||||
LogicalConnection(LogicalConnection&& other)
|
||||
: current_medium_(std::move(other.current_medium_)),
|
||||
physical_connections_(std::move(other.physical_connections_)),
|
||||
incoming_payloads_(std::move(other.incoming_payloads_)),
|
||||
outgoing_payloads_(std::move(other.outgoing_payloads_)) {}
|
||||
LogicalConnection& operator=(const LogicalConnection&) = delete;
|
||||
LogicalConnection&& operator=(LogicalConnection&&) = delete;
|
||||
~LogicalConnection() = default;
|
||||
|
||||
void PhysicalConnectionEstablished(
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
const std::string& connection_token);
|
||||
void PhysicalConnectionClosed(
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result);
|
||||
void CloseAllPhysicalConnections();
|
||||
|
||||
void IncomingPayloadStarted(
|
||||
std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadType type,
|
||||
std::int64_t total_size_bytes);
|
||||
void ChunkReceived(std::int64_t payload_id, std::int64_t size_bytes);
|
||||
void IncomingPayloadDone(
|
||||
std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code);
|
||||
void OutgoingPayloadStarted(
|
||||
std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadType type,
|
||||
std::int64_t total_size_bytes);
|
||||
void ChunkSent(std::int64_t payload_id, std::int64_t size_bytes);
|
||||
void OutgoingPayloadDone(
|
||||
std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code);
|
||||
|
||||
std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection>
|
||||
GetEstablisedConnections();
|
||||
|
||||
private:
|
||||
void FinishPhysicalConnection(
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection* established_connection,
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result);
|
||||
std::vector<location::nearby::analytics::proto::ConnectionsLog::Payload>
|
||||
ResolvePendingPayloads(
|
||||
absl::btree_map<std::int64_t, std::unique_ptr<PendingPayload>>&
|
||||
pending_payloads,
|
||||
location::nearby::proto::connections::DisconnectionReason reason);
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
GetPendingPayloadResultCodeFromReason(
|
||||
location::nearby::proto::connections::DisconnectionReason reason);
|
||||
|
||||
location::nearby::proto::connections::Medium current_medium_ =
|
||||
location::nearby::proto::connections::UNKNOWN_MEDIUM;
|
||||
absl::btree_map<location::nearby::proto::connections::Medium,
|
||||
std::unique_ptr<location::nearby::analytics::proto::
|
||||
ConnectionsLog::EstablishedConnection>>
|
||||
physical_connections_;
|
||||
absl::btree_map<std::int64_t, std::unique_ptr<PendingPayload>>
|
||||
incoming_payloads_;
|
||||
absl::btree_map<std::int64_t, std::unique_ptr<PendingPayload>>
|
||||
outgoing_payloads_;
|
||||
};
|
||||
|
||||
bool CanRecordAnalyticsLocked(absl::string_view method_name)
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Callbacks the ConnectionsLog proto byte array data to the EventLogger with
|
||||
// ClientSession sub-proto.
|
||||
void LogClientSessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
// Callbacks the ConnectionsLog proto byte array data to the EventLogger.
|
||||
void LogEvent(location::nearby::proto::connections::EventType event_type);
|
||||
|
||||
void UpdateStrategySessionLocked(
|
||||
connections::Strategy strategy,
|
||||
location::nearby::proto::connections::SessionRole role)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RecordAdvertisingPhaseDurationAndReasonLocked(bool on_stop) const
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishAdvertisingPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RecordDiscoveryPhaseDurationAndReasonLocked(bool on_stop) const
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishDiscoveryPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool UpdateAdvertiserConnectionRequestLocked(
|
||||
location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest*
|
||||
request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool UpdateDiscovererConnectionRequestLocked(
|
||||
location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest*
|
||||
request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool BothEndpointsRespondedLocked(
|
||||
location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest*
|
||||
request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void LocalEndpointRespondedLocked(
|
||||
const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionRequestResponse response)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RemoteEndpointRespondedLocked(
|
||||
const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionRequestResponse response)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void MarkConnectionRequestIgnoredLocked(
|
||||
location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest*
|
||||
request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void OnIncomingConnectionAttemptLocked(
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void OnOutgoingConnectionAttemptLocked(
|
||||
const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool ConnectionAttemptResultCodeExistedLocked(
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptDirection
|
||||
direction,
|
||||
const std::string& connection_token,
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool EraseIfBandwidthUpgradeRecordExistedLocked(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::BandwidthUpgradeResult result,
|
||||
location::nearby::proto::connections::BandwidthUpgradeErrorStage
|
||||
error_stage,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishUpgradeAttemptLocked(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::BandwidthUpgradeResult result,
|
||||
location::nearby::proto::connections::BandwidthUpgradeErrorStage
|
||||
error_stage,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code,
|
||||
bool erase_item = true) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishStrategySessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
result_code) = 0;
|
||||
|
||||
int GetLatestUpdateIndexLocked(
|
||||
const std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>& list)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
location::nearby::proto::connections::ConnectionsStrategy
|
||||
StrategyToConnectionStrategy(connections::Strategy strategy);
|
||||
location::nearby::proto::connections::PayloadType
|
||||
PayloadTypeToProtoPayloadType(connections::PayloadType type);
|
||||
|
||||
// Not owned by AnalyticsRecorder. Pointer must refer to a valid object
|
||||
// that outlives the one constructed.
|
||||
::nearby::analytics::EventLogger* event_logger_;
|
||||
|
||||
// Protects all sub-protos reading and writing in ConnectionLog.
|
||||
Mutex mutex_;
|
||||
|
||||
// ClientSession
|
||||
std::unique_ptr<
|
||||
location::nearby::analytics::proto::ConnectionsLog::ClientSession>
|
||||
client_session_;
|
||||
absl::Time started_client_session_time_;
|
||||
bool session_was_logged_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool start_client_session_was_logged_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
|
||||
// Current StrategySession
|
||||
connections::Strategy current_strategy_ ABSL_GUARDED_BY(mutex_) =
|
||||
connections::Strategy::kNone;
|
||||
std::unique_ptr<
|
||||
location::nearby::analytics::proto::ConnectionsLog::StrategySession>
|
||||
current_strategy_session_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::Time started_strategy_session_time_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// Current AdvertisingPhase
|
||||
std::unique_ptr<
|
||||
location::nearby::analytics::proto::ConnectionsLog::AdvertisingPhase>
|
||||
current_advertising_phase_;
|
||||
absl::Time started_advertising_phase_time_ = absl::InfinitePast();
|
||||
|
||||
// Current DiscoveryPhase
|
||||
std::unique_ptr<
|
||||
location::nearby::analytics::proto::ConnectionsLog::DiscoveryPhase>
|
||||
current_discovery_phase_;
|
||||
absl::Time started_discovery_phase_time_ = absl::InfinitePast();
|
||||
|
||||
absl::btree_map<std::string,
|
||||
std::unique_ptr<location::nearby::analytics::proto::
|
||||
ConnectionsLog::ConnectionRequest>>
|
||||
incoming_connection_requests_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::btree_map<std::string,
|
||||
std::unique_ptr<location::nearby::analytics::proto::
|
||||
ConnectionsLog::ConnectionRequest>>
|
||||
outgoing_connection_requests_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::btree_map<std::string, std::unique_ptr<LogicalConnection>>
|
||||
active_connections_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::btree_map<std::string,
|
||||
std::unique_ptr<location::nearby::analytics::proto::
|
||||
ConnectionsLog::BandwidthUpgradeAttempt>>
|
||||
bandwidth_upgrade_attempts_ ABSL_GUARDED_BY(mutex_);
|
||||
virtual void Sync() = 0;
|
||||
};
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
} // namespace nearby::analytics
|
||||
|
||||
#endif // ANALYTICS_ANALYTICS_RECORDER_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
@@ -26,8 +26,7 @@ struct DiscoveryMetadataParams {
|
||||
bool is_extended_advertisement_supported = false;
|
||||
int connected_ap_frequency = 0;
|
||||
bool is_nfc_available = false;
|
||||
std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>
|
||||
std::vector<nearby::analytics::OperationResultWithMedium>
|
||||
operation_result_with_mediums = {};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
// Copyright 2026 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 ANALYTICS_MOCK_ANALYTICS_RECORDER_H_
|
||||
#define ANALYTICS_MOCK_ANALYTICS_RECORDER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/advertising_metadata_params.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/connection_attempt_metadata_params.h"
|
||||
#include "connections/implementation/analytics/discovery_metadata_params.h"
|
||||
#include "connections/payload_type.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "internal/platform/error_code_params.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby::analytics {
|
||||
|
||||
class MockAnalyticsRecorder : public AnalyticsRecorder {
|
||||
public:
|
||||
MockAnalyticsRecorder() = default;
|
||||
~MockAnalyticsRecorder() override = default;
|
||||
|
||||
// Advertising phase
|
||||
MOCK_METHOD(void, OnStartAdvertising,
|
||||
(connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>&
|
||||
mediums,
|
||||
AdvertisingMetadataParams* advertising_metadata_params),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnStopAdvertising, (), (override));
|
||||
|
||||
MOCK_METHOD(int, GetNextAdvertisingUpdateIndex, (), (override));
|
||||
|
||||
// Connection listening
|
||||
MOCK_METHOD(void, OnStartedIncomingConnectionListening,
|
||||
(connections::Strategy strategy), (override));
|
||||
MOCK_METHOD(void, OnStoppedIncomingConnectionListening, (), (override));
|
||||
|
||||
// Discovery phase
|
||||
MOCK_METHOD(void, OnStartDiscovery,
|
||||
(connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>&
|
||||
mediums,
|
||||
DiscoveryMetadataParams* discovery_metadata_params),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnStopDiscovery, (), (override));
|
||||
|
||||
MOCK_METHOD(int, GetNextDiscoveryUpdateIndex, (), (override));
|
||||
MOCK_METHOD(void, OnEndpointFound,
|
||||
(location::nearby::proto::connections::Medium medium),
|
||||
(override));
|
||||
|
||||
// Connection request
|
||||
MOCK_METHOD(void, OnRequestConnection,
|
||||
(const connections::Strategy& strategy,
|
||||
const std::string& endpoint_id),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(void, OnConnectionRequestReceived,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
MOCK_METHOD(void, OnConnectionRequestSent,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
MOCK_METHOD(void, OnRemoteEndpointAccepted,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
MOCK_METHOD(void, OnLocalEndpointAccepted,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
MOCK_METHOD(void, OnRemoteEndpointRejected,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
MOCK_METHOD(void, OnLocalEndpointRejected,
|
||||
(const std::string& remote_endpoint_id), (override));
|
||||
|
||||
// Connection attempt
|
||||
MOCK_METHOD(
|
||||
void, OnIncomingConnectionAttempt,
|
||||
(location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params),
|
||||
(override));
|
||||
MOCK_METHOD(
|
||||
void, OnOutgoingConnectionAttempt,
|
||||
(const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params),
|
||||
(override));
|
||||
|
||||
// Connection established
|
||||
MOCK_METHOD(void, OnConnectionEstablished,
|
||||
(const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
const std::string& connection_token),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnConnectionClosed,
|
||||
(const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
SafeDisconnectionResult result),
|
||||
(override));
|
||||
|
||||
// Payload
|
||||
MOCK_METHOD(void, OnIncomingPayloadStarted,
|
||||
(const std::string& endpoint_id, std::int64_t payload_id,
|
||||
connections::PayloadType type, std::int64_t total_size_bytes),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnPayloadChunkReceived,
|
||||
(const std::string& endpoint_id, std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnIncomingPayloadDone,
|
||||
(const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnOutgoingPayloadStarted,
|
||||
(const std::vector<std::string>& endpoint_ids,
|
||||
std::int64_t payload_id, connections::PayloadType type,
|
||||
std::int64_t total_size_bytes),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnPayloadChunkSent,
|
||||
(const std::string& endpoint_id, std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnOutgoingPayloadDone,
|
||||
(const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code),
|
||||
(override));
|
||||
|
||||
// BandwidthUpgrade
|
||||
MOCK_METHOD(void, OnBandwidthUpgradeStarted,
|
||||
(const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium from_medium,
|
||||
location::nearby::proto::connections::Medium to_medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptDirection
|
||||
direction,
|
||||
const std::string& connection_token),
|
||||
(override));
|
||||
MOCK_METHOD(void, UpdateBwUpgradeNetworkInfo,
|
||||
(const std::string& endpoint_id, int num_interfaces,
|
||||
int num_ipv6_only_interfaces),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnBandwidthUpgradeError,
|
||||
(const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::BandwidthUpgradeResult
|
||||
result,
|
||||
location::nearby::proto::connections::BandwidthUpgradeErrorStage
|
||||
error_stage,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnBandwidthUpgradeSuccess, (const std::string& endpoint_id),
|
||||
(override));
|
||||
|
||||
// Error Code
|
||||
MOCK_METHOD(void, OnErrorCode, (const ErrorCodeParams& params), (override));
|
||||
|
||||
MOCK_METHOD(void, LogStartSession, (), (override));
|
||||
MOCK_METHOD(void, LogSession, (), (override));
|
||||
|
||||
MOCK_METHOD(bool, IsSessionLogged, (), (override));
|
||||
|
||||
MOCK_METHOD(
|
||||
location::nearby::proto::connections::OperationResultCategory,
|
||||
GetOperationResultCategory,
|
||||
(location::nearby::proto::connections::OperationResultCode result_code),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(void, Sync, (), (override));
|
||||
};
|
||||
|
||||
} // namespace nearby::analytics
|
||||
|
||||
#endif // ANALYTICS_MOCK_ANALYTICS_RECORDER_H_
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2026 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 ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_
|
||||
#define ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby::analytics {
|
||||
|
||||
struct OperationResultWithMedium {
|
||||
location::nearby::proto::connections::Medium medium =
|
||||
location::nearby::proto::connections::UNKNOWN_MEDIUM;
|
||||
std::optional<int> update_index;
|
||||
location::nearby::proto::connections::OperationResultCategory
|
||||
result_category = location::nearby::proto::connections::CATEGORY_UNKNOWN;
|
||||
location::nearby::proto::connections::OperationResultCode result_code =
|
||||
location::nearby::proto::connections::DETAIL_UNKNOWN;
|
||||
std::optional<location::nearby::proto::connections::ConnectionMode>
|
||||
connection_mode;
|
||||
|
||||
void set_medium(location::nearby::proto::connections::Medium m) {
|
||||
medium = m;
|
||||
}
|
||||
void set_update_index(int i) { update_index = i; }
|
||||
void set_result_category(
|
||||
location::nearby::proto::connections::OperationResultCategory c) {
|
||||
result_category = c;
|
||||
}
|
||||
void set_result_code(
|
||||
location::nearby::proto::connections::OperationResultCode c) {
|
||||
result_code = c;
|
||||
}
|
||||
void set_connection_mode(
|
||||
location::nearby::proto::connections::ConnectionMode m) {
|
||||
connection_mode = m;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nearby::analytics
|
||||
|
||||
#endif // ANALYTICS_OPERATION_RESULT_WITH_MEDIUM_H_
|
||||
@@ -1,102 +0,0 @@
|
||||
// Copyright 2022-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.
|
||||
// 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 NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_PACKET_META_DATA_H_
|
||||
#define NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_PACKET_META_DATA_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/system_clock.h"
|
||||
#include "internal/platform/system_clock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
|
||||
struct PacketMetaData {
|
||||
int packet_size;
|
||||
absl::Time file_io_start_time;
|
||||
absl::Time file_io_end_time;
|
||||
absl::Time encryption_start_time;
|
||||
absl::Time encryption_end_time;
|
||||
absl::Time socket_io_start_time;
|
||||
absl::Time socket_io_end_time;
|
||||
|
||||
void Reset() {
|
||||
file_io_start_time = SystemClock::ElapsedRealtime();
|
||||
socket_io_start_time = SystemClock::ElapsedRealtime();
|
||||
socket_io_start_time = SystemClock::ElapsedRealtime();
|
||||
packet_size = 0;
|
||||
}
|
||||
|
||||
void SetPacketSize(int packet_size) {
|
||||
this->packet_size = packet_size;
|
||||
}
|
||||
|
||||
int GetPacketSize() {
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
void StartFileIo() {
|
||||
file_io_start_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
void StopFileIo() {
|
||||
file_io_end_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
void StartEncryption() {
|
||||
encryption_start_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
void StopEncryption() {
|
||||
encryption_end_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
void StartSocketIo() {
|
||||
socket_io_start_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
void StopSocketIo() {
|
||||
socket_io_end_time = SystemClock::ElapsedRealtime();
|
||||
}
|
||||
|
||||
int64_t GetEncryptionTimeInMillis() {
|
||||
if (encryption_end_time > encryption_start_time) {
|
||||
return absl::ToInt64Milliseconds(encryption_end_time -
|
||||
encryption_start_time);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
int64_t GetFileIoTimeInMillis() {
|
||||
if (file_io_end_time > file_io_start_time) {
|
||||
return absl::ToInt64Milliseconds(file_io_end_time - file_io_start_time);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
int64_t GetSocketIoTimeInMillis() {
|
||||
if (socket_io_end_time > socket_io_start_time) {
|
||||
return absl::ToInt64Milliseconds(socket_io_end_time -
|
||||
socket_io_start_time);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
|
||||
#endif // NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_PACKET_META_DATA_H_
|
||||
@@ -1,333 +0,0 @@
|
||||
// Copyright 2022-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.
|
||||
// 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 "connections/implementation/analytics/throughput_recorder.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <new>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/system_clock.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
|
||||
namespace {
|
||||
constexpr int kDefaultThroughoutKbps = 0;
|
||||
constexpr int kKbInBytes = 1024;
|
||||
constexpr int kSecInMs = 1000;
|
||||
} // namespace
|
||||
|
||||
ThroughputRecorder::ThroughputRecorder(int64_t payload_id)
|
||||
: payload_id_(payload_id) {}
|
||||
|
||||
ThroughputRecorderContainer& ThroughputRecorderContainer::GetInstance() {
|
||||
alignas(ThroughputRecorderContainer) static char
|
||||
storage[sizeof(ThroughputRecorderContainer)];
|
||||
static ThroughputRecorderContainer* env =
|
||||
new (&storage) ThroughputRecorderContainer();
|
||||
return *env;
|
||||
}
|
||||
|
||||
void ThroughputRecorder::Start(PayloadType payload_type,
|
||||
PayloadDirection payload_direction) {
|
||||
std::string direction =
|
||||
(payload_direction == PayloadDirection::INCOMING_PAYLOAD) ? "; Receive"
|
||||
: "; Send";
|
||||
|
||||
VLOG(1) << "Start TP profiling for payload_id:" << payload_id_ << direction;
|
||||
|
||||
if (payload_type == PayloadType::kUnknown) {
|
||||
VLOG(1) << "Ignore ThroughputRecorder::start for Unknown Payload type";
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
start_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
payload_type_ = payload_type;
|
||||
payload_direction_ = payload_direction;
|
||||
// Add packetLostAlarm later
|
||||
}
|
||||
|
||||
bool ThroughputRecorder::Stop() {
|
||||
MutexLock lock(&mutex_);
|
||||
VLOG(1) << "Stop TP profiling for payload_id:" << payload_id_;
|
||||
if (payload_type_ == PayloadType::kUnknown) {
|
||||
VLOG(1) << "Ignore ThroughputRecorder::stop as it never start";
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// Add packetLostAlarm stop process later
|
||||
absl::Time stop_timestamp = SystemClock::ElapsedRealtime();
|
||||
int64_t total_byte_size = 0;
|
||||
int medium_size = throughputs_.size();
|
||||
|
||||
// The worse case is the socket/connect blocking the write request, never
|
||||
// got return when writing a frame out, it would get a very good data rate
|
||||
// for this case. e.g. use 60 seconds to send a file and failed, the counter
|
||||
// only get the duration as 30 seconds because the last write request
|
||||
// blocked.
|
||||
if (!success_) {
|
||||
if (!throughputs_.empty()) {
|
||||
for (auto& tp : throughputs_) {
|
||||
tp.second.SetLastTimestamp(stop_timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate throughput by medium
|
||||
for (auto& tp : throughputs_) {
|
||||
tp.second.dump();
|
||||
total_byte_size += tp.second.GetTotalByteSize();
|
||||
}
|
||||
|
||||
throughputs_.clear();
|
||||
|
||||
int64_t total_millis =
|
||||
absl::ToInt64Milliseconds(stop_timestamp - start_timestamp_);
|
||||
throughput_kbps_ = CalculateThroughputKBps(total_byte_size, total_millis);
|
||||
int throughput_mbps = CalculateThroughputMBps(throughput_kbps_);
|
||||
|
||||
// calculate overall throughput if there are multiple mediums
|
||||
if (medium_size > 1) {
|
||||
if (throughput_kbps_ != kDefaultThroughoutKbps) {
|
||||
std::string dump_content = absl::StrFormat(
|
||||
"%s %s data(%d bytes) %s, overall used %d milliseconds, "
|
||||
"throughput "
|
||||
"is %d MB/s (%d KB/s), File IO takes %d ms, %s takes %d "
|
||||
"ms, "
|
||||
"Socket IO takes %d ms",
|
||||
(payload_direction_ == PayloadDirection::INCOMING_PAYLOAD)
|
||||
? "Received"
|
||||
: "Sent",
|
||||
ToString(payload_type_), total_byte_size,
|
||||
success_ ? "SUCCEEDED" : "FAILED", total_millis, throughput_mbps,
|
||||
throughput_kbps_, file_io_time_,
|
||||
(payload_direction_ == PayloadDirection::INCOMING_PAYLOAD)
|
||||
? "Decryption"
|
||||
: "Encryption",
|
||||
encryption_time_, socket_io_time_);
|
||||
LOG(INFO) << dump_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThroughputRecorder::MarkAsSuccess() {
|
||||
MutexLock lock(&mutex_);
|
||||
success_ = true;
|
||||
}
|
||||
|
||||
int ThroughputRecorder::CalculateThroughputKBps(int64_t total_byte_size,
|
||||
int64_t total_millis) {
|
||||
if (total_millis > 0) {
|
||||
return (int)(total_byte_size * kSecInMs / kKbInBytes / total_millis);
|
||||
}
|
||||
return kDefaultThroughoutKbps;
|
||||
}
|
||||
|
||||
int ThroughputRecorder::CalculateThroughputMBps(int throughputKBps) {
|
||||
return throughputKBps / kKbInBytes;
|
||||
}
|
||||
|
||||
void ThroughputRecorder::Throughput::Add(int frame_size, int64_t file_io_time,
|
||||
int64_t encryption_time,
|
||||
int64_t socket_io_time) {
|
||||
total_byte_size_ += frame_size;
|
||||
// reset the last timestamp
|
||||
last_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
file_io_time_ += file_io_time;
|
||||
encryption_time_ += encryption_time;
|
||||
socket_io_time_ += socket_io_time;
|
||||
}
|
||||
|
||||
bool ThroughputRecorder::Throughput::dump() {
|
||||
int64_t total_millis =
|
||||
absl::ToInt64Milliseconds(last_timestamp_ - start_timestamp_);
|
||||
int throughput_kbps = CalculateThroughputKBps(total_byte_size_, total_millis);
|
||||
if (throughput_kbps == kDefaultThroughoutKbps) {
|
||||
return false;
|
||||
}
|
||||
int throughpu_mbps = CalculateThroughputMBps(throughput_kbps);
|
||||
int64_t other =
|
||||
total_millis - file_io_time_ - encryption_time_ - socket_io_time_;
|
||||
std::string dump_content = absl::StrFormat(
|
||||
"%s %s data(%ld bytes) via %s used %ld milliseconds, throughput is %d "
|
||||
"MB/s (%d KB/s), File IO takes %ld ms, %s takes %ld ms, "
|
||||
"Socket IO takes %ld ms, "
|
||||
"Other takes %ld ms",
|
||||
(payload_direction_ == PayloadDirection::INCOMING_PAYLOAD) ? "Received"
|
||||
: "Sent",
|
||||
ToString(payload_type_), total_byte_size_,
|
||||
location::nearby::proto::connections::Medium_Name(medium_), total_millis,
|
||||
throughpu_mbps, throughput_kbps, file_io_time_,
|
||||
(payload_direction_ == PayloadDirection::INCOMING_PAYLOAD) ? "Decryption"
|
||||
: "Encryption",
|
||||
encryption_time_, socket_io_time_, other);
|
||||
LOG(INFO) << dump_content;
|
||||
return true;
|
||||
}
|
||||
|
||||
ThroughputRecorder::Throughput& ThroughputRecorder::GetThroughput(
|
||||
Medium medium, int64_t duration_millis) {
|
||||
auto it = throughputs_.find(medium);
|
||||
if (it == throughputs_.end()) {
|
||||
auto throughput = new Throughput(
|
||||
medium,
|
||||
SystemClock::ElapsedRealtime() - absl::Milliseconds(duration_millis),
|
||||
payload_type_, payload_direction_);
|
||||
throughputs_.emplace(medium, std::move(*throughput));
|
||||
delete throughput;
|
||||
return throughputs_.find(medium)->second;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int ThroughputRecorder::GetThroughputsSize() {
|
||||
MutexLock lock(&mutex_);
|
||||
return throughputs_.size();
|
||||
}
|
||||
|
||||
int ThroughputRecorder::GetThroughputKbps() { return throughput_kbps_; }
|
||||
|
||||
int64_t ThroughputRecorder::GetDurationMillis() { return duration_millis_; }
|
||||
|
||||
void ThroughputRecorder::OnFrameSent(Medium medium,
|
||||
PacketMetaData& packetMetaData) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (payload_type_ == PayloadType::kUnknown) {
|
||||
VLOG(1) << "PayloadType is invalid, return";
|
||||
return;
|
||||
}
|
||||
|
||||
duration_millis_ = packetMetaData.GetEncryptionTimeInMillis() +
|
||||
packetMetaData.GetFileIoTimeInMillis() +
|
||||
packetMetaData.GetSocketIoTimeInMillis();
|
||||
GetThroughput(medium, duration_millis_)
|
||||
.Add(packetMetaData.packet_size, packetMetaData.GetFileIoTimeInMillis(),
|
||||
packetMetaData.GetEncryptionTimeInMillis(),
|
||||
packetMetaData.GetSocketIoTimeInMillis());
|
||||
CalculateDurationTimes(packetMetaData);
|
||||
}
|
||||
|
||||
void ThroughputRecorder::OnFrameReceived(Medium medium,
|
||||
PacketMetaData& packetMetaData) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (payload_type_ == PayloadType::kUnknown) {
|
||||
VLOG(1) << "PayloadType is invalid, return";
|
||||
return;
|
||||
}
|
||||
|
||||
// Add packetLostAlarm process later
|
||||
duration_millis_ = packetMetaData.GetEncryptionTimeInMillis() +
|
||||
packetMetaData.GetFileIoTimeInMillis() +
|
||||
packetMetaData.GetSocketIoTimeInMillis();
|
||||
GetThroughput(medium, duration_millis_)
|
||||
.Add(packetMetaData.packet_size, packetMetaData.GetFileIoTimeInMillis(),
|
||||
packetMetaData.GetEncryptionTimeInMillis(),
|
||||
packetMetaData.GetSocketIoTimeInMillis());
|
||||
CalculateDurationTimes(packetMetaData);
|
||||
}
|
||||
|
||||
void ThroughputRecorder::CalculateDurationTimes(PacketMetaData packetMetaData) {
|
||||
encryption_time_ += packetMetaData.GetEncryptionTimeInMillis();
|
||||
socket_io_time_ += packetMetaData.GetSocketIoTimeInMillis();
|
||||
file_io_time_ += packetMetaData.GetFileIoTimeInMillis();
|
||||
}
|
||||
|
||||
std::string ThroughputRecorder::ToString(PayloadType type) {
|
||||
switch (type) {
|
||||
case PayloadType::kBytes:
|
||||
return std::string("Bytes");
|
||||
case PayloadType::kStream:
|
||||
return std::string("Stream");
|
||||
case PayloadType::kFile:
|
||||
return std::string("File");
|
||||
case PayloadType::kUnknown:
|
||||
return std::string("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
// Inplementation for ThroughputRecorderContainer
|
||||
|
||||
void ThroughputRecorderContainer::Shutdown() {
|
||||
MutexLock lock(&mutex_);
|
||||
VLOG(1) << __func__ << ". Num of Instance:" << throughput_recorders_.size();
|
||||
for (auto& throughput_recorder : throughput_recorders_) {
|
||||
VLOG(1) << "Stop instance: " << throughput_recorder.second;
|
||||
throughput_recorder.second->Stop();
|
||||
delete throughput_recorder.second;
|
||||
}
|
||||
throughput_recorders_.clear();
|
||||
}
|
||||
|
||||
ThroughputRecorder* ThroughputRecorderContainer::GetTPRecorder(
|
||||
const int64_t payload_id, PayloadDirection payload_direction) {
|
||||
MutexLock lock(&mutex_);
|
||||
auto it = throughput_recorders_.find(
|
||||
std::pair<int64_t, PayloadDirection>(payload_id, payload_direction));
|
||||
if (it == throughput_recorders_.end()) {
|
||||
auto instance = new ThroughputRecorder(payload_id);
|
||||
std::string direction =
|
||||
(payload_direction == PayloadDirection::INCOMING_PAYLOAD) ? "; Receive"
|
||||
: "; Send";
|
||||
VLOG(1) << "Add ThroughputRecorder instance : " << instance
|
||||
<< " for payload_id:" << payload_id << direction;
|
||||
throughput_recorders_.emplace(
|
||||
std::pair<int64_t, PayloadDirection>(payload_id, payload_direction),
|
||||
instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void ThroughputRecorderContainer::StopTPRecorder(
|
||||
const int64_t payload_id, PayloadDirection payload_direction) {
|
||||
MutexLock lock(&mutex_);
|
||||
std::string direction =
|
||||
(payload_direction == PayloadDirection::INCOMING_PAYLOAD) ? "; Receive"
|
||||
: "; Send";
|
||||
auto it = throughput_recorders_.find(
|
||||
std::pair<int64_t, PayloadDirection>(payload_id, payload_direction));
|
||||
if (it != throughput_recorders_.end()) {
|
||||
VLOG(1) << "Found and stop/delete ThroughputRecorder instance : "
|
||||
<< &(it->second) << " for payload_id:" << payload_id << direction;
|
||||
it->second->Stop();
|
||||
delete it->second;
|
||||
throughput_recorders_.erase(
|
||||
std::pair<int64_t, PayloadDirection>(payload_id, payload_direction));
|
||||
return;
|
||||
}
|
||||
VLOG(1) << "No ThroughputRecorder found for :" << payload_id;
|
||||
}
|
||||
|
||||
int ThroughputRecorderContainer::GetSize() {
|
||||
MutexLock lock(&mutex_);
|
||||
return throughput_recorders_.size();
|
||||
}
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
@@ -1,144 +0,0 @@
|
||||
// Copyright 2022-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.
|
||||
// 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 NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_THROUGHPUT_RECORDER_H_
|
||||
#define NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_THROUGHPUT_RECORDER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/payload_type.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
|
||||
// The following aliases are only for users' convenience.
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::nearby::connections::PayloadType;
|
||||
// Enum to represent if a payload is incoming or outgoing.
|
||||
using ::nearby::connections::PayloadDirection;
|
||||
|
||||
class ThroughputRecorder {
|
||||
public:
|
||||
explicit ThroughputRecorder(int64_t payload_id);
|
||||
~ThroughputRecorder() = default;
|
||||
|
||||
void Start(PayloadType payload_type, PayloadDirection payload_direction);
|
||||
bool Stop() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
static int CalculateThroughputKBps(int64_t total_byte_size,
|
||||
int64_t total_millis);
|
||||
static int CalculateThroughputMBps(int throughputKBps);
|
||||
|
||||
class Throughput {
|
||||
public:
|
||||
Throughput() = default;
|
||||
~Throughput() = default;
|
||||
Throughput(Medium medium, absl::Time start_timestamp,
|
||||
PayloadType payload_type, PayloadDirection payload_direction)
|
||||
: medium_(medium),
|
||||
start_timestamp_(start_timestamp),
|
||||
payload_type_(payload_type),
|
||||
payload_direction_(payload_direction) {}
|
||||
|
||||
void Add(int frame_size, int64_t file_io_time, int64_t encryption_time,
|
||||
int64_t socket_io_time);
|
||||
|
||||
void SetLastTimestamp(absl::Time time_stamp) {
|
||||
last_timestamp_ = time_stamp;
|
||||
}
|
||||
|
||||
int64_t GetTotalByteSize() { return total_byte_size_; }
|
||||
|
||||
bool dump();
|
||||
|
||||
private:
|
||||
Medium medium_;
|
||||
absl::Time start_timestamp_;
|
||||
PayloadType payload_type_;
|
||||
int64_t total_byte_size_ = 0;
|
||||
absl::Time last_timestamp_;
|
||||
PayloadDirection payload_direction_ = PayloadDirection::INCOMING_PAYLOAD;
|
||||
int64_t file_io_time_ = 0;
|
||||
int64_t encryption_time_ = 0;
|
||||
int64_t socket_io_time_ = 0;
|
||||
};
|
||||
|
||||
Throughput& GetThroughput(Medium medium, int64_t duration_millis);
|
||||
int GetThroughputsSize();
|
||||
int GetThroughputKbps();
|
||||
int64_t GetDurationMillis();
|
||||
void OnFrameSent(Medium medium, PacketMetaData& packetMetaData);
|
||||
void OnFrameReceived(Medium medium, PacketMetaData& packetMetaData);
|
||||
void MarkAsSuccess();
|
||||
|
||||
private:
|
||||
void CalculateDurationTimes(PacketMetaData packetMetaData);
|
||||
static std::string ToString(PayloadType type);
|
||||
|
||||
Mutex mutex_;
|
||||
int64_t payload_id_ = 0;
|
||||
absl::Time start_timestamp_;
|
||||
PayloadType payload_type_ = PayloadType::kUnknown;
|
||||
PayloadDirection payload_direction_ = PayloadDirection::INCOMING_PAYLOAD;
|
||||
absl::flat_hash_map<Medium, Throughput> throughputs_;
|
||||
bool success_ = false;
|
||||
|
||||
int64_t file_io_time_ = 0;
|
||||
int64_t encryption_time_ = 0;
|
||||
int64_t socket_io_time_ = 0;
|
||||
int64_t duration_millis_ = 0;
|
||||
int throughput_kbps_ = 0;
|
||||
};
|
||||
|
||||
class ThroughputRecorderContainer {
|
||||
public:
|
||||
ThroughputRecorderContainer(const ThroughputRecorderContainer&) = delete;
|
||||
ThroughputRecorderContainer& operator=(const ThroughputRecorderContainer&) =
|
||||
delete;
|
||||
|
||||
static ThroughputRecorderContainer& GetInstance();
|
||||
void Shutdown() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
ThroughputRecorder* GetTPRecorder(int64_t payload_id,
|
||||
PayloadDirection payload_direction)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void StopTPRecorder(int64_t payload_id, PayloadDirection payload_direction)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
int GetSize() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
// This is a singleton object, for which destructor will never be called.
|
||||
// Constructor will be invoked once from Instance() static method.
|
||||
// Object is create in-place (with a placement new) to guarantee that
|
||||
// destructor is not scheduled for execution at exit.
|
||||
ThroughputRecorderContainer() = default;
|
||||
~ThroughputRecorderContainer() = default;
|
||||
|
||||
Mutex mutex_;
|
||||
// std::pair<int64_t, PayloadDirection> for <payload id, payload direction>
|
||||
absl::flat_hash_map<std::pair<int64_t, PayloadDirection>, ThroughputRecorder*>
|
||||
throughput_recorders_ ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
|
||||
#endif // NEARBY_CONNECTIONS_IMPLEMENTATION_ANALYTICS_THROUGHPUT_RECORDER_H_
|
||||
@@ -1,233 +0,0 @@
|
||||
// Copyright 2022-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.
|
||||
// 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 "connections/implementation/analytics/throughput_recorder.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
namespace {
|
||||
// TODO(b/246693797): Add unit tests coverage for throughput recorder code
|
||||
|
||||
constexpr int64_t kPayloadIdA = 123456789;
|
||||
constexpr int64_t kPayloadIdB = 987654321;
|
||||
constexpr int kFrameSize = 10 * 64 * 1024;
|
||||
constexpr int64_t kTotalByteSize1GB = 1024 * 1024 * 1024;
|
||||
constexpr int64_t kTotalMillis10Sec = 10 * 1000;
|
||||
constexpr int kTPResultKBPerSec = 1024 * 1024 / 10;
|
||||
constexpr int kTPKBPerSec = 100 * 1024;
|
||||
constexpr int kTPResultMBPerSec = 100;
|
||||
|
||||
// class ThroughputRecorderTest : public testing::Test {
|
||||
class ThroughputRecorderTest : public testing::TestWithParam<bool> {
|
||||
protected:
|
||||
ThroughputRecorderTest() = default;
|
||||
~ThroughputRecorderTest() override {
|
||||
ThroughputRecorderContainer::GetInstance().Shutdown();
|
||||
}
|
||||
|
||||
ThroughputRecorderContainer& tp_recorder_container_ =
|
||||
ThroughputRecorderContainer::GetInstance();
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ParametrisedTestThroughputRecorderTest,
|
||||
ThroughputRecorderTest, testing::Values(true, false));
|
||||
|
||||
TEST(ThroughputRecorder, CalculateThroughputKBps) {
|
||||
EXPECT_EQ(ThroughputRecorder::CalculateThroughputKBps(kTotalByteSize1GB,
|
||||
kTotalMillis10Sec),
|
||||
kTPResultKBPerSec);
|
||||
EXPECT_EQ(ThroughputRecorder::CalculateThroughputKBps(kTotalByteSize1GB, 0),
|
||||
0);
|
||||
}
|
||||
|
||||
TEST(ThroughputRecorder, CalculateThroughputMBps) {
|
||||
EXPECT_EQ(ThroughputRecorder::CalculateThroughputMBps(kTPKBPerSec),
|
||||
kTPResultMBPerSec);
|
||||
}
|
||||
|
||||
TEST(ThroughputRecorderContainer, InstanceCreate_ContainerSize) {
|
||||
ThroughputRecorderContainer& TPRecorderContainer =
|
||||
ThroughputRecorderContainer::GetInstance();
|
||||
TPRecorderContainer.GetTPRecorder(kPayloadIdA,
|
||||
PayloadDirection::OUTGOING_PAYLOAD);
|
||||
TPRecorderContainer.GetTPRecorder(kPayloadIdB,
|
||||
PayloadDirection::INCOMING_PAYLOAD);
|
||||
EXPECT_EQ(ThroughputRecorderContainer::GetInstance().GetSize(), 2);
|
||||
ThroughputRecorderContainer::GetInstance().Shutdown();
|
||||
EXPECT_EQ(ThroughputRecorderContainer::GetInstance().GetSize(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ThroughputRecorderTest, OnFrameSentSaveTransferredSize) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
TPRecorder->Start(PayloadType::kFile, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
|
||||
PacketMetaData packet_meta_data;
|
||||
packet_meta_data.SetPacketSize(kFrameSize);
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
|
||||
auto throughput =
|
||||
TPRecorder->GetThroughput(location::nearby::proto::connections::BLE, 0);
|
||||
EXPECT_EQ(throughput.GetTotalByteSize(), kFrameSize * 3);
|
||||
}
|
||||
|
||||
TEST_F(ThroughputRecorderTest, OnIgnoreUnkownPaylaodType) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
TPRecorder->Start(PayloadType::kUnknown, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
|
||||
PacketMetaData packet_meta_data;
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
EXPECT_EQ(TPRecorder->GetThroughputsSize(), 0);
|
||||
|
||||
TPRecorder->Start(PayloadType::kUnknown, PayloadDirection::INCOMING_PAYLOAD);
|
||||
TPRecorder->OnFrameReceived(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
EXPECT_EQ(TPRecorder->GetThroughputsSize(), 0);
|
||||
}
|
||||
|
||||
TEST_P(ThroughputRecorderTest, OnFrameSentStopAndDump) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
TPRecorder->Start(PayloadType::kFile, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
|
||||
PacketMetaData packet_meta_data;
|
||||
packet_meta_data.SetPacketSize(kFrameSize);
|
||||
packet_meta_data.StartFileIo();
|
||||
absl::SleepFor(absl::Milliseconds(5));
|
||||
packet_meta_data.StopFileIo();
|
||||
packet_meta_data.StartEncryption();
|
||||
absl::SleepFor(absl::Milliseconds(6));
|
||||
packet_meta_data.StopEncryption();
|
||||
packet_meta_data.StartSocketIo();
|
||||
absl::SleepFor(absl::Milliseconds(7));
|
||||
packet_meta_data.StopSocketIo();
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
EXPECT_EQ(TPRecorder->GetDurationMillis(),
|
||||
packet_meta_data.GetEncryptionTimeInMillis() +
|
||||
packet_meta_data.GetFileIoTimeInMillis() +
|
||||
packet_meta_data.GetSocketIoTimeInMillis());
|
||||
|
||||
packet_meta_data.SetPacketSize(kFrameSize);
|
||||
packet_meta_data.StartFileIo();
|
||||
absl::SleepFor(absl::Milliseconds(15));
|
||||
packet_meta_data.StopFileIo();
|
||||
packet_meta_data.StartEncryption();
|
||||
absl::SleepFor(absl::Milliseconds(16));
|
||||
packet_meta_data.StopEncryption();
|
||||
packet_meta_data.StartSocketIo();
|
||||
absl::SleepFor(absl::Milliseconds(17));
|
||||
packet_meta_data.StopSocketIo();
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
|
||||
if (GetParam() == true) {
|
||||
LOG(INFO) << "MarkAsSuccess";
|
||||
TPRecorder->MarkAsSuccess();
|
||||
}
|
||||
EXPECT_TRUE(TPRecorder->Stop());
|
||||
EXPECT_NE(TPRecorder->GetThroughputKbps(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ThroughputRecorderTest, OnFrameSentStopAndDumpForMultiMeadium) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
TPRecorder->Start(PayloadType::kFile, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
|
||||
PacketMetaData packet_meta_data1;
|
||||
packet_meta_data1.SetPacketSize(kFrameSize);
|
||||
packet_meta_data1.StartFileIo();
|
||||
absl::SleepFor(absl::Milliseconds(5));
|
||||
packet_meta_data1.StopFileIo();
|
||||
packet_meta_data1.StartEncryption();
|
||||
absl::SleepFor(absl::Milliseconds(6));
|
||||
packet_meta_data1.StopEncryption();
|
||||
packet_meta_data1.StartSocketIo();
|
||||
absl::SleepFor(absl::Milliseconds(7));
|
||||
packet_meta_data1.StopSocketIo();
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data1);
|
||||
|
||||
PacketMetaData packet_meta_data2;
|
||||
packet_meta_data2.SetPacketSize(kFrameSize);
|
||||
packet_meta_data2.StartFileIo();
|
||||
absl::SleepFor(absl::Milliseconds(15));
|
||||
packet_meta_data2.StopFileIo();
|
||||
packet_meta_data2.StartEncryption();
|
||||
absl::SleepFor(absl::Milliseconds(16));
|
||||
packet_meta_data2.StopEncryption();
|
||||
packet_meta_data2.StartSocketIo();
|
||||
absl::SleepFor(absl::Milliseconds(17));
|
||||
packet_meta_data2.StopSocketIo();
|
||||
TPRecorder->OnFrameSent(location::nearby::proto::connections::WIFI_LAN,
|
||||
packet_meta_data2);
|
||||
|
||||
TPRecorder->MarkAsSuccess();
|
||||
EXPECT_TRUE(TPRecorder->Stop());
|
||||
EXPECT_NE(TPRecorder->GetThroughputKbps(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ThroughputRecorderTest, OnFrameReceivedCheckDurationMillis) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::INCOMING_PAYLOAD);
|
||||
TPRecorder->Start(PayloadType::kFile, PayloadDirection::INCOMING_PAYLOAD);
|
||||
|
||||
PacketMetaData packet_meta_data;
|
||||
packet_meta_data.SetPacketSize(kFrameSize);
|
||||
packet_meta_data.StartFileIo();
|
||||
absl::SleepFor(absl::Milliseconds(5));
|
||||
packet_meta_data.StopFileIo();
|
||||
packet_meta_data.StartEncryption();
|
||||
absl::SleepFor(absl::Milliseconds(6));
|
||||
packet_meta_data.StopEncryption();
|
||||
packet_meta_data.StartSocketIo();
|
||||
absl::SleepFor(absl::Milliseconds(7));
|
||||
packet_meta_data.StopSocketIo();
|
||||
TPRecorder->OnFrameReceived(location::nearby::proto::connections::BLE,
|
||||
packet_meta_data);
|
||||
EXPECT_EQ(TPRecorder->GetDurationMillis(),
|
||||
packet_meta_data.GetEncryptionTimeInMillis() +
|
||||
packet_meta_data.GetFileIoTimeInMillis() +
|
||||
packet_meta_data.GetSocketIoTimeInMillis());
|
||||
}
|
||||
|
||||
TEST_F(ThroughputRecorderTest, OnTPRecorderNotStarted) {
|
||||
auto TPRecorder = tp_recorder_container_.GetTPRecorder(
|
||||
kPayloadIdA, PayloadDirection::OUTGOING_PAYLOAD);
|
||||
auto throughput =
|
||||
TPRecorder->GetThroughput(location::nearby::proto::connections::BLE, 0);
|
||||
EXPECT_FALSE(throughput.dump());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/service_id_constants.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -30,16 +29,16 @@ BaseBwuHandler::BaseBwuHandler(
|
||||
IncomingConnectionCallback incoming_connection_callback)
|
||||
: incoming_connection_callback_(std::move(incoming_connection_callback)) {}
|
||||
|
||||
ByteArray BaseBwuHandler::InitializeUpgradedMediumForEndpoint(
|
||||
std::string BaseBwuHandler::InitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const std::string& endpoint_id) {
|
||||
std::string upgrade_service_id = WrapInitiatorUpgradeServiceId(service_id);
|
||||
|
||||
// Perform any medium-specific handling in the child class.
|
||||
ByteArray upgrade_path_available_frame =
|
||||
std::string upgrade_path_available_frame =
|
||||
HandleInitializeUpgradedMediumForEndpoint(client, upgrade_service_id,
|
||||
endpoint_id);
|
||||
if (!upgrade_path_available_frame.Empty()) {
|
||||
if (!upgrade_path_available_frame.empty()) {
|
||||
upgrade_service_id_to_active_endpoint_ids_[upgrade_service_id].insert(
|
||||
endpoint_id);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -35,7 +34,7 @@ class BaseBwuHandler : public BwuHandler {
|
||||
IncomingConnectionCallback incoming_connection_callback);
|
||||
|
||||
// BwuHandler implementation:
|
||||
ByteArray InitializeUpgradedMediumForEndpoint(
|
||||
std::string InitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const std::string& endpoint_id) final;
|
||||
void RevertInitiatorState() final;
|
||||
@@ -51,7 +50,7 @@ class BaseBwuHandler : public BwuHandler {
|
||||
// respectively, to handle medium-specific logic.
|
||||
// HandleRevertInitiatorStateForService is only invoked after the last
|
||||
// endpoint for the service is reverted.
|
||||
virtual ByteArray HandleInitializeUpgradedMediumForEndpoint(
|
||||
virtual std::string HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) = 0;
|
||||
virtual void HandleRevertInitiatorStateForService(
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/service_id_constants.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/expected.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -55,8 +54,8 @@ class BwuHandlerImpl : public BaseBwuHandler {
|
||||
const std::vector<InputData>& handle_revert_calls() const {
|
||||
return handle_revert_calls_;
|
||||
}
|
||||
void set_handle_initialize_output(ByteArray bytes) {
|
||||
handle_initialize_output_ = bytes;
|
||||
void set_handle_initialize_output(absl::string_view bytes) {
|
||||
handle_initialize_output_ = std::string(bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -73,7 +72,7 @@ class BwuHandlerImpl : public BaseBwuHandler {
|
||||
const std::string& endpoint_id) final {}
|
||||
|
||||
// BaseBwuHandler implementation:
|
||||
ByteArray HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) final {
|
||||
handle_initialize_calls_.push_back({.client = client,
|
||||
@@ -86,7 +85,7 @@ class BwuHandlerImpl : public BaseBwuHandler {
|
||||
handle_revert_calls_.push_back({.service_id = upgrade_service_id});
|
||||
}
|
||||
|
||||
ByteArray handle_initialize_output_;
|
||||
std::string handle_initialize_output_;
|
||||
std::vector<InputData> handle_initialize_calls_;
|
||||
std::vector<InputData> handle_revert_calls_;
|
||||
};
|
||||
@@ -95,7 +94,7 @@ TEST(BaseBwuHandlerTest, InitializeAndRevert) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{"not empty"};
|
||||
absl::string_view expected_output{"not empty"};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
|
||||
// Initialize two upgrade endpoints for service A and one for service B.
|
||||
@@ -150,7 +149,7 @@ TEST(BaseBwuHandlerTest, InitializeAndRevertAll) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{"not empty"};
|
||||
absl::string_view expected_output{"not empty"};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
|
||||
handler.InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"A",
|
||||
@@ -169,7 +168,7 @@ TEST(BaseBwuHandlerTest, Initialize_Failure_EmptyUpgradePathAvailableFrame) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{};
|
||||
absl::string_view expected_output{};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
|
||||
handler.InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"A",
|
||||
@@ -191,7 +190,7 @@ TEST(BaseBwuHandlerTest, Initialize_StillWorkWithUpgradeServiceIdSuffix) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{"not empty"};
|
||||
absl::string_view expected_output{"not empty"};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
|
||||
// The method should be robust and not add _another_ upgrade suffix
|
||||
@@ -208,7 +207,7 @@ TEST(BaseBwuHandlerTest, Revert_Failure_CantFindService) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{"not empty"};
|
||||
absl::string_view expected_output{"not empty"};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
handler.InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"A",
|
||||
/*endpoint_id=*/"1");
|
||||
@@ -222,7 +221,7 @@ TEST(BaseBwuHandlerTest, Revert_Failure_CantFindEndpoint) {
|
||||
ClientProxy client;
|
||||
BwuHandlerImpl handler;
|
||||
|
||||
ByteArray expected_output{"not empty"};
|
||||
absl::string_view expected_output{"not empty"};
|
||||
handler.set_handle_initialize_output(expected_output);
|
||||
handler.InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"A",
|
||||
/*endpoint_id=*/"1");
|
||||
|
||||
@@ -40,15 +40,13 @@
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
|
||||
namespace {
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::proto::connections::Medium::BLE;
|
||||
using ::location::nearby::proto::connections::Medium::BLE_L2CAP;
|
||||
using DisconnectionReason =
|
||||
::location::nearby::proto::connections::DisconnectionReason;
|
||||
using ::nearby::analytics::SafeDisconnectionResult;
|
||||
using ::location::nearby::proto::connections::DisconnectionReason;
|
||||
|
||||
Exception WriteInt(OutputStream* writer, std::int32_t value) {
|
||||
return Base64Utils::WriteInt(writer, value);
|
||||
@@ -92,17 +90,10 @@ BaseEndpointChannel::BaseEndpointChannel(
|
||||
try_count_(try_count) {}
|
||||
|
||||
ExceptionOr<ByteArray> BaseEndpointChannel::Read() {
|
||||
PacketMetaData packet_meta_data;
|
||||
return Read(packet_meta_data);
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
PacketMetaData& packet_meta_data) {
|
||||
ByteArray result;
|
||||
{
|
||||
MutexLock lock(&reader_mutex_);
|
||||
|
||||
packet_meta_data.StartSocketIo();
|
||||
ExceptionOr<std::int32_t> read_int;
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
@@ -133,8 +124,6 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
if (!read_bytes.ok()) {
|
||||
return read_bytes;
|
||||
}
|
||||
packet_meta_data.StopSocketIo();
|
||||
packet_meta_data.SetPacketSize(read_int.result() + sizeof(std::int32_t));
|
||||
result = std::move(read_bytes.result());
|
||||
}
|
||||
|
||||
@@ -144,7 +133,6 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
if (IsEncryptionEnabledLocked()) {
|
||||
// If encryption is enabled, decode the message.
|
||||
std::string input(std::move(result));
|
||||
packet_meta_data.StartEncryption();
|
||||
std::unique_ptr<std::string> decrypted_data =
|
||||
crypto_context_->DecodeMessageFromPeer(input);
|
||||
if (decrypted_data) {
|
||||
@@ -157,7 +145,7 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
// and let it through if it is, otherwise message is erased.
|
||||
// TODO(apolyudov): verify this happens at most once per session.
|
||||
result = {};
|
||||
auto parsed = parser::FromBytes(ByteArray(input));
|
||||
auto parsed = parser::FromBytes(input);
|
||||
if (parsed.ok()) {
|
||||
if (parser::GetFrameType(parsed.result()) ==
|
||||
location::nearby::connections::V1Frame::KEEP_ALIVE) {
|
||||
@@ -175,7 +163,6 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
<< ": Unable to parse data as unencrypted message.";
|
||||
}
|
||||
}
|
||||
packet_meta_data.StopEncryption();
|
||||
if (result.Empty()) {
|
||||
LOG(WARNING) << __func__ << ": Unable to parse read result.";
|
||||
return ExceptionOr<ByteArray>(message_exception);
|
||||
@@ -190,13 +177,7 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read(
|
||||
return ExceptionOr<ByteArray>(result);
|
||||
}
|
||||
|
||||
Exception BaseEndpointChannel::Write(const ByteArray& data) {
|
||||
PacketMetaData packet_meta_data;
|
||||
return Write(data.AsStringView(), packet_meta_data);
|
||||
}
|
||||
|
||||
Exception BaseEndpointChannel::Write(absl::string_view data,
|
||||
PacketMetaData& packet_meta_data) {
|
||||
Exception BaseEndpointChannel::Write(absl::string_view data) {
|
||||
{
|
||||
MutexLock pause_lock(&is_paused_mutex_);
|
||||
if (is_paused_) {
|
||||
@@ -217,9 +198,7 @@ Exception BaseEndpointChannel::Write(absl::string_view data,
|
||||
MutexLock crypto_lock(&crypto_mutex_);
|
||||
if (IsEncryptionEnabledLocked()) {
|
||||
// If encryption is enabled, encode the message.
|
||||
packet_meta_data.StartEncryption();
|
||||
encrypted = crypto_context_->EncodeMessageToPeer(data);
|
||||
packet_meta_data.StopEncryption();
|
||||
if (!encrypted) {
|
||||
LOG(WARNING) << __func__ << ": Failed to encrypt data.";
|
||||
return {Exception::kIo};
|
||||
@@ -235,7 +214,6 @@ Exception BaseEndpointChannel::Write(absl::string_view data,
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
packet_meta_data.StartSocketIo();
|
||||
Exception write_exception;
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
@@ -262,8 +240,6 @@ Exception BaseEndpointChannel::Write(absl::string_view data,
|
||||
<< ": Failed to flush writer: " << flush_exception.value;
|
||||
return flush_exception;
|
||||
}
|
||||
packet_meta_data.StopSocketIo();
|
||||
packet_meta_data.SetPacketSize(data_size + sizeof(std::uint32_t));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -326,7 +302,7 @@ void BaseEndpointChannel::SetAnalyticsRecorder(
|
||||
|
||||
void BaseEndpointChannel::Close(
|
||||
location::nearby::proto::connections::DisconnectionReason reason) {
|
||||
Close(reason, ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
Close(reason, SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
|
||||
void BaseEndpointChannel::Close(
|
||||
@@ -490,5 +466,4 @@ std::unique_ptr<std::string> BaseEndpointChannel::EncodeMessageForTests(
|
||||
return crypto_context_->EncodeMessageToPeer(data);
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/condition_variable.h"
|
||||
@@ -32,10 +31,7 @@
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
using analytics::PacketMetaData;
|
||||
namespace nearby::connections {
|
||||
|
||||
class BaseEndpointChannel : public EndpointChannel {
|
||||
public:
|
||||
@@ -51,20 +47,16 @@ class BaseEndpointChannel : public EndpointChannel {
|
||||
~BaseEndpointChannel() override = default;
|
||||
|
||||
// EndpointChannel:
|
||||
ExceptionOr<ByteArray> Read() override;
|
||||
ExceptionOr<ByteArray> Read(PacketMetaData& packet_meta_data)
|
||||
ExceptionOr<ByteArray> Read()
|
||||
ABSL_LOCKS_EXCLUDED(reader_mutex_, crypto_mutex_,
|
||||
last_read_mutex_) override;
|
||||
Exception Write(const ByteArray& data) override;
|
||||
Exception Write(absl::string_view data, PacketMetaData& packet_meta_data)
|
||||
Exception Write(absl::string_view data)
|
||||
ABSL_LOCKS_EXCLUDED(writer_mutex_, crypto_mutex_) override;
|
||||
void Close() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override;
|
||||
void Close(location::nearby::proto::connections::DisconnectionReason reason)
|
||||
override;
|
||||
void Close(
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result) override;
|
||||
void Close(location::nearby::proto::connections::DisconnectionReason reason,
|
||||
nearby::analytics::SafeDisconnectionResult result) override;
|
||||
bool IsClosed() const ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override;
|
||||
std::string GetType() const override;
|
||||
std::string GetServiceId() const override;
|
||||
@@ -176,7 +168,6 @@ class BaseEndpointChannel : public EndpointChannel {
|
||||
std::string endpoint_id_ = "";
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
#endif // CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_
|
||||
|
||||
@@ -108,20 +108,26 @@ std::function<void(const ByteArray&)> MakeDataMonitor(const std::string& label,
|
||||
|
||||
std::pair<std::shared_ptr<EncryptionContext>,
|
||||
std::shared_ptr<EncryptionContext>>
|
||||
DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
BaseEndpointChannel* channel_b) {
|
||||
DoDhKeyExchange(std::shared_ptr<TestEndpointChannel> channel_a,
|
||||
std::shared_ptr<TestEndpointChannel> channel_b) {
|
||||
std::shared_ptr<EncryptionContext> context_a;
|
||||
std::shared_ptr<EncryptionContext> context_b;
|
||||
EncryptionRunner crypto_a;
|
||||
EncryptionRunner crypto_b;
|
||||
ClientProxy proxy_a;
|
||||
ClientProxy proxy_b;
|
||||
CountDownLatch latch(2);
|
||||
std::shared_ptr<EndpointChannel> shared_channel_a = channel_a;
|
||||
std::shared_ptr<EndpointChannel> shared_channel_b = channel_b;
|
||||
|
||||
// Create a shared_ptr for the latch to prevent Use-After-Free if the
|
||||
// negotiation times out and this function returns early.
|
||||
auto latch = std::make_shared<CountDownLatch>(2);
|
||||
|
||||
crypto_a.StartClient(
|
||||
&proxy_a, "endpoint_id", channel_a,
|
||||
&proxy_a, "endpoint_id", shared_channel_a,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&latch, &context_a](
|
||||
[latch, &context_a](
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
@@ -131,20 +137,19 @@ DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
auto context = ukey2->ToConnectionContext();
|
||||
EXPECT_NE(context, nullptr);
|
||||
context_a = std::move(context);
|
||||
latch.CountDown();
|
||||
latch->CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&latch](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
[latch](const std::string& endpoint_id) {
|
||||
LOG(INFO) << "client-A side key negotiation failed";
|
||||
latch.CountDown();
|
||||
latch->CountDown();
|
||||
},
|
||||
});
|
||||
crypto_b.StartServer(
|
||||
&proxy_b, "endpoint_id", channel_b,
|
||||
&proxy_b, "endpoint_id", shared_channel_b,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&latch, &context_b](
|
||||
[latch, &context_b](
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
@@ -154,16 +159,15 @@ DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
auto context = ukey2->ToConnectionContext();
|
||||
EXPECT_NE(context, nullptr);
|
||||
context_b = std::move(context);
|
||||
latch.CountDown();
|
||||
latch->CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&latch](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
[latch](const std::string& endpoint_id) {
|
||||
LOG(INFO) << "client-B side key negotiation failed";
|
||||
latch.CountDown();
|
||||
latch->CountDown();
|
||||
},
|
||||
});
|
||||
EXPECT_TRUE(latch.Await(absl::Milliseconds(5000)).result());
|
||||
EXPECT_TRUE(latch->Await(absl::Milliseconds(5000)).result());
|
||||
return std::make_pair(std::move(context_a), std::move(context_b));
|
||||
}
|
||||
|
||||
@@ -174,7 +178,7 @@ class BaseEndpointChannelTest : public ::testing::Test {
|
||||
NearbyFlags::GetInstance().ResetOverridedValues();
|
||||
}
|
||||
|
||||
const ByteArray kTestData{"test_data"};
|
||||
const absl::string_view kTestData = "test_data";
|
||||
};
|
||||
|
||||
TEST_F(BaseEndpointChannelTest, ReadSucceedsWhenFlagDisabled) {
|
||||
@@ -189,7 +193,7 @@ TEST_F(BaseEndpointChannelTest, ReadSucceedsWhenFlagDisabled) {
|
||||
|
||||
channel_a.Write(kTestData);
|
||||
ByteArray rx_message = std::move(channel_b.Read().result());
|
||||
EXPECT_EQ(rx_message, kTestData);
|
||||
EXPECT_EQ(rx_message.AsStringView(), kTestData);
|
||||
}
|
||||
|
||||
TEST_F(BaseEndpointChannelTest, ReadCallsDispatchPacketWhenFlagEnabled) {
|
||||
@@ -203,13 +207,14 @@ TEST_F(BaseEndpointChannelTest, ReadCallsDispatchPacketWhenFlagEnabled) {
|
||||
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
|
||||
|
||||
EXPECT_CALL(channel_b, DispatchPacket)
|
||||
.WillOnce(::testing::Return(ExceptionOr<ByteArray>(kTestData)));
|
||||
.WillOnce(::testing::Return(
|
||||
ExceptionOr<ByteArray>(ByteArray(std::string(kTestData)))));
|
||||
|
||||
channel_a.Write(kTestData);
|
||||
|
||||
auto read_byte = channel_b.Read();
|
||||
EXPECT_TRUE(read_byte.ok());
|
||||
EXPECT_EQ(read_byte.result(), kTestData);
|
||||
EXPECT_EQ(read_byte.result().AsStringView(), kTestData);
|
||||
}
|
||||
|
||||
TEST_F(BaseEndpointChannelTest,
|
||||
@@ -243,10 +248,10 @@ TEST_F(BaseEndpointChannelTest, ReadWrite) {
|
||||
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
|
||||
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
|
||||
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
|
||||
ByteArray tx_message{"data message"};
|
||||
absl::string_view tx_message = "data message";
|
||||
channel_a.Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b.Read().result());
|
||||
EXPECT_EQ(rx_message, tx_message);
|
||||
EXPECT_EQ(rx_message.AsStringView(), tx_message);
|
||||
}
|
||||
|
||||
TEST_F(BaseEndpointChannelTest, ChannelUnencryptedByDefault) {
|
||||
@@ -264,20 +269,22 @@ TEST_F(BaseEndpointChannelTest, TryDecrypt) {
|
||||
absl::string_view kMessage = "message";
|
||||
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
|
||||
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
|
||||
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
|
||||
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
|
||||
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
|
||||
auto channel_a = std::make_shared<TestEndpointChannel>(pipe_b.first.get(),
|
||||
pipe_a.second.get());
|
||||
auto channel_b = std::make_shared<TestEndpointChannel>(pipe_a.first.get(),
|
||||
pipe_b.second.get());
|
||||
auto [context_a, context_b] = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context_a, nullptr);
|
||||
ASSERT_NE(context_b, nullptr);
|
||||
channel_a.EnableEncryption(context_a);
|
||||
channel_b.EnableEncryption(context_b);
|
||||
channel_a->EnableEncryption(context_a);
|
||||
channel_b->EnableEncryption(context_b);
|
||||
std::unique_ptr<std::string> encrypted_message =
|
||||
channel_a.EncodeMessageForTests(kMessage);
|
||||
channel_a->EncodeMessageForTests(kMessage);
|
||||
|
||||
ExceptionOr<ByteArray> decrypted_message =
|
||||
channel_b.TryDecrypt(ByteArray(*encrypted_message));
|
||||
channel_b->TryDecrypt(ByteArray(*encrypted_message));
|
||||
|
||||
EXPECT_TRUE(channel_b.IsEncrypted());
|
||||
EXPECT_TRUE(channel_b->IsEncrypted());
|
||||
EXPECT_TRUE(decrypted_message.ok());
|
||||
EXPECT_EQ(decrypted_message.result().AsStringView(), kMessage);
|
||||
}
|
||||
@@ -285,16 +292,18 @@ TEST_F(BaseEndpointChannelTest, TryDecrypt) {
|
||||
TEST_F(BaseEndpointChannelTest, TryDecryptFailsWhenDecryptionFails) {
|
||||
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
|
||||
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
|
||||
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
|
||||
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
|
||||
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
|
||||
auto channel_a = std::make_shared<TestEndpointChannel>(pipe_b.first.get(),
|
||||
pipe_a.second.get());
|
||||
auto channel_b = std::make_shared<TestEndpointChannel>(pipe_a.first.get(),
|
||||
pipe_b.second.get());
|
||||
auto [context_a, context_b] = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context_a, nullptr);
|
||||
channel_a.EnableEncryption(context_a);
|
||||
channel_a->EnableEncryption(context_a);
|
||||
|
||||
ExceptionOr<ByteArray> result =
|
||||
channel_a.TryDecrypt(ByteArray("invalid message"));
|
||||
channel_a->TryDecrypt(ByteArray("invalid message"));
|
||||
|
||||
EXPECT_TRUE(channel_a.IsEncrypted());
|
||||
EXPECT_TRUE(channel_a->IsEncrypted());
|
||||
EXPECT_FALSE(result.ok());
|
||||
EXPECT_EQ(result.exception(), Exception::kExecution);
|
||||
}
|
||||
@@ -332,12 +341,12 @@ TEST_F(BaseEndpointChannelTest, NotEncryptedReadWriteCanBeIntercepted) {
|
||||
EXPECT_EQ(channel_b.GetType(), "BLE");
|
||||
|
||||
// Start data transfer
|
||||
ByteArray tx_message{"data message"};
|
||||
absl::string_view tx_message = "data message";
|
||||
channel_a.Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b.Read().result());
|
||||
|
||||
// Verify expectations.
|
||||
EXPECT_EQ(rx_message, tx_message);
|
||||
EXPECT_EQ(rx_message.AsStringView(), tx_message);
|
||||
{
|
||||
absl::MutexLock lock(mutex);
|
||||
std::string message{tx_message};
|
||||
@@ -365,13 +374,15 @@ TEST_F(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
|
||||
// to server "b".
|
||||
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
|
||||
// to server "a".
|
||||
TestEndpointChannel channel_a(server_a.first.get(), client_a.second.get());
|
||||
TestEndpointChannel channel_b(server_b.first.get(), client_b.second.get());
|
||||
auto channel_a = std::make_shared<TestEndpointChannel>(server_a.first.get(),
|
||||
client_a.second.get());
|
||||
auto channel_b = std::make_shared<TestEndpointChannel>(server_b.first.get(),
|
||||
client_b.second.get());
|
||||
|
||||
ON_CALL(channel_a, GetMedium).WillByDefault([]() {
|
||||
ON_CALL(*channel_a, GetMedium).WillByDefault([]() {
|
||||
return Medium::BLUETOOTH;
|
||||
});
|
||||
ON_CALL(channel_b, GetMedium).WillByDefault([]() {
|
||||
ON_CALL(*channel_b, GetMedium).WillByDefault([]() {
|
||||
return Medium::BLUETOOTH;
|
||||
});
|
||||
|
||||
@@ -384,24 +395,24 @@ TEST_F(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
|
||||
MakeDataMonitor("monitor_b", &capture_b, &mutex)));
|
||||
|
||||
// Run DH key exchange; setup encryption contexts for channels.
|
||||
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
|
||||
auto [context_a, context_b] = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context_a, nullptr);
|
||||
ASSERT_NE(context_b, nullptr);
|
||||
channel_a.EnableEncryption(context_a);
|
||||
channel_b.EnableEncryption(context_b);
|
||||
channel_a->EnableEncryption(context_a);
|
||||
channel_b->EnableEncryption(context_b);
|
||||
|
||||
EXPECT_EQ(channel_a.GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_EQ(channel_b.GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_TRUE(channel_a.IsEncrypted());
|
||||
EXPECT_TRUE(channel_b.IsEncrypted());
|
||||
EXPECT_EQ(channel_a->GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_EQ(channel_b->GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_TRUE(channel_a->IsEncrypted());
|
||||
EXPECT_TRUE(channel_b->IsEncrypted());
|
||||
|
||||
// Start data transfer
|
||||
ByteArray tx_message{"data message"};
|
||||
channel_a.Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b.Read().result());
|
||||
absl::string_view tx_message = "data message";
|
||||
channel_a->Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b->Read().result());
|
||||
|
||||
// Verify expectations.
|
||||
EXPECT_EQ(rx_message, tx_message);
|
||||
EXPECT_EQ(rx_message.AsStringView(), tx_message);
|
||||
{
|
||||
absl::MutexLock lock(mutex);
|
||||
std::string message{tx_message};
|
||||
@@ -410,8 +421,8 @@ TEST_F(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
|
||||
}
|
||||
|
||||
// Shutdown test environment.
|
||||
channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
channel_a->Close(DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
channel_b->Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
}
|
||||
|
||||
TEST_F(BaseEndpointChannelTest, CanBesuspendedAndResumed) {
|
||||
@@ -432,8 +443,8 @@ TEST_F(BaseEndpointChannelTest, CanBesuspendedAndResumed) {
|
||||
EXPECT_EQ(channel_b.GetType(), "WIFI_LAN");
|
||||
|
||||
// Start data transfer
|
||||
ByteArray tx_message{"data message"};
|
||||
ByteArray more_message{"more data"};
|
||||
absl::string_view tx_message = "data message";
|
||||
absl::string_view more_message = "more data";
|
||||
channel_a.Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b.Read().result());
|
||||
|
||||
@@ -459,7 +470,7 @@ TEST_F(BaseEndpointChannelTest, CanBesuspendedAndResumed) {
|
||||
// Resume; verify that data transfer comepleted.
|
||||
channel_a.Resume();
|
||||
EXPECT_TRUE(latch.Await(absl::Milliseconds(1000)).result());
|
||||
EXPECT_EQ(read_more, more_message);
|
||||
EXPECT_EQ(read_more.AsStringView(), more_message);
|
||||
|
||||
// Shutdown test environment.
|
||||
channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -485,43 +496,45 @@ TEST_F(BaseEndpointChannelTest, ReadUnencryptedFrameOnEncryptedChannel) {
|
||||
// Setup test communication environment.
|
||||
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
|
||||
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
|
||||
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
|
||||
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
|
||||
auto channel_a = std::make_shared<TestEndpointChannel>(pipe_b.first.get(),
|
||||
pipe_a.second.get());
|
||||
auto channel_b = std::make_shared<TestEndpointChannel>(pipe_a.first.get(),
|
||||
pipe_b.second.get());
|
||||
|
||||
ON_CALL(channel_a, GetMedium).WillByDefault([]() {
|
||||
ON_CALL(*channel_a, GetMedium).WillByDefault([]() {
|
||||
return Medium::BLUETOOTH;
|
||||
});
|
||||
ON_CALL(channel_b, GetMedium).WillByDefault([]() {
|
||||
ON_CALL(*channel_b, GetMedium).WillByDefault([]() {
|
||||
return Medium::BLUETOOTH;
|
||||
});
|
||||
|
||||
// Run DH key exchange; setup encryption contexts for channels. But only
|
||||
// encrypt |channel_b|.
|
||||
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
|
||||
auto [context_a, context_b] = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context_a, nullptr);
|
||||
ASSERT_NE(context_b, nullptr);
|
||||
channel_b.EnableEncryption(context_b);
|
||||
channel_b->EnableEncryption(context_b);
|
||||
|
||||
EXPECT_EQ(channel_a.GetType(), "BLUETOOTH");
|
||||
EXPECT_EQ(channel_b.GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_EQ(channel_a->GetType(), "BLUETOOTH");
|
||||
EXPECT_EQ(channel_b->GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
|
||||
// An unencrypted KeepAlive should succeed.
|
||||
ByteArray keep_alive_message = parser::ForKeepAlive();
|
||||
channel_a.Write(keep_alive_message);
|
||||
ExceptionOr<ByteArray> result = channel_b.Read();
|
||||
std::string keep_alive_message = parser::ForKeepAlive();
|
||||
channel_a->Write(keep_alive_message);
|
||||
ExceptionOr<ByteArray> result = channel_b->Read();
|
||||
EXPECT_TRUE(result.ok());
|
||||
EXPECT_EQ(result.result(), keep_alive_message);
|
||||
EXPECT_EQ(result.result().AsStringView(), keep_alive_message);
|
||||
|
||||
// An unencrypted data frame should fail.
|
||||
ByteArray tx_message{"data message"};
|
||||
channel_a.Write(tx_message);
|
||||
result = channel_b.Read();
|
||||
absl::string_view tx_message = "data message";
|
||||
channel_a->Write(tx_message);
|
||||
result = channel_b->Read();
|
||||
EXPECT_FALSE(result.ok());
|
||||
EXPECT_EQ(result.exception(), Exception::kInvalidProtocolBuffer);
|
||||
|
||||
// Shutdown test environment.
|
||||
channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
channel_a->Close(DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
channel_b->Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#include "connections/advertising_options.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/connection_attempt_metadata_params.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
#include "connections/implementation/bwu_manager.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/connections_authentication_transport.h"
|
||||
@@ -51,7 +53,6 @@
|
||||
#include "connections/implementation/mediums/webrtc_peer_id.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "connections/implementation/pcp.h"
|
||||
#include "connections/implementation/proto/offline_wire_formats.pb.h"
|
||||
#include "connections/implementation/webrtc_state.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
@@ -84,11 +85,24 @@
|
||||
#include "internal/platform/runnable.h"
|
||||
#include "internal/platform/wifi.h"
|
||||
#include "internal/platform/wifi_lan_connection_info.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby::connections {
|
||||
|
||||
namespace {
|
||||
using ::location::nearby::connections::ConnectionRequestFrame;
|
||||
using ::location::nearby::connections::ConnectionResponseFrame;
|
||||
using ::location::nearby::connections::ConnectionsDevice;
|
||||
using ::location::nearby::connections::MediumMetadata;
|
||||
using ::location::nearby::connections::OfflineFrame;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::location::nearby::connections::PresenceDevice;
|
||||
using ::location::nearby::connections::V1Frame;
|
||||
using ::location::nearby::proto::connections::OperationResultCode;
|
||||
using ::location::nearby::proto::connections::WifiDirectAuthType;
|
||||
using ::nearby::analytics::AnalyticsRecorder;
|
||||
using ::nearby::analytics::OperationResultWithMedium;
|
||||
using ::securegcm::UKey2Handshake;
|
||||
|
||||
constexpr int kEndpointCancelAlarmTimeout = 10;
|
||||
|
||||
std::string AuthenticationStatusToString(nearby::AuthenticationStatus status) {
|
||||
@@ -101,20 +115,8 @@ std::string AuthenticationStatusToString(nearby::AuthenticationStatus status) {
|
||||
return "failure";
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::ConnectionRequestFrame;
|
||||
using ::location::nearby::connections::ConnectionResponseFrame;
|
||||
using ::location::nearby::connections::ConnectionsDevice;
|
||||
using ::location::nearby::connections::MediumMetadata;
|
||||
using ::location::nearby::connections::OfflineFrame;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::location::nearby::connections::PresenceDevice;
|
||||
using ::location::nearby::connections::V1Frame;
|
||||
using ::location::nearby::proto::connections::OperationResultCode;
|
||||
using ::location::nearby::proto::connections::WifiDirectAuthType;
|
||||
using ::securegcm::UKey2Handshake;
|
||||
} // namespace
|
||||
|
||||
BasePcpHandler::BasePcpHandler(Mediums* mediums,
|
||||
EndpointManager* endpoint_manager,
|
||||
@@ -212,8 +214,7 @@ std::vector<ConnectionInfoVariant> BasePcpHandler::GetConnectionInfoFromResult(
|
||||
}
|
||||
WifiLanConnectionInfo info(
|
||||
std::string(ip_address.begin(), ip_address.end()),
|
||||
absl::StrCat(absl::Hex(port, absl::kZeroPad16)), "",
|
||||
{});
|
||||
absl::StrCat(absl::Hex(port, absl::kZeroPad16)), "", {});
|
||||
connection_infos.push_back(info);
|
||||
}
|
||||
}
|
||||
@@ -279,11 +280,10 @@ Status BasePcpHandler::StartAdvertising(
|
||||
// Save the advertising options for local reference in later process
|
||||
// like upgrading bandwidth.
|
||||
advertising_listener_ = info.listener;
|
||||
client->StartedAdvertising(
|
||||
service_id, GetStrategy(), info.listener,
|
||||
absl::MakeSpan(result.mediums),
|
||||
std::move(result.operation_result_with_mediums),
|
||||
compatible_advertising_options);
|
||||
client->StartedAdvertising(service_id, GetStrategy(), info.listener,
|
||||
absl::MakeSpan(result.mediums),
|
||||
result.operation_result_with_mediums,
|
||||
compatible_advertising_options);
|
||||
client->UpdateLocalEndpointInfo(info.endpoint_info.string_data());
|
||||
response.Set({Status::kSuccess});
|
||||
});
|
||||
@@ -424,25 +424,25 @@ BooleanMediumSelector BasePcpHandler::ComputeIntersectionOfSupportedMediums(
|
||||
pending_connection_info.connection_options.connection_info
|
||||
.supported_wifi_direct_auth_types;
|
||||
LOG(INFO) << "Remote supported WifiDirect auth types: "
|
||||
<< absl::StrJoin(
|
||||
remote_supported_wifi_direct_auth_types, ", ",
|
||||
[](std::string* out, int auth_type) {
|
||||
absl::StrAppend(
|
||||
out,
|
||||
WifiDirectAuthType_Name(
|
||||
static_cast<WifiDirectAuthType>(auth_type)));
|
||||
});
|
||||
<< absl::StrJoin(
|
||||
remote_supported_wifi_direct_auth_types, ", ",
|
||||
[](std::string* out, int auth_type) {
|
||||
absl::StrAppend(
|
||||
out,
|
||||
WifiDirectAuthType_Name(
|
||||
static_cast<WifiDirectAuthType>(auth_type)));
|
||||
});
|
||||
auto local_supported_wifi_direct_auth_types =
|
||||
mediums_->GetWifiDirect().GetSupportedWifiDirectAuthTypes();
|
||||
LOG(INFO) << "Local supported WifiDirect auth types: "
|
||||
<< absl::StrJoin(
|
||||
local_supported_wifi_direct_auth_types, ", ",
|
||||
[](std::string* out, int auth_type) {
|
||||
absl::StrAppend(
|
||||
out,
|
||||
WifiDirectAuthType_Name(
|
||||
static_cast<WifiDirectAuthType>(auth_type)));
|
||||
});
|
||||
<< absl::StrJoin(
|
||||
local_supported_wifi_direct_auth_types, ", ",
|
||||
[](std::string* out, int auth_type) {
|
||||
absl::StrAppend(
|
||||
out,
|
||||
WifiDirectAuthType_Name(
|
||||
static_cast<WifiDirectAuthType>(auth_type)));
|
||||
});
|
||||
bool found_common_auth_type = false;
|
||||
for (const auto& auth_type : local_supported_wifi_direct_auth_types) {
|
||||
if (auth_type == WifiDirectAuthType::WIFI_DIRECT_TYPE_UNKNOWN) {
|
||||
@@ -510,11 +510,11 @@ Status BasePcpHandler::StartDiscovery(ClientProxy* client,
|
||||
MutexLock lock(&discovered_endpoint_mutex_);
|
||||
discovered_endpoints_.clear();
|
||||
}
|
||||
client->StartedDiscovery(
|
||||
service_id, GetStrategy(), std::move(listener),
|
||||
absl::MakeSpan(result.mediums),
|
||||
std::move(result.operation_result_with_mediums),
|
||||
stripped_discovery_options);
|
||||
client->StartedDiscovery(service_id, GetStrategy(),
|
||||
std::move(listener),
|
||||
absl::MakeSpan(result.mediums),
|
||||
result.operation_result_with_mediums,
|
||||
stripped_discovery_options);
|
||||
response.Set({Status::kSuccess});
|
||||
});
|
||||
return WaitForResult(absl::StrCat("StartDiscovery(", service_id, ")"),
|
||||
@@ -587,34 +587,50 @@ void BasePcpHandler::RunOnPcpHandlerThread(const std::string& name,
|
||||
serial_executor_.Execute(name, std::move(runnable));
|
||||
}
|
||||
|
||||
EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() {
|
||||
EncryptionRunner::ResultListener BasePcpHandler::GetResultListener(
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel) {
|
||||
std::weak_ptr<EndpointChannel> weak_channel = endpoint_channel;
|
||||
|
||||
return {
|
||||
.on_success_cb =
|
||||
[this](const std::string& endpoint_id,
|
||||
std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token) {
|
||||
[this, weak_channel](const std::string& endpoint_id,
|
||||
std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token) {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
|
||||
RunOnPcpHandlerThread(
|
||||
"encryption-success",
|
||||
[this, endpoint_id, raw_ukey2 = ukey2.release(), auth_token,
|
||||
raw_auth_token]() RUN_ON_PCP_HANDLER_THREAD() mutable {
|
||||
OnEncryptionSuccessRunnable(
|
||||
endpoint_id, std::unique_ptr<UKey2Handshake>(raw_ukey2),
|
||||
auth_token, raw_auth_token);
|
||||
});
|
||||
[this, endpoint_id, weak_channel, raw_ukey2 = ukey2.release(),
|
||||
auth_token, raw_auth_token]()
|
||||
RUN_ON_PCP_HANDLER_THREAD() mutable {
|
||||
std::unique_ptr<UKey2Handshake> ukey2(raw_ukey2);
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
OnEncryptionSuccessRunnable(endpoint_id, std::move(ukey2),
|
||||
auth_token, raw_auth_token,
|
||||
channel);
|
||||
});
|
||||
},
|
||||
.on_failure_cb =
|
||||
[this](const std::string& endpoint_id, EndpointChannel* channel) {
|
||||
[this, weak_channel](const std::string& endpoint_id) {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
|
||||
RunOnPcpHandlerThread(
|
||||
"encryption-failure",
|
||||
[this, endpoint_id, channel]() RUN_ON_PCP_HANDLER_THREAD() {
|
||||
LOG(ERROR)
|
||||
<< "Encryption failed for endpoint_id=" << endpoint_id
|
||||
<< " on medium="
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium());
|
||||
OnEncryptionFailureRunnable(endpoint_id, channel);
|
||||
});
|
||||
[this, endpoint_id, weak_channel]()
|
||||
RUN_ON_PCP_HANDLER_THREAD() {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
LOG(ERROR)
|
||||
<< "Encryption failed for endpoint_id=" << endpoint_id
|
||||
<< " on medium="
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium());
|
||||
OnEncryptionFailureRunnable(endpoint_id, channel);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -622,36 +638,49 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() {
|
||||
EncryptionRunner::ResultListener BasePcpHandler::GetResultListenerV3(
|
||||
const NearbyDeviceProvider& device_provider,
|
||||
const NearbyDevice& remote_device,
|
||||
const EndpointChannel& endpoint_channel) {
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel) {
|
||||
std::weak_ptr<EndpointChannel> weak_channel = endpoint_channel;
|
||||
|
||||
return {
|
||||
.on_success_cb =
|
||||
[this, &device_provider, &remote_device, &endpoint_channel](
|
||||
[this, &device_provider, &remote_device, weak_channel](
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token) {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
|
||||
RunOnPcpHandlerThread(
|
||||
"encryption-success",
|
||||
[this, &device_provider, &remote_device, &endpoint_channel,
|
||||
raw_ukey2 = ukey2.release(), auth_token,
|
||||
raw_auth_token]() RUN_ON_PCP_HANDLER_THREAD() mutable {
|
||||
OnEncryptionSuccessRunnableV3(
|
||||
remote_device, std::unique_ptr<UKey2Handshake>(raw_ukey2),
|
||||
auth_token, raw_auth_token, endpoint_channel,
|
||||
device_provider);
|
||||
});
|
||||
[this, &device_provider, &remote_device, weak_channel,
|
||||
raw_ukey2 = ukey2.release(), auth_token, raw_auth_token]()
|
||||
RUN_ON_PCP_HANDLER_THREAD() mutable {
|
||||
std::unique_ptr<UKey2Handshake> ukey2(raw_ukey2);
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
OnEncryptionSuccessRunnableV3(
|
||||
remote_device, std::move(ukey2), auth_token,
|
||||
raw_auth_token, channel, device_provider);
|
||||
});
|
||||
},
|
||||
.on_failure_cb =
|
||||
[this](const std::string& endpoint_id, EndpointChannel* channel) {
|
||||
[this, weak_channel](const std::string& endpoint_id) {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
|
||||
RunOnPcpHandlerThread(
|
||||
"encryption-failure",
|
||||
[this, endpoint_id, channel]() RUN_ON_PCP_HANDLER_THREAD() {
|
||||
LOG(ERROR)
|
||||
<< "Encryption failed for endpoint_id=" << endpoint_id
|
||||
<< " on medium="
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium());
|
||||
OnEncryptionFailureRunnable(endpoint_id, channel);
|
||||
});
|
||||
[this, endpoint_id, weak_channel]()
|
||||
RUN_ON_PCP_HANDLER_THREAD() {
|
||||
auto channel = weak_channel.lock();
|
||||
if (!channel) return;
|
||||
LOG(ERROR)
|
||||
<< "Encryption failed for endpoint_id=" << endpoint_id
|
||||
<< " on medium="
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium());
|
||||
OnEncryptionFailureRunnable(endpoint_id, channel);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -659,7 +688,7 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListenerV3(
|
||||
void BasePcpHandler::OnEncryptionSuccessRunnableV3(
|
||||
const NearbyDevice& remote_device, std::unique_ptr<UKey2Handshake> ukey2,
|
||||
absl::string_view auth_token, const ByteArray& raw_auth_token,
|
||||
const EndpointChannel& endpoint_channel,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
const NearbyDeviceProvider& device_provider) {
|
||||
// Quick fail if we've been removed from pending connections while we were
|
||||
// busy running UKEY2.
|
||||
@@ -674,7 +703,11 @@ void BasePcpHandler::OnEncryptionSuccessRunnableV3(
|
||||
}
|
||||
|
||||
BasePcpHandler::PendingConnectionInfo& pending_connection_info = it->second;
|
||||
|
||||
// Verify pointer equality to avoid accidental action on superseded
|
||||
// channels.
|
||||
if (endpoint_channel != pending_connection_info.channel) {
|
||||
return;
|
||||
}
|
||||
// TODO(b/300149127): Add test coverage.
|
||||
if (!ukey2) {
|
||||
// Fail early, if there is no crypto context.
|
||||
@@ -697,8 +730,15 @@ void BasePcpHandler::OnEncryptionSuccessRunnableV3(
|
||||
//
|
||||
// TODO(b/305004353): Authenticate the connection in the responder role for
|
||||
// outgoing connections.
|
||||
if (!pending_connection_info.is_incoming) {
|
||||
if (pending_connection_info.is_incoming) {
|
||||
LOG(ERROR) << __func__ << ": only outgoing connections are supported";
|
||||
ProcessPreConnectionInitiationFailure(
|
||||
pending_connection_info.client, pending_connection_info.medium,
|
||||
remote_device.GetEndpointId(), pending_connection_info.channel.get(),
|
||||
pending_connection_info.is_incoming, /*log_failure=*/true,
|
||||
pending_connection_info.start_time, {Status::kConnectionRejected},
|
||||
OperationResultCode::DETAIL_UNKNOWN,
|
||||
pending_connection_info.result.lock().get());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -724,7 +764,8 @@ void BasePcpHandler::OnEncryptionSuccessRunnableV3(
|
||||
|
||||
void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
const std::string& endpoint_id, std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token) {
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel) {
|
||||
// Quick fail if we've been removed from pending connections while we were
|
||||
// busy running UKEY2.
|
||||
// TODO(b/316421187): Add test coverage
|
||||
@@ -738,6 +779,12 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
|
||||
BasePcpHandler::PendingConnectionInfo& pending_connection_info = it->second;
|
||||
|
||||
// Verify pointer equality to avoid accidental action on superseded
|
||||
// channels.
|
||||
if (endpoint_channel != pending_connection_info.channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ukey2) {
|
||||
// Fail early, if there is no crypto context.
|
||||
ProcessPreConnectionInitiationFailure(
|
||||
@@ -801,24 +848,21 @@ void BasePcpHandler::RegisterDeviceAfterEncryptionSuccess(
|
||||
}
|
||||
|
||||
void BasePcpHandler::OnEncryptionFailureRunnable(
|
||||
const std::string& endpoint_id, EndpointChannel* endpoint_channel) {
|
||||
const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel) {
|
||||
auto it = pending_connections_.find(endpoint_id);
|
||||
if (it == pending_connections_.end()) {
|
||||
LOG(INFO)
|
||||
<< "Connection not found on UKEY negotination complete; endpoint_id="
|
||||
<< "Connection not found on UKEY negotiation complete; endpoint_id="
|
||||
<< endpoint_id;
|
||||
return;
|
||||
}
|
||||
|
||||
BasePcpHandler::PendingConnectionInfo& pending_connection_info = it->second;
|
||||
// We had a bug here, caused by a race with EncryptionRunner. We now verify
|
||||
// the EndpointChannel to avoid it. In a simultaneous connection, we clean
|
||||
// up one of the two EndpointChannels and then update our pendingConnections
|
||||
// with the winning channel's state. Closing a channel that was in the
|
||||
// middle of EncryptionRunner would trigger onEncryptionFailed, and, since
|
||||
// the map had already updated with the winning EndpointChannel, we closed
|
||||
// it too by accident.
|
||||
if (*endpoint_channel != *pending_connection_info.channel) {
|
||||
|
||||
// Verify pointer equality to avoid accidental action on superseded
|
||||
// channels.
|
||||
if (endpoint_channel != pending_connection_info.channel) {
|
||||
LOG(INFO) << "Not destroying channel [mismatch]: passed="
|
||||
<< endpoint_channel->GetName()
|
||||
<< "; expected=" << pending_connection_info.channel->GetName();
|
||||
@@ -871,8 +915,8 @@ ConnectionInfo BasePcpHandler::FillConnectionInfo(
|
||||
connection_info.supported_wifi_direct_auth_types =
|
||||
mediums_->GetWifiDirect().GetSupportedWifiDirectAuthTypes();
|
||||
VLOG(1) << "Set SupportedWifiDirectAuthTypes for WIFI_DIRECT: "
|
||||
<< absl::StrJoin(connection_info.supported_wifi_direct_auth_types,
|
||||
",");
|
||||
<< absl::StrJoin(connection_info.supported_wifi_direct_auth_types,
|
||||
",");
|
||||
} else {
|
||||
connection_info.supported_wifi_direct_auth_types = {};
|
||||
}
|
||||
@@ -975,8 +1019,8 @@ Status BasePcpHandler::RequestConnection(
|
||||
client, channel_medium, endpoint_id, channel.get(),
|
||||
/*is_incoming=*/false, /*log_failure=*/true, start_time,
|
||||
{Status::kEndpointIoError},
|
||||
client->GetAnalyticsRecorder()
|
||||
.GetChannelIoErrorResultCodeFromMedium(channel_medium),
|
||||
AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium(
|
||||
channel_medium),
|
||||
result.get());
|
||||
return;
|
||||
}
|
||||
@@ -1005,17 +1049,32 @@ Status BasePcpHandler::RequestConnection(
|
||||
pending_connection_info.medium = channel->GetMedium();
|
||||
pending_connection_info.channel = std::move(channel);
|
||||
|
||||
EndpointChannel* endpoint_channel =
|
||||
pending_connections_
|
||||
.emplace(endpoint_id, std::move(pending_connection_info))
|
||||
.first->second.channel.get();
|
||||
std::shared_ptr<EndpointChannel> channel_to_close_on_failure =
|
||||
pending_connection_info.channel;
|
||||
auto [it, inserted] = pending_connections_.emplace(
|
||||
endpoint_id, std::move(pending_connection_info));
|
||||
if (!inserted) {
|
||||
LOG(ERROR) << "Failed to add outgoing connection to pending set; "
|
||||
"endpoint_id="
|
||||
<< endpoint_id
|
||||
<< ". Likely a collision with an existing pending "
|
||||
"connection.";
|
||||
if (channel_to_close_on_failure) {
|
||||
channel_to_close_on_failure->Close(
|
||||
location::nearby::proto::connections::DisconnectionReason::
|
||||
IO_ERROR);
|
||||
}
|
||||
result->Set({Status::kEndpointIoError});
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel = it->second.channel;
|
||||
|
||||
LOG(INFO) << "Initiating secure connection: endpoint_id="
|
||||
<< endpoint_id;
|
||||
// Next, we'll set up encryption. When it's done, our future will return
|
||||
// and RequestConnection() will finish.
|
||||
encryption_runner_.StartClient(client, endpoint_id, endpoint_channel,
|
||||
GetResultListener());
|
||||
GetResultListener(endpoint_channel));
|
||||
});
|
||||
LOG(INFO) << "Waiting for connection to complete: endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -1122,8 +1181,8 @@ Status BasePcpHandler::RequestConnectionV3(
|
||||
client, channel_medium, endpoint_id, channel.get(),
|
||||
/*is_incoming=*/false, /*log_failure=*/true, start_time,
|
||||
{Status::kEndpointIoError},
|
||||
client->GetAnalyticsRecorder()
|
||||
.GetChannelIoErrorResultCodeFromMedium(channel_medium),
|
||||
AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium(
|
||||
channel_medium),
|
||||
result.get());
|
||||
return;
|
||||
}
|
||||
@@ -1144,7 +1203,7 @@ Status BasePcpHandler::RequestConnectionV3(
|
||||
pending_connection_info.client = client;
|
||||
pending_connection_info.remote_endpoint_info = endpoint->endpoint_info;
|
||||
pending_connection_info.nonce = connection_info.nonce;
|
||||
pending_connection_info.is_incoming = true;
|
||||
pending_connection_info.is_incoming = false;
|
||||
pending_connection_info.start_time = start_time;
|
||||
pending_connection_info.listener = info.listener;
|
||||
pending_connection_info.connection_options = connection_options;
|
||||
@@ -1152,10 +1211,25 @@ Status BasePcpHandler::RequestConnectionV3(
|
||||
pending_connection_info.medium = channel->GetMedium();
|
||||
pending_connection_info.channel = std::move(channel);
|
||||
|
||||
EndpointChannel* endpoint_channel =
|
||||
pending_connections_
|
||||
.emplace(endpoint_id, std::move(pending_connection_info))
|
||||
.first->second.channel.get();
|
||||
std::shared_ptr<EndpointChannel> channel_to_close_on_failure =
|
||||
pending_connection_info.channel;
|
||||
auto [it, inserted] = pending_connections_.emplace(
|
||||
endpoint_id, std::move(pending_connection_info));
|
||||
if (!inserted) {
|
||||
LOG(ERROR) << "Failed to add outgoing connection to pending set; "
|
||||
"endpoint_id="
|
||||
<< endpoint_id
|
||||
<< ". Likely a collision with an existing pending "
|
||||
"connection.";
|
||||
if (channel_to_close_on_failure) {
|
||||
channel_to_close_on_failure->Close(
|
||||
location::nearby::proto::connections::DisconnectionReason::
|
||||
IO_ERROR);
|
||||
}
|
||||
result->Set({Status::kEndpointIoError});
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel = it->second.channel;
|
||||
|
||||
LOG(INFO) << "Initiating secure connection: endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -1165,7 +1239,7 @@ Status BasePcpHandler::RequestConnectionV3(
|
||||
encryption_runner_.StartClient(
|
||||
client, endpoint_id, endpoint_channel,
|
||||
GetResultListenerV3(*(client->GetLocalDeviceProvider()),
|
||||
remote_device, *endpoint_channel));
|
||||
remote_device, endpoint_channel));
|
||||
});
|
||||
LOG(INFO) << "Waiting for connection to complete: endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -1231,22 +1305,21 @@ void BasePcpHandler::StripOutUnavailableMediums(
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ConnectionsLog::OperationResultWithMedium>
|
||||
OperationResultWithMedium
|
||||
BasePcpHandler::GetOperationResultWithMediumByResultCode(
|
||||
ClientProxy* client, location::nearby::proto::connections::Medium medium,
|
||||
int update_index,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code,
|
||||
location::nearby::proto::connections::ConnectionMode connection_mode) {
|
||||
auto operation_result_with_medium =
|
||||
std::make_unique<ConnectionsLog::OperationResultWithMedium>();
|
||||
operation_result_with_medium->set_medium(medium);
|
||||
operation_result_with_medium->set_result_code(operation_result_code);
|
||||
operation_result_with_medium->set_result_category(
|
||||
OperationResultWithMedium operation_result_with_medium;
|
||||
operation_result_with_medium.set_medium(medium);
|
||||
operation_result_with_medium.set_result_code(operation_result_code);
|
||||
operation_result_with_medium.set_result_category(
|
||||
client->GetAnalyticsRecorder().GetOperationResultCategory(
|
||||
operation_result_code));
|
||||
operation_result_with_medium->set_connection_mode(connection_mode);
|
||||
operation_result_with_medium->set_update_index(update_index);
|
||||
operation_result_with_medium.set_connection_mode(connection_mode);
|
||||
operation_result_with_medium.set_update_index(update_index);
|
||||
|
||||
return operation_result_with_medium;
|
||||
}
|
||||
@@ -1512,8 +1585,7 @@ Status BasePcpHandler::AcceptConnection(ClientProxy* client,
|
||||
|
||||
Exception write_exception =
|
||||
channel->Write(parser::ForConnectionResponse(
|
||||
Status::kSuccess, client->GetLocalOsInfo(),
|
||||
client->GetLocalMultiplexSocketBitmask()));
|
||||
Status::kSuccess, client->GetLocalOsInfo()));
|
||||
if (!write_exception.Ok()) {
|
||||
LOG(INFO) << "AcceptConnection: failed to send response: endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -1574,8 +1646,7 @@ Status BasePcpHandler::RejectConnection(ClientProxy* client,
|
||||
|
||||
Exception write_exception =
|
||||
channel->Write(parser::ForConnectionResponse(
|
||||
Status::kConnectionRejected, client->GetLocalOsInfo(),
|
||||
client->GetLocalMultiplexSocketBitmask()));
|
||||
Status::kConnectionRejected, client->GetLocalOsInfo()));
|
||||
if (!write_exception.Ok()) {
|
||||
LOG(INFO) << "RejectConnection: failed to send response: endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -1600,8 +1671,7 @@ Status BasePcpHandler::RejectConnection(ClientProxy* client,
|
||||
|
||||
void BasePcpHandler::OnIncomingFrame(
|
||||
OfflineFrame& frame, const std::string& endpoint_id, ClientProxy* client,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
PacketMetaData& packet_meta_data) {
|
||||
location::nearby::proto::connections::Medium medium) {
|
||||
CountDownLatch latch(1);
|
||||
RunOnPcpHandlerThread(
|
||||
"incoming-frame",
|
||||
@@ -1967,8 +2037,7 @@ Exception BasePcpHandler::OnIncomingConnection(
|
||||
/*is_incoming=*/true,
|
||||
/*log_failure=*/wrapped_frame.exception() != Exception::kNoData,
|
||||
start_time, {Status::kError},
|
||||
client->GetAnalyticsRecorder().GetChannelIoErrorResultCodeFromMedium(
|
||||
medium),
|
||||
AnalyticsRecorder::GetChannelIoErrorResultCodeFromMedium(medium),
|
||||
nullptr);
|
||||
}
|
||||
return wrapped_frame.GetException();
|
||||
@@ -2133,14 +2202,23 @@ Exception BasePcpHandler::OnIncomingConnection(
|
||||
pending_connection_info.medium = channel->GetMedium();
|
||||
pending_connection_info.channel = std::move(channel);
|
||||
|
||||
auto* owned_channel = pending_connections_
|
||||
.emplace(connection_request.endpoint_id(),
|
||||
std::move(pending_connection_info))
|
||||
.first->second.channel.get();
|
||||
auto [it, inserted] = pending_connections_.emplace(
|
||||
connection_request.endpoint_id(), std::move(pending_connection_info));
|
||||
// This should not happen since BreakTie() above should have checked that
|
||||
// the endpoint_id is not already in pending_connections_.
|
||||
if (!inserted) {
|
||||
LOG(ERROR) << "Failed to add incoming connection to pending set; "
|
||||
"endpoint_id="
|
||||
<< connection_request.endpoint_id()
|
||||
<< ". Likely a collision with an existing pending connection.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel = it->second.channel;
|
||||
|
||||
// Next, we'll set up encryption.
|
||||
encryption_runner_.StartServer(client, connection_request.endpoint_id(),
|
||||
owned_channel, GetResultListener());
|
||||
endpoint_channel,
|
||||
GetResultListener(endpoint_channel));
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
@@ -2383,26 +2461,6 @@ void BasePcpHandler::EvaluateConnectionResult(ClientProxy* client,
|
||||
std::move(context))) {
|
||||
response_code = {Status::kEndpointUnknown};
|
||||
}
|
||||
|
||||
std::shared_ptr<EndpointChannel> channel =
|
||||
channel_manager_->GetChannelForEndpoint(endpoint_id);
|
||||
if (channel != nullptr) {
|
||||
if (client->IsMultiplexSocketSupported(endpoint_id,
|
||||
channel->GetMedium())) {
|
||||
if (!channel->EnableMultiplexSocket()) {
|
||||
LOG(INFO) << "MultiplexSocket is not implemented for Medium: "
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium());
|
||||
} else {
|
||||
LOG(INFO) << "MultiplexSocket is supported for Medium: "
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
channel->GetMedium())
|
||||
<< " on both sides.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(INFO) << "channel is null";
|
||||
}
|
||||
} else {
|
||||
LOG(INFO) << "Pending connection rejected; endpoint_id=" << endpoint_id;
|
||||
response_code = {Status::kConnectionRejected};
|
||||
@@ -2477,8 +2535,8 @@ ExceptionOr<OfflineFrame> BasePcpHandler::ReadConnectionRequestFrame(
|
||||
return ExceptionOr<OfflineFrame>(wrapped_bytes.exception());
|
||||
}
|
||||
|
||||
ByteArray bytes = std::move(wrapped_bytes.result());
|
||||
ExceptionOr<OfflineFrame> wrapped_frame = parser::FromBytes(bytes);
|
||||
ExceptionOr<OfflineFrame> wrapped_frame =
|
||||
parser::FromBytes(wrapped_bytes.result().AsStringView());
|
||||
if (wrapped_frame.GetException().Raised(Exception::kInvalidProtocolBuffer)) {
|
||||
return ExceptionOr<OfflineFrame>(Exception::kIo);
|
||||
}
|
||||
@@ -2510,7 +2568,7 @@ void BasePcpHandler::LogConnectionAttemptFailure(
|
||||
connections_attempt_metadata_params;
|
||||
if (endpoint_channel != nullptr) {
|
||||
connections_attempt_metadata_params =
|
||||
client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams(
|
||||
AnalyticsRecorder::BuildConnectionAttemptMetadataParams(
|
||||
endpoint_channel->GetTechnology(), endpoint_channel->GetBand(),
|
||||
endpoint_channel->GetFrequency(), endpoint_channel->GetTryCount());
|
||||
connections_attempt_metadata_params->operation_result_code =
|
||||
@@ -2536,12 +2594,11 @@ void BasePcpHandler::LogConnectionAttemptSuccess(
|
||||
connections_attempt_metadata_params;
|
||||
if (pending_connection_info.channel != nullptr) {
|
||||
connections_attempt_metadata_params =
|
||||
pending_connection_info.client->GetAnalyticsRecorder()
|
||||
.BuildConnectionAttemptMetadataParams(
|
||||
pending_connection_info.channel->GetTechnology(),
|
||||
pending_connection_info.channel->GetBand(),
|
||||
pending_connection_info.channel->GetFrequency(),
|
||||
pending_connection_info.channel->GetTryCount());
|
||||
AnalyticsRecorder::BuildConnectionAttemptMetadataParams(
|
||||
pending_connection_info.channel->GetTechnology(),
|
||||
pending_connection_info.channel->GetBand(),
|
||||
pending_connection_info.channel->GetFrequency(),
|
||||
pending_connection_info.channel->GetTryCount());
|
||||
connections_attempt_metadata_params->operation_result_code =
|
||||
OperationResultCode::DETAIL_SUCCESS;
|
||||
} else {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "connections/advertising_options.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
#include "connections/implementation/bwu_manager.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/encryption_runner.h"
|
||||
@@ -158,10 +158,10 @@ class BasePcpHandler : public PcpHandler,
|
||||
const std::string& endpoint_id) override;
|
||||
|
||||
// @EndpointManagerReaderThread
|
||||
void OnIncomingFrame(location::nearby::connections::OfflineFrame& frame,
|
||||
const std::string& endpoint_id, ClientProxy* client,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
analytics::PacketMetaData& packet_meta_data) override;
|
||||
void OnIncomingFrame(
|
||||
location::nearby::connections::OfflineFrame& frame,
|
||||
const std::string& endpoint_id, ClientProxy* client,
|
||||
location::nearby::proto::connections::Medium medium) override;
|
||||
|
||||
// Called when an endpoint disconnects while we're waiting for both sides to
|
||||
// approve/reject the connection.
|
||||
@@ -190,8 +190,7 @@ class BasePcpHandler : public PcpHandler,
|
||||
// If success, the mediums on which we are now advertising/discovering, for
|
||||
// analytics.
|
||||
std::vector<location::nearby::proto::connections::Medium> mediums;
|
||||
std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>
|
||||
std::vector<nearby::analytics::OperationResultWithMedium>
|
||||
operation_result_with_mediums;
|
||||
};
|
||||
|
||||
@@ -413,8 +412,7 @@ class BasePcpHandler : public PcpHandler,
|
||||
|
||||
void StripOutWifiHotspotMedium(ConnectionInfo& connection_info);
|
||||
|
||||
std::unique_ptr<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>
|
||||
nearby::analytics::OperationResultWithMedium
|
||||
GetOperationResultWithMediumByResultCode(
|
||||
ClientProxy* client, location::nearby::proto::connections::Medium medium,
|
||||
int update_index,
|
||||
@@ -476,11 +474,11 @@ class BasePcpHandler : public PcpHandler,
|
||||
// Only (possibly) vector for incoming connections.
|
||||
std::vector<location::nearby::proto::connections::Medium> supported_mediums;
|
||||
|
||||
// Keep track of a channel before we pass it to EndpointChannelManager. This
|
||||
// is owned until the call to OnEncryptionSuccessRunnableV3 or
|
||||
// OnEncryptionSuccessRunnable when ownership is transferred to the
|
||||
// EndpointManager.
|
||||
std::unique_ptr<EndpointChannel> channel;
|
||||
// Keep track of a channel before it is registered with the
|
||||
// EndpointManager. This reference is held during the handshake phase and
|
||||
// passed to the EndpointManager upon successful encryption
|
||||
// (OnEncryptionSuccessRunnableV3 or OnEncryptionSuccessRunnable).
|
||||
std::shared_ptr<EndpointChannel> channel;
|
||||
|
||||
// Crypto context; initially empty; established first thing after channel
|
||||
// creation by running UKey2 session. While it is in progress, we keep track
|
||||
@@ -509,24 +507,27 @@ class BasePcpHandler : public PcpHandler,
|
||||
void OnEncryptionFailureImpl(const std::string& endpoint_id,
|
||||
EndpointChannel* channel);
|
||||
|
||||
EncryptionRunner::ResultListener GetResultListener();
|
||||
EncryptionRunner::ResultListener GetResultListener(
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel);
|
||||
EncryptionRunner::ResultListener GetResultListenerV3(
|
||||
const NearbyDeviceProvider& device_provider,
|
||||
const NearbyDevice& remote_device,
|
||||
const EndpointChannel& endpoint_channel);
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel);
|
||||
|
||||
void OnEncryptionSuccessRunnable(
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token);
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel);
|
||||
void OnEncryptionSuccessRunnableV3(
|
||||
const NearbyDevice& remote_device,
|
||||
std::unique_ptr<::securegcm::UKey2Handshake> ukey2,
|
||||
absl::string_view auth_token, const ByteArray& raw_auth_token,
|
||||
const EndpointChannel& endpoint_channel,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
const NearbyDeviceProvider& device_provider);
|
||||
void OnEncryptionFailureRunnable(const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel);
|
||||
void OnEncryptionFailureRunnable(
|
||||
const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel);
|
||||
void RegisterDeviceAfterEncryptionSuccess(
|
||||
std::string_view endpoint_id,
|
||||
std::unique_ptr<::securegcm::UKey2Handshake> ukey2,
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include "connections/advertising_options.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/mock_analytics_recorder.h"
|
||||
#include "connections/implementation/base_endpoint_channel.h"
|
||||
#include "connections/implementation/bwu_manager.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
@@ -55,8 +56,6 @@
|
||||
#include "connections/status.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "connections/v3/connection_listening_options.h"
|
||||
#include "internal/analytics/mock_event_logger.h"
|
||||
#include "internal/analytics/sharing_log_matchers.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/interop/authentication_status.h"
|
||||
#include "internal/interop/authentication_transport.h"
|
||||
@@ -72,29 +71,21 @@
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/pipe.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
#include "proto/connections_enums.proto.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::location::nearby::proto::connections::EventType;
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::nearby::analytics::HasEventType;
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::protobuf_matchers::EqualsProto;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::Matcher;
|
||||
using ::testing::MockFunction;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
using ::testing::StrictMock;
|
||||
using ::testing::proto::Partially;
|
||||
|
||||
constexpr absl::string_view kTestEndpointId = "REMOTETEST";
|
||||
|
||||
@@ -171,7 +162,7 @@ class MockEndpointChannel : public BaseEndpointChannel {
|
||||
output_stream_(std::move(writer)) {}
|
||||
|
||||
ExceptionOr<ByteArray> DoRead() { return BaseEndpointChannel::Read(); }
|
||||
Exception DoWrite(const ByteArray& data) {
|
||||
Exception DoWrite(absl::string_view data) {
|
||||
if (broken_write_) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
@@ -182,7 +173,7 @@ class MockEndpointChannel : public BaseEndpointChannel {
|
||||
}
|
||||
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override));
|
||||
MOCK_METHOD(Exception, Write, (const ByteArray& data), (override));
|
||||
MOCK_METHOD(Exception, Write, (absl::string_view data), (override));
|
||||
MOCK_METHOD(void, CloseImpl, (), (override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::Medium, GetMedium, (),
|
||||
(const, override));
|
||||
@@ -454,15 +445,20 @@ class BasePcpHandlerTest
|
||||
};
|
||||
|
||||
BasePcpHandlerTest() {
|
||||
client_ = std::make_unique<ClientProxy>(&mock_event_logger_);
|
||||
client_ = std::make_unique<ClientProxy>(CreateAnalyticsRecorder());
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
MacAddress::FromString("12:34:56:78:9a:bc", remote_mac_address_);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
env_.Stop();
|
||||
void TearDown() override { env_.Stop(); }
|
||||
|
||||
std::unique_ptr<analytics::AnalyticsRecorder> CreateAnalyticsRecorder() {
|
||||
auto recorder =
|
||||
std::make_unique<analytics::MockAnalyticsRecorder>();
|
||||
mock_analytics_recorder_ptr_ = recorder.get();
|
||||
return recorder;
|
||||
}
|
||||
|
||||
void StartAdvertising(ClientProxy* client, MockPcpHandler* pcp_handler,
|
||||
@@ -576,26 +572,26 @@ class BasePcpHandlerTest
|
||||
// the peer channel. The rest of the exchange must happen for the benefit of
|
||||
// DH key exchange.
|
||||
EXPECT_CALL(*channel_a, Read())
|
||||
.WillRepeatedly(Invoke(
|
||||
[channel = channel_a.get()]() { return channel->DoRead(); }));
|
||||
.WillRepeatedly(
|
||||
[channel = channel_a.get()]() { return channel->DoRead(); });
|
||||
EXPECT_CALL(*channel_a, Write(_))
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}))
|
||||
.WillRepeatedly(
|
||||
Invoke([channel = channel_a.get()](const ByteArray& data) {
|
||||
[channel = channel_a.get()](absl::string_view data) {
|
||||
return channel->DoWrite(data);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*channel_a, GetMedium).WillRepeatedly(Return(medium));
|
||||
EXPECT_CALL(*channel_a, GetLastReadTimestamp)
|
||||
.WillRepeatedly(Return(absl::Now()));
|
||||
EXPECT_CALL(*channel_a, IsPaused).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*channel_b, Read())
|
||||
.WillRepeatedly(Invoke(
|
||||
[channel = channel_b.get()]() { return channel->DoRead(); }));
|
||||
.WillRepeatedly(
|
||||
[channel = channel_b.get()]() { return channel->DoRead(); });
|
||||
EXPECT_CALL(*channel_b, Write(_))
|
||||
.WillRepeatedly(
|
||||
Invoke([channel = channel_b.get()](const ByteArray& data) {
|
||||
[channel = channel_b.get()](absl::string_view data) {
|
||||
return channel->DoWrite(data);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*channel_b, GetMedium).WillRepeatedly(Return(medium));
|
||||
EXPECT_CALL(*channel_b, GetLastReadTimestamp)
|
||||
.WillRepeatedly(Return(absl::Now()));
|
||||
@@ -622,20 +618,20 @@ class BasePcpHandlerTest
|
||||
// the peer channel. The rest of the exchange must happen for the benefit of
|
||||
// DH key exchange.
|
||||
EXPECT_CALL(*channel_a, Read())
|
||||
.WillRepeatedly(Invoke(
|
||||
[channel = channel_a.get()]() { return channel->DoRead(); }));
|
||||
.WillRepeatedly(
|
||||
[channel = channel_a.get()]() { return channel->DoRead(); });
|
||||
EXPECT_CALL(*channel_a, GetMedium).WillRepeatedly(Return(medium));
|
||||
EXPECT_CALL(*channel_a, GetLastReadTimestamp)
|
||||
.WillRepeatedly(Return(absl::Now()));
|
||||
EXPECT_CALL(*channel_a, IsPaused).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*channel_b, Read())
|
||||
.WillRepeatedly(Invoke(
|
||||
[channel = channel_b.get()]() { return channel->DoRead(); }));
|
||||
.WillRepeatedly(
|
||||
[channel = channel_b.get()]() { return channel->DoRead(); });
|
||||
EXPECT_CALL(*channel_b, Write(_))
|
||||
.WillRepeatedly(
|
||||
Invoke([channel = channel_b.get()](const ByteArray& data) {
|
||||
[channel = channel_b.get()](absl::string_view data) {
|
||||
return channel->DoWrite(data);
|
||||
}));
|
||||
});
|
||||
EXPECT_CALL(*channel_b, GetMedium).WillRepeatedly(Return(medium));
|
||||
EXPECT_CALL(*channel_b, GetLastReadTimestamp)
|
||||
.WillRepeatedly(Return(absl::Now()));
|
||||
@@ -646,7 +642,7 @@ class BasePcpHandlerTest
|
||||
void RequestConnection(
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<MockEndpointChannel> channel_a,
|
||||
MockEndpointChannel* channel_b, ClientProxy* client,
|
||||
std::shared_ptr<MockEndpointChannel> channel_b, ClientProxy* client,
|
||||
MockPcpHandler* pcp_handler,
|
||||
location::nearby::proto::connections::Medium connect_medium,
|
||||
std::atomic_int* flag = nullptr,
|
||||
@@ -675,15 +671,15 @@ class BasePcpHandlerTest
|
||||
auto allowed_mediums = pcp_handler->GetDiscoveryMediums(client);
|
||||
|
||||
EXPECT_CALL(*pcp_handler, ConnectImpl)
|
||||
.WillOnce(Invoke([&channel_a, connect_medium](
|
||||
ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
.WillOnce([&channel_a, connect_medium](
|
||||
ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
return MockPcpHandler::ConnectImplResult{
|
||||
.medium = connect_medium,
|
||||
.status = {Status::kSuccess},
|
||||
.endpoint_channel = std::move(channel_a),
|
||||
};
|
||||
}));
|
||||
});
|
||||
|
||||
for (const auto& discovered_medium : allowed_mediums) {
|
||||
pcp_handler->OnEndpointFound(
|
||||
@@ -716,7 +712,7 @@ class BasePcpHandlerTest
|
||||
void RequestConnectionV3(
|
||||
const NearbyDevice& remote_device,
|
||||
std::unique_ptr<MockEndpointChannel> channel_a,
|
||||
MockEndpointChannel* channel_b, ClientProxy* client,
|
||||
std::shared_ptr<MockEndpointChannel> channel_b, ClientProxy* client,
|
||||
MockPcpHandler* pcp_handler,
|
||||
location::nearby::proto::connections::Medium connect_medium,
|
||||
FakePresenceDeviceProvider* fake_presence_device_provider,
|
||||
@@ -756,15 +752,15 @@ class BasePcpHandlerTest
|
||||
|
||||
EXPECT_CALL(*pcp_handler, ConnectImpl)
|
||||
.WillRepeatedly(
|
||||
Invoke([&channel_a, connect_medium](
|
||||
ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
[&channel_a, connect_medium](
|
||||
ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
return MockPcpHandler::ConnectImplResult{
|
||||
.medium = connect_medium,
|
||||
.status = {Status::kSuccess},
|
||||
.endpoint_channel = std::move(channel_a),
|
||||
};
|
||||
}));
|
||||
});
|
||||
|
||||
for (const auto& discovered_medium : allowed_mediums) {
|
||||
pcp_handler->OnEndpointFound(
|
||||
@@ -796,7 +792,7 @@ class BasePcpHandlerTest
|
||||
void RequestConnectionWifiLanFail(
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<MockEndpointChannel> channel_a,
|
||||
MockEndpointChannel* channel_b, ClientProxy* client,
|
||||
std::shared_ptr<MockEndpointChannel> channel_b, ClientProxy* client,
|
||||
MockPcpHandler* pcp_handler, std::atomic_int* flag = nullptr,
|
||||
Status expected_result = {Status::kSuccess}) {
|
||||
ConnectionRequestInfo info{
|
||||
@@ -824,8 +820,8 @@ class BasePcpHandlerTest
|
||||
|
||||
EXPECT_CALL(*pcp_handler, ConnectImpl)
|
||||
.WillRepeatedly(
|
||||
Invoke([&channel_a](ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
[&channel_a](ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
if (endpoint->medium ==
|
||||
location::nearby::proto::connections::WIFI_LAN) {
|
||||
LOG(INFO) << "Connect with Medium WIFI_LAN failed.";
|
||||
@@ -844,7 +840,7 @@ class BasePcpHandlerTest
|
||||
.endpoint_channel = std::move(channel_a),
|
||||
};
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
for (const auto& discovered_medium : allowed_mediums) {
|
||||
pcp_handler->OnEndpointFound(
|
||||
@@ -900,7 +896,7 @@ class BasePcpHandlerTest
|
||||
MediumEnvironment& env_ = MediumEnvironment::Instance();
|
||||
NiceMock<MockNearbyDevice> mock_device_;
|
||||
MacAddress remote_mac_address_;
|
||||
nearby::analytics::MockEventLogger mock_event_logger_;
|
||||
nearby::analytics::MockAnalyticsRecorder* mock_analytics_recorder_ptr_;
|
||||
std::unique_ptr<ClientProxy> client_;
|
||||
};
|
||||
|
||||
@@ -1137,12 +1133,13 @@ TEST_F(BasePcpHandlerTest, WifiMediumFailFallBackToBT) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnectionWifiLanFail(endpoint_id, std::move(channel_a),
|
||||
channel_b.get(), client_.get(), &pcp_handler);
|
||||
RequestConnectionWifiLanFail(endpoint_id, std::move(channel_a), channel_b,
|
||||
client_.get(), &pcp_handler);
|
||||
LOG(INFO) << "RequestConnection complete";
|
||||
channel_b->Close();
|
||||
bwu.Shutdown();
|
||||
@@ -1162,12 +1159,13 @@ TEST_P(BasePcpHandlerTest, RequestConnectionChangesState) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnection("1234", std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
RequestConnection("1234", std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium);
|
||||
LOG(INFO) << "RequestConnection complete";
|
||||
EXPECT_TRUE(pcp_handler.HasOutgoingConnections(client_.get()));
|
||||
EXPECT_FALSE(pcp_handler.HasIncomingConnections(client_.get()));
|
||||
@@ -1208,12 +1206,13 @@ TEST_P(BasePcpHandlerTest, CanRequestConnectionPresence) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnection("1234", std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
RequestConnection("1234", std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium);
|
||||
LOG(INFO) << "RequestConnection complete";
|
||||
channel_b->Close();
|
||||
bwu.Shutdown();
|
||||
@@ -1237,12 +1236,13 @@ TEST_P(BasePcpHandlerTest, CanRequestConnectionLegacy) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnection("1234", std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
RequestConnection("1234", std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium);
|
||||
LOG(INFO) << "RequestConnection complete";
|
||||
channel_b->Close();
|
||||
bwu.Shutdown();
|
||||
@@ -1267,11 +1267,12 @@ TEST_P(BasePcpHandlerTest, RequestConnectionV3) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
const auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnectionV3(mock_device_, std::move(channel_a), channel_b.get(),
|
||||
RequestConnectionV3(mock_device_, std::move(channel_a), channel_b,
|
||||
client_.get(), &pcp_handler, connect_medium, &provider);
|
||||
LOG(INFO) << "RequestConnectionV3 complete";
|
||||
channel_b->Close();
|
||||
@@ -1298,12 +1299,13 @@ TEST_P(BasePcpHandlerTest, RequestConnectionV3_AuthenticationFailure) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
const auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnectionV3(
|
||||
mock_device_, std::move(channel_a), channel_b.get(), client_.get(),
|
||||
mock_device_, std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium, &provider, /*flag=*/nullptr,
|
||||
/*expected_result=*/{Status::kSuccess},
|
||||
/*expected_authentication_status=*/AuthenticationStatus::kFailure);
|
||||
@@ -1329,7 +1331,8 @@ TEST_P(BasePcpHandlerTest, RequestConnectionV3_ConnectImplFailure) {
|
||||
auto mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnectionForConnectFailure(connect_medium);
|
||||
const auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
ConnectionRequestInfo info{
|
||||
@@ -1353,7 +1356,7 @@ TEST_P(BasePcpHandlerTest, RequestConnectionV3_ConnectImplFailure) {
|
||||
auto allowed_mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
|
||||
EXPECT_CALL(pcp_handler, ConnectImpl)
|
||||
.WillRepeatedly(Invoke(
|
||||
.WillRepeatedly(
|
||||
[connect_medium](ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
return MockPcpHandler::ConnectImplResult{
|
||||
@@ -1361,7 +1364,7 @@ TEST_P(BasePcpHandlerTest, RequestConnectionV3_ConnectImplFailure) {
|
||||
.status = {Status::kError},
|
||||
.endpoint_channel = nullptr,
|
||||
};
|
||||
}));
|
||||
});
|
||||
|
||||
for (const auto& discovered_medium : allowed_mediums) {
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -1404,7 +1407,8 @@ TEST_P(BasePcpHandlerTest, RequestConnection_ConnectImplFailure) {
|
||||
auto mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnectionForConnectFailure(connect_medium);
|
||||
const auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
ConnectionRequestInfo info{
|
||||
@@ -1428,7 +1432,7 @@ TEST_P(BasePcpHandlerTest, RequestConnection_ConnectImplFailure) {
|
||||
auto allowed_mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
|
||||
EXPECT_CALL(pcp_handler, ConnectImpl)
|
||||
.WillRepeatedly(Invoke(
|
||||
.WillRepeatedly(
|
||||
[connect_medium](ClientProxy* client,
|
||||
MockPcpHandler::DiscoveredEndpoint* endpoint) {
|
||||
return MockPcpHandler::ConnectImplResult{
|
||||
@@ -1436,7 +1440,7 @@ TEST_P(BasePcpHandlerTest, RequestConnection_ConnectImplFailure) {
|
||||
.status = {Status::kError},
|
||||
.endpoint_channel = nullptr,
|
||||
};
|
||||
}));
|
||||
});
|
||||
|
||||
for (const auto& discovered_medium : allowed_mediums) {
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -1476,12 +1480,13 @@ TEST_P(BasePcpHandlerTest, IoError_RequestConnectionV3Fails) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(AtLeast(1));
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(AtLeast(1));
|
||||
channel_b->broken_write_ = true;
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnectionV3(mock_device_, std::move(channel_a), channel_b.get(),
|
||||
RequestConnectionV3(mock_device_, std::move(channel_a), channel_b,
|
||||
client_.get(), &pcp_handler, connect_medium, nullptr,
|
||||
nullptr, {Status::kEndpointIoError});
|
||||
LOG(INFO) << "RequestConnectionV3 complete";
|
||||
@@ -1504,13 +1509,14 @@ TEST_P(BasePcpHandlerTest, IoError_RequestConnectionFails) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(AtLeast(1));
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(AtLeast(1));
|
||||
channel_b->broken_write_ = true;
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium, nullptr,
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium, nullptr,
|
||||
{Status::kEndpointIoError});
|
||||
LOG(INFO) << "RequestConnection complete";
|
||||
channel_b->Close();
|
||||
@@ -1532,11 +1538,12 @@ TEST_P(BasePcpHandlerTest, AcceptConnectionChangesState) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium);
|
||||
LOG(INFO) << "Attempting to accept connection: id=" << endpoint_id;
|
||||
EXPECT_EQ(pcp_handler.AcceptConnection(client_.get(), endpoint_id, {}),
|
||||
Status{Status::kSuccess});
|
||||
@@ -1560,9 +1567,10 @@ TEST_P(BasePcpHandlerTest, RejectConnectionChangesState) {
|
||||
auto mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b,
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
LOG(INFO) << "Attempting to reject connection: id=" << endpoint_id;
|
||||
EXPECT_EQ(pcp_handler.RejectConnection(client_.get(), endpoint_id),
|
||||
@@ -1582,17 +1590,17 @@ TEST_P(BasePcpHandlerTest, OnIncomingFrameChangesState) {
|
||||
EndpointManager em(&ecm);
|
||||
BwuManager bwu(m, em, ecm, {}, {});
|
||||
MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu);
|
||||
analytics::PacketMetaData packet_meta_data;
|
||||
StartDiscovery(client_.get(), &pcp_handler);
|
||||
auto mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
client_.get(), &pcp_handler, connect_medium);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b, client_.get(),
|
||||
&pcp_handler, connect_medium);
|
||||
LOG(INFO) << "Attempting to accept connection: id=" << endpoint_id;
|
||||
EXPECT_CALL(mock_connection_listener_.accepted_cb, Call).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.disconnected_cb, Call)
|
||||
@@ -1601,11 +1609,11 @@ TEST_P(BasePcpHandlerTest, OnIncomingFrameChangesState) {
|
||||
Status{Status::kSuccess});
|
||||
LOG(INFO) << "Simulating remote accept: id=" << endpoint_id;
|
||||
OsInfo os_info;
|
||||
auto frame = parser::FromBytes(parser::ForConnectionResponse(
|
||||
Status::kSuccess, os_info, /*multiplex_socket_bitmask=*/0));
|
||||
auto frame = parser::FromBytes(
|
||||
parser::ForConnectionResponse(Status::kSuccess, os_info));
|
||||
EXPECT_CALL(mock_connection_listener_.bandwidth_changed_cb, Call).Times(1);
|
||||
pcp_handler.OnIncomingFrame(frame.result(), endpoint_id, client_.get(),
|
||||
connect_medium, packet_meta_data);
|
||||
connect_medium);
|
||||
LOG(INFO) << "Closing connection: id=" << endpoint_id;
|
||||
channel_b->Close();
|
||||
bwu.Shutdown();
|
||||
@@ -1629,10 +1637,11 @@ TEST_P(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b,
|
||||
client_.get(), &pcp_handler, connect_medium,
|
||||
&destroyed_flag);
|
||||
mediums_count = mediums.size();
|
||||
@@ -1671,11 +1680,12 @@ TEST_P(BasePcpHandlerTest, MultipleMediumsProduceSingleEndpointLostEvent) {
|
||||
auto connect_medium = mediums[mediums.size() - 1];
|
||||
auto channel_pair = SetupConnection(connect_medium);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
std::shared_ptr<MockEndpointChannel> channel_b =
|
||||
std::move(channel_pair.second);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b,
|
||||
client_.get(), &pcp_handler, connect_medium,
|
||||
&destroyed_flag);
|
||||
auto allowed_mediums = pcp_handler.GetDiscoveryMediums(client_.get());
|
||||
@@ -1787,7 +1797,7 @@ TEST_F(BasePcpHandlerTest, InjectEndpoint) {
|
||||
EXPECT_TRUE(client_->IsDiscovering());
|
||||
|
||||
EXPECT_CALL(pcp_handler, InjectEndpointImpl(client_.get(), service_id, _))
|
||||
.WillOnce(Invoke([&pcp_handler, &endpoint_id](
|
||||
.WillOnce([&pcp_handler, &endpoint_id](
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const OutOfBandConnectionMetadata& metadata) {
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -1803,7 +1813,7 @@ TEST_F(BasePcpHandlerTest, InjectEndpoint) {
|
||||
MockContext{nullptr},
|
||||
}));
|
||||
return Status{Status::kSuccess};
|
||||
}));
|
||||
});
|
||||
pcp_handler.InjectEndpoint(
|
||||
client_.get(), service_id,
|
||||
OutOfBandConnectionMetadata{
|
||||
@@ -1851,30 +1861,30 @@ TEST_F(BasePcpHandlerTest,
|
||||
|
||||
::testing::InSequence seq;
|
||||
EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call)
|
||||
.WillOnce(Invoke([id = endpoint_id](const std::string& endpoint_id,
|
||||
.WillOnce([id = endpoint_id](const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info,
|
||||
const std::string& service_id) {
|
||||
EXPECT_EQ(endpoint_id, id);
|
||||
EXPECT_EQ(endpoint_info, ByteArray{"ABCD"});
|
||||
}));
|
||||
});
|
||||
|
||||
EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call)
|
||||
.WillOnce(Invoke([id = endpoint_id](const std::string& endpoint_id) {
|
||||
.WillOnce([id = endpoint_id](const std::string& endpoint_id) {
|
||||
EXPECT_EQ(endpoint_id, id);
|
||||
}));
|
||||
});
|
||||
|
||||
EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call)
|
||||
.WillOnce(Invoke([id = endpoint_id](const std::string& endpoint_id,
|
||||
.WillOnce([id = endpoint_id](const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info,
|
||||
const std::string& service_id) {
|
||||
EXPECT_EQ(endpoint_id, id);
|
||||
EXPECT_EQ(endpoint_info, ByteArray{"ABCDEF"});
|
||||
}));
|
||||
});
|
||||
|
||||
EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call)
|
||||
.WillOnce(Invoke([id = endpoint_id](const std::string& endpoint_id) {
|
||||
.WillOnce([id = endpoint_id](const std::string& endpoint_id) {
|
||||
EXPECT_EQ(endpoint_id, id);
|
||||
}));
|
||||
});
|
||||
|
||||
// Found endpoint on Bluetooth
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -1964,7 +1974,7 @@ TEST_F(BasePcpHandlerTest, TestStartStopEndpointLostAlarm) {
|
||||
EXPECT_TRUE(client_->IsDiscovering());
|
||||
|
||||
EXPECT_CALL(pcp_handler, InjectEndpointImpl)
|
||||
.WillOnce(Invoke([&pcp_handler, &endpoint_id](
|
||||
.WillOnce([&pcp_handler, &endpoint_id](
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const OutOfBandConnectionMetadata& metadata) {
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -1980,7 +1990,7 @@ TEST_F(BasePcpHandlerTest, TestStartStopEndpointLostAlarm) {
|
||||
MockContext{nullptr},
|
||||
}));
|
||||
return Status{Status::kSuccess};
|
||||
}));
|
||||
});
|
||||
pcp_handler.InjectEndpoint(
|
||||
client_.get(), service_id,
|
||||
OutOfBandConnectionMetadata{
|
||||
@@ -2027,7 +2037,7 @@ TEST_F(BasePcpHandlerTest, TestStartEndpointLostByMediumAlarms) {
|
||||
EXPECT_TRUE(client_->IsDiscovering());
|
||||
|
||||
EXPECT_CALL(pcp_handler, InjectEndpointImpl)
|
||||
.WillOnce(Invoke([&pcp_handler, &endpoint_id](
|
||||
.WillOnce([&pcp_handler, &endpoint_id](
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const OutOfBandConnectionMetadata& metadata) {
|
||||
pcp_handler.OnEndpointFound(
|
||||
@@ -2043,7 +2053,7 @@ TEST_F(BasePcpHandlerTest, TestStartEndpointLostByMediumAlarms) {
|
||||
MockContext{nullptr},
|
||||
}));
|
||||
return Status{Status::kSuccess};
|
||||
}));
|
||||
});
|
||||
pcp_handler.InjectEndpoint(
|
||||
client_.get(), service_id,
|
||||
OutOfBandConnectionMetadata{
|
||||
@@ -2094,7 +2104,7 @@ TEST_F(BasePcpHandlerTest, TestEndpointFoundStopsAlarm) {
|
||||
EXPECT_CALL(pcp_handler, InjectEndpointImpl)
|
||||
.Times(2)
|
||||
.WillRepeatedly(
|
||||
Invoke([&pcp_handler, &endpoint_id, &first_call](
|
||||
[&pcp_handler, &endpoint_id, &first_call](
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const OutOfBandConnectionMetadata& metadata) {
|
||||
ByteArray endpoint_info;
|
||||
@@ -2117,7 +2127,7 @@ TEST_F(BasePcpHandlerTest, TestEndpointFoundStopsAlarm) {
|
||||
MockContext{nullptr},
|
||||
}));
|
||||
return Status{Status::kSuccess};
|
||||
}));
|
||||
});
|
||||
pcp_handler.InjectEndpoint(
|
||||
client_.get(), service_id,
|
||||
OutOfBandConnectionMetadata{
|
||||
@@ -2271,20 +2281,20 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithUnknown) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()->mutable_connection_request()->clear_connections_device();
|
||||
frame.mutable_v1()->mutable_connection_request()->clear_presence_device();
|
||||
ASSERT_FALSE(frame.v1().connection_request().has_connections_device());
|
||||
ASSERT_FALSE(frame.v1().connection_request().has_presence_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_TRUE(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2321,20 +2331,20 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithUnknown) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()->mutable_connection_request()->clear_connections_device();
|
||||
frame.mutable_v1()->mutable_connection_request()->clear_presence_device();
|
||||
ASSERT_FALSE(frame.v1().connection_request().has_connections_device());
|
||||
ASSERT_FALSE(frame.v1().connection_request().has_presence_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_EQ(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2370,21 +2380,21 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithConnections) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()
|
||||
->mutable_connection_request()
|
||||
->mutable_connections_device()
|
||||
->set_endpoint_id("ABCD");
|
||||
ASSERT_TRUE(frame.v1().connection_request().has_connections_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_EQ(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2420,21 +2430,21 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithPresence) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()
|
||||
->mutable_connection_request()
|
||||
->mutable_presence_device()
|
||||
->set_endpoint_id("ABCD");
|
||||
ASSERT_TRUE(frame.v1().connection_request().has_presence_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_TRUE(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2469,21 +2479,21 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithConnections) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()
|
||||
->mutable_connection_request()
|
||||
->mutable_connections_device()
|
||||
->set_endpoint_id("ABCD");
|
||||
ASSERT_TRUE(frame.v1().connection_request().has_connections_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_TRUE(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2518,21 +2528,21 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithPresence) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "ABCD",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
});
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()
|
||||
->mutable_connection_request()
|
||||
->mutable_presence_device()
|
||||
->set_endpoint_id("ABCD");
|
||||
ASSERT_TRUE(frame.v1().connection_request().has_presence_device());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_EQ(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2544,7 +2554,8 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithPresence) {
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
|
||||
env_.Start();
|
||||
env_.Start({.use_simulated_clock = true});
|
||||
client_ = std::make_unique<ClientProxy>(CreateAnalyticsRecorder());
|
||||
Mediums m;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
@@ -2561,6 +2572,8 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
|
||||
MockPcpHandler::StartOperationResult{.status = {Status::kSuccess}}));
|
||||
EXPECT_CALL(pcp_handler, CanReceiveIncomingConnection)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_,
|
||||
OnStartedIncomingConnectionListening(_));
|
||||
EXPECT_TRUE(pcp_handler
|
||||
.StartListeningForIncomingConnections(client_.get(),
|
||||
"service", options, {})
|
||||
@@ -2568,7 +2581,7 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
|
||||
ASSERT_TRUE(client_->IsListeningForIncomingConnections());
|
||||
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(client_.get()));
|
||||
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
|
||||
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
|
||||
std::string serialized_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "",
|
||||
.local_endpoint_info = ByteArray("local endpoint"),
|
||||
@@ -2576,53 +2589,19 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
|
||||
// At this point the connection request doesn't have an endpoint ID field
|
||||
// set, so we do that here.
|
||||
location::nearby::connections::OfflineFrame frame;
|
||||
frame.ParseFromString(serialized_frame.AsStringView());
|
||||
frame.ParseFromString(serialized_frame);
|
||||
frame.mutable_v1()->mutable_connection_request()->set_endpoint_id("");
|
||||
ASSERT_TRUE(frame.v1().connection_request().has_endpoint_id());
|
||||
// do a dummy write to get to the actual write.
|
||||
channel_pair.first->Write(ByteArray());
|
||||
channel_pair.first->Write(ByteArray(frame.SerializeAsString()));
|
||||
absl::string_view expected_log = R"pb(
|
||||
event_type: CLIENT_SESSION
|
||||
client_session {
|
||||
strategy_session {
|
||||
connection_attempt {
|
||||
type: INITIAL
|
||||
direction: INCOMING
|
||||
medium: BLUETOOTH
|
||||
attempt_result: RESULT_ERROR
|
||||
operation_result {
|
||||
result_category: CATEGORY_CONNECTIVITY_ERROR
|
||||
result_code: CONNECTIVITY_CHANNEL_IO_ERROR_ON_BT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)pb";
|
||||
absl::string_view client_session_log = R"pb(
|
||||
event_type: CLIENT_SESSION
|
||||
client_session { duration_millis: 0 }
|
||||
version: "v1.5.0"
|
||||
)pb";
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::STOP_STRATEGY_SESSION))))
|
||||
.Times(1);
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::STOP_CLIENT_SESSION))))
|
||||
.Times(3);
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::START_CLIENT_SESSION))))
|
||||
.Times(3);
|
||||
channel_pair.first->Write("");
|
||||
channel_pair.first->Write(frame.SerializeAsString());
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_, LogSession()).Times(3);
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_, LogStartSession()).Times(3);
|
||||
EXPECT_CALL(
|
||||
mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(EqualsProto(client_session_log))))
|
||||
.Times(2);
|
||||
EXPECT_CALL(mock_event_logger_, Log(Matcher<const ConnectionsLog&>(
|
||||
Partially(EqualsProto(expected_log)))));
|
||||
|
||||
*mock_analytics_recorder_ptr_,
|
||||
OnIncomingConnectionAttempt(
|
||||
location::nearby::proto::connections::INITIAL, Medium::BLUETOOTH,
|
||||
location::nearby::proto::connections::RESULT_ERROR, _, _, _));
|
||||
EXPECT_EQ(pcp_handler
|
||||
.OnIncomingConnection(
|
||||
client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -2636,7 +2615,7 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
|
||||
TEST_F(BasePcpHandlerTest, IncomingConnectionWithNoDataFailsWithoutLogging) {
|
||||
env_.Start({.use_simulated_clock = true});
|
||||
// Recreate ClientProxy so that AnalyticRecorder uses simulated clock.
|
||||
client_ = std::make_unique<ClientProxy>(&mock_event_logger_);
|
||||
client_ = std::make_unique<ClientProxy>(CreateAnalyticsRecorder());
|
||||
Mediums m;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
@@ -2653,6 +2632,8 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionWithNoDataFailsWithoutLogging) {
|
||||
MockPcpHandler::StartOperationResult{.status = {Status::kSuccess}}));
|
||||
EXPECT_CALL(pcp_handler, CanReceiveIncomingConnection)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_,
|
||||
OnStartedIncomingConnectionListening(_));
|
||||
EXPECT_TRUE(pcp_handler
|
||||
.StartListeningForIncomingConnections(client_.get(),
|
||||
"service", options, {})
|
||||
@@ -2664,59 +2645,8 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionWithNoDataFailsWithoutLogging) {
|
||||
std::move(input_a), std::move(output_a));
|
||||
EXPECT_CALL(*input_channel, Read())
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kNoData)));
|
||||
absl::string_view expected_log = R"pb(
|
||||
event_type: CLIENT_SESSION
|
||||
client_session {
|
||||
strategy_session {
|
||||
connection_attempt {
|
||||
type: INITIAL
|
||||
direction: INCOMING
|
||||
attempt_result: RESULT_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
)pb";
|
||||
absl::string_view client_session_log = R"pb(
|
||||
event_type: CLIENT_SESSION
|
||||
client_session { duration_millis: 0 }
|
||||
version: "v1.5.0"
|
||||
)pb";
|
||||
absl::string_view client_session_log2 = R"pb(
|
||||
event_type: CLIENT_SESSION
|
||||
client_session {
|
||||
duration_millis: 0
|
||||
strategy_session {
|
||||
duration_millis: 0
|
||||
strategy: UNKNOWN_STRATEGY
|
||||
role: ADVERTISER
|
||||
}
|
||||
}
|
||||
version: "v1.5.0"
|
||||
)pb";
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::STOP_STRATEGY_SESSION))))
|
||||
.Times(1);
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::STOP_CLIENT_SESSION))))
|
||||
.Times(3);
|
||||
EXPECT_CALL(mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(
|
||||
HasEventType(EventType::START_CLIENT_SESSION))))
|
||||
.Times(3);
|
||||
EXPECT_CALL(
|
||||
mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(EqualsProto(client_session_log))))
|
||||
.Times(2);
|
||||
EXPECT_CALL(
|
||||
mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(EqualsProto(client_session_log2))));
|
||||
EXPECT_CALL(
|
||||
mock_event_logger_,
|
||||
Log(Matcher<const ConnectionsLog&>(Partially(EqualsProto(expected_log)))))
|
||||
.Times(0);
|
||||
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_, LogSession()).Times(3);
|
||||
EXPECT_CALL(*mock_analytics_recorder_ptr_, LogStartSession()).Times(3);
|
||||
EXPECT_EQ(
|
||||
pcp_handler
|
||||
.OnIncomingConnection(client_.get(), ByteArray("remote endpoint"),
|
||||
@@ -3020,5 +2950,4 @@ TEST_F(BasePcpHandlerTest, TestForceUpdateEndpointIdAdvertisingOption) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/expected.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -53,7 +52,7 @@ class BwuHandler {
|
||||
// that hasn't already been done), and returns a serialized UpgradePathInfo
|
||||
// that can be sent to the Responder.
|
||||
// @BwuHandlerThread
|
||||
virtual ByteArray InitializeUpgradedMediumForEndpoint(
|
||||
virtual std::string InitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const std::string& endpoint_id) = 0;
|
||||
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/connection_attempt_metadata_params.h"
|
||||
#include "connections/implementation/awdl_bwu_handler.h"
|
||||
#include "connections/implementation/bluetooth_bwu_handler.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
@@ -38,16 +37,7 @@
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "connections/implementation/service_id_constants.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#ifdef NO_WEBRTC
|
||||
#include "connections/implementation/webrtc_bwu_handler_stub.h"
|
||||
#else
|
||||
#include "connections/implementation/webrtc_bwu_handler.h"
|
||||
#endif
|
||||
#include "connections/implementation/wifi_direct_bwu_handler.h"
|
||||
#include "connections/implementation/wifi_hotspot_bwu_handler.h"
|
||||
#include "connections/implementation/wifi_lan_bwu_handler.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancelable_alarm.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/expected.h"
|
||||
@@ -72,6 +62,8 @@ using ::location::nearby::proto::connections::ConnectionAttemptResult;
|
||||
using ::location::nearby::proto::connections::ConnectionAttemptType;
|
||||
using ::location::nearby::proto::connections::DisconnectionReason;
|
||||
using ::location::nearby::proto::connections::OperationResultCode;
|
||||
using ::nearby::analytics::AnalyticsRecorder;
|
||||
|
||||
} // namespace
|
||||
|
||||
BwuManager::BwuManager(
|
||||
@@ -135,43 +127,37 @@ void BwuManager::InitBwuHandlers() {
|
||||
if (config_.allow_upgrade_to.awdl) {
|
||||
handlers_.emplace(
|
||||
Medium::AWDL,
|
||||
std::make_unique<AwdlBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetAwdl().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
if (config_.allow_upgrade_to.wifi_hotspot) {
|
||||
handlers_.emplace(
|
||||
Medium::WIFI_HOTSPOT,
|
||||
std::make_unique<WifiHotspotBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetWifiHotspot().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
if (config_.allow_upgrade_to.wifi_direct) {
|
||||
handlers_.emplace(
|
||||
Medium::WIFI_DIRECT,
|
||||
std::make_unique<WifiDirectBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetWifiDirect().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
if (config_.allow_upgrade_to.wifi_lan) {
|
||||
handlers_.emplace(
|
||||
Medium::WIFI_LAN,
|
||||
std::make_unique<WifiLanBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetWifiLan().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
if (config_.allow_upgrade_to.web_rtc) {
|
||||
handlers_.emplace(
|
||||
Medium::WEB_RTC,
|
||||
std::make_unique<WebrtcBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetWebRtc().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
if (config_.allow_upgrade_to.bluetooth) {
|
||||
handlers_.emplace(
|
||||
Medium::BLUETOOTH,
|
||||
std::make_unique<BluetoothBwuHandler>(
|
||||
*mediums_,
|
||||
mediums_->GetBluetoothClassic().CreateBwuHandler(
|
||||
absl::bind_front(&BwuManager::OnIncomingConnection, this)));
|
||||
}
|
||||
}
|
||||
@@ -197,8 +183,9 @@ void BwuManager::Shutdown() {
|
||||
medium_ = Medium::UNKNOWN_MEDIUM;
|
||||
endpoint_id_to_bwu_medium_.clear();
|
||||
for (auto& medium_handler_pair : handlers_) {
|
||||
assert(medium_handler_pair.second);
|
||||
medium_handler_pair.second->RevertInitiatorState();
|
||||
if (medium_handler_pair.second != nullptr) {
|
||||
medium_handler_pair.second->RevertInitiatorState();
|
||||
}
|
||||
}
|
||||
handlers_.clear();
|
||||
|
||||
@@ -341,12 +328,12 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client,
|
||||
}
|
||||
|
||||
std::string service_id = channel->GetServiceId();
|
||||
ByteArray bytes = handler->InitializeUpgradedMediumForEndpoint(
|
||||
std::string bytes = handler->InitializeUpgradedMediumForEndpoint(
|
||||
client, service_id, endpoint_id);
|
||||
|
||||
// Because we grab the endpointChannel first thing, it is possible the
|
||||
// endpointChannel is stale by the time we attempt to write over it.
|
||||
if (bytes.Empty()) {
|
||||
if (bytes.empty()) {
|
||||
LOG(ERROR) << "BwuManager couldn't complete the upgrade for endpoint "
|
||||
<< endpoint_id << " to medium "
|
||||
<< location::nearby::proto::connections::Medium_Name(
|
||||
@@ -401,8 +388,7 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client,
|
||||
|
||||
void BwuManager::OnIncomingFrame(OfflineFrame& frame,
|
||||
const std::string& endpoint_id,
|
||||
ClientProxy* client, Medium medium,
|
||||
PacketMetaData& packet_meta_data) {
|
||||
ClientProxy* client, Medium medium) {
|
||||
V1Frame::FrameType frame_type = parser::GetFrameType(frame);
|
||||
if (frame_type != V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION) return;
|
||||
|
||||
@@ -549,7 +535,7 @@ BwuHandler* BwuManager::GetHandlerForMedium(Medium medium) const {
|
||||
}
|
||||
|
||||
void BwuManager::OnBwuNegotiationFrame(
|
||||
ClientProxy* client, const BandwidthUpgradeNegotiationFrame frame,
|
||||
ClientProxy* client, const BandwidthUpgradeNegotiationFrame& frame,
|
||||
const std::string& endpoint_id) {
|
||||
LOG(INFO) << "OnBwuNegotiationFrame: processing incoming "
|
||||
<< BandwidthUpgradeNegotiationFrame::EventType_Name(
|
||||
@@ -586,9 +572,19 @@ void BwuManager::OnBwuNegotiationFrame(
|
||||
OperationResultCode::NEARBY_GENERIC_REMOTE_UPGRADE_FAILURE);
|
||||
break;
|
||||
case BandwidthUpgradeNegotiationFrame::LAST_WRITE_TO_PRIOR_CHANNEL:
|
||||
if (!in_progress_upgrades_.contains(endpoint_id)) {
|
||||
LOG(ERROR) << "Received LAST_WRITE_TO_PRIOR_CHANNEL for endpoint "
|
||||
<< endpoint_id << " but no upgrade is in progress.";
|
||||
return;
|
||||
}
|
||||
ProcessLastWriteToPriorChannelEvent(client, endpoint_id);
|
||||
break;
|
||||
case BandwidthUpgradeNegotiationFrame::SAFE_TO_CLOSE_PRIOR_CHANNEL:
|
||||
if (!in_progress_upgrades_.contains(endpoint_id)) {
|
||||
LOG(ERROR) << "Received SAFE_TO_CLOSE_PRIOR_CHANNEL for endpoint "
|
||||
<< endpoint_id << " but no upgrade is in progress.";
|
||||
return;
|
||||
}
|
||||
ProcessSafeToClosePriorChannelEvent(client, endpoint_id);
|
||||
break;
|
||||
default:
|
||||
@@ -680,7 +676,7 @@ void BwuManager::OnIncomingConnection(
|
||||
connections_attempt_metadata_params;
|
||||
if (channel != nullptr) {
|
||||
connections_attempt_metadata_params =
|
||||
client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams(
|
||||
AnalyticsRecorder::BuildConnectionAttemptMetadataParams(
|
||||
channel->GetTechnology(), channel->GetBand(),
|
||||
channel->GetFrequency(), channel->GetTryCount());
|
||||
connections_attempt_metadata_params->operation_result_code =
|
||||
@@ -891,7 +887,7 @@ void BwuManager::ProcessBwuPathAvailableEvent(
|
||||
if (channel != nullptr) {
|
||||
std::unique_ptr<ConnectionAttemptMetadataParams>
|
||||
connections_attempt_metadata_params =
|
||||
client->GetAnalyticsRecorder().BuildConnectionAttemptMetadataParams(
|
||||
AnalyticsRecorder::BuildConnectionAttemptMetadataParams(
|
||||
channel->GetTechnology(), channel->GetBand(),
|
||||
channel->GetFrequency(), channel->GetTryCount());
|
||||
connections_attempt_metadata_params->operation_result_code =
|
||||
@@ -1138,7 +1134,7 @@ bool BwuManager::ReadClientIntroductionFrame(
|
||||
auto data = channel->Read();
|
||||
timeout_alarm.Cancel();
|
||||
if (!data.ok()) return false;
|
||||
auto transfer(parser::FromBytes(data.result()));
|
||||
auto transfer(parser::FromBytes(data.result().AsStringView()));
|
||||
if (!transfer.ok()) {
|
||||
LOG(ERROR) << "In ReadClientIntroductionFrame, attempted to read a "
|
||||
"ClientIntroductionFrame from EndpointChannel "
|
||||
@@ -1189,7 +1185,7 @@ bool BwuManager::ReadClientIntroductionAckFrame(EndpointChannel* channel) {
|
||||
auto data = channel->Read();
|
||||
timeout_alarm.Cancel();
|
||||
if (!data.ok()) return false;
|
||||
auto transfer(parser::FromBytes(data.result()));
|
||||
auto transfer(parser::FromBytes(data.result().AsStringView()));
|
||||
if (!transfer.ok()) return false;
|
||||
OfflineFrame frame = transfer.result();
|
||||
if (!frame.has_v1() || !frame.v1().has_bandwidth_upgrade_negotiation())
|
||||
@@ -1219,9 +1215,8 @@ void BwuManager::ProcessLastWriteToPriorChannelEvent(
|
||||
// loss). But now that we've received this definitive final write over that
|
||||
// prior EndpointChannel, we can let the remote device that they can safely
|
||||
// close their end of this now-dormant EndpointChannel.
|
||||
EndpointChannel* previous_endpoint_channel =
|
||||
previous_endpoint_channels_[endpoint_id].get();
|
||||
if (!previous_endpoint_channel) {
|
||||
auto it = previous_endpoint_channels_.find(endpoint_id);
|
||||
if (it == previous_endpoint_channels_.end()) {
|
||||
LOG(ERROR)
|
||||
<< "BwuManager received a BWU_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL "
|
||||
"OfflineFrame for unknown endpoint "
|
||||
@@ -1229,6 +1224,12 @@ void BwuManager::ProcessLastWriteToPriorChannelEvent(
|
||||
successfully_upgraded_endpoints_.emplace(endpoint_id);
|
||||
return;
|
||||
}
|
||||
EndpointChannel* previous_endpoint_channel = it->second.get();
|
||||
if (!previous_endpoint_channel) {
|
||||
LOG(ERROR) << "previous_endpoint_channel is null for endpoint "
|
||||
<< endpoint_id;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "ProcessLastWriteToPriorChannelEvent: service_id="
|
||||
<< previous_endpoint_channel->GetServiceId()
|
||||
@@ -1281,6 +1282,13 @@ void BwuManager::ProcessSafeToClosePriorChannelEvent(
|
||||
// or not (as is the case with Android's Bluetooth sockets, where closing
|
||||
// instantly throws an IOException on the remote device).
|
||||
auto item = previous_endpoint_channels_.extract(endpoint_id);
|
||||
if (item.empty()) {
|
||||
LOG(ERROR)
|
||||
<< "BwuManager received a BWU_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL "
|
||||
"OfflineFrame for unknown endpoint "
|
||||
<< endpoint_id << ", can't complete the upgrade protocol.";
|
||||
return;
|
||||
}
|
||||
auto& previous_endpoint_channel = item.mapped();
|
||||
if (previous_endpoint_channel == nullptr) {
|
||||
LOG(ERROR)
|
||||
|
||||
@@ -92,8 +92,7 @@ class BwuManager : public EndpointManager::FrameProcessor {
|
||||
// @EndpointManagerReaderThread
|
||||
void OnIncomingFrame(location::nearby::connections::OfflineFrame& frame,
|
||||
const std::string& endpoint_id, ClientProxy* client,
|
||||
Medium medium,
|
||||
PacketMetaData& packet_meta_data) override;
|
||||
Medium medium) override;
|
||||
|
||||
// Cleans up in-progress upgrades after endpoint disconnection.
|
||||
// @EndpointManagerReaderThread
|
||||
@@ -144,7 +143,7 @@ class BwuManager : public EndpointManager::FrameProcessor {
|
||||
// upgrade.
|
||||
void OnBwuNegotiationFrame(
|
||||
ClientProxy* client,
|
||||
const location::nearby::connections::BandwidthUpgradeNegotiationFrame
|
||||
const location::nearby::connections::BandwidthUpgradeNegotiationFrame&
|
||||
frame,
|
||||
const string& endpoint_id);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
@@ -41,19 +42,17 @@
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/service_address.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
namespace {
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame;
|
||||
using ::location::nearby::connections::MediumRole;
|
||||
using ::location::nearby::connections::OfflineFrame;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::location::nearby::connections::V1Frame;
|
||||
using ::location::nearby::proto::connections::DisconnectionReason;
|
||||
using ::nearby::analytics::SafeDisconnectionResult;
|
||||
|
||||
constexpr absl::string_view kServiceIdA = "ServiceA";
|
||||
constexpr absl::string_view kServiceIdB = "ServiceB";
|
||||
@@ -148,7 +147,7 @@ class BwuManagerTest : public ::testing::Test {
|
||||
void UnRegisterChannelForEndpoint(absl::string_view endpoint_id) {
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(endpoint_id), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
|
||||
// Upgrade from |initial_medium| to |upgrade_medium|, close down the BLUETOOTH
|
||||
@@ -188,12 +187,12 @@ class BwuManagerTest : public ::testing::Test {
|
||||
parser::FromBytes(parser::ForBwuLastWrite());
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(endpoint_id), &client_,
|
||||
initial_medium, packet_meta_data_);
|
||||
initial_medium);
|
||||
ExceptionOr<OfflineFrame> safe_to_close_frame =
|
||||
parser::FromBytes(parser::ForBwuSafeToClose());
|
||||
bwu_manager_->OnIncomingFrame(safe_to_close_frame.result(),
|
||||
std::string(endpoint_id), &client_,
|
||||
initial_medium, packet_meta_data_);
|
||||
initial_medium);
|
||||
|
||||
return upgraded_channel;
|
||||
}
|
||||
@@ -209,7 +208,6 @@ class BwuManagerTest : public ::testing::Test {
|
||||
FakeBwuHandler* fake_wifi_direct_bwu_handler_ = nullptr;
|
||||
FakeBwuHandler* fake_wifi_hotspot_bwu_handler_ = nullptr;
|
||||
std::unique_ptr<BwuManager> bwu_manager_;
|
||||
PacketMetaData packet_meta_data_;
|
||||
};
|
||||
|
||||
TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
|
||||
@@ -233,9 +231,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
|
||||
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId1),
|
||||
Medium::WIFI_LAN);
|
||||
EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId1)));
|
||||
ecm.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
ecm.UnregisterChannelForEndpoint(std::string(kEndpointId1),
|
||||
DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
|
||||
auto channel2 = std::make_unique<FakeEndpointChannel>(
|
||||
Medium::BLUETOOTH, std::string(kServiceIdA));
|
||||
@@ -244,9 +242,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
|
||||
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId2),
|
||||
Medium::WIFI_HOTSPOT);
|
||||
EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId2)));
|
||||
ecm.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
ecm.UnregisterChannelForEndpoint(std::string(kEndpointId2),
|
||||
DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
|
||||
auto channel3 = std::make_unique<FakeEndpointChannel>(
|
||||
Medium::BLUETOOTH, std::string(kServiceIdA));
|
||||
@@ -255,9 +253,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
|
||||
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId3),
|
||||
Medium::WIFI_DIRECT);
|
||||
EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId3)));
|
||||
ecm.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId3), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
ecm.UnregisterChannelForEndpoint(std::string(kEndpointId3),
|
||||
DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
|
||||
auto channel4 = std::make_unique<FakeEndpointChannel>(
|
||||
Medium::WEB_RTC, std::string(kServiceIdA));
|
||||
@@ -266,9 +264,9 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
|
||||
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId4),
|
||||
Medium::BLUETOOTH);
|
||||
EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId4)));
|
||||
ecm.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId4), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
ecm.UnregisterChannelForEndpoint(std::string(kEndpointId4),
|
||||
DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
|
||||
bwu_manager->Shutdown();
|
||||
}
|
||||
@@ -308,9 +306,9 @@ TEST(BwuManagerBaseTest, InitiateBwu_NeedToSwitchRole_Success) {
|
||||
Medium::WIFI_HOTSPOT);
|
||||
EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId1)));
|
||||
|
||||
ecm.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
ecm.UnregisterChannelForEndpoint(std::string(kEndpointId1),
|
||||
DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
bwu_manager->Shutdown();
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
@@ -370,12 +368,12 @@ TEST_P(BwuManagerTestParam, InitiateBwu_Success) {
|
||||
parser::FromBytes(parser::ForBwuLastWrite());
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
ExceptionOr<OfflineFrame> safe_to_close_frame =
|
||||
parser::FromBytes(parser::ForBwuSafeToClose());
|
||||
bwu_manager_->OnIncomingFrame(safe_to_close_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
// Confirm that upgrade channel is resumed after initial channel is shut down.
|
||||
// Note: If we didn't grab the shared initial channel pointer above, this
|
||||
@@ -501,7 +499,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id, std::string(kEndpointId1), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -515,7 +513,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id, std::string(kEndpointId2), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -549,7 +547,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id, std::string(kEndpointId1), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -569,7 +567,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id, std::string(kEndpointId2), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -606,7 +604,7 @@ TEST_F(BwuManagerTest,
|
||||
EXPECT_EQ(2u, ecm_.GetConnectedEndpointsCount());
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
EXPECT_EQ(1u, ecm_.GetConnectedEndpointsCount());
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_A, std::string(kEndpointId1), latch,
|
||||
@@ -626,7 +624,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
EXPECT_EQ(0u, ecm_.GetConnectedEndpointsCount());
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_B, std::string(kEndpointId2), latch,
|
||||
@@ -660,7 +658,7 @@ TEST_F(BwuManagerTest,
|
||||
EXPECT_EQ(2u, ecm_.GetConnectedEndpointsCount());
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
EXPECT_EQ(1u, ecm_.GetConnectedEndpointsCount());
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_A, std::string(kEndpointId1), latch,
|
||||
@@ -680,7 +678,7 @@ TEST_F(BwuManagerTest,
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
EXPECT_EQ(0u, ecm_.GetConnectedEndpointsCount());
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_B, std::string(kEndpointId2), latch,
|
||||
@@ -736,7 +734,7 @@ TEST_F(
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_A, std::string(kEndpointId1), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -761,7 +759,7 @@ TEST_F(
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId2), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_A, std::string(kEndpointId2), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -782,7 +780,7 @@ TEST_F(
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId3), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_B, std::string(kEndpointId3), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -803,7 +801,7 @@ TEST_F(
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId4), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_B, std::string(kEndpointId4), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -826,7 +824,7 @@ TEST_F(
|
||||
CountDownLatch latch(1);
|
||||
ecm_.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId5), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kUnsafeDisconnection);
|
||||
bwu_manager_->OnEndpointDisconnect(
|
||||
&client_, upgrade_service_id_B, std::string(kEndpointId5), latch,
|
||||
DisconnectionReason::LOCAL_DISCONNECTION);
|
||||
@@ -871,7 +869,7 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagEnabled) {
|
||||
parser::FromBytes(parser::ForBwuFailure(info));
|
||||
bwu_manager_->OnIncomingFrame(upgrade_failure.result(),
|
||||
std::string(kEndpointId3), &client_,
|
||||
Medium::WEB_RTC, packet_meta_data_);
|
||||
Medium::WEB_RTC);
|
||||
|
||||
// With the flag enabled, we can safely revert WebRTC just for service B
|
||||
// because service B has no active WebRTC endpoints.
|
||||
@@ -908,7 +906,7 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagDisabled) {
|
||||
parser::FromBytes(parser::ForBwuFailure(info));
|
||||
bwu_manager_->OnIncomingFrame(upgrade_failure.result(),
|
||||
std::string(kEndpointId3), &client_,
|
||||
Medium::WEB_RTC, packet_meta_data_);
|
||||
Medium::WEB_RTC);
|
||||
|
||||
// With the flag disabled, we don't revert if there are still connected
|
||||
// endpoints for _any_ service. We don't have service-level bookkeeping; we
|
||||
@@ -924,12 +922,12 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_WifiDirect) {
|
||||
OfflineFrame frame;
|
||||
CreateInitialEndpoint(&client_, kServiceIdA, kEndpointId1, Medium::BLUETOOTH);
|
||||
|
||||
ByteArray bytes = parser::ForBwuWifiDirectPathAvailable(
|
||||
std::string bytes = parser::ForBwuWifiDirectPathAvailable(
|
||||
/*ssid=*/"", /*password=*/"", /*port=*/2143,
|
||||
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
|
||||
/*gateway=*/"123.234.23.1", /*service_name=*/"NC-WifiDirectTest",
|
||||
/*gateway=*/"123.234.23.1", /*device_name=*/"NC-WifiDirectTest",
|
||||
/*pin=*/"b592f7d3");
|
||||
frame.ParseFromString(std::string(bytes));
|
||||
frame.ParseFromString(bytes);
|
||||
|
||||
::nearby::connections::V1Frame* v1_frame = frame.mutable_v1();
|
||||
::nearby::connections::BandwidthUpgradeNegotiationFrame* sub_frame =
|
||||
@@ -938,7 +936,7 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_WifiDirect) {
|
||||
upgrade_path_info = sub_frame->mutable_upgrade_path_info();
|
||||
upgrade_path_info->set_supports_client_introduction_ack(false);
|
||||
bwu_manager_->OnIncomingFrame(frame, std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
CountDownLatch latch(1);
|
||||
bwu_manager_->OnEndpointDisconnect(&client_, (std::string)kServiceIdA,
|
||||
std::string(kEndpointId1), latch,
|
||||
@@ -973,7 +971,7 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_Hotspot) {
|
||||
upgrade_path_info->set_supports_client_introduction_ack(false);
|
||||
upgrade_path_info->set_supports_disabling_encryption(true);
|
||||
bwu_manager_->OnIncomingFrame(frame, std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
CountDownLatch latch(1);
|
||||
bwu_manager_->OnEndpointDisconnect(&client_, (std::string)kServiceIdA,
|
||||
std::string(kEndpointId1), latch,
|
||||
@@ -1001,7 +999,7 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_Wlan) {
|
||||
upgrade_path_info->set_supports_client_introduction_ack(false);
|
||||
|
||||
bwu_manager_->OnIncomingFrame(frame, std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
CountDownLatch latch(1);
|
||||
bwu_manager_->OnEndpointDisconnect(&client_, (std::string)kServiceIdA,
|
||||
std::string(kEndpointId1), latch,
|
||||
@@ -1040,7 +1038,7 @@ TEST_F(BwuManagerTest, BlockBwuFrameBeforeAccept) {
|
||||
upgrade_path_info2->set_supports_client_introduction_ack(false);
|
||||
upgrade_path_info2->set_supports_disabling_encryption(true);
|
||||
bwu_manager_->OnIncomingFrame(frame2, std::string(kEndpointId2), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
CountDownLatch latch2(1);
|
||||
// The BWU frame should be drop, so the inProgressUpgrades should be empty.
|
||||
ASSERT_EQ(bwu_manager_->IsUpgradeOngoing(std::string(kEndpointId2)), false);
|
||||
@@ -1084,16 +1082,100 @@ TEST_F(BwuManagerTest, BlockBwuFrameFromAdvertiser) {
|
||||
EXPECT_TRUE(client_.IsConnectedToEndpoint(std::string(kEndpointId2)));
|
||||
|
||||
bwu_manager_->OnIncomingFrame(frame, std::string(kEndpointId2), &client_,
|
||||
Medium::BLUETOOTH, packet_meta_data_);
|
||||
Medium::BLUETOOTH);
|
||||
CountDownLatch latch2(1);
|
||||
// The BWU frame should be drop, so the IsUpgradeOngoing should be empty.
|
||||
ASSERT_EQ(bwu_manager_->IsUpgradeOngoing(std::string(kEndpointId2)), false);
|
||||
UnRegisterChannelForEndpoint(kEndpointId2);
|
||||
}
|
||||
|
||||
TEST_F(BwuManagerTest, ReceiveUnexpectedSafeToClose_NoCrash) {
|
||||
ExceptionOr<OfflineFrame> safe_to_close_frame =
|
||||
parser::FromBytes(parser::ForBwuSafeToClose());
|
||||
bwu_manager_->OnIncomingFrame(safe_to_close_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
}
|
||||
|
||||
TEST_F(BwuManagerTest, ReceiveUnexpectedLastWrite_NoCrashOrWedge) {
|
||||
ExceptionOr<OfflineFrame> last_write_frame =
|
||||
parser::FromBytes(parser::ForBwuLastWrite());
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
}
|
||||
|
||||
TEST_F(BwuManagerTest, ReceiveEarlyLastWrite_Success) {
|
||||
CreateInitialEndpoint(&client_, kServiceIdA, kEndpointId1, Medium::BLUETOOTH);
|
||||
std::shared_ptr<EndpointChannel> shared_initial_channel =
|
||||
ecm_.GetChannelForEndpoint(std::string(kEndpointId1));
|
||||
|
||||
bwu_manager_->InitiateBwuForEndpoint(&client_, std::string(kEndpointId1),
|
||||
Medium::WEB_RTC);
|
||||
ASSERT_TRUE(bwu_manager_->IsUpgradeOngoing(std::string(kEndpointId1)));
|
||||
|
||||
ExceptionOr<OfflineFrame> last_write_frame =
|
||||
parser::FromBytes(parser::ForBwuLastWrite());
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
FakeEndpointChannel* upgraded_channel =
|
||||
fake_web_rtc_bwu_handler_->NotifyBwuManagerOfIncomingConnection(
|
||||
/*initialize_call_index=*/0u, bwu_manager_.get());
|
||||
|
||||
ExceptionOr<OfflineFrame> safe_to_close_frame =
|
||||
parser::FromBytes(parser::ForBwuSafeToClose());
|
||||
bwu_manager_->OnIncomingFrame(safe_to_close_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
auto old_channel =
|
||||
dynamic_cast<FakeEndpointChannel*>(shared_initial_channel.get());
|
||||
EXPECT_FALSE(upgraded_channel->IsPaused());
|
||||
EXPECT_TRUE(old_channel->is_closed());
|
||||
EXPECT_EQ(location::nearby::proto::connections::DisconnectionReason::UPGRADED,
|
||||
old_channel->disconnection_reason());
|
||||
UnRegisterChannelForEndpoint(kEndpointId1);
|
||||
}
|
||||
|
||||
TEST_F(BwuManagerTest, ReceiveUnexpectedLastWriteBeforeUpgrade_NoWedge) {
|
||||
ExceptionOr<OfflineFrame> last_write_frame =
|
||||
parser::FromBytes(parser::ForBwuLastWrite());
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
CreateInitialEndpoint(&client_, kServiceIdA, kEndpointId1, Medium::BLUETOOTH);
|
||||
std::shared_ptr<EndpointChannel> shared_initial_channel =
|
||||
ecm_.GetChannelForEndpoint(std::string(kEndpointId1));
|
||||
|
||||
bwu_manager_->InitiateBwuForEndpoint(&client_, std::string(kEndpointId1),
|
||||
Medium::WEB_RTC);
|
||||
|
||||
FakeEndpointChannel* upgraded_channel =
|
||||
fake_web_rtc_bwu_handler_->NotifyBwuManagerOfIncomingConnection(
|
||||
/*initialize_call_index=*/0u, bwu_manager_.get());
|
||||
|
||||
bwu_manager_->OnIncomingFrame(last_write_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
ExceptionOr<OfflineFrame> safe_to_close_frame =
|
||||
parser::FromBytes(parser::ForBwuSafeToClose());
|
||||
bwu_manager_->OnIncomingFrame(safe_to_close_frame.result(),
|
||||
std::string(kEndpointId1), &client_,
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
auto old_channel =
|
||||
dynamic_cast<FakeEndpointChannel*>(shared_initial_channel.get());
|
||||
EXPECT_FALSE(upgraded_channel->IsPaused());
|
||||
EXPECT_TRUE(old_channel->is_closed());
|
||||
UnRegisterChannelForEndpoint(kEndpointId1);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(BwuManagerTestParam, BwuManagerTestParam,
|
||||
testing::Bool());
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -38,12 +38,15 @@
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/advertising_metadata_params.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/connection_attempt_metadata_params.h"
|
||||
#include "connections/implementation/analytics/discovery_metadata_params.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/implementation/mediums/advertisements/dct_advertisement.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "connections/payload.h"
|
||||
#include "connections/payload_type.h"
|
||||
#include "connections/status.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "connections/v3/bandwidth_info.h"
|
||||
@@ -52,7 +55,6 @@
|
||||
#include "connections/v3/connections_device.h"
|
||||
#include "connections/v3/connections_device_provider.h"
|
||||
#include "connections/v3/listeners.h"
|
||||
#include "internal/analytics/event_logger.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/base/files.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
@@ -60,7 +62,9 @@
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancelable_alarm.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/device_info_impl.h"
|
||||
#ifndef NEARBY_CHROMIUM
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#endif
|
||||
#include "internal/platform/error_code_params.h"
|
||||
#include "internal/platform/error_code_recorder.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
@@ -77,9 +81,9 @@
|
||||
namespace nearby::connections {
|
||||
|
||||
namespace {
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::MediumRole;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::nearby::analytics::AnalyticsRecorder;
|
||||
|
||||
constexpr char kEndpointIdChars[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
@@ -95,11 +99,154 @@ constexpr absl::string_view kAdvertisingTimestamp = "nc.advertising.timestamp";
|
||||
|
||||
constexpr absl::Duration kAdvertisingKeepAliveDuration = absl::Seconds(30);
|
||||
|
||||
class NoOpAnalyticsRecorder : public AnalyticsRecorder {
|
||||
public:
|
||||
NoOpAnalyticsRecorder() = default;
|
||||
~NoOpAnalyticsRecorder() override = default;
|
||||
|
||||
// Advertising phase
|
||||
void OnStartAdvertising(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>& mediums,
|
||||
AdvertisingMetadataParams* advertising_metadata_params) override {}
|
||||
void OnStopAdvertising() override {}
|
||||
|
||||
int GetNextAdvertisingUpdateIndex() override { return 0; }
|
||||
|
||||
// Connection listening
|
||||
void OnStartedIncomingConnectionListening(
|
||||
connections::Strategy strategy) override {}
|
||||
void OnStoppedIncomingConnectionListening() override {}
|
||||
|
||||
// Discovery phase
|
||||
void OnStartDiscovery(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<location::nearby::proto::connections::Medium>& mediums,
|
||||
DiscoveryMetadataParams* discovery_metadata_params) override {}
|
||||
void OnStopDiscovery() override {}
|
||||
|
||||
int GetNextDiscoveryUpdateIndex() override { return 0; }
|
||||
void OnEndpointFound(
|
||||
location::nearby::proto::connections::Medium medium) override {}
|
||||
|
||||
// Connection request
|
||||
void OnRequestConnection(const connections::Strategy& strategy,
|
||||
const std::string& endpoint_id) override {}
|
||||
|
||||
void OnConnectionRequestReceived(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
void OnConnectionRequestSent(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
void OnRemoteEndpointAccepted(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
void OnLocalEndpointAccepted(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
void OnRemoteEndpointRejected(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
void OnLocalEndpointRejected(
|
||||
const std::string& remote_endpoint_id) override {}
|
||||
|
||||
// Connection attempt
|
||||
void OnIncomingConnectionAttempt(
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
override {}
|
||||
void OnOutgoingConnectionAttempt(
|
||||
const std::string& remote_endpoint_id,
|
||||
location::nearby::proto::connections::ConnectionAttemptType type,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptResult result,
|
||||
absl::Duration duration, const std::string& connection_token,
|
||||
ConnectionAttemptMetadataParams* connection_attempt_metadata_params)
|
||||
override {}
|
||||
|
||||
// Connection established
|
||||
void OnConnectionEstablished(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
const std::string& connection_token) override {}
|
||||
void OnConnectionClosed(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium medium,
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
nearby::analytics::SafeDisconnectionResult result) override {}
|
||||
|
||||
// Payload
|
||||
void OnIncomingPayloadStarted(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
connections::PayloadType type,
|
||||
std::int64_t total_size_bytes) override {}
|
||||
void OnPayloadChunkReceived(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes) override {}
|
||||
void OnIncomingPayloadDone(
|
||||
const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) override {}
|
||||
void OnOutgoingPayloadStarted(
|
||||
const std::vector<std::string>& endpoint_ids, std::int64_t payload_id,
|
||||
connections::PayloadType type, std::int64_t total_size_bytes) override {}
|
||||
void OnPayloadChunkSent(const std::string& endpoint_id,
|
||||
std::int64_t payload_id,
|
||||
std::int64_t chunk_size_bytes) override {}
|
||||
void OnOutgoingPayloadDone(
|
||||
const std::string& endpoint_id, std::int64_t payload_id,
|
||||
location::nearby::proto::connections::PayloadStatus status,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) override {}
|
||||
|
||||
// BandwidthUpgrade
|
||||
void OnBandwidthUpgradeStarted(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::Medium from_medium,
|
||||
location::nearby::proto::connections::Medium to_medium,
|
||||
location::nearby::proto::connections::ConnectionAttemptDirection
|
||||
direction,
|
||||
const std::string& connection_token) override {}
|
||||
void UpdateBwUpgradeNetworkInfo(const std::string& endpoint_id,
|
||||
int num_interfaces,
|
||||
int num_ipv6_only_interfaces) override {}
|
||||
void OnBandwidthUpgradeError(
|
||||
const std::string& endpoint_id,
|
||||
location::nearby::proto::connections::BandwidthUpgradeResult result,
|
||||
location::nearby::proto::connections::BandwidthUpgradeErrorStage
|
||||
error_stage,
|
||||
location::nearby::proto::connections::OperationResultCode
|
||||
operation_result_code) override {}
|
||||
void OnBandwidthUpgradeSuccess(const std::string& endpoint_id) override {}
|
||||
|
||||
// Error Code
|
||||
void OnErrorCode(const ErrorCodeParams& params) override {}
|
||||
|
||||
void LogStartSession() override {}
|
||||
void LogSession() override {}
|
||||
|
||||
bool IsSessionLogged() override { return false; }
|
||||
|
||||
location::nearby::proto::connections::OperationResultCategory
|
||||
GetOperationResultCategory(
|
||||
location::nearby::proto::connections::OperationResultCode result_code)
|
||||
override {
|
||||
return location::nearby::proto::connections::OperationResultCategory::
|
||||
CATEGORY_UNKNOWN;
|
||||
}
|
||||
|
||||
void Sync() override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger)
|
||||
: client_id_(Prng().NextInt64()) {
|
||||
VLOG(1) << "ClientProxy ctor event_logger=" << event_logger;
|
||||
ClientProxy::ClientProxy(std::unique_ptr<AnalyticsRecorder> analytics_recorder)
|
||||
: client_id_(Prng().NextInt64()),
|
||||
analytics_recorder_(std::move(analytics_recorder)) {
|
||||
if (analytics_recorder_ == nullptr) {
|
||||
analytics_recorder_ = std::make_unique<NoOpAnalyticsRecorder>();
|
||||
}
|
||||
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableNearbyConnectionsPreferences)) {
|
||||
@@ -108,8 +255,6 @@ ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger)
|
||||
|
||||
is_dct_enabled_ = NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::kEnableDct);
|
||||
analytics_recorder_ =
|
||||
std::make_unique<analytics::AnalyticsRecorder>(event_logger);
|
||||
error_code_recorder_ = std::make_unique<ErrorCodeRecorder>(
|
||||
[this](const ErrorCodeParams& params) {
|
||||
analytics_recorder_->OnErrorCode(params);
|
||||
@@ -186,6 +331,7 @@ const NearbyDevice* ClientProxy::GetLocalDevice() {
|
||||
}
|
||||
|
||||
std::string ClientProxy::GetConnectionToken(const std::string& endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
return item->first.connection_token;
|
||||
@@ -216,6 +362,7 @@ std::string ClientProxy::GetSavePath(
|
||||
|
||||
std::optional<MacAddress> ClientProxy::GetBluetoothMacAddress(
|
||||
const std::string& endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
auto item = bluetooth_mac_addresses_.find(endpoint_id);
|
||||
if (item != bluetooth_mac_addresses_.end()) return item->second;
|
||||
return std::nullopt;
|
||||
@@ -223,6 +370,7 @@ std::optional<MacAddress> ClientProxy::GetBluetoothMacAddress(
|
||||
|
||||
void ClientProxy::SetBluetoothMacAddress(const std::string& endpoint_id,
|
||||
MacAddress bluetooth_mac_address) {
|
||||
MutexLock lock(&mutex_);
|
||||
bluetooth_mac_addresses_[endpoint_id] = bluetooth_mac_address;
|
||||
}
|
||||
|
||||
@@ -260,7 +408,7 @@ void ClientProxy::StartedAdvertising(
|
||||
const std::string& service_id, Strategy strategy,
|
||||
const ConnectionListener& listener,
|
||||
absl::Span<location::nearby::proto::connections::Medium> mediums,
|
||||
const std::vector<ConnectionsLog::OperationResultWithMedium>&
|
||||
const std::vector<analytics::OperationResultWithMedium>&
|
||||
operation_result_with_mediums,
|
||||
const AdvertisingOptions& advertising_options) {
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -281,9 +429,9 @@ void ClientProxy::StartedAdvertising(
|
||||
mediums.begin(), mediums.end());
|
||||
std::unique_ptr<AdvertisingMetadataParams> advertising_metadata_params;
|
||||
advertising_metadata_params =
|
||||
GetAnalyticsRecorder().BuildAdvertisingMetadataParams();
|
||||
AnalyticsRecorder::BuildAdvertisingMetadataParams();
|
||||
advertising_metadata_params->operation_result_with_mediums =
|
||||
std::move(operation_result_with_mediums);
|
||||
operation_result_with_mediums;
|
||||
analytics_recorder_->OnStartAdvertising(strategy, medium_vector,
|
||||
advertising_metadata_params.get());
|
||||
}
|
||||
@@ -399,7 +547,7 @@ void ClientProxy::StartedDiscovery(
|
||||
const std::string& service_id, Strategy strategy,
|
||||
DiscoveryListener listener,
|
||||
absl::Span<location::nearby::proto::connections::Medium> mediums,
|
||||
const std::vector<ConnectionsLog::OperationResultWithMedium>&
|
||||
const std::vector<analytics::OperationResultWithMedium>&
|
||||
operation_result_with_mediums,
|
||||
const DiscoveryOptions& discovery_options) {
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -409,10 +557,9 @@ void ClientProxy::StartedDiscovery(
|
||||
const std::vector<location::nearby::proto::connections::Medium> medium_vector(
|
||||
mediums.begin(), mediums.end());
|
||||
std::unique_ptr<DiscoveryMetadataParams> discovery_metadata_params;
|
||||
discovery_metadata_params =
|
||||
GetAnalyticsRecorder().BuildDiscoveryMetadataParams();
|
||||
discovery_metadata_params = AnalyticsRecorder::BuildDiscoveryMetadataParams();
|
||||
discovery_metadata_params->operation_result_with_mediums =
|
||||
std::move(operation_result_with_mediums);
|
||||
operation_result_with_mediums;
|
||||
analytics_recorder_->OnStartDiscovery(strategy, medium_vector,
|
||||
discovery_metadata_params.get());
|
||||
}
|
||||
@@ -875,16 +1022,19 @@ bool ClientProxy::IsConnectionRejected(const std::string& endpoint_id) const {
|
||||
}
|
||||
|
||||
bool ClientProxy::LocalConnectionIsAccepted(std::string endpoint_id) const {
|
||||
MutexLock lock(&mutex_);
|
||||
return ConnectionStatusesContains(
|
||||
endpoint_id, ClientProxy::Connection::kLocalEndpointAccepted);
|
||||
}
|
||||
|
||||
bool ClientProxy::RemoteConnectionIsAccepted(std::string endpoint_id) const {
|
||||
MutexLock lock(&mutex_);
|
||||
return ConnectionStatusesContains(
|
||||
endpoint_id, ClientProxy::Connection::kRemoteEndpointAccepted);
|
||||
}
|
||||
|
||||
bool ClientProxy::AutoUpgradeBandwidth() const {
|
||||
MutexLock lock(&mutex_);
|
||||
bool result = false;
|
||||
if (IsAdvertising() && (GetAdvertisingOptions().strategy.IsNone() ||
|
||||
GetAdvertisingOptions().auto_upgrade_bandwidth)) {
|
||||
@@ -899,6 +1049,7 @@ bool ClientProxy::AutoUpgradeBandwidth() const {
|
||||
}
|
||||
|
||||
bool ClientProxy::ShouldEnforceTopologyConstraints() const {
|
||||
MutexLock lock(&mutex_);
|
||||
bool result = false;
|
||||
if (IsAdvertising() &&
|
||||
(GetAdvertisingOptions().strategy.IsNone() ||
|
||||
@@ -919,6 +1070,7 @@ void ClientProxy::AddCancellationFlag(const std::string& endpoint_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
auto item = cancellation_flags_.find(endpoint_id);
|
||||
if (item != cancellation_flags_.end()) {
|
||||
// A new flag may be added to the map with the same endpoint, even if a
|
||||
@@ -933,19 +1085,21 @@ void ClientProxy::AddCancellationFlag(const std::string& endpoint_id) {
|
||||
return;
|
||||
}
|
||||
cancellation_flags_.emplace(endpoint_id,
|
||||
std::make_unique<CancellationFlag>());
|
||||
std::make_shared<CancellationFlag>());
|
||||
}
|
||||
|
||||
CancellationFlag* ClientProxy::GetCancellationFlag(
|
||||
std::shared_ptr<CancellationFlag> ClientProxy::GetCancellationFlag(
|
||||
const std::string& endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto item = cancellation_flags_.find(endpoint_id);
|
||||
if (item == cancellation_flags_.end()) {
|
||||
return default_cancellation_flag_.get();
|
||||
return default_cancellation_flag_;
|
||||
}
|
||||
return item->second.get();
|
||||
return item->second;
|
||||
}
|
||||
|
||||
void ClientProxy::CancelEndpoint(const std::string& endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto item = cancellation_flags_.find(endpoint_id);
|
||||
if (item != cancellation_flags_.end()) {
|
||||
item->second->Cancel();
|
||||
@@ -956,6 +1110,7 @@ const OsInfo& ClientProxy::GetLocalOsInfo() const { return local_os_info_; }
|
||||
|
||||
std::optional<OsInfo> ClientProxy::GetRemoteOsInfo(
|
||||
absl::string_view endpoint_id) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
return item->first.os_info;
|
||||
@@ -965,11 +1120,13 @@ std::optional<OsInfo> ClientProxy::GetRemoteOsInfo(
|
||||
|
||||
void ClientProxy::SetLocalOsType(
|
||||
const location::nearby::connections::OsInfo::OsType& os_type) {
|
||||
MutexLock lock(&mutex_);
|
||||
local_os_info_.set_type(os_type);
|
||||
}
|
||||
|
||||
void ClientProxy::SetRemoteOsInfo(absl::string_view endpoint_id,
|
||||
const OsInfo& remote_os_info) {
|
||||
MutexLock lock(&mutex_);
|
||||
ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
item->first.os_info.emplace(remote_os_info);
|
||||
@@ -1016,8 +1173,9 @@ bool ClientProxy::IsPayloadReceivedAckEnabled(absl::string_view endpoint_id) {
|
||||
}
|
||||
|
||||
void ClientProxy::CancelAllEndpoints() {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& item : cancellation_flags_) {
|
||||
CancellationFlag* cancellation_flag = item.second.get();
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag = item.second;
|
||||
if (cancellation_flag->Cancelled()) {
|
||||
continue;
|
||||
}
|
||||
@@ -1120,14 +1278,17 @@ void ClientProxy::AppendConnectionStatus(const std::string& endpoint_id,
|
||||
}
|
||||
|
||||
AdvertisingOptions ClientProxy::GetAdvertisingOptions() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return advertising_options_;
|
||||
}
|
||||
|
||||
DiscoveryOptions ClientProxy::GetDiscoveryOptions() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return discovery_options_;
|
||||
}
|
||||
|
||||
v3::ConnectionListeningOptions ClientProxy::GetListeningOptions() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return listening_options_;
|
||||
}
|
||||
|
||||
@@ -1204,30 +1365,9 @@ OsInfo::OsType ClientProxy::OSNameToOsInfoType(api::OSName osName) {
|
||||
}
|
||||
}
|
||||
|
||||
std::int32_t ClientProxy::GetLocalMultiplexSocketBitmask() const {
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplex)) {
|
||||
std::int32_t multiplex_bitmask =
|
||||
(NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth)
|
||||
? kBtMultiplexEnabled
|
||||
: 0) |
|
||||
(NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexWifiLan)
|
||||
? kWifiLanMultiplexEnabled
|
||||
: 0);
|
||||
LOG(INFO) << "ClientProxy [GetLocalMultiplexSocketBitmask]: "
|
||||
<< multiplex_bitmask;
|
||||
return multiplex_bitmask;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClientProxy::SetRemoteMultiplexSocketBitmask(
|
||||
absl::string_view endpoint_id, int remote_multiplex_socket_bitmask) {
|
||||
MutexLock lock(&mutex_);
|
||||
ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
item->first.remote_multiplex_socket_bitmask =
|
||||
@@ -1237,62 +1377,31 @@ void ClientProxy::SetRemoteMultiplexSocketBitmask(
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientProxy::IsLocalMultiplexSocketSupported(Medium medium) {
|
||||
int bitmask = GetLocalMultiplexSocketBitmask();
|
||||
switch (medium) {
|
||||
case Medium::BLUETOOTH:
|
||||
LOG(INFO) << "ClientProxy [IsLocalMultiplexSocketSupported]: "
|
||||
<< (bitmask & kBtMultiplexEnabled);
|
||||
return (bitmask & kBtMultiplexEnabled) != 0;
|
||||
case Medium::WIFI_LAN:
|
||||
return (bitmask & kWifiLanMultiplexEnabled) != 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
bool ClientProxy::GetWebRtcNonCellular() {
|
||||
MutexLock lock(&mutex_);
|
||||
return webrtc_non_cellular_;
|
||||
}
|
||||
|
||||
std::optional<std::int32_t> ClientProxy::GetRemoteMultiplexSocketBitmask(
|
||||
absl::string_view endpoint_id) const {
|
||||
const ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
return item->first.remote_multiplex_socket_bitmask;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ClientProxy::IsMultiplexSocketSupported(absl::string_view endpoint_id,
|
||||
Medium medium) {
|
||||
ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item == nullptr) {
|
||||
return false;
|
||||
}
|
||||
int combined_result = GetLocalMultiplexSocketBitmask() &
|
||||
item->first.remote_multiplex_socket_bitmask;
|
||||
|
||||
switch (medium) {
|
||||
case Medium::BLUETOOTH:
|
||||
return (combined_result & kBtMultiplexEnabled) != 0;
|
||||
case Medium::WIFI_LAN:
|
||||
return (combined_result & kWifiLanMultiplexEnabled) != 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientProxy::GetWebRtcNonCellular() { return webrtc_non_cellular_; }
|
||||
|
||||
void ClientProxy::SetWebRtcNonCellular(bool webrtc_non_cellular) {
|
||||
MutexLock lock(&mutex_);
|
||||
VLOG(1) << "ClientProxy: client=" << GetClientId()
|
||||
<< (webrtc_non_cellular ? " disallow" : " allow")
|
||||
<< " to use mobile data.";
|
||||
webrtc_non_cellular_ = webrtc_non_cellular;
|
||||
}
|
||||
|
||||
bool ClientProxy::IsDctEnabled() const { return is_dct_enabled_; }
|
||||
bool ClientProxy::IsDctEnabled() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return is_dct_enabled_;
|
||||
}
|
||||
|
||||
uint8_t ClientProxy::GetDctDedup() const { return dct_dedup_; }
|
||||
uint8_t ClientProxy::GetDctDedup() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return dct_dedup_;
|
||||
}
|
||||
|
||||
void ClientProxy::UpdateDctDeviceName(absl::string_view device_name) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!dct_device_name_.empty() && dct_device_name_ != device_name) {
|
||||
// Need to update dedup value if device name is changed.
|
||||
absl::BitGen bitgen;
|
||||
@@ -1314,6 +1423,7 @@ void ClientProxy::UpdateDctDeviceName(absl::string_view device_name) {
|
||||
|
||||
std::optional<MediumRole> ClientProxy::GetMediumRole(
|
||||
absl::string_view endpoint_id) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const ConnectionPair* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
return item->first.connection_options.connection_info.medium_role;
|
||||
@@ -1322,6 +1432,7 @@ std::optional<MediumRole> ClientProxy::GetMediumRole(
|
||||
}
|
||||
|
||||
std::optional<std::string> ClientProxy::GetEndpointIdForDct() const {
|
||||
MutexLock lock(&mutex_);
|
||||
if (dct_endpoint_id_.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -1329,13 +1440,20 @@ std::optional<std::string> ClientProxy::GetEndpointIdForDct() const {
|
||||
return dct_endpoint_id_;
|
||||
}
|
||||
|
||||
#ifdef NEARBY_CHROMIUM
|
||||
void ClientProxy::InitializePreferencesManager() {
|
||||
// This method is not currently used by Chromium.
|
||||
NOTREACHED();
|
||||
}
|
||||
#else
|
||||
void ClientProxy::InitializePreferencesManager() {
|
||||
LOG(INFO) << "ClientProxy [InitializePreferencesManager]: client="
|
||||
<< GetClientId();
|
||||
auto device_info_ = std::make_unique<nearby::DeviceInfoImpl>();
|
||||
std::unique_ptr<nearby::api::DeviceInfo> device_info_ =
|
||||
nearby::api::ImplementationPlatform::CreateDeviceInfo();
|
||||
|
||||
FilePath preferences_path =
|
||||
device_info_->GetAppDataPath().append(FilePath(kPreferencesFilePath));
|
||||
device_info_->GetLocalAppDataPath(FilePath(kPreferencesFilePath));
|
||||
|
||||
if (!Files::FileExists(preferences_path)) {
|
||||
Files::CreateDirectories(preferences_path);
|
||||
@@ -1350,6 +1468,7 @@ void ClientProxy::InitializePreferencesManager() {
|
||||
<< GetClientId();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ClientProxy::SaveClientInfoToPreferences() {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/operation_result_with_medium.h"
|
||||
#include "connections/implementation/proto/offline_wire_formats.pb.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
@@ -41,7 +42,6 @@
|
||||
#include "connections/v3/connection_listening_options.h"
|
||||
#include "connections/v3/connections_device_provider.h"
|
||||
#include "connections/v3/listeners.h"
|
||||
#include "internal/analytics/event_logger.h"
|
||||
#include "internal/interop/device.h"
|
||||
#include "internal/interop/device_provider.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/os_name.h"
|
||||
#include "internal/platform/scheduled_executor.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
|
||||
namespace nearby::connections {
|
||||
|
||||
@@ -66,8 +65,8 @@ class ClientProxy final {
|
||||
static constexpr absl::Duration
|
||||
kHighPowerAdvertisementEndpointIdCacheTimeout = absl::Seconds(30);
|
||||
|
||||
explicit ClientProxy(
|
||||
::nearby::analytics::EventLogger* event_logger = nullptr);
|
||||
explicit ClientProxy(std::unique_ptr<nearby::analytics::AnalyticsRecorder>
|
||||
analytics_recorder = nullptr);
|
||||
~ClientProxy();
|
||||
ClientProxy(ClientProxy&&) = default;
|
||||
ClientProxy& operator=(ClientProxy&&) = default;
|
||||
@@ -109,8 +108,7 @@ class ClientProxy final {
|
||||
const std::string& service_id, Strategy strategy,
|
||||
const ConnectionListener& connection_lifecycle_listener,
|
||||
absl::Span<location::nearby::proto::connections::Medium> mediums,
|
||||
const std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>&
|
||||
const std::vector<analytics::OperationResultWithMedium>&
|
||||
operation_result_with_medium,
|
||||
const AdvertisingOptions& advertising_options = AdvertisingOptions{});
|
||||
// Marks this client as not advertising.
|
||||
@@ -134,8 +132,7 @@ class ClientProxy final {
|
||||
const std::string& service_id, Strategy strategy,
|
||||
DiscoveryListener discovery_listener,
|
||||
absl::Span<location::nearby::proto::connections::Medium> mediums,
|
||||
const std::vector<location::nearby::analytics::proto::ConnectionsLog::
|
||||
OperationResultWithMedium>&
|
||||
const std::vector<analytics::OperationResultWithMedium>&
|
||||
operation_result_with_medium,
|
||||
const DiscoveryOptions& discovery_options = DiscoveryOptions{});
|
||||
// Marks this client as not discovering at all.
|
||||
@@ -264,7 +261,8 @@ class ClientProxy final {
|
||||
// Adds a CancellationFlag for endpoint id.
|
||||
void AddCancellationFlag(const std::string& endpoint_id);
|
||||
// Returns the CancellationFlag for endpoint id,
|
||||
CancellationFlag* GetCancellationFlag(const std::string& endpoint_id);
|
||||
std::shared_ptr<CancellationFlag> GetCancellationFlag(
|
||||
const std::string& endpoint_id);
|
||||
// Sets the CancellationFlag to true for endpoint id.
|
||||
void CancelEndpoint(const std::string& endpoint_id);
|
||||
// Cancels all CancellationFlags.
|
||||
@@ -311,19 +309,9 @@ class ClientProxy final {
|
||||
bool IsSafeToDisconnectEnabled(absl::string_view endpoint_id);
|
||||
bool IsPayloadReceivedAckEnabled(absl::string_view endpoint_id);
|
||||
|
||||
// Returns the multiplex socket supports status for local device.
|
||||
std::int32_t GetLocalMultiplexSocketBitmask() const;
|
||||
// Sets the multiplex socket supports status for remote device.
|
||||
void SetRemoteMultiplexSocketBitmask(absl::string_view endpoint_id,
|
||||
int remote_multiplex_socket_bitmask);
|
||||
// Returns true if the multiplex socket is supported for the given medium.
|
||||
bool IsLocalMultiplexSocketSupported(Medium medium);
|
||||
|
||||
// Gets the multiplex socket supports status for remote device.
|
||||
std::optional<std::int32_t> GetRemoteMultiplexSocketBitmask(
|
||||
absl::string_view endpoint_id) const;
|
||||
// Returns true if the multiplex socket is supported for the given medium.
|
||||
bool IsMultiplexSocketSupported(absl::string_view endpoint_id, Medium medium);
|
||||
|
||||
// Gets the WebRTC non cellular network status.
|
||||
bool GetWebRtcNonCellular();
|
||||
@@ -345,18 +333,6 @@ class ClientProxy final {
|
||||
std::optional<location::nearby::connections::MediumRole> GetMediumRole(
|
||||
absl::string_view endpoint_id) const;
|
||||
|
||||
/** Bitmask for bt multiplex connection support. */
|
||||
// Note. Deprecates the first and second bit of BT_MULTIPLEX_ENABLED and
|
||||
// WIFI_LAN_MULTIPLEX_ENABLED and shift them to the third and the forth bit.
|
||||
// The reason is we need to escape the (0, 1) bit which has been set in some
|
||||
// devices without salt enabled. If accompany with the devices with salted
|
||||
// enabled, the frames passed cannot be decrypted and the connection shall be
|
||||
// failed. Please refer to b/295925531#comment#14 for the details.
|
||||
enum MultiplexSocketBitmask : uint32_t {
|
||||
kBtMultiplexEnabled = 1 << 2,
|
||||
kWifiLanMultiplexEnabled = 1 << 3,
|
||||
};
|
||||
|
||||
// Forces client to regenerate a new local endpoint id.
|
||||
void ClearCachedLocalEndpointId();
|
||||
|
||||
@@ -519,11 +495,11 @@ class ClientProxy final {
|
||||
// Maps endpoint_id to CancellationFlag. CancellationFlags are passed around
|
||||
// as raw pointers to other classes in Nearby Connections, so it is important
|
||||
// that objects in this map are not cleared, even if they are cancelled.
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<CancellationFlag>>
|
||||
absl::flat_hash_map<std::string, std::shared_ptr<CancellationFlag>>
|
||||
cancellation_flags_;
|
||||
// A default cancellation flag with isCancelled set be true.
|
||||
std::unique_ptr<CancellationFlag> default_cancellation_flag_ =
|
||||
std::make_unique<CancellationFlag>(true);
|
||||
std::shared_ptr<CancellationFlag> default_cancellation_flag_ =
|
||||
std::make_shared<CancellationFlag>(true);
|
||||
|
||||
// An app lifecycle monitor for monitoring the app lifecycle state.
|
||||
std::unique_ptr<api::AppLifecycleMonitor> app_lifecycle_monitor_;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -32,17 +33,18 @@
|
||||
#include "connections/advertising_options.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/discovery_options.h"
|
||||
#include "connections/implementation/analytics/mock_analytics_recorder.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "connections/payload.h"
|
||||
#include "connections/status.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "connections/v3/bandwidth_info.h"
|
||||
#include "connections/v3/connection_listening_options.h"
|
||||
#include "connections/v3/connection_result.h"
|
||||
#include "connections/v3/connections_device_provider.h"
|
||||
#include "connections/v3/listeners.h"
|
||||
#include "internal/analytics/mock_event_logger.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/interop/device.h"
|
||||
#include "internal/interop/device_provider.h"
|
||||
@@ -51,19 +53,15 @@
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::OsInfo;
|
||||
using ::location::nearby::proto::connections::CLIENT_SESSION;
|
||||
using ::location::nearby::proto::connections::START_CLIENT_SESSION;
|
||||
using ::location::nearby::proto::connections::STOP_CLIENT_SESSION;
|
||||
using ::testing::_;
|
||||
using ::testing::IsEmpty;
|
||||
using ::testing::MockFunction;
|
||||
using ::testing::StrictMock;
|
||||
@@ -77,46 +75,6 @@ constexpr FeatureFlags::Flags kTestCases[] = {
|
||||
},
|
||||
};
|
||||
|
||||
class FakeEventLogger : public ::nearby::analytics::MockEventLogger {
|
||||
public:
|
||||
explicit FakeEventLogger() = default;
|
||||
|
||||
void Log(const ConnectionsLog& message) override {
|
||||
MutexLock lock(&mutex_);
|
||||
logs_.push_back(message);
|
||||
}
|
||||
|
||||
int GetCompleteClientSessionCount() {
|
||||
MutexLock lock(&mutex_);
|
||||
bool has_start_client_session = false;
|
||||
bool has_client_session = false;
|
||||
int session_count = 0;
|
||||
// We expect series of START_CLIENT_SESSION, CLIENT_SESSION and
|
||||
// STOP_CLIENT_SESSION events, possibly interleaved with other events.
|
||||
for (const auto& log : logs_) {
|
||||
if (log.event_type() == START_CLIENT_SESSION) {
|
||||
EXPECT_FALSE(has_start_client_session);
|
||||
EXPECT_FALSE(has_client_session);
|
||||
has_start_client_session = true;
|
||||
} else if (log.event_type() == CLIENT_SESSION) {
|
||||
EXPECT_TRUE(has_start_client_session);
|
||||
EXPECT_FALSE(has_client_session);
|
||||
has_client_session = true;
|
||||
} else if (log.event_type() == STOP_CLIENT_SESSION) {
|
||||
EXPECT_TRUE(has_start_client_session);
|
||||
EXPECT_TRUE(has_client_session);
|
||||
has_start_client_session = false;
|
||||
has_client_session = false;
|
||||
++session_count;
|
||||
}
|
||||
}
|
||||
return session_count;
|
||||
}
|
||||
|
||||
Mutex mutex_;
|
||||
std::vector<ConnectionsLog> logs_;
|
||||
};
|
||||
|
||||
class MockDeviceProvider : public nearby::NearbyDeviceProvider {
|
||||
public:
|
||||
MOCK_METHOD((const NearbyDevice*), GetLocalDevice, (), (override));
|
||||
@@ -165,8 +123,14 @@ class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags::Flags> {
|
||||
/*use_simulated_clock=*/true,
|
||||
/*use_temporary_directory_for_app_path=*/true};
|
||||
env_.Start(config);
|
||||
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
|
||||
client2_ = std::make_unique<ClientProxy>(&event_logger2_);
|
||||
auto analytics_recorder1 =
|
||||
std::make_unique<analytics::MockAnalyticsRecorder>();
|
||||
mock_analytics_recorder1_ptr_ = analytics_recorder1.get();
|
||||
client1_ = std::make_unique<ClientProxy>(std::move(analytics_recorder1));
|
||||
auto analytics_recorder2 =
|
||||
std::make_unique<analytics::MockAnalyticsRecorder>();
|
||||
mock_analytics_recorder2_ptr_ = analytics_recorder2.get();
|
||||
client2_ = std::make_unique<ClientProxy>(std::move(analytics_recorder2));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -360,10 +324,7 @@ class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags::Flags> {
|
||||
ClientProxy* client2() { return client2_.get(); }
|
||||
|
||||
void FastForward(absl::Duration duration) {
|
||||
(*env_.GetSimulatedClock())
|
||||
->FastForward(
|
||||
ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout +
|
||||
absl::Milliseconds(100));
|
||||
env_.FastForward(duration);
|
||||
// make sure the timer based callback is executed.
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
}
|
||||
@@ -383,8 +344,8 @@ class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags::Flags> {
|
||||
MediumEnvironment& env_ = MediumEnvironment::Instance();
|
||||
Strategy strategy_{Strategy::kP2pPointToPoint};
|
||||
const std::string service_id_{"service"};
|
||||
FakeEventLogger event_logger1_;
|
||||
FakeEventLogger event_logger2_;
|
||||
analytics::MockAnalyticsRecorder* mock_analytics_recorder1_ptr_;
|
||||
analytics::MockAnalyticsRecorder* mock_analytics_recorder2_ptr_;
|
||||
std::unique_ptr<ClientProxy> client1_;
|
||||
std::unique_ptr<ClientProxy> client2_;
|
||||
std::string auth_token_ = "auth_token";
|
||||
@@ -437,7 +398,7 @@ TEST_P(ClientProxyTest, CanCancelEndpoint) {
|
||||
// `CancellationFlag` pointers are passed to other classes in Nearby
|
||||
// Connections, and by using the pointers directly, we test their
|
||||
// consumption of `CancellationFlag` pointers.
|
||||
CancellationFlag* cancellation_flag =
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag =
|
||||
client2()->GetCancellationFlag(advertising_endpoint.id);
|
||||
|
||||
EXPECT_FALSE(
|
||||
@@ -473,7 +434,7 @@ TEST_P(ClientProxyTest, CanCancelAllEndpoints) {
|
||||
// `CancellationFlag` pointers are passed to other classes in Nearby
|
||||
// Connections, and by using the pointers directly, we test their
|
||||
// consumption of `CancellationFlag` pointers.
|
||||
CancellationFlag* cancellation_flag =
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag =
|
||||
client2()->GetCancellationFlag(advertising_endpoint.id);
|
||||
|
||||
EXPECT_FALSE(
|
||||
@@ -540,6 +501,26 @@ TEST_P(ClientProxyTest, CanCancelAllEndpointsWithDifferentEndpoint) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ClientProxyTest, GetCancellationFlagRace) {
|
||||
std::string endpoint_id = "test_endpoint";
|
||||
client1()->AddCancellationFlag(endpoint_id);
|
||||
|
||||
std::atomic<bool> run{true};
|
||||
SingleThreadExecutor executor;
|
||||
executor.Execute([&]() {
|
||||
while (run) {
|
||||
client1()->GetCancellationFlag(endpoint_id);
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
client1()->Reset();
|
||||
client1()->AddCancellationFlag(endpoint_id);
|
||||
}
|
||||
|
||||
run = false;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ParametrisedClientProxyTest, ClientProxyTest,
|
||||
::testing::ValuesIn(kTestCases));
|
||||
|
||||
@@ -1161,11 +1142,13 @@ TEST_F(ClientProxyTest, NotLogSessionForStoppedAdvertisingWithConnection) {
|
||||
|
||||
// After
|
||||
StopAdvertising(client1()); // No Advertising
|
||||
EXPECT_EQ(event_logger1_.GetCompleteClientSessionCount(), 0);
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_, LogSession()).Times(1);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest,
|
||||
LogSessionForStoppedAdvertisingWhenNoConnectionsAndNoDiscovering) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
|
||||
@@ -1174,36 +1157,47 @@ TEST_F(ClientProxyTest,
|
||||
advertising_endpoint.id)); // No Connections
|
||||
EXPECT_FALSE(client1()->IsDiscovering()); // No Discovery
|
||||
EXPECT_TRUE(client1()->IsAdvertising()); // Advertising
|
||||
EXPECT_EQ(event_logger1_.GetCompleteClientSessionCount(), 0);
|
||||
|
||||
// After
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_, OnStopAdvertising());
|
||||
StopAdvertising(client1());
|
||||
EXPECT_GT(event_logger1_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, NotLogSessionForStoppedDiscoveryWithConnection) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartDiscovery(strategy_, mediums_, _));
|
||||
StartDiscovery(client2(), GetDiscoveryListener());
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnEndpointFound(Medium::BLUETOOTH));
|
||||
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
|
||||
|
||||
// Before
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnConnectionRequestReceived(advertising_endpoint.id));
|
||||
OnDiscoveryConnectionInitiated(
|
||||
client2(), advertising_endpoint); // Connections are available
|
||||
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
|
||||
EXPECT_TRUE(client2()->IsDiscovering()); // Discovering
|
||||
|
||||
// After
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
|
||||
StopDiscovery(client2());
|
||||
EXPECT_EQ(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest,
|
||||
NotLogSessionForStoppedDiscoveryWithoutConnectionsAndAdvertising) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartDiscovery(strategy_, mediums_, _));
|
||||
StartDiscovery(client2(), GetDiscoveryListener());
|
||||
|
||||
// Before
|
||||
@@ -1213,30 +1207,40 @@ TEST_F(ClientProxyTest,
|
||||
advertising_endpoint.id)); // No Connections
|
||||
|
||||
// After
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
|
||||
StopDiscovery(client2());
|
||||
EXPECT_GT(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, LogSessionOnDisconnectedWithOneConnection) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartDiscovery(strategy_, mediums_, _));
|
||||
StartDiscovery(client2(), GetDiscoveryListener());
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnEndpointFound(Medium::BLUETOOTH));
|
||||
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnConnectionRequestReceived(advertising_endpoint.id));
|
||||
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
|
||||
|
||||
// Before
|
||||
EXPECT_FALSE(client2()->IsAdvertising()); // No Advertising
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
|
||||
StopDiscovery(client2()); // No Discovery
|
||||
EXPECT_TRUE(client2()->HasPendingConnectionToEndpoint(
|
||||
advertising_endpoint.id)); // One Connection
|
||||
|
||||
// After
|
||||
OnDiscoveryConnectionDisconnected(client2(), advertising_endpoint);
|
||||
EXPECT_GT(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest,
|
||||
NotLogSessionOnDisconnectedWithoutConnectionsDiscoveringAdvertising) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
|
||||
@@ -1248,13 +1252,16 @@ TEST_F(ClientProxyTest,
|
||||
|
||||
// After
|
||||
client2()->OnDisconnected(advertising_endpoint.id, /*notify=*/false);
|
||||
EXPECT_EQ(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, NotLogSessionOnDisconnectedWhenMoreThanOneConnection) {
|
||||
ClientProxy client3;
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint_1 =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint_2 =
|
||||
StartAdvertising(client2(), advertising_connection_listener_);
|
||||
StartDiscovery(&client3, GetDiscoveryListener());
|
||||
@@ -1275,15 +1282,22 @@ TEST_F(ClientProxyTest, NotLogSessionOnDisconnectedWhenMoreThanOneConnection) {
|
||||
|
||||
// After
|
||||
client2()->OnDisconnected(advertising_endpoint_1.id, /*notify=*/false);
|
||||
EXPECT_EQ(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest,
|
||||
NotLogSessionOnDisconnectedForDiscoveringWithOnlyOneConnection) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartDiscovery(strategy_, mediums_, _));
|
||||
StartDiscovery(client2(), GetDiscoveryListener());
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnEndpointFound(Medium::BLUETOOTH));
|
||||
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnConnectionRequestReceived(advertising_endpoint.id));
|
||||
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
|
||||
|
||||
// Before
|
||||
@@ -1294,26 +1308,27 @@ TEST_F(ClientProxyTest,
|
||||
|
||||
// After
|
||||
OnDiscoveryConnectionDisconnected(client2(), advertising_endpoint);
|
||||
// Since we are no longer checking IsDiscovering(), we complete sessions now
|
||||
// solely based on advertising.
|
||||
EXPECT_EQ(event_logger2_.GetCompleteClientSessionCount(), 1);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, LogSessionForResetClientProxy) {
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_,
|
||||
OnStartAdvertising(strategy_, mediums_, _));
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnStartDiscovery(strategy_, mediums_, _));
|
||||
StartDiscovery(client2(), GetDiscoveryListener());
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnEndpointFound(Medium::BLUETOOTH));
|
||||
OnDiscoveryEndpointFound(client2(), advertising_endpoint);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_,
|
||||
OnConnectionRequestReceived(advertising_endpoint.id));
|
||||
OnDiscoveryConnectionInitiated(client2(), advertising_endpoint);
|
||||
|
||||
EXPECT_EQ(event_logger1_.GetCompleteClientSessionCount(), 0);
|
||||
EXPECT_CALL(*mock_analytics_recorder1_ptr_, OnStopAdvertising());
|
||||
client1()->Reset();
|
||||
// TODO(b/290936886): Why are there more than one complete sessions?
|
||||
EXPECT_GT(event_logger1_.GetCompleteClientSessionCount(), 0);
|
||||
|
||||
EXPECT_EQ(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
EXPECT_CALL(*mock_analytics_recorder2_ptr_, OnStopDiscovery());
|
||||
client2()->Reset();
|
||||
EXPECT_GT(event_logger2_.GetCompleteClientSessionCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, GetLocalInfoCorrect) {
|
||||
@@ -1483,91 +1498,12 @@ TEST_F(ClientProxyTest, TestAutoBwuWhenListeningWithAutoBwu) {
|
||||
EXPECT_TRUE(client1()->AutoUpgradeBandwidth());
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, TestMultiplexSocketBitmask) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplex)) {
|
||||
EXPECT_EQ(client1()->GetLocalMultiplexSocketBitmask(), 0);
|
||||
}
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::kEnableMultiplex,
|
||||
true);
|
||||
EXPECT_EQ(client1()->GetLocalMultiplexSocketBitmask(), 0);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth,
|
||||
true);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexWifiLan,
|
||||
true);
|
||||
EXPECT_EQ(
|
||||
client1()->GetLocalMultiplexSocketBitmask(),
|
||||
ClientProxy::kBtMultiplexEnabled | ClientProxy::kWifiLanMultiplexEnabled);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::kEnableMultiplex,
|
||||
false);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth,
|
||||
false);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexWifiLan,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, TestRemoteMultiplexSocketBitmask) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::kEnableMultiplex,
|
||||
true);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth,
|
||||
true);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexWifiLan,
|
||||
true);
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
OnAdvertisingConnectionInitiated(client1(), advertising_endpoint);
|
||||
client1()->SetRemoteMultiplexSocketBitmask(
|
||||
advertising_endpoint.id,
|
||||
ClientProxy::kBtMultiplexEnabled | ClientProxy::kWifiLanMultiplexEnabled);
|
||||
ASSERT_TRUE(client1()
|
||||
->GetRemoteMultiplexSocketBitmask(advertising_endpoint.id)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
client1()
|
||||
->GetRemoteMultiplexSocketBitmask(advertising_endpoint.id)
|
||||
.value(),
|
||||
ClientProxy::kBtMultiplexEnabled | ClientProxy::kWifiLanMultiplexEnabled);
|
||||
EXPECT_TRUE(client1()->IsMultiplexSocketSupported(advertising_endpoint.id,
|
||||
Medium::BLUETOOTH));
|
||||
EXPECT_TRUE(client1()->IsMultiplexSocketSupported(advertising_endpoint.id,
|
||||
Medium::WIFI_LAN));
|
||||
EXPECT_FALSE(client1()->IsMultiplexSocketSupported(advertising_endpoint.id,
|
||||
Medium::WIFI_AWARE));
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::kEnableMultiplex,
|
||||
false);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth,
|
||||
false);
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexWifiLan,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(ClientProxyTest, SaveClientInfoFromPreferences) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableNearbyConnectionsPreferences,
|
||||
true);
|
||||
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
|
||||
client1_ = std::make_unique<ClientProxy>();
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
std::string endpoint_id = advertising_endpoint.id;
|
||||
@@ -1575,7 +1511,7 @@ TEST_F(ClientProxyTest, SaveClientInfoFromPreferences) {
|
||||
|
||||
// Destroy the client and create a new one.
|
||||
client1_.reset();
|
||||
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
|
||||
client1_ = std::make_unique<ClientProxy>();
|
||||
|
||||
// The new client should load the same endpoint ID.
|
||||
EXPECT_EQ(client1()->GetLocalEndpointId(), endpoint_id);
|
||||
@@ -1590,7 +1526,7 @@ TEST_F(ClientProxyTest, NotLoadClientInfoFromPreferencesOnExpired) {
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableNearbyConnectionsPreferences,
|
||||
true);
|
||||
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
|
||||
client1_ = std::make_unique<ClientProxy>();
|
||||
Endpoint advertising_endpoint =
|
||||
StartAdvertising(client1(), advertising_connection_listener_);
|
||||
std::string endpoint_id = advertising_endpoint.id;
|
||||
@@ -1600,7 +1536,7 @@ TEST_F(ClientProxyTest, NotLoadClientInfoFromPreferencesOnExpired) {
|
||||
client1_.reset();
|
||||
FastForward(absl::Hours(25));
|
||||
|
||||
client1_ = std::make_unique<ClientProxy>(&event_logger1_);
|
||||
client1_ = std::make_unique<ClientProxy>();
|
||||
|
||||
// The new client should load the same endpoint ID.
|
||||
EXPECT_NE(client1()->GetLocalEndpointId(), endpoint_id);
|
||||
|
||||
@@ -14,30 +14,30 @@
|
||||
|
||||
#include "connections/implementation/connections_authentication_transport.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
ConnectionsAuthenticationTransport::ConnectionsAuthenticationTransport(
|
||||
const EndpointChannel& channel) {
|
||||
channel_ = const_cast<EndpointChannel*>(&channel);
|
||||
}
|
||||
std::shared_ptr<EndpointChannel> channel)
|
||||
: channel_(std::move(channel)) {}
|
||||
|
||||
void ConnectionsAuthenticationTransport::WriteMessage(
|
||||
absl::string_view message) const {
|
||||
// channel_ should never be null.
|
||||
// channel_ is guaranteed valid by shared_ptr ownership
|
||||
CHECK(channel_ != nullptr);
|
||||
channel_->Write(ByteArray(message.data(), message.size()));
|
||||
channel_->Write(message);
|
||||
}
|
||||
|
||||
std::string ConnectionsAuthenticationTransport::ReadMessage() const {
|
||||
// channel_ should never be null.
|
||||
// channel_ is guaranteed valid by shared_ptr ownership
|
||||
CHECK(channel_ != nullptr);
|
||||
auto response = channel_->Read();
|
||||
if (response.ok()) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef THIRD_PARTY_NEARBY_CONNECTIONS_IMPLEMENTATION_CONNECTIONS_AUTHENTICATION_TRANSPORT_H_
|
||||
#define THIRD_PARTY_NEARBY_CONNECTIONS_IMPLEMENTATION_CONNECTIONS_AUTHENTICATION_TRANSPORT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
@@ -30,12 +31,13 @@ namespace connections {
|
||||
class ConnectionsAuthenticationTransport
|
||||
: public nearby::AuthenticationTransport {
|
||||
public:
|
||||
explicit ConnectionsAuthenticationTransport(const EndpointChannel& channel);
|
||||
explicit ConnectionsAuthenticationTransport(
|
||||
std::shared_ptr<EndpointChannel> channel);
|
||||
void WriteMessage(absl::string_view message) const override;
|
||||
std::string ReadMessage() const override;
|
||||
|
||||
private:
|
||||
EndpointChannel* channel_;
|
||||
std::shared_ptr<EndpointChannel> channel_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "connections/implementation/connections_authentication_transport.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -23,12 +22,9 @@
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mock_endpoint_channel.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -36,84 +32,40 @@ namespace {
|
||||
|
||||
using ::testing::_;
|
||||
|
||||
class MockEndpointChannel : public EndpointChannel {
|
||||
public:
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override));
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, Read, (PacketMetaData&), (override));
|
||||
MOCK_METHOD(Exception, Write, (const ByteArray& data), (override));
|
||||
MOCK_METHOD(Exception, Write, (absl::string_view data, PacketMetaData&),
|
||||
(override));
|
||||
MOCK_METHOD(void, Close, (), (override));
|
||||
MOCK_METHOD(
|
||||
void, Close,
|
||||
(location::nearby::proto::connections::DisconnectionReason reason),
|
||||
(override));
|
||||
MOCK_METHOD(void, Close,
|
||||
(location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result),
|
||||
(override));
|
||||
MOCK_METHOD(bool, IsClosed, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetType, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetServiceId, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetName, (), (const, override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::Medium, GetMedium, (),
|
||||
(const, override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::ConnectionTechnology,
|
||||
GetTechnology, (), (const, override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::ConnectionBand, GetBand, (),
|
||||
(const, override));
|
||||
MOCK_METHOD(int, GetFrequency, (), (const, override));
|
||||
MOCK_METHOD(int, GetTryCount, (), (const, override));
|
||||
MOCK_METHOD(int, GetMaxTransmitPacketSize, (), (const, override));
|
||||
MOCK_METHOD(void, EnableEncryption, (std::shared_ptr<EncryptionContext>),
|
||||
(override));
|
||||
MOCK_METHOD(void, DisableEncryption, (), (override));
|
||||
MOCK_METHOD(bool, IsEncrypted, (), (override));
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, TryDecrypt, (const ByteArray& data),
|
||||
(override));
|
||||
MOCK_METHOD(bool, IsPaused, (), (const, override));
|
||||
MOCK_METHOD(void, Pause, (), (override));
|
||||
MOCK_METHOD(void, Resume, (), (override));
|
||||
MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const, override));
|
||||
MOCK_METHOD(absl::Time, GetLastWriteTimestamp, (), (const, override));
|
||||
MOCK_METHOD(uint32_t, GetNextKeepAliveSeqNo, (), (const, override));
|
||||
MOCK_METHOD(void, SetAnalyticsRecorder,
|
||||
(analytics::AnalyticsRecorder*, const std::string&), (override));
|
||||
|
||||
std::vector<std::string> messages_;
|
||||
};
|
||||
|
||||
TEST(ConnectionsAuthenticationTransportTest, TestWriteMessage) {
|
||||
MockEndpointChannel channel;
|
||||
std::vector<std::string> messages;
|
||||
auto channel = std::make_shared<MockEndpointChannel>();
|
||||
ConnectionsAuthenticationTransport transport(channel);
|
||||
EXPECT_CALL(channel, Write(_)).WillOnce([&channel](const ByteArray& data) {
|
||||
channel.messages_.push_back(data.string_data());
|
||||
return Exception{
|
||||
.value = Exception::Value::kSuccess,
|
||||
};
|
||||
});
|
||||
EXPECT_CALL(*channel, Write(_))
|
||||
.WillOnce([&messages](absl::string_view data) {
|
||||
messages.push_back(std::string(data));
|
||||
return Exception{
|
||||
.value = Exception::Value::kSuccess,
|
||||
};
|
||||
});
|
||||
transport.WriteMessage("hello world");
|
||||
EXPECT_THAT(channel.messages_, testing::ElementsAre("hello world"));
|
||||
EXPECT_THAT(messages, testing::ElementsAre("hello world"));
|
||||
}
|
||||
|
||||
TEST(ConnectionsAuthenticationTransportTest, TestReadMessage) {
|
||||
MockEndpointChannel channel;
|
||||
std::vector<std::string> messages;
|
||||
auto channel = std::make_shared<MockEndpointChannel>();
|
||||
ConnectionsAuthenticationTransport transport(channel);
|
||||
channel.messages_.push_back("hello world");
|
||||
EXPECT_CALL(channel, Read()).WillOnce([&channel]() {
|
||||
std::string ret = channel.messages_[0];
|
||||
channel.messages_.erase(channel.messages_.begin());
|
||||
messages.push_back("hello world");
|
||||
EXPECT_CALL(*channel, Read()).WillOnce([&messages]() {
|
||||
std::string ret = messages[0];
|
||||
messages.erase(messages.begin());
|
||||
return ExceptionOr<ByteArray>(ByteArray(ret));
|
||||
});
|
||||
EXPECT_EQ(transport.ReadMessage(), "hello world");
|
||||
}
|
||||
|
||||
TEST(ConnectionsAuthenticationTransportTest, TestReadMessageFail) {
|
||||
MockEndpointChannel channel;
|
||||
std::vector<std::string> messages;
|
||||
auto channel = std::make_shared<MockEndpointChannel>();
|
||||
ConnectionsAuthenticationTransport transport(channel);
|
||||
channel.messages_.push_back("hello world");
|
||||
EXPECT_CALL(channel, Read()).WillOnce([]() {
|
||||
messages.push_back("hello world");
|
||||
EXPECT_CALL(*channel, Read()).WillOnce([]() {
|
||||
return ExceptionOr<ByteArray>(Exception::Value::kIo);
|
||||
});
|
||||
EXPECT_EQ(transport.ReadMessage(), "");
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "connections/implementation/encryption_runner.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -22,7 +21,6 @@
|
||||
|
||||
#include "securegcm/ukey2_handshake.h"
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
@@ -70,9 +68,9 @@ bool HandleEncryptionSuccess(const std::string& endpoint_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
void CancelableAlarmRunnable(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel) {
|
||||
void CancelableAlarmRunnable(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel) {
|
||||
LOG(INFO) << "Timing out encryption for client " << client->GetClientId()
|
||||
<< " to endpoint_id=" << endpoint_id << " after "
|
||||
<< absl::FormatDuration(kTimeout);
|
||||
@@ -82,18 +80,31 @@ void CancelableAlarmRunnable(ClientProxy* client,
|
||||
class ServerRunnable final {
|
||||
public:
|
||||
ServerRunnable(ClientProxy* client, ScheduledExecutor* alarm_executor,
|
||||
const std::string& endpoint_id, EndpointChannel* channel,
|
||||
const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
EncryptionRunner::ResultListener listener)
|
||||
: client_(client),
|
||||
alarm_executor_(alarm_executor),
|
||||
endpoint_id_(endpoint_id),
|
||||
channel_(channel),
|
||||
weak_channel_(channel),
|
||||
listener_(std::move(listener)) {}
|
||||
|
||||
void operator()() {
|
||||
// Lock the weak pointer. If it fails, the channel was freed.
|
||||
auto channel = weak_channel_.lock();
|
||||
// The IsClosed() check is to provide an early exit if channel has been
|
||||
// closed. Otherwise the Read() and Write() calls on the channel below will
|
||||
// return error and exit.
|
||||
if (!channel || channel->IsClosed()) {
|
||||
return;
|
||||
}
|
||||
CancelableAlarm timeout_alarm(
|
||||
"EncryptionRunner.StartServer() timeout",
|
||||
[this]() { CancelableAlarmRunnable(client_, endpoint_id_, channel_); },
|
||||
[this, weak_channel = weak_channel_]() {
|
||||
if (auto channel = weak_channel.lock()) {
|
||||
CancelableAlarmRunnable(client_, endpoint_id_, channel);
|
||||
}
|
||||
},
|
||||
kTimeout, alarm_executor_);
|
||||
|
||||
std::unique_ptr<securegcm::UKey2Handshake> server =
|
||||
@@ -105,7 +116,7 @@ class ServerRunnable final {
|
||||
}
|
||||
|
||||
// Message 1 (Client Init)
|
||||
ExceptionOr<ByteArray> client_init = channel_->Read();
|
||||
ExceptionOr<ByteArray> client_init = channel->Read();
|
||||
if (!client_init.ok()) {
|
||||
LogException();
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
@@ -119,7 +130,7 @@ class ServerRunnable final {
|
||||
if (!parse_result.success) {
|
||||
LogException();
|
||||
if (parse_result.alert_to_send != nullptr) {
|
||||
HandleAlertException(parse_result);
|
||||
HandleAlertException(parse_result, channel);
|
||||
}
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
return;
|
||||
@@ -139,8 +150,7 @@ class ServerRunnable final {
|
||||
return;
|
||||
}
|
||||
|
||||
Exception write_exception =
|
||||
channel_->Write(ByteArray(std::move(*server_init)));
|
||||
Exception write_exception = channel->Write(*server_init);
|
||||
if (!write_exception.Ok()) {
|
||||
LogException();
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
@@ -151,7 +161,7 @@ class ServerRunnable final {
|
||||
<< endpoint_id_ << ").";
|
||||
|
||||
// Message 3 (Client Finish)
|
||||
ExceptionOr<ByteArray> client_finish = channel_->Read();
|
||||
ExceptionOr<ByteArray> client_finish = channel->Read();
|
||||
|
||||
if (!client_finish.ok()) {
|
||||
LogException();
|
||||
@@ -166,7 +176,7 @@ class ServerRunnable final {
|
||||
if (!parse_result.success) {
|
||||
LogException();
|
||||
if (parse_result.alert_to_send != nullptr) {
|
||||
HandleAlertException(parse_result);
|
||||
HandleAlertException(parse_result, channel);
|
||||
}
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
return;
|
||||
@@ -192,13 +202,13 @@ class ServerRunnable final {
|
||||
|
||||
void HandleHandshakeOrIoException(CancelableAlarm* timeout_alarm) {
|
||||
timeout_alarm->Cancel();
|
||||
listener_.CallFailureCallback(endpoint_id_, channel_);
|
||||
listener_.CallFailureCallback(endpoint_id_);
|
||||
}
|
||||
|
||||
void HandleAlertException(
|
||||
const securegcm::UKey2Handshake::ParseResult& parse_result) const {
|
||||
Exception write_exception =
|
||||
channel_->Write(ByteArray(*parse_result.alert_to_send));
|
||||
const securegcm::UKey2Handshake::ParseResult& parse_result,
|
||||
std::shared_ptr<EndpointChannel> channel) const {
|
||||
Exception write_exception = channel->Write(*parse_result.alert_to_send);
|
||||
if (!write_exception.Ok()) {
|
||||
LOG(WARNING) << "In StartServer(), client " << client_->GetClientId()
|
||||
<< " failed to pass the alert error message to endpoint(id="
|
||||
@@ -209,25 +219,39 @@ class ServerRunnable final {
|
||||
ClientProxy* client_;
|
||||
ScheduledExecutor* alarm_executor_;
|
||||
const std::string endpoint_id_;
|
||||
EndpointChannel* channel_;
|
||||
std::weak_ptr<EndpointChannel> weak_channel_;
|
||||
EncryptionRunner::ResultListener listener_;
|
||||
};
|
||||
|
||||
class ClientRunnable final {
|
||||
public:
|
||||
ClientRunnable(ClientProxy* client, ScheduledExecutor* alarm_executor,
|
||||
const std::string& endpoint_id, EndpointChannel* channel,
|
||||
const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
EncryptionRunner::ResultListener listener)
|
||||
: client_(client),
|
||||
alarm_executor_(alarm_executor),
|
||||
endpoint_id_(endpoint_id),
|
||||
channel_(channel),
|
||||
weak_channel_(channel),
|
||||
listener_(std::move(listener)) {}
|
||||
|
||||
void operator()() {
|
||||
// Lock the weak pointer. If it fails, the channel was freed.
|
||||
auto channel = weak_channel_.lock();
|
||||
// The IsClosed() check is to provide an early exit if channel has been
|
||||
// closed. Otherwise the Read() and Write() calls on the channel below will
|
||||
// return error and exit.
|
||||
if (!channel || channel->IsClosed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CancelableAlarm timeout_alarm(
|
||||
"EncryptionRunner.StartClient() timeout",
|
||||
[this]() { CancelableAlarmRunnable(client_, endpoint_id_, channel_); },
|
||||
[this, weak_channel = weak_channel_]() {
|
||||
if (auto channel = weak_channel.lock()) {
|
||||
CancelableAlarmRunnable(client_, endpoint_id_, channel);
|
||||
}
|
||||
},
|
||||
kTimeout, alarm_executor_);
|
||||
|
||||
std::unique_ptr<securegcm::UKey2Handshake> crypto =
|
||||
@@ -251,7 +275,7 @@ class ClientRunnable final {
|
||||
return;
|
||||
}
|
||||
|
||||
Exception write_init_exception = channel_->Write(ByteArray(*client_init));
|
||||
Exception write_init_exception = channel->Write(*client_init);
|
||||
if (!write_init_exception.Ok()) {
|
||||
LogException();
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
@@ -262,7 +286,7 @@ class ClientRunnable final {
|
||||
<< endpoint_id_ << ").";
|
||||
|
||||
// Message 2 (Server Init)
|
||||
ExceptionOr<ByteArray> server_init = channel_->Read();
|
||||
ExceptionOr<ByteArray> server_init = channel->Read();
|
||||
|
||||
if (!server_init.ok()) {
|
||||
LogException();
|
||||
@@ -277,7 +301,7 @@ class ClientRunnable final {
|
||||
if (!parse_result.success) {
|
||||
LogException();
|
||||
if (parse_result.alert_to_send != nullptr) {
|
||||
HandleAlertException(parse_result);
|
||||
HandleAlertException(parse_result, channel);
|
||||
}
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
return;
|
||||
@@ -297,8 +321,7 @@ class ClientRunnable final {
|
||||
return;
|
||||
}
|
||||
|
||||
Exception write_finish_exception =
|
||||
channel_->Write(ByteArray(*client_finish));
|
||||
Exception write_finish_exception = channel->Write(*client_finish);
|
||||
if (!write_finish_exception.Ok()) {
|
||||
LogException();
|
||||
HandleHandshakeOrIoException(&timeout_alarm);
|
||||
@@ -325,13 +348,13 @@ class ClientRunnable final {
|
||||
|
||||
void HandleHandshakeOrIoException(CancelableAlarm* timeout_alarm) {
|
||||
timeout_alarm->Cancel();
|
||||
listener_.CallFailureCallback(endpoint_id_, channel_);
|
||||
listener_.CallFailureCallback(endpoint_id_);
|
||||
}
|
||||
|
||||
void HandleAlertException(
|
||||
const securegcm::UKey2Handshake::ParseResult& parse_result) const {
|
||||
Exception write_exception =
|
||||
channel_->Write(ByteArray(*parse_result.alert_to_send));
|
||||
const securegcm::UKey2Handshake::ParseResult& parse_result,
|
||||
std::shared_ptr<EndpointChannel> channel) const {
|
||||
Exception write_exception = channel->Write(*parse_result.alert_to_send);
|
||||
if (!write_exception.Ok()) {
|
||||
LOG(WARNING) << "In StartClient(), client " << client_->GetClientId()
|
||||
<< " failed to pass the alert error message to endpoint(id="
|
||||
@@ -342,7 +365,7 @@ class ClientRunnable final {
|
||||
ClientProxy* client_;
|
||||
ScheduledExecutor* alarm_executor_;
|
||||
const std::string endpoint_id_;
|
||||
EndpointChannel* channel_;
|
||||
std::weak_ptr<EndpointChannel> weak_channel_;
|
||||
EncryptionRunner::ResultListener listener_;
|
||||
};
|
||||
|
||||
@@ -350,19 +373,19 @@ class ClientRunnable final {
|
||||
|
||||
EncryptionRunner::~EncryptionRunner() { Shutdown(); }
|
||||
|
||||
void EncryptionRunner::StartServer(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel,
|
||||
EncryptionRunner::ResultListener listener) {
|
||||
void EncryptionRunner::StartServer(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
EncryptionRunner::ResultListener listener) {
|
||||
ServerRunnable runnable(client, &alarm_executor_, endpoint_id,
|
||||
endpoint_channel, std::move(listener));
|
||||
server_executor_.Execute("encryption-server", std::move(runnable));
|
||||
}
|
||||
|
||||
void EncryptionRunner::StartClient(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel,
|
||||
EncryptionRunner::ResultListener listener) {
|
||||
void EncryptionRunner::StartClient(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
EncryptionRunner::ResultListener listener) {
|
||||
ClientRunnable runnable(client, &alarm_executor_, endpoint_id,
|
||||
endpoint_channel, std::move(listener));
|
||||
client_executor_.Execute("encryption-client", std::move(runnable));
|
||||
@@ -391,9 +414,9 @@ void EncryptionRunner::ResultListener::CallSuccessCallback(
|
||||
}
|
||||
|
||||
void EncryptionRunner::ResultListener::CallFailureCallback(
|
||||
const std::string& endpoint_id, EndpointChannel* channel) {
|
||||
const std::string& endpoint_id) {
|
||||
if (on_failure_cb) {
|
||||
std::move(on_failure_cb)(endpoint_id, channel);
|
||||
std::move(on_failure_cb)(endpoint_id);
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ class EncryptionRunner {
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token);
|
||||
void CallFailureCallback(const std::string& endpoint_id,
|
||||
EndpointChannel* channel);
|
||||
void CallFailureCallback(const std::string& endpoint_id);
|
||||
void Reset();
|
||||
|
||||
// @EncryptionRunnerThread
|
||||
@@ -56,27 +55,19 @@ class EncryptionRunner {
|
||||
const ByteArray& raw_auth_token) &&>
|
||||
on_success_cb;
|
||||
|
||||
// Encryption has failed. The remote_endpoint_id and channel are given so
|
||||
// that any pending state can be cleaned up.
|
||||
//
|
||||
// We return the EndpointChannel because, at this stage, simultaneous
|
||||
// connections are a possibility. Use this channel to verify that the state
|
||||
// you're cleaning up is for this EndpointChannel, and not state for another
|
||||
// channel to the same endpoint.
|
||||
// Encryption has failed.
|
||||
//
|
||||
// @EncryptionRunnerThread
|
||||
absl::AnyInvocable<void(const std::string& endpoint_id,
|
||||
EndpointChannel* channel) &&>
|
||||
on_failure_cb;
|
||||
absl::AnyInvocable<void(const std::string& endpoint_id)> on_failure_cb;
|
||||
};
|
||||
|
||||
// @AnyThread
|
||||
void StartServer(ClientProxy* client, const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
ResultListener result_listener);
|
||||
// @AnyThread
|
||||
void StartClient(ClientProxy* client, const std::string& endpoint_id,
|
||||
EndpointChannel* endpoint_channel,
|
||||
std::shared_ptr<EndpointChannel> endpoint_channel,
|
||||
ResultListener result_listener);
|
||||
|
||||
// @AnyThread
|
||||
|
||||
@@ -35,8 +35,7 @@
|
||||
#include "proto/connections_enums.pb.h"
|
||||
#include "third_party/ukey2/src/main/cpp/include/securegcm/ukey2_handshake.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
@@ -52,16 +51,8 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
read_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return in_ ? in_->Read(kChunkSize) : ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
ExceptionOr<ByteArray> Read(PacketMetaData& packet_meta_data) override {
|
||||
read_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return in_ ? in_->Read(kChunkSize) : ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
Exception Write(const ByteArray& data) override {
|
||||
write_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return out_ ? out_->Write(data.AsStringView()) : Exception{Exception::kIo};
|
||||
}
|
||||
Exception Write(absl::string_view data,
|
||||
PacketMetaData& packet_meta_data) override {
|
||||
|
||||
Exception Write(absl::string_view data) override {
|
||||
write_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return out_ ? out_->Write(data) : Exception{Exception::kIo};
|
||||
}
|
||||
@@ -73,10 +64,8 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
override {
|
||||
Close();
|
||||
}
|
||||
void Close(
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result) override {
|
||||
void Close(location::nearby::proto::connections::DisconnectionReason reason,
|
||||
nearby::analytics::SafeDisconnectionResult result) override {
|
||||
Close();
|
||||
}
|
||||
bool IsClosed() const override { return false; }
|
||||
@@ -124,21 +113,24 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
};
|
||||
|
||||
struct User {
|
||||
User(InputStream* reader, OutputStream* writer) : channel(reader, writer) {}
|
||||
User(InputStream* reader, OutputStream* writer)
|
||||
: channel(std::make_shared<FakeEndpointChannel>(reader, writer)) {}
|
||||
|
||||
FakeEndpointChannel channel;
|
||||
std::shared_ptr<FakeEndpointChannel> channel;
|
||||
EncryptionRunner crypto;
|
||||
ClientProxy client;
|
||||
};
|
||||
|
||||
struct Response {
|
||||
Response() : latch(2) {}
|
||||
explicit Response(int count) : latch(count) {}
|
||||
enum class Status {
|
||||
kUnknown = 0,
|
||||
kDone = 1,
|
||||
kFailed = 2,
|
||||
};
|
||||
|
||||
CountDownLatch latch{2};
|
||||
CountDownLatch latch;
|
||||
Status server_status = Status::kUnknown;
|
||||
Status client_status = Status::kUnknown;
|
||||
};
|
||||
@@ -155,7 +147,7 @@ TEST(EncryptionRunnerTest, ReadWrite) {
|
||||
Response response;
|
||||
|
||||
user_a.crypto.StartServer(
|
||||
&user_a.client, "endpoint_id", &user_a.channel,
|
||||
&user_a.client, "endpoint_id", user_a.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -166,15 +158,14 @@ TEST(EncryptionRunnerTest, ReadWrite) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_a](const std::string& endpoint_id) {
|
||||
user_a.channel->Close();
|
||||
response.server_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
});
|
||||
user_b.crypto.StartClient(
|
||||
&user_b.client, "endpoint_id", &user_b.channel,
|
||||
&user_b.client, "endpoint_id", user_b.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -185,9 +176,8 @@ TEST(EncryptionRunnerTest, ReadWrite) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_b](const std::string& endpoint_id) {
|
||||
user_b.channel->Close();
|
||||
response.client_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
@@ -204,14 +194,13 @@ TEST(EncryptionRunnerTest, ClientWriteFails) {
|
||||
/*writer=*/from_a_to_b.second.get());
|
||||
User user_b(/*reader=*/from_a_to_b.first.get(),
|
||||
/*writer=*/from_b_to_a.second.get());
|
||||
Response response;
|
||||
response.latch = CountDownLatch(1);
|
||||
Response response(1);
|
||||
|
||||
// Close server's input stream, so client can't write to it.
|
||||
from_b_to_a.first->Close();
|
||||
|
||||
user_b.crypto.StartClient(
|
||||
&user_b.client, "endpoint_id", &user_b.channel,
|
||||
&user_b.client, "endpoint_id", user_b.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -222,9 +211,8 @@ TEST(EncryptionRunnerTest, ClientWriteFails) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_a](const std::string& endpoint_id) {
|
||||
user_a.channel->Close();
|
||||
response.client_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
@@ -240,14 +228,13 @@ TEST(EncryptionRunnerTest, ServerWriteFails) {
|
||||
/*writer=*/from_a_to_b.second.get());
|
||||
User user_b(/*reader=*/from_a_to_b.first.get(),
|
||||
/*writer=*/from_b_to_a.second.get());
|
||||
Response response;
|
||||
response.latch = CountDownLatch(1);
|
||||
Response response(1);
|
||||
|
||||
// Close client's input stream, so server can't write to it.
|
||||
from_a_to_b.first->Close();
|
||||
|
||||
user_a.crypto.StartServer(
|
||||
&user_a.client, "endpoint_id", &user_a.channel,
|
||||
&user_a.client, "endpoint_id", user_a.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -258,24 +245,22 @@ TEST(EncryptionRunnerTest, ServerWriteFails) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_a](const std::string& endpoint_id) {
|
||||
user_a.channel->Close();
|
||||
response.server_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
});
|
||||
user_b.crypto.StartClient(
|
||||
&user_b.client, "endpoint_id", &user_b.channel,
|
||||
&user_b.client, "endpoint_id", user_b.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[](const std::string& endpoint_id,
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token) {},
|
||||
.on_success_cb = [](const std::string& endpoint_id,
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2,
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token) {},
|
||||
.on_failure_cb =
|
||||
[](const std::string& endpoint_id, EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&user_b](const std::string& endpoint_id) {
|
||||
user_b.channel->Close();
|
||||
},
|
||||
});
|
||||
EXPECT_TRUE(response.latch.Await(absl::Milliseconds(5000)).result());
|
||||
@@ -287,11 +272,10 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage1) {
|
||||
auto from_client_to_server = CreatePipe();
|
||||
User user_a(/*reader=*/from_client_to_server.first.get(),
|
||||
/*writer=*/from_server_to_client.second.get());
|
||||
Response response;
|
||||
response.latch = CountDownLatch(1);
|
||||
Response response(1);
|
||||
|
||||
user_a.crypto.StartServer(
|
||||
&user_a.client, "endpoint_id", &user_a.channel,
|
||||
&user_a.client, "endpoint_id", user_a.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -302,9 +286,8 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage1) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_a](const std::string& endpoint_id) {
|
||||
user_a.channel->Close();
|
||||
response.server_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
@@ -328,11 +311,10 @@ TEST(EncryptionRunnerTest, ServerSendsGarbageMessage2) {
|
||||
auto from_client_to_server = CreatePipe();
|
||||
User user_b(/*reader=*/from_server_to_client.first.get(),
|
||||
/*writer=*/from_client_to_server.second.get());
|
||||
Response response;
|
||||
response.latch = CountDownLatch(1);
|
||||
Response response(1);
|
||||
|
||||
user_b.crypto.StartClient(
|
||||
&user_b.client, "endpoint_id", &user_b.channel,
|
||||
&user_b.client, "endpoint_id", user_b.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -343,9 +325,8 @@ TEST(EncryptionRunnerTest, ServerSendsGarbageMessage2) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_b](const std::string& endpoint_id) {
|
||||
user_b.channel->Close();
|
||||
response.client_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
@@ -374,11 +355,10 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage3) {
|
||||
/*writer=*/from_server_to_client.second.get());
|
||||
User user_b(/*reader=*/from_server_to_client.first.get(),
|
||||
/*writer=*/from_client_to_server.second.get());
|
||||
Response response;
|
||||
response.latch = CountDownLatch(1);
|
||||
Response response(1);
|
||||
|
||||
user_a.crypto.StartServer(
|
||||
&user_a.client, "endpoint_id", &user_a.channel,
|
||||
&user_a.client, "endpoint_id", user_a.channel,
|
||||
{
|
||||
.on_success_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
@@ -389,9 +369,8 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage3) {
|
||||
response.latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&response](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
channel->Close();
|
||||
[&response, &user_a](const std::string& endpoint_id) {
|
||||
user_a.channel->Close();
|
||||
response.server_status = Response::Status::kFailed;
|
||||
response.latch.CountDown();
|
||||
},
|
||||
@@ -411,7 +390,8 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage3) {
|
||||
EXPECT_TRUE(server_init.ok());
|
||||
|
||||
// Client crypto parses message 2.
|
||||
client_crypto->ParseHandshakeMessage(std::string(server_init.result()));
|
||||
client_crypto->ParseHandshakeMessage(
|
||||
std::string(server_init.result().data(), server_init.result().size()));
|
||||
|
||||
// Client sends garbage instead of message 3
|
||||
from_client_to_server.second->Write("Garbage");
|
||||
@@ -427,5 +407,4 @@ TEST(EncryptionRunnerTest, ClientSendsGarbageMessage3) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -23,14 +23,10 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
using analytics::PacketMetaData;
|
||||
namespace nearby::connections {
|
||||
|
||||
class EndpointChannel {
|
||||
public:
|
||||
@@ -41,15 +37,9 @@ class EndpointChannel {
|
||||
virtual ExceptionOr<ByteArray>
|
||||
Read() = 0; // throws Exception::IO, Exception::INTERRUPTED
|
||||
|
||||
virtual ExceptionOr<ByteArray> Read(PacketMetaData& packet_meta_data) = 0;
|
||||
virtual Exception Write(absl::string_view data) = 0; // throws Exception::IO
|
||||
|
||||
virtual Exception Write(const ByteArray& data) = 0; // throws Exception::IO
|
||||
|
||||
virtual Exception Write(
|
||||
absl::string_view data,
|
||||
PacketMetaData& packet_meta_data) = 0; // throws Exception::IO
|
||||
// Closes this EndpointChannel, without tracking the closure in analytics.
|
||||
|
||||
virtual void Close() = 0;
|
||||
|
||||
// Closes this EndpointChannel and records the closure with the given reason.
|
||||
@@ -60,8 +50,7 @@ class EndpointChannel {
|
||||
// and safe disconnection result.
|
||||
virtual void Close(
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result) = 0;
|
||||
nearby::analytics::SafeDisconnectionResult result) = 0;
|
||||
|
||||
// True if the EndpointChannel is currently closed.
|
||||
virtual bool IsClosed() const = 0;
|
||||
@@ -150,7 +139,6 @@ inline bool operator!=(const EndpointChannel& lhs, const EndpointChannel& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
#endif // CORE_INTERNAL_ENDPOINT_CHANNEL_H_
|
||||
|
||||
@@ -29,10 +29,7 @@
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
|
||||
namespace nearby::connections {
|
||||
namespace {
|
||||
const absl::Duration kDataTransferDelay = absl::Milliseconds(500);
|
||||
}
|
||||
@@ -46,7 +43,7 @@ EndpointChannelManager::~EndpointChannelManager() {
|
||||
|
||||
void EndpointChannelManager::RegisterChannelForEndpoint(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel) {
|
||||
std::shared_ptr<EndpointChannel> channel) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
LOG(INFO) << "EndpointChannelManager registered channel of type "
|
||||
@@ -59,7 +56,7 @@ void EndpointChannelManager::RegisterChannelForEndpoint(
|
||||
|
||||
void EndpointChannelManager::ReplaceChannelForEndpoint(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel, bool enable_encryption) {
|
||||
std::shared_ptr<EndpointChannel> channel, bool enable_encryption) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (client->IsSafeToDisconnectEnabled(endpoint_id) &&
|
||||
channel_state_.IsWaitingForSafeToDisconnectTimeout(endpoint_id)) {
|
||||
@@ -106,7 +103,7 @@ std::shared_ptr<EndpointChannel> EndpointChannelManager::GetChannelForEndpoint(
|
||||
|
||||
void EndpointChannelManager::SetActiveEndpointChannel(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel, bool enable_encryption) {
|
||||
std::shared_ptr<EndpointChannel> channel, bool enable_encryption) {
|
||||
// Update the channel first, then encrypt this new channel, if
|
||||
// crypto context is present.
|
||||
channel->SetAnalyticsRecorder(&client->GetAnalyticsRecorder(), endpoint_id);
|
||||
@@ -183,13 +180,13 @@ void EndpointChannelManager::ChannelState::DestroyAll() {
|
||||
for (auto& item : endpoints_) {
|
||||
RemoveEndpoint(item.first, DisconnectionReason::SHUTDOWN,
|
||||
/* safe_to_disconnect_enabled */ false,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
endpoints_.clear();
|
||||
}
|
||||
|
||||
void EndpointChannelManager::ChannelState::UpdateChannelForEndpoint(
|
||||
const std::string& endpoint_id, std::unique_ptr<EndpointChannel> channel) {
|
||||
const std::string& endpoint_id, std::shared_ptr<EndpointChannel> channel) {
|
||||
// Create EndpointData instance, if necessary, and populate channel.
|
||||
endpoints_[endpoint_id].channel = std::move(channel);
|
||||
}
|
||||
@@ -365,5 +362,4 @@ bool EndpointChannelManager::UnregisterChannelForEndpoint(
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -21,18 +21,16 @@
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
using DisconnectionReason =
|
||||
::location::nearby::proto::connections::DisconnectionReason;
|
||||
using SafeDisconnectionResult = ::location::nearby::analytics::proto::
|
||||
ConnectionsLog::EstablishedConnection::SafeDisconnectionResult;
|
||||
using SafeDisconnectionResult = nearby::analytics::SafeDisconnectionResult;
|
||||
|
||||
// NOTE(std::string):
|
||||
// All the strings in internal class public interfaces should be exchanged as
|
||||
@@ -59,7 +57,7 @@ class EndpointChannelManager final {
|
||||
// be closed before continuing the registration.
|
||||
void RegisterChannelForEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel)
|
||||
std::shared_ptr<EndpointChannel> channel)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Replaces the EndpointChannel to be associated with an endpoint from here on
|
||||
@@ -67,7 +65,7 @@ class EndpointChannelManager final {
|
||||
// to the newly-provided EndpointChannel.
|
||||
void ReplaceChannelForEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
bool enable_encryption)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
@@ -168,7 +166,7 @@ class EndpointChannelManager final {
|
||||
// Stores a new EndpointChannel for the endpoint.
|
||||
// Prevoius one is destroyed, if it existed.
|
||||
void UpdateChannelForEndpoint(const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel);
|
||||
std::shared_ptr<EndpointChannel> channel);
|
||||
|
||||
// Stores a new EncryptionContext for the endpoint.
|
||||
// Prevoius one is destroyed, if it existed.
|
||||
@@ -207,7 +205,7 @@ class EndpointChannelManager final {
|
||||
|
||||
void SetActiveEndpointChannel(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
bool enable_encryption)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
@@ -215,7 +213,6 @@ class EndpointChannelManager final {
|
||||
ChannelState channel_state_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
#endif // CORE_INTERNAL_ENDPOINT_CHANNEL_MANAGER_H_
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/base_endpoint_channel.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/encryption_runner.h"
|
||||
@@ -39,16 +40,14 @@
|
||||
#include "internal/platform/multi_thread_executor.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/pipe.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::proto::connections::DisconnectionReason;
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::nearby::analytics::SafeDisconnectionResult;
|
||||
using EncryptionContext = BaseEndpointChannel::EncryptionContext;
|
||||
|
||||
constexpr size_t kChunkSize = 64 * 1024;
|
||||
@@ -110,8 +109,8 @@ std::function<void(const ByteArray&)> MakeDataMonitor(absl::string_view label,
|
||||
|
||||
std::pair<std::unique_ptr<EncryptionContext>,
|
||||
std::unique_ptr<EncryptionContext>>
|
||||
DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
BaseEndpointChannel* channel_b) {
|
||||
DoDhKeyExchange(std::shared_ptr<EndpointChannel> channel_a,
|
||||
std::shared_ptr<EndpointChannel> channel_b) {
|
||||
std::unique_ptr<EncryptionContext> context_a;
|
||||
std::unique_ptr<EncryptionContext> context_b;
|
||||
EncryptionRunner crypto_a;
|
||||
@@ -136,8 +135,7 @@ DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&latch](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
[&latch](const std::string& endpoint_id) {
|
||||
LOG(INFO) << "client-A side key negotiation failed";
|
||||
latch.CountDown();
|
||||
},
|
||||
@@ -159,8 +157,7 @@ DoDhKeyExchange(BaseEndpointChannel* channel_a,
|
||||
latch.CountDown();
|
||||
},
|
||||
.on_failure_cb =
|
||||
[&latch](const std::string& endpoint_id,
|
||||
EndpointChannel* channel) {
|
||||
[&latch](const std::string& endpoint_id) {
|
||||
LOG(INFO) << "client-B side key negotiation failed";
|
||||
latch.CountDown();
|
||||
},
|
||||
@@ -185,9 +182,9 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
|
||||
// to server "b".
|
||||
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
|
||||
// to server "a".
|
||||
auto channel_a = std::make_unique<MockEndpointChannel>(server_a.first.get(),
|
||||
auto channel_a = std::make_shared<MockEndpointChannel>(server_a.first.get(),
|
||||
client_a.second.get());
|
||||
auto channel_b = std::make_unique<MockEndpointChannel>(server_b.first.get(),
|
||||
auto channel_b = std::make_shared<MockEndpointChannel>(server_b.first.get(),
|
||||
client_b.second.get());
|
||||
auto channel_a_raw = channel_a.get();
|
||||
auto channel_b_raw = channel_b.get();
|
||||
@@ -208,7 +205,7 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
|
||||
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
|
||||
|
||||
// Run DH key exchange; setup encryption contexts for channels.
|
||||
auto context = DoDhKeyExchange(channel_a.get(), channel_b.get());
|
||||
auto context = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context.first, nullptr);
|
||||
ASSERT_NE(context.second, nullptr);
|
||||
|
||||
@@ -227,12 +224,12 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
|
||||
EXPECT_EQ(channel_a_raw->GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
EXPECT_EQ(channel_b_raw->GetType(), "ENCRYPTED_BLUETOOTH");
|
||||
|
||||
ByteArray tx_message{"data message"};
|
||||
absl::string_view tx_message = "data message";
|
||||
channel_a_raw->Write(tx_message);
|
||||
ByteArray rx_message = std::move(channel_b_raw->Read().result());
|
||||
|
||||
// Verify expectations.
|
||||
EXPECT_EQ(rx_message, tx_message);
|
||||
EXPECT_EQ(rx_message.AsStringView(), tx_message);
|
||||
{
|
||||
absl::MutexLock lock(mutex);
|
||||
std::string message{tx_message};
|
||||
@@ -245,10 +242,10 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
|
||||
channel_b_raw->Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
ecm_a.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
ecm_b.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId), DisconnectionReason::REMOTE_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
|
||||
TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
|
||||
@@ -266,9 +263,9 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
|
||||
// to server "b".
|
||||
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
|
||||
// to server "a".
|
||||
auto channel_a = std::make_unique<MockEndpointChannel>(server_a.first.get(),
|
||||
auto channel_a = std::make_shared<MockEndpointChannel>(server_a.first.get(),
|
||||
client_a.second.get());
|
||||
auto channel_b = std::make_unique<MockEndpointChannel>(server_b.first.get(),
|
||||
auto channel_b = std::make_shared<MockEndpointChannel>(server_b.first.get(),
|
||||
client_b.second.get());
|
||||
auto channel_a_raw = channel_a.get();
|
||||
auto channel_b_raw = channel_b.get();
|
||||
@@ -289,7 +286,7 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
|
||||
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
|
||||
|
||||
// Run DH key exchange; setup encryption contexts for channels.
|
||||
auto context = DoDhKeyExchange(channel_a.get(), channel_b.get());
|
||||
auto context = DoDhKeyExchange(channel_a, channel_b);
|
||||
ASSERT_NE(context.first, nullptr);
|
||||
ASSERT_NE(context.second, nullptr);
|
||||
|
||||
@@ -313,12 +310,11 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
|
||||
channel_b_raw->Close(DisconnectionReason::REMOTE_DISCONNECTION);
|
||||
ecm_a.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId), DisconnectionReason::LOCAL_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
ecm_b.UnregisterChannelForEndpoint(
|
||||
std::string(kEndpointId), DisconnectionReason::REMOTE_DISCONNECTION,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/implementation/analytics/throughput_recorder.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/endpoint_channel_manager.h"
|
||||
@@ -34,7 +33,6 @@
|
||||
#include "connections/implementation/service_id_constants.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "connections/payload_type.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
@@ -45,20 +43,17 @@
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
#include "internal/proto/analytics/connections_log.pb.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
|
||||
namespace {
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ::location::nearby::connections::KeepAliveFrame;
|
||||
using ::location::nearby::connections::OfflineFrame;
|
||||
using ::location::nearby::connections::PayloadTransferFrame;
|
||||
using ::location::nearby::connections::V1Frame;
|
||||
using ::location::nearby::proto::connections::DisconnectionReason;
|
||||
using ::nearby::analytics::PacketMetaData;
|
||||
using ::nearby::analytics::SafeDisconnectionResult;
|
||||
|
||||
// We set this to 11s to provide sufficient time for an in-progress WebRTC
|
||||
// bandwidth upgrade to resolve. This is chosen to be slightly longer than the
|
||||
@@ -207,7 +202,7 @@ ExceptionOr<OfflineFrame> EndpointManager::TryDecryptFrame(
|
||||
if (decrypted.ok()) {
|
||||
VLOG(1) << "Message decrypted after "
|
||||
<< SystemClock::ElapsedRealtime() - start_time;
|
||||
return parser::FromBytes(decrypted.result());
|
||||
return parser::FromBytes(decrypted.result().AsStringView());
|
||||
}
|
||||
if (decrypted.exception() == Exception::kExecution) {
|
||||
return decrypted.exception();
|
||||
@@ -235,8 +230,7 @@ ExceptionOr<bool> EndpointManager::HandleData(
|
||||
// a replacement for this endpoint since we last checked with the
|
||||
// EndpointChannelManager.
|
||||
while (true) {
|
||||
PacketMetaData packet_meta_data;
|
||||
ExceptionOr<ByteArray> bytes = endpoint_channel->Read(packet_meta_data);
|
||||
ExceptionOr<ByteArray> bytes = endpoint_channel->Read();
|
||||
if (!bytes.ok()) {
|
||||
LOG(INFO) << "Stop reading on read-time exception: " << bytes.exception();
|
||||
// Treat kNoData as kIo.
|
||||
@@ -245,7 +239,8 @@ ExceptionOr<bool> EndpointManager::HandleData(
|
||||
}
|
||||
return ExceptionOr<bool>(bytes.exception());
|
||||
}
|
||||
ExceptionOr<OfflineFrame> wrapped_frame = parser::FromBytes(bytes.result());
|
||||
ExceptionOr<OfflineFrame> wrapped_frame =
|
||||
parser::FromBytes(bytes.result().AsStringView());
|
||||
if (!wrapped_frame.ok() && try_decrypting) {
|
||||
// Workaround for a race condition where the remote party has sent an
|
||||
// encrypted message but our end was still configured as unencrypted when
|
||||
@@ -316,8 +311,7 @@ ExceptionOr<bool> EndpointManager::HandleData(
|
||||
}
|
||||
|
||||
frame_processor->OnIncomingFrame(frame, endpoint_id, client,
|
||||
endpoint_channel->GetMedium(),
|
||||
packet_meta_data);
|
||||
endpoint_channel->GetMedium());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +450,6 @@ EndpointManager::~EndpointManager() {
|
||||
MutexLock lock(&mutex_);
|
||||
is_shutdown_ = true;
|
||||
}
|
||||
analytics::ThroughputRecorderContainer::GetInstance().Shutdown();
|
||||
CountDownLatch latch(1);
|
||||
RunOnEndpointManagerThread("bring-down-endpoints", [this, &latch]() {
|
||||
LOG(INFO) << "Bringing down endpoints";
|
||||
@@ -539,103 +532,94 @@ void EndpointManager::RegisterEndpoint(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& connection_options,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
const ConnectionListener& listener, const std::string& connection_token) {
|
||||
CountDownLatch latch(1);
|
||||
|
||||
// NOTE (unique_ptr<> capture):
|
||||
// std::unique_ptr<> is not copyable, so we can not pass it to
|
||||
// lambda capture, because lambda eventually is converted to
|
||||
// std::function<>. Instead, we release() a pointer, and pass a raw pointer,
|
||||
// which is copyalbe. We ignore the risk of job not scheduled (and an
|
||||
// associated risk of memory leak), because this may only happen during
|
||||
// service shutdown.
|
||||
RunOnEndpointManagerThread(
|
||||
"register-endpoint",
|
||||
[this, client, channel = channel.release(), &endpoint_id, &info,
|
||||
&connection_options, &listener, &connection_token, &latch]() {
|
||||
if (endpoints_.contains(endpoint_id)) {
|
||||
LOG(WARNING) << "Registering duplicate endpoint " << endpoint_id;
|
||||
// We must remove old endpoint state before registering a new one
|
||||
// for the same endpoint_id.
|
||||
RemoveEndpointState(endpoint_id);
|
||||
}
|
||||
RunOnEndpointManagerThread("register-endpoint", [this, client, channel,
|
||||
&endpoint_id, &info,
|
||||
&connection_options,
|
||||
&listener, &connection_token,
|
||||
&latch]() {
|
||||
if (endpoints_.contains(endpoint_id)) {
|
||||
LOG(WARNING) << "Registering duplicate endpoint " << endpoint_id;
|
||||
// We must remove old endpoint state before registering a new one
|
||||
// for the same endpoint_id.
|
||||
RemoveEndpointState(endpoint_id);
|
||||
}
|
||||
|
||||
absl::Duration keep_alive_interval =
|
||||
absl::Milliseconds(connection_options.keep_alive_interval_millis);
|
||||
absl::Duration keep_alive_timeout =
|
||||
absl::Milliseconds(connection_options.keep_alive_timeout_millis);
|
||||
LOG(INFO) << "Registering endpoint " << endpoint_id << " for client "
|
||||
<< client->GetClientId()
|
||||
<< " with keep-alive frame as interval="
|
||||
<< absl::FormatDuration(keep_alive_interval)
|
||||
<< ", timeout=" << absl::FormatDuration(keep_alive_timeout);
|
||||
absl::Duration keep_alive_interval =
|
||||
absl::Milliseconds(connection_options.keep_alive_interval_millis);
|
||||
absl::Duration keep_alive_timeout =
|
||||
absl::Milliseconds(connection_options.keep_alive_timeout_millis);
|
||||
LOG(INFO) << "Registering endpoint " << endpoint_id << " for client "
|
||||
<< client->GetClientId() << " with keep-alive frame as interval="
|
||||
<< absl::FormatDuration(keep_alive_interval)
|
||||
<< ", timeout=" << absl::FormatDuration(keep_alive_timeout);
|
||||
|
||||
// Pass ownership of channel to EndpointChannelManager
|
||||
LOG(INFO) << "Registering endpoint with channel manager: endpoint "
|
||||
<< endpoint_id;
|
||||
channel_manager_->RegisterChannelForEndpoint(
|
||||
client, endpoint_id, std::unique_ptr<EndpointChannel>(channel));
|
||||
// Pass ownership of channel to EndpointChannelManager
|
||||
LOG(INFO) << "Registering endpoint with channel manager: endpoint "
|
||||
<< endpoint_id;
|
||||
channel_manager_->RegisterChannelForEndpoint(client, endpoint_id, channel);
|
||||
|
||||
EndpointState& endpoint_state =
|
||||
endpoints_
|
||||
.emplace(endpoint_id,
|
||||
EndpointState(endpoint_id, channel_manager_))
|
||||
.first->second;
|
||||
EndpointState& endpoint_state =
|
||||
endpoints_
|
||||
.emplace(endpoint_id, EndpointState(endpoint_id, channel_manager_))
|
||||
.first->second;
|
||||
|
||||
LOG(INFO) << "Starting workers: endpoint " << endpoint_id;
|
||||
// For every endpoint, there's normally only one Read handler instance
|
||||
// running on a dedicated thread. This instance reads data from the
|
||||
// endpoint and delegates incoming frames to various FrameProcessors.
|
||||
// Once the frame has been properly handled, it starts reading again
|
||||
// for the next frame. If the handler fails its read and no other
|
||||
// EndpointChannels are available for this endpoint, a disconnection
|
||||
// will be initiated.
|
||||
endpoint_state.StartEndpointReader([this, client, endpoint_id]() {
|
||||
LOG(INFO) << "Starting workers: endpoint " << endpoint_id;
|
||||
// For every endpoint, there's normally only one Read handler instance
|
||||
// running on a dedicated thread. This instance reads data from the
|
||||
// endpoint and delegates incoming frames to various FrameProcessors.
|
||||
// Once the frame has been properly handled, it starts reading again
|
||||
// for the next frame. If the handler fails its read and no other
|
||||
// EndpointChannels are available for this endpoint, a disconnection
|
||||
// will be initiated.
|
||||
endpoint_state.StartEndpointReader([this, client, endpoint_id]() {
|
||||
EndpointChannelLoopRunnable(
|
||||
"Read", client, endpoint_id,
|
||||
[this, client, endpoint_id](EndpointChannel* channel) {
|
||||
return HandleData(endpoint_id, client, channel);
|
||||
});
|
||||
});
|
||||
|
||||
// For every endpoint, there's only one KeepAliveManager instance
|
||||
// running on a dedicated thread. This instance will periodically send
|
||||
// out a ping* to the endpoint while listening for an incoming pong**.
|
||||
// If it fails to send the ping, or if no pong is heard within
|
||||
// keep_alive_timeout, it initiates a disconnection.
|
||||
//
|
||||
// (*) Bluetooth requires a constant outgoing stream of messages. If
|
||||
// there's silence, Android will break the socket. This is why we
|
||||
// ping.
|
||||
// (**) Wifi Hotspots can fail to notice a connection has been lost,
|
||||
// and they will happily keep writing to /dev/null. This is why we
|
||||
// listen for the pong.
|
||||
VLOG(1) << "EndpointManager enabling KeepAlive for endpoint "
|
||||
<< endpoint_id;
|
||||
endpoint_state.StartEndpointKeepAliveManager(
|
||||
[this, client, endpoint_id, keep_alive_interval, keep_alive_timeout](
|
||||
Mutex* keep_alive_waiter_mutex,
|
||||
ConditionVariable* keep_alive_waiter) {
|
||||
EndpointChannelLoopRunnable(
|
||||
"Read", client, endpoint_id,
|
||||
[this, client, endpoint_id](EndpointChannel* channel) {
|
||||
return HandleData(endpoint_id, client, channel);
|
||||
"KeepAliveManager", client, endpoint_id,
|
||||
[this, keep_alive_interval, keep_alive_timeout,
|
||||
keep_alive_waiter_mutex,
|
||||
keep_alive_waiter](EndpointChannel* channel) {
|
||||
return HandleKeepAlive(
|
||||
channel, keep_alive_interval, keep_alive_timeout,
|
||||
keep_alive_waiter_mutex, keep_alive_waiter);
|
||||
});
|
||||
});
|
||||
LOG(INFO) << "Registering endpoint " << endpoint_id
|
||||
<< ", workers started and notifying client.";
|
||||
|
||||
// For every endpoint, there's only one KeepAliveManager instance
|
||||
// running on a dedicated thread. This instance will periodically send
|
||||
// out a ping* to the endpoint while listening for an incoming pong**.
|
||||
// If it fails to send the ping, or if no pong is heard within
|
||||
// keep_alive_timeout, it initiates a disconnection.
|
||||
//
|
||||
// (*) Bluetooth requires a constant outgoing stream of messages. If
|
||||
// there's silence, Android will break the socket. This is why we
|
||||
// ping.
|
||||
// (**) Wifi Hotspots can fail to notice a connection has been lost,
|
||||
// and they will happily keep writing to /dev/null. This is why we
|
||||
// listen for the pong.
|
||||
VLOG(1) << "EndpointManager enabling KeepAlive for endpoint "
|
||||
<< endpoint_id;
|
||||
endpoint_state.StartEndpointKeepAliveManager(
|
||||
[this, client, endpoint_id, keep_alive_interval,
|
||||
keep_alive_timeout](Mutex* keep_alive_waiter_mutex,
|
||||
ConditionVariable* keep_alive_waiter) {
|
||||
EndpointChannelLoopRunnable(
|
||||
"KeepAliveManager", client, endpoint_id,
|
||||
[this, keep_alive_interval, keep_alive_timeout,
|
||||
keep_alive_waiter_mutex,
|
||||
keep_alive_waiter](EndpointChannel* channel) {
|
||||
return HandleKeepAlive(
|
||||
channel, keep_alive_interval, keep_alive_timeout,
|
||||
keep_alive_waiter_mutex, keep_alive_waiter);
|
||||
});
|
||||
});
|
||||
LOG(INFO) << "Registering endpoint " << endpoint_id
|
||||
<< ", workers started and notifying client.";
|
||||
|
||||
// It's now time to let the client know of this new connection so that
|
||||
// they can accept or reject it.
|
||||
client->OnConnectionInitiated(endpoint_id, info, connection_options,
|
||||
listener, connection_token);
|
||||
latch.CountDown();
|
||||
});
|
||||
// It's now time to let the client know of this new connection so that
|
||||
// they can accept or reject it.
|
||||
client->OnConnectionInitiated(endpoint_id, info, connection_options,
|
||||
listener, connection_token);
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
}
|
||||
|
||||
@@ -666,17 +650,15 @@ int EndpointManager::GetMaxTransmitPacketSize(const std::string& endpoint_id) {
|
||||
std::vector<std::string> EndpointManager::SendPayloadChunk(
|
||||
const PayloadTransferFrame::PayloadHeader& payload_header,
|
||||
const PayloadTransferFrame::PayloadChunk& payload_chunk,
|
||||
const std::vector<std::string>& endpoint_ids,
|
||||
PacketMetaData& packet_meta_data) {
|
||||
ByteArray bytes =
|
||||
const std::vector<std::string>& endpoint_ids) {
|
||||
std::string bytes =
|
||||
parser::ForDataPayloadTransfer(payload_header, payload_chunk);
|
||||
|
||||
return SendTransferFrameBytes(
|
||||
endpoint_ids, bytes, payload_header.id(),
|
||||
/*offset=*/payload_chunk.offset(),
|
||||
/*packet_type=*/
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::DATA),
|
||||
packet_meta_data);
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::DATA));
|
||||
}
|
||||
|
||||
// Designed to run asynchronously. It is called from IO thread pools, and
|
||||
@@ -722,7 +704,7 @@ void EndpointManager::DiscardEndpoint(ClientProxy* client,
|
||||
// of `serial_executor_` and will still have access to a valid
|
||||
// `is_shutdown_`.
|
||||
//
|
||||
// TODO(b/280653613): Develop a more robost solution to prevent
|
||||
// TODO(b/280653613): Develop a more robust solution to prevent
|
||||
// accessing an already destroyed `ClientProxy` during destruction.
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -743,15 +725,13 @@ std::vector<std::string> EndpointManager::SendControlMessage(
|
||||
const PayloadTransferFrame::PayloadHeader& header,
|
||||
const PayloadTransferFrame::ControlMessage& control,
|
||||
const std::vector<std::string>& endpoint_ids) {
|
||||
ByteArray bytes = parser::ForControlPayloadTransfer(header, control);
|
||||
PacketMetaData packet_meta_data;
|
||||
std::string bytes = parser::ForControlPayloadTransfer(header, control);
|
||||
|
||||
return SendTransferFrameBytes(
|
||||
endpoint_ids, bytes, header.id(),
|
||||
/*offset=*/control.offset(),
|
||||
/*packet_type=*/
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::CONTROL),
|
||||
packet_meta_data);
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::CONTROL));
|
||||
}
|
||||
|
||||
// @EndpointManagerThread
|
||||
@@ -762,7 +742,7 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client,
|
||||
<< ", reason: " << reason;
|
||||
|
||||
SafeDisconnectionResult safe_disconnect_result =
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION;
|
||||
SafeDisconnectionResult::kSafeDisconnection;
|
||||
|
||||
// Grab the service ID before we destroy the channel.
|
||||
EndpointChannel* channel =
|
||||
@@ -775,11 +755,13 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client,
|
||||
bool is_safe_disconnection =
|
||||
ApplySafeToDisconnect(endpoint_id, channel, reason);
|
||||
safe_disconnect_result =
|
||||
is_safe_disconnection
|
||||
? ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION
|
||||
: ConnectionsLog::EstablishedConnection::UNSAFE_DISCONNECTION;
|
||||
is_safe_disconnection ? SafeDisconnectionResult::kSafeDisconnection
|
||||
: SafeDisconnectionResult::kUnsafeDisconnection;
|
||||
LOG(INFO) << "[safe-to-disconnect] safe_disconnect_result:"
|
||||
<< (safe_disconnect_result ? "true" : "false");
|
||||
<< (safe_disconnect_result ==
|
||||
SafeDisconnectionResult::kSafeDisconnection
|
||||
? "true"
|
||||
: "false");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -920,21 +902,19 @@ CountDownLatch EndpointManager::NotifyFrameProcessorsOnEndpointDisconnect(
|
||||
|
||||
std::vector<std::string> EndpointManager::SendPayloadAck(
|
||||
std::int64_t payload_id, const std::vector<std::string>& endpoint_ids) {
|
||||
ByteArray bytes = parser::ForPayloadAckPayloadTransfer(payload_id);
|
||||
PacketMetaData packet_meta_data;
|
||||
std::string bytes = parser::ForPayloadAckPayloadTransfer(payload_id);
|
||||
|
||||
return SendTransferFrameBytes(
|
||||
endpoint_ids, bytes, payload_id,
|
||||
/* offset= */ -1,
|
||||
/*packet_type=*/
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::PAYLOAD_ACK),
|
||||
packet_meta_data);
|
||||
PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::PAYLOAD_ACK));
|
||||
}
|
||||
|
||||
std::vector<std::string> EndpointManager::SendTransferFrameBytes(
|
||||
const std::vector<std::string>& endpoint_ids, const ByteArray& bytes,
|
||||
const std::vector<std::string>& endpoint_ids, const std::string& bytes,
|
||||
std::int64_t payload_id, std::int64_t offset,
|
||||
const std::string& packet_type, PacketMetaData& packet_meta_data) {
|
||||
const std::string& packet_type) {
|
||||
std::vector<std::string> failed_endpoint_ids;
|
||||
for (const std::string& endpoint_id : endpoint_ids) {
|
||||
std::shared_ptr<EndpointChannel> channel =
|
||||
@@ -953,16 +933,12 @@ std::vector<std::string> EndpointManager::SendTransferFrameBytes(
|
||||
continue;
|
||||
}
|
||||
|
||||
Exception write_exception =
|
||||
channel->Write(bytes.AsStringView(), packet_meta_data);
|
||||
Exception write_exception = channel->Write(bytes);
|
||||
if (!write_exception.Ok()) {
|
||||
failed_endpoint_ids.push_back(endpoint_id);
|
||||
LOG(INFO) << "Failed to send packet; endpoint_id=" << endpoint_id;
|
||||
continue;
|
||||
}
|
||||
analytics::ThroughputRecorderContainer::GetInstance()
|
||||
.GetTPRecorder(payload_id, PayloadDirection::OUTGOING_PAYLOAD)
|
||||
->OnFrameSent(channel->GetMedium(), packet_meta_data);
|
||||
}
|
||||
|
||||
return failed_endpoint_ids;
|
||||
@@ -978,7 +954,7 @@ EndpointManager::EndpointState::~EndpointState() {
|
||||
VLOG(1) << "EndpointState destructor " << endpoint_id_;
|
||||
channel_manager_->UnregisterChannelForEndpoint(
|
||||
endpoint_id_, DisconnectionReason::SHUTDOWN,
|
||||
ConnectionsLog::EstablishedConnection::SAFE_DISCONNECTION);
|
||||
SafeDisconnectionResult::kSafeDisconnection);
|
||||
}
|
||||
|
||||
// Make sure the KeepAlive thread isn't blocking shutdown.
|
||||
@@ -1007,5 +983,4 @@ void EndpointManager::RunOnEndpointManagerThread(const std::string& name,
|
||||
serial_executor_->Execute(name, std::move(runnable));
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define CORE_INTERNAL_ENDPOINT_MANAGER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -24,10 +23,9 @@
|
||||
|
||||
#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/time/time.h"
|
||||
#include "connections/implementation/analytics/packet_meta_data.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/endpoint_channel_manager.h"
|
||||
@@ -36,6 +34,8 @@
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/condition_variable.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
@@ -79,8 +79,7 @@ class EndpointManager {
|
||||
virtual void OnIncomingFrame(
|
||||
location::nearby::connections::OfflineFrame& offline_frame,
|
||||
const std::string& from_endpoint_id, ClientProxy* to_client,
|
||||
location::nearby::proto::connections::Medium current_medium,
|
||||
analytics::PacketMetaData& packet_meta_data) = 0;
|
||||
location::nearby::proto::connections::Medium current_medium) = 0;
|
||||
|
||||
// Implementations must call barrier.CountDown() once
|
||||
// they're done. This parallelizes the disconnection event across all frame
|
||||
@@ -114,7 +113,7 @@ class EndpointManager {
|
||||
void RegisterEndpoint(ClientProxy* client, const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& connection_options,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
std::shared_ptr<EndpointChannel> channel,
|
||||
const ConnectionListener& listener,
|
||||
const std::string& connection_token);
|
||||
// Called when a client explicitly asks to disconnect from this endpoint. In
|
||||
@@ -133,8 +132,7 @@ class EndpointManager {
|
||||
payload_header,
|
||||
const location::nearby::connections::PayloadTransferFrame::PayloadChunk&
|
||||
payload_chunk,
|
||||
const std::vector<std::string>& endpoint_ids,
|
||||
analytics::PacketMetaData& packet_meta_data);
|
||||
const std::vector<std::string>& endpoint_ids);
|
||||
std::vector<std::string> SendControlMessage(
|
||||
const location::nearby::connections::PayloadTransferFrame::PayloadHeader&
|
||||
payload_header,
|
||||
@@ -283,9 +281,8 @@ class EndpointManager {
|
||||
|
||||
std::vector<std::string> SendTransferFrameBytes(
|
||||
const std::vector<std::string>& endpoint_ids,
|
||||
const ByteArray& payload_transfer_frame_bytes, std::int64_t payload_id,
|
||||
std::int64_t offset, const std::string& packet_type,
|
||||
analytics::PacketMetaData& packet_meta_data);
|
||||
const std::string& payload_transfer_frame_bytes, std::int64_t payload_id,
|
||||
std::int64_t offset, const std::string& packet_type);
|
||||
|
||||
// Executes all jobs sequentially, on a serial_executor_.
|
||||
void RunOnEndpointManagerThread(const std::string& name, Runnable runnable);
|
||||
|
||||
@@ -29,11 +29,10 @@
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/connection_options.h"
|
||||
#include "connections/implementation/analytics/analytics_recorder.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/endpoint_channel_manager.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/implementation/mock_endpoint_channel.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/status.h"
|
||||
@@ -63,68 +62,12 @@ using ::testing::MockFunction;
|
||||
using ::testing::Return;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
class MockEndpointChannel : public EndpointChannel {
|
||||
public:
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override));
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, Read, (PacketMetaData & packet_meta_data),
|
||||
(override));
|
||||
MOCK_METHOD(Exception, Write, (const ByteArray& data), (override));
|
||||
MOCK_METHOD(Exception, Write,
|
||||
(absl::string_view data, PacketMetaData& packet_meta_data),
|
||||
(override));
|
||||
MOCK_METHOD(void, Close, (), (override));
|
||||
MOCK_METHOD(void, Close, (DisconnectionReason reason), (override));
|
||||
MOCK_METHOD(void, Close,
|
||||
(DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result),
|
||||
(override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::ConnectionTechnology,
|
||||
GetTechnology, (), (const, override));
|
||||
MOCK_METHOD(location::nearby::proto::connections::ConnectionBand, GetBand, (),
|
||||
(const, override));
|
||||
MOCK_METHOD(int, GetFrequency, (), (const, override));
|
||||
MOCK_METHOD(int, GetTryCount, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetType, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetServiceId, (), (const, override));
|
||||
MOCK_METHOD(std::string, GetName, (), (const, override));
|
||||
MOCK_METHOD(Medium, GetMedium, (), (const, override));
|
||||
MOCK_METHOD(int, GetMaxTransmitPacketSize, (), (const, override));
|
||||
MOCK_METHOD(void, EnableEncryption,
|
||||
(std::shared_ptr<EncryptionContext> context), (override));
|
||||
MOCK_METHOD(void, DisableEncryption, (), (override));
|
||||
MOCK_METHOD(bool, IsPaused, (), (const, override));
|
||||
MOCK_METHOD(bool, IsEncrypted, (), (override));
|
||||
MOCK_METHOD(ExceptionOr<ByteArray>, TryDecrypt, (const ByteArray& data),
|
||||
(override));
|
||||
MOCK_METHOD(void, Pause, (), (override));
|
||||
MOCK_METHOD(void, Resume, (), (override));
|
||||
MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const, override));
|
||||
MOCK_METHOD(absl::Time, GetLastWriteTimestamp, (), (const, override));
|
||||
MOCK_METHOD(uint32_t, GetNextKeepAliveSeqNo, (), (const, override));
|
||||
MOCK_METHOD(void, SetAnalyticsRecorder,
|
||||
(analytics::AnalyticsRecorder*, const std::string&), (override));
|
||||
|
||||
bool IsClosed() const override {
|
||||
absl::MutexLock lock(mutex_);
|
||||
return closed_;
|
||||
}
|
||||
void DoClose() {
|
||||
absl::MutexLock lock(mutex_);
|
||||
closed_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable absl::Mutex mutex_;
|
||||
bool closed_ = false;
|
||||
};
|
||||
|
||||
class MockFrameProcessor : public EndpointManager::FrameProcessor {
|
||||
public:
|
||||
MOCK_METHOD(void, OnIncomingFrame,
|
||||
(OfflineFrame & offline_frame,
|
||||
const std::string& from_endpoint_id, ClientProxy* to_client,
|
||||
Medium current_medium, PacketMetaData& packet_meta_data),
|
||||
Medium current_medium),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(void, OnEndpointDisconnect,
|
||||
@@ -277,11 +220,12 @@ TEST_F(EndpointManagerTest, RegisterFrameProcessorWorks) {
|
||||
0 /*keep_alive_interval_millis*/,
|
||||
0 /*keep_alive_timeout_millis*/};
|
||||
|
||||
auto read_data = parser::ForConnectionRequestConnections({}, connection_info);
|
||||
std::string read_data =
|
||||
parser::ForConnectionRequestConnections({}, connection_info);
|
||||
EXPECT_CALL(*connect_request, OnIncomingFrame);
|
||||
EXPECT_CALL(*connect_request, OnEndpointDisconnect);
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(read_data)))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(ByteArray(read_data))))
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo)));
|
||||
EXPECT_CALL(*endpoint_channel, Write(_))
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
@@ -318,6 +262,8 @@ TEST_F(EndpointManagerTest, UnregisterFrameProcessorWorks) {
|
||||
|
||||
TEST_F(EndpointManagerTest, SendControlMessageAndPayloadAckWorks) {
|
||||
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
|
||||
absl::Mutex close_mutex;
|
||||
bool closed = false;
|
||||
PayloadTransferFrame::PayloadHeader header;
|
||||
PayloadTransferFrame::ControlMessage control;
|
||||
header.set_id(12345);
|
||||
@@ -326,22 +272,24 @@ TEST_F(EndpointManagerTest, SendControlMessageAndPayloadAckWorks) {
|
||||
control.set_offset(150);
|
||||
control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED);
|
||||
|
||||
ON_CALL(*endpoint_channel, Read(_))
|
||||
.WillByDefault([channel = endpoint_channel.get()]() {
|
||||
if (channel->IsClosed()) return ExceptionOr<ByteArray>(Exception::kIo);
|
||||
ON_CALL(*endpoint_channel, Read())
|
||||
.WillByDefault([&, channel = endpoint_channel.get()]() {
|
||||
absl::MutexLock lock(close_mutex);
|
||||
if (closed) return ExceptionOr<ByteArray>(Exception::kIo);
|
||||
LOG(INFO) << "Simulate read delay: wait";
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
LOG(INFO) << "Simulate read delay: done";
|
||||
if (channel->IsClosed()) return ExceptionOr<ByteArray>(Exception::kIo);
|
||||
if (closed) return ExceptionOr<ByteArray>(Exception::kIo);
|
||||
return ExceptionOr<ByteArray>(ByteArray{});
|
||||
});
|
||||
ON_CALL(*endpoint_channel, Close(_))
|
||||
.WillByDefault(
|
||||
[channel = endpoint_channel.get()](DisconnectionReason reason) {
|
||||
channel->DoClose();
|
||||
[&, channel = endpoint_channel.get()](DisconnectionReason reason) {
|
||||
absl::MutexLock lock(close_mutex);
|
||||
closed = true;
|
||||
LOG(INFO) << "Channel closed";
|
||||
});
|
||||
EXPECT_CALL(*endpoint_channel, Write(_, _))
|
||||
EXPECT_CALL(*endpoint_channel, Write(_))
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
|
||||
RegisterEndpoint(std::move(endpoint_channel), false);
|
||||
@@ -358,7 +306,7 @@ TEST_F(EndpointManagerTest, SendControlMessageAndPayloadAckWorks) {
|
||||
|
||||
TEST_F(EndpointManagerTest, SingleReadOnReadError) {
|
||||
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(
|
||||
Return(ExceptionOr<ByteArray>(Exception::kInvalidProtocolBuffer)));
|
||||
EXPECT_CALL(*endpoint_channel, Write(_))
|
||||
@@ -376,7 +324,7 @@ TEST_F(EndpointManagerTest, ReadInvalidUnencryptedPayloadIgnoresFrame) {
|
||||
CountDownLatch latch(1);
|
||||
const ByteArray payload("not a valid frame");
|
||||
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(payload)))
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo)));
|
||||
EXPECT_CALL(*endpoint_channel, TryDecrypt(Eq(payload)))
|
||||
@@ -400,7 +348,7 @@ class EndpointManagerFuzzTest
|
||||
// too.
|
||||
// 4. Invalid frame is ignored. No bad side effects.
|
||||
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(payload)))
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo)));
|
||||
EXPECT_CALL(*endpoint_channel, TryDecrypt(Eq(payload)))
|
||||
@@ -416,7 +364,7 @@ class EndpointManagerFuzzTest
|
||||
// 2. EndpointManager receives an invalid encrypted frame.
|
||||
// 3. No calls to TryDecrypt.
|
||||
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(payload)))
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo)));
|
||||
EXPECT_CALL(*endpoint_channel, IsEncrypted()).WillRepeatedly(Return(true));
|
||||
@@ -429,7 +377,9 @@ class EndpointManagerFuzzTest
|
||||
|
||||
auto InvalidPayloadDomain() {
|
||||
return Filter(
|
||||
[](ByteArray payload) { return !parser::FromBytes(payload).ok(); },
|
||||
[](ByteArray payload) {
|
||||
return !parser::FromBytes(payload.AsStringView()).ok();
|
||||
},
|
||||
Map([](std::string payloadString) { return ByteArray(payloadString); },
|
||||
String()));
|
||||
}
|
||||
@@ -461,16 +411,16 @@ TEST_F(EndpointManagerTest, TryDecrypt) {
|
||||
std::vector<Medium>{Medium::BLE} /*supported_mediums*/,
|
||||
0 /*keep_alive_interval_millis*/,
|
||||
0 /*keep_alive_timeout_millis*/};
|
||||
ByteArray decrypted_data =
|
||||
std::string decrypted_data =
|
||||
parser::ForConnectionRequestConnections({}, connection_info);
|
||||
EXPECT_CALL(*connect_request, OnIncomingFrame);
|
||||
EXPECT_CALL(*connect_request, OnEndpointDisconnect);
|
||||
EXPECT_CALL(*endpoint_channel, Read(_))
|
||||
EXPECT_CALL(*endpoint_channel, Read())
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(payload)))
|
||||
.WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo)));
|
||||
EXPECT_CALL(*endpoint_channel, TryDecrypt(Eq(payload)))
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(Exception::kFailed)))
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(decrypted_data)));
|
||||
.WillOnce(Return(ExceptionOr<ByteArray>(ByteArray(decrypted_data))));
|
||||
EXPECT_CALL(*endpoint_channel, Write(_))
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
em_.RegisterFrameProcessor(V1Frame::CONNECTION_REQUEST,
|
||||
|
||||
@@ -87,9 +87,9 @@ class FakeBwuHandler : public BaseBwuHandler {
|
||||
medium_, *handle_initialize_calls_[initialize_call_index].service_id);
|
||||
FakeEndpointChannel* upgraded_channel_raw = upgraded_channel.get();
|
||||
upgraded_channel->set_read_output(
|
||||
ExceptionOr<ByteArray>(parser::ForBwuIntroduction(
|
||||
ExceptionOr<ByteArray>(ByteArray(parser::ForBwuIntroduction(
|
||||
*handle_initialize_calls_[initialize_call_index].endpoint_id,
|
||||
false /* supports_disabling_encryption */)));
|
||||
false /* supports_disabling_encryption */))));
|
||||
auto connection = std::make_unique<IncomingSocketConnection>();
|
||||
connection->channel = std::move(upgraded_channel);
|
||||
|
||||
@@ -133,7 +133,7 @@ class FakeBwuHandler : public BaseBwuHandler {
|
||||
}
|
||||
|
||||
// BaseBwuHandler:
|
||||
ByteArray HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) final {
|
||||
handle_initialize_calls_.push_back({.client = client,
|
||||
@@ -178,7 +178,7 @@ class FakeBwuHandler : public BaseBwuHandler {
|
||||
return parser::ForBwuWifiDirectPathAvailable(
|
||||
/*ssid=*/"", /*password=*/"", /*port=*/2143,
|
||||
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
|
||||
/*gateway=*/"123.234.23.1", /*service_name=*/"NC-WifiDirectTest",
|
||||
/*gateway=*/"123.234.23.1", /*device_name=*/"NC-WifiDirectTest",
|
||||
/*pin=*/"b592f7d3");
|
||||
case location::nearby::proto::connections::UNKNOWN_MEDIUM:
|
||||
case location::nearby::proto::connections::MDNS:
|
||||
@@ -188,7 +188,7 @@ class FakeBwuHandler : public BaseBwuHandler {
|
||||
case location::nearby::proto::connections::BLE_L2CAP:
|
||||
case location::nearby::proto::connections::USB:
|
||||
case location::nearby::proto::connections::AWDL:
|
||||
return ByteArray{};
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/system_clock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace nearby::connections {
|
||||
|
||||
// An endpoint channel implementation used for testing. The read and write
|
||||
// output can be set.
|
||||
@@ -46,16 +45,7 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
read_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return read_output_;
|
||||
}
|
||||
ExceptionOr<ByteArray> Read(PacketMetaData& packet_meta_data) override {
|
||||
read_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return read_output_;
|
||||
}
|
||||
Exception Write(const ByteArray& data) override {
|
||||
write_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return write_output_;
|
||||
}
|
||||
Exception Write(absl::string_view data,
|
||||
PacketMetaData& packet_meta_data) override {
|
||||
Exception Write(absl::string_view data) override {
|
||||
write_timestamp_ = SystemClock::ElapsedRealtime();
|
||||
return write_output_;
|
||||
}
|
||||
@@ -65,10 +55,8 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
is_closed_ = true;
|
||||
disconnection_reason_ = reason;
|
||||
}
|
||||
void Close(
|
||||
location::nearby::proto::connections::DisconnectionReason reason,
|
||||
location::nearby::analytics::proto::ConnectionsLog::
|
||||
EstablishedConnection::SafeDisconnectionResult result) override {
|
||||
void Close(location::nearby::proto::connections::DisconnectionReason reason,
|
||||
nearby::analytics::SafeDisconnectionResult result) override {
|
||||
Close(reason);
|
||||
}
|
||||
bool IsClosed() const override { return is_closed_; }
|
||||
@@ -128,7 +116,6 @@ class FakeEndpointChannel : public EndpointChannel {
|
||||
mutable uint32_t next_keep_alive_seq_no_ = 0;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace nearby::connections
|
||||
|
||||
#endif // NEARBY_CONNECTIONS_IMPLEMENTATION_FAKE_ENDPOINT_CHANNEL_H_
|
||||
|
||||
Regular → Executable
+10
-23
@@ -31,9 +31,6 @@ namespace nearby_connections_feature {
|
||||
// The timeout in millis to report peripheral device lost.
|
||||
constexpr auto kBlePeripheralLostTimeoutMillis =
|
||||
flags::Flag<int64_t>(kConfigPackage, "45411439", 12000);
|
||||
// Disable instant on lost on BLE without extended feature.
|
||||
constexpr auto kDisableInstantOnLostOnBleWithoutExtended =
|
||||
flags::Flag<bool>(kConfigPackage, "45687098", true);
|
||||
// When true, enable advertising for instant on lost feature.
|
||||
constexpr auto kEnableAdvertisingForInstantOnLost =
|
||||
flags::Flag<bool>(kConfigPackage, "45708614", true);
|
||||
@@ -55,34 +52,25 @@ constexpr auto kEnableDynamicRoleSwitch =
|
||||
// Enable/Disable GATT client disconnection.
|
||||
constexpr auto kEnableGattClientDisconnection =
|
||||
flags::Flag<bool>(kConfigPackage, "45698964", false);
|
||||
// When true, enable instant on lost feature.
|
||||
// When true, enable multiplexing in NC.
|
||||
constexpr auto kEnableMultiplex =
|
||||
flags::Flag<bool>(kConfigPackage, "45647946", false);
|
||||
// Enable/disable multiplex in NC for AWDL.
|
||||
constexpr auto kEnableMultiplexAwdl =
|
||||
flags::Flag<bool>(kConfigPackage, "45690761", false);
|
||||
// When true, enable multiplexing in NC for Bluetooth.
|
||||
constexpr auto kEnableMultiplexBluetooth =
|
||||
flags::Flag<bool>(kConfigPackage, "45676646", false);
|
||||
// When true, enable multiplexing in NC for Wifi.
|
||||
constexpr auto kEnableMultiplexWifiLan =
|
||||
flags::Flag<bool>(kConfigPackage, "45676647", false);
|
||||
// Enable/Disable preferences for Nearby Connections.
|
||||
constexpr auto kEnableNearbyConnectionsPreferences =
|
||||
flags::Flag<bool>(kConfigPackage, "45732423", false);
|
||||
// Enable/Disable payload manager to skip chunk update.
|
||||
constexpr auto kEnablePayloadManagerToSkipChunkUpdate =
|
||||
flags::Flag<bool>(kConfigPackage, "45415729", true);
|
||||
// Enable/Disable payload-received-ack feature.
|
||||
constexpr auto kEnablePayloadReceivedAck =
|
||||
flags::Flag<bool>(kConfigPackage, "45425840", false);
|
||||
// Enable/Disable safe-to-disconnect feature.
|
||||
constexpr auto kEnableSafeToDisconnect =
|
||||
flags::Flag<bool>(kConfigPackage, "45425789", false);
|
||||
// When true, enable scanning for instant on lost feature.
|
||||
constexpr auto kEnableScanningForInstantOnLost =
|
||||
flags::Flag<bool>(kConfigPackage, "45708613", true);
|
||||
// Enable/Disable usage of shared CBPeripheralManager for GATT and L2CAP
|
||||
// servers.
|
||||
constexpr auto kEnableSharedPeripheralManager =
|
||||
flags::Flag<bool>(kConfigPackage, "45770787", false);
|
||||
// Enable/Disable single copy read/write for input/output buffers.
|
||||
constexpr auto kEnableSingleCopy =
|
||||
flags::Flag<bool>(kConfigPackage, "45782646", true);
|
||||
// Stop BLE_V2 scanning when upgrading to WIFI Hotspot or WFD.
|
||||
constexpr auto kEnableStopBleScanningOnWifiUpgrade =
|
||||
flags::Flag<bool>(kConfigPackage, "45687902", false);
|
||||
@@ -92,6 +80,9 @@ constexpr auto kEnableWifiDirect =
|
||||
// by default, enable Wi-Fi Hotspot client.
|
||||
constexpr auto kEnableWifiHotspotClient =
|
||||
flags::Flag<bool>(kConfigPackage, "45648734", true);
|
||||
// When true, fix the BleServerSocket deadlock/use-after-free (b/494335036).
|
||||
constexpr auto kFixBleServerSocketDeadlock =
|
||||
flags::Flag<bool>(kConfigPackage, "45782647", true);
|
||||
// Default max transmit packet size for medium.
|
||||
constexpr auto kMediumDefaultMaxTransmitPacketSize =
|
||||
flags::Flag<int64_t>(kConfigPackage, "45669529", 65536);
|
||||
@@ -101,10 +92,6 @@ constexpr auto kMediumMaxAllowedReadBytes =
|
||||
// Disable/Enable refactor of BLE/L2CAP in Nearby Connections SDK.
|
||||
constexpr auto kRefactorBleL2cap =
|
||||
flags::Flag<bool>(kConfigPackage, "45737079", false);
|
||||
// Enable/Disable usage of shared CBPeripheralManager for GATT and L2CAP
|
||||
// servers.
|
||||
constexpr auto kEnableSharedPeripheralManager =
|
||||
flags::Flag<bool>(kConfigPackage, "45770787", false);
|
||||
// Set the safe-to-disconnect version.
|
||||
// 0. Disabled all. 1. safe-to-disconnect 2. reserved 3.
|
||||
// auto-reconnect(deprecated)
|
||||
|
||||
@@ -24,11 +24,10 @@ cc_test(
|
||||
],
|
||||
tags = ["componentid:148515"],
|
||||
deps = [
|
||||
"//connections/implementation:internal",
|
||||
"//internal/platform:base",
|
||||
"//connections/implementation:offline_frames",
|
||||
"//internal/platform/implementation/g3",
|
||||
"//testing/fuzzing:fuzztest",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -12,13 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
nearby::ByteArray byte_array;
|
||||
byte_array.SetData(reinterpret_cast<const char*>(data), size);
|
||||
|
||||
absl::string_view byte_array(reinterpret_cast<const char*>(data), size);
|
||||
nearby::connections::parser::FromBytes(byte_array);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -21,46 +21,75 @@ cc_library(
|
||||
name = "mediums",
|
||||
srcs = [
|
||||
"awdl.cc",
|
||||
"awdl_bwu_handler.cc",
|
||||
"awdl_endpoint_channel.cc",
|
||||
"ble.cc",
|
||||
"ble_endpoint_channel.cc",
|
||||
"ble_l2cap_endpoint_channel.cc",
|
||||
"bluetooth_bwu_handler.cc",
|
||||
"bluetooth_classic.cc",
|
||||
"bluetooth_endpoint_channel.cc",
|
||||
"bluetooth_radio.cc",
|
||||
"mediums.cc",
|
||||
"webrtc.cc",
|
||||
"webrtc_stub.cc",
|
||||
"wifi_direct.cc",
|
||||
"wifi_direct_bwu_handler.cc",
|
||||
"wifi_direct_endpoint_channel.cc",
|
||||
"wifi_hotspot.cc",
|
||||
"wifi_hotspot_bwu_handler.cc",
|
||||
"wifi_hotspot_endpoint_channel.cc",
|
||||
"wifi_lan.cc",
|
||||
"wifi_lan_bwu_handler.cc",
|
||||
"wifi_lan_endpoint_channel.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"awdl.h",
|
||||
"awdl_bwu_handler.h",
|
||||
"awdl_endpoint_channel.h",
|
||||
"ble.h",
|
||||
"ble_endpoint_channel.h",
|
||||
"ble_l2cap_endpoint_channel.h",
|
||||
"bluetooth_bwu_handler.h",
|
||||
"bluetooth_classic.h",
|
||||
"bluetooth_endpoint_channel.h",
|
||||
"bluetooth_radio.h",
|
||||
"mediums.h",
|
||||
"webrtc.h",
|
||||
"webrtc_stub.h",
|
||||
"wifi.h",
|
||||
"wifi_direct.h",
|
||||
"wifi_direct_bwu_handler.h",
|
||||
"wifi_direct_endpoint_channel.h",
|
||||
"wifi_hotspot.h",
|
||||
"wifi_hotspot_bwu_handler.h",
|
||||
"wifi_hotspot_endpoint_channel.h",
|
||||
"wifi_lan.h",
|
||||
"wifi_lan_bwu_handler.h",
|
||||
"wifi_lan_endpoint_channel.h",
|
||||
],
|
||||
copts = ["-DNO_WEBRTC"],
|
||||
local_defines = select({
|
||||
"//:webrtc_enabled": [],
|
||||
"//conditions:default": ["NO_WEBRTC"],
|
||||
}),
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":utils",
|
||||
":webrtc_utils",
|
||||
":webrtc",
|
||||
":webrtc_peer_id",
|
||||
":webrtc_socket",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation:bwu_handler",
|
||||
"//connections/implementation:client_proxy",
|
||||
"//connections/implementation:endpoint_channel",
|
||||
"//connections/implementation:offline_frames",
|
||||
"//connections/implementation:service_id_constants",
|
||||
"//connections/implementation:types",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//connections/implementation/mediums/ble",
|
||||
"//connections/implementation/mediums/ble:ble_advertisement_header",
|
||||
"//connections/implementation/mediums/ble:ble_socket",
|
||||
"//connections/implementation/mediums/ble:bloom_filter",
|
||||
"//connections/implementation/mediums/multiplex",
|
||||
"//connections/implementation/mediums/webrtc",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//internal/base:masker",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
@@ -73,10 +102,8 @@ cc_library(
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation:wifi_utils",
|
||||
"//proto/mediums:web_rtc_signaling_frames_cc_proto",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:create_peerconnection_factory", # buildcleaner: keep
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:jsep",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/base:nullability",
|
||||
"@com_google_absl//absl/container:btree",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
@@ -87,21 +114,18 @@ cc_library(
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
],
|
||||
] + select({
|
||||
"//:webrtc_enabled": [
|
||||
"//connections/implementation/mediums/webrtc:webrtc_impl",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "webrtc_utils",
|
||||
srcs = [
|
||||
"webrtc_peer_id.cc",
|
||||
"webrtc_peer_id_stub.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"webrtc_peer_id.h",
|
||||
"webrtc_peer_id_stub.h",
|
||||
"webrtc_socket.h",
|
||||
"webrtc_socket_stub.h",
|
||||
],
|
||||
name = "webrtc_peer_id",
|
||||
srcs = ["webrtc_peer_id.cc"],
|
||||
hdrs = ["webrtc_peer_id.h"],
|
||||
visibility = [
|
||||
"//connections/implementation:__pkg__",
|
||||
"//connections/implementation/mediums:__pkg__",
|
||||
@@ -109,7 +133,6 @@ cc_library(
|
||||
],
|
||||
deps = [
|
||||
":utils",
|
||||
"//connections/implementation/mediums/webrtc:data_types",
|
||||
"//internal/platform:base",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
@@ -131,12 +154,10 @@ cc_library(
|
||||
name = "utils",
|
||||
srcs = ["utils.cc"],
|
||||
hdrs = ["utils.h"],
|
||||
copts = ["-DNO_WEBRTC"],
|
||||
visibility = [
|
||||
"//connections/implementation:__pkg__",
|
||||
"//connections/implementation/mediums/advertisements:__pkg__",
|
||||
"//connections/implementation/mediums/ble:__subpackages__",
|
||||
"//connections/implementation/mediums/multiplex:__pkg__",
|
||||
"//internal/platform/implementation/windows:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
@@ -145,6 +166,31 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "webrtc_socket",
|
||||
hdrs = ["webrtc_socket.h"],
|
||||
visibility = ["//connections/implementation:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "webrtc",
|
||||
hdrs = ["webrtc.h"],
|
||||
visibility = ["//connections/implementation:__subpackages__"],
|
||||
deps = [
|
||||
":webrtc_peer_id",
|
||||
":webrtc_socket",
|
||||
"//connections/implementation:bwu_handler",
|
||||
"//connections/implementation/proto:offline_wire_formats_cc_proto",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "core_internal_mediums_test",
|
||||
size = "small",
|
||||
@@ -180,19 +226,53 @@ cc_test(
|
||||
"//internal/platform/implementation:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "bwu_handler_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"awdl_bwu_handler_test.cc",
|
||||
"bluetooth_bwu_handler_test.cc",
|
||||
"wifi_direct_bwu_handler_test.cc",
|
||||
"wifi_hotspot_bwu_handler_test.cc",
|
||||
"wifi_lan_bwu_handler_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":mediums",
|
||||
"//connections/implementation:bwu_handler",
|
||||
"//connections/implementation:client_proxy",
|
||||
"//connections/implementation:endpoint_channel",
|
||||
"//connections/implementation:offline_frames",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:mock_platform",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/flags:platform_flags",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:platform",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "core_internal_mediums_webrtc_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"webrtc_peer_id_test.cc",
|
||||
"webrtc_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
tags = [
|
||||
@@ -200,8 +280,8 @@ cc_test(
|
||||
"requires-net:external",
|
||||
],
|
||||
deps = [
|
||||
":mediums",
|
||||
":webrtc_utils",
|
||||
":webrtc_peer_id",
|
||||
":webrtc_socket",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:cancellation_flag",
|
||||
"//internal/platform:comm",
|
||||
|
||||
@@ -23,28 +23,23 @@
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/mediums/awdl_bwu_handler.h"
|
||||
#include "connections/implementation/mediums/utils.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/implementation/psk_info.h"
|
||||
#include "internal/platform/implementation/wifi_utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/nsd_service_info.h"
|
||||
#include "internal/platform/socket.h"
|
||||
#include "internal/platform/types.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace {
|
||||
|
||||
using MultiplexSocket = mediums::multiplex::MultiplexSocket;
|
||||
using location::nearby::proto::connections::OperationResultCode;
|
||||
constexpr absl::string_view kAwdlServiceIdSuffixForServiceType = "_AWDL";
|
||||
|
||||
@@ -479,5 +474,11 @@ ErrorOr<AwdlSocket> Awdl::InternalConnect(
|
||||
return socket;
|
||||
}
|
||||
|
||||
std::unique_ptr<BwuHandler> Awdl::CreateBwuHandler(
|
||||
BwuHandler::IncomingConnectionCallback incoming_connection_callback) {
|
||||
return std::make_unique<AwdlBwuHandler>(
|
||||
this, std::move(incoming_connection_callback));
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define CORE_INTERNAL_MEDIUMS_AWDL_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -24,12 +25,9 @@
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/implementation/psk_info.h"
|
||||
#include "internal/platform/multi_thread_executor.h"
|
||||
@@ -133,6 +131,9 @@ class Awdl {
|
||||
AwdlCredential GetCredentials(const std::string& service_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
std::unique_ptr<BwuHandler> CreateBwuHandler(
|
||||
BwuHandler::IncomingConnectionCallback incoming_connection_callback);
|
||||
|
||||
private:
|
||||
struct AdvertisingInfo {
|
||||
bool Empty() const { return nsd_service_infos.empty(); }
|
||||
|
||||
+12
-9
@@ -12,29 +12,30 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/awdl_bwu_handler.h"
|
||||
#include "connections/implementation/mediums/awdl_bwu_handler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/awdl_endpoint_channel.h"
|
||||
#include "connections/implementation/base_bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "connections/implementation/mediums/awdl_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/utils.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "connections/implementation/service_id_constants.h"
|
||||
#include "internal/base/masker.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/implementation/psk_info.h"
|
||||
@@ -56,9 +57,10 @@ constexpr absl::string_view kAwdlServiceIdSuffixForServiceType = "_AWDL";
|
||||
} // namespace
|
||||
|
||||
AwdlBwuHandler::AwdlBwuHandler(
|
||||
Mediums& mediums, IncomingConnectionCallback incoming_connection_callback)
|
||||
Awdl* absl_nonnull awdl_medium,
|
||||
IncomingConnectionCallback incoming_connection_callback)
|
||||
: BaseBwuHandler(std::move(incoming_connection_callback)),
|
||||
mediums_(mediums) {}
|
||||
awdl_medium_(*awdl_medium) {}
|
||||
|
||||
// Called by BWU target. Retrieves a new medium info from incoming message,
|
||||
// and establishes connection over AWDL using this info.
|
||||
@@ -148,9 +150,10 @@ AwdlBwuHandler::CreateUpgradedEndpointChannel(
|
||||
<< service_name << ", service_type:" << service_type
|
||||
<< ") for endpoint " << endpoint_id;
|
||||
|
||||
ErrorOr<AwdlSocket> socket_result =
|
||||
awdl_medium_.Connect(upgrade_service_id, nsd_service_info, psk_info,
|
||||
client->GetCancellationFlag(endpoint_id));
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag =
|
||||
client->GetCancellationFlag(endpoint_id);
|
||||
ErrorOr<AwdlSocket> socket_result = awdl_medium_.Connect(
|
||||
upgrade_service_id, nsd_service_info, psk_info, cancellation_flag.get());
|
||||
if (socket_result.has_error()) {
|
||||
LOG(ERROR) << "Failed to connect to the AWDL service (service_name:"
|
||||
<< service_name << ", service_type:" << service_type
|
||||
@@ -185,7 +188,7 @@ AwdlBwuHandler::CreateUpgradedEndpointChannel(
|
||||
// Called by BWU initiator. Set up AWDL upgraded medium for this endpoint,
|
||||
// and returns a upgrade path info (service_name, port) for remote party to
|
||||
// perform discovery.
|
||||
ByteArray AwdlBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string AwdlBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) {
|
||||
if (!awdl_medium_.IsAcceptingConnections(upgrade_service_id)) {
|
||||
+8
-11
@@ -12,21 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_AWDL_BWU_HANDLER_H_
|
||||
#define CORE_INTERNAL_AWDL_BWU_HANDLER_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_AWDL_BWU_HANDLER_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_AWDL_BWU_HANDLER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "connections/implementation/base_bwu_handler.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/nsd_service_info.h"
|
||||
|
||||
@@ -37,8 +35,8 @@ namespace connections {
|
||||
// per-Medium-specific operations needed to upgrade an EndpointChannel.
|
||||
class AwdlBwuHandler : public BaseBwuHandler {
|
||||
public:
|
||||
explicit AwdlBwuHandler(
|
||||
Mediums& mediums,
|
||||
AwdlBwuHandler(
|
||||
Awdl* absl_nonnull awdl_medium,
|
||||
IncomingConnectionCallback incoming_connection_callback);
|
||||
|
||||
private:
|
||||
@@ -68,7 +66,7 @@ class AwdlBwuHandler : public BaseBwuHandler {
|
||||
const std::string& endpoint_id) final {}
|
||||
|
||||
// BaseBwuHandler implementation:
|
||||
ByteArray HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) final;
|
||||
void HandleRevertInitiatorStateForService(
|
||||
@@ -82,12 +80,11 @@ class AwdlBwuHandler : public BaseBwuHandler {
|
||||
std::string GenerateServiceName();
|
||||
std::string GeneratePassword();
|
||||
|
||||
Mediums& mediums_;
|
||||
Awdl& awdl_medium_{mediums_.GetAwdl()};
|
||||
Awdl& awdl_medium_;
|
||||
NsdServiceInfo nsd_service_info_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_AWDL_BWU_HANDLER_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_AWDL_BWU_HANDLER_H_
|
||||
@@ -0,0 +1,495 @@
|
||||
// Copyright 2026 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 "connections/implementation/mediums/awdl_bwu_handler.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "connections/implementation/mediums/awdl_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/awdl.h"
|
||||
#include "internal/platform/implementation/platform.h"
|
||||
#include "internal/platform/implementation/psk_info.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/mock_input_stream.h"
|
||||
#include "internal/platform/mock_output_stream.h"
|
||||
#include "internal/platform/nsd_service_info.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
|
||||
class MockAwdlSocket : public api::AwdlSocket {
|
||||
public:
|
||||
MOCK_METHOD(InputStream&, GetInputStream, (), (override));
|
||||
MOCK_METHOD(OutputStream&, GetOutputStream, (), (override));
|
||||
MOCK_METHOD(Exception, Close, (), (override));
|
||||
};
|
||||
|
||||
class MockAwdlServerSocket : public api::AwdlServerSocket {
|
||||
public:
|
||||
MOCK_METHOD(std::string, GetIPAddress, (), (const, override));
|
||||
MOCK_METHOD(int, GetPort, (), (const, override));
|
||||
MOCK_METHOD(std::unique_ptr<api::AwdlSocket>, Accept, (), (override));
|
||||
MOCK_METHOD(Exception, Close, (), (override));
|
||||
};
|
||||
|
||||
class MockAwdlMedium : public api::AwdlMedium {
|
||||
public:
|
||||
MOCK_METHOD(bool, IsNetworkConnected, (), (const, override));
|
||||
MOCK_METHOD(bool, StartAdvertising, (const NsdServiceInfo& nsd_service_info),
|
||||
(override));
|
||||
MOCK_METHOD(bool, StopAdvertising, (const NsdServiceInfo& nsd_service_info),
|
||||
(override));
|
||||
MOCK_METHOD(bool, StartDiscovery,
|
||||
(const std::string& service_type,
|
||||
DiscoveredServiceCallback callback),
|
||||
(override));
|
||||
MOCK_METHOD(bool, StopDiscovery, (const std::string& service_type),
|
||||
(override));
|
||||
MOCK_METHOD(std::unique_ptr<api::AwdlSocket>, ConnectToService,
|
||||
(const NsdServiceInfo& remote_service_info,
|
||||
CancellationFlag* cancellation_flag),
|
||||
(override));
|
||||
MOCK_METHOD(std::unique_ptr<api::AwdlSocket>, ConnectToService,
|
||||
(const NsdServiceInfo& remote_service_info,
|
||||
const api::PskInfo& psk_info,
|
||||
CancellationFlag* cancellation_flag),
|
||||
(override));
|
||||
MOCK_METHOD(std::unique_ptr<api::AwdlServerSocket>, ListenForService,
|
||||
(int port), (override));
|
||||
MOCK_METHOD(std::unique_ptr<api::AwdlServerSocket>, ListenForService,
|
||||
(const api::PskInfo& psk_info, int port), (override));
|
||||
MOCK_METHOD((std::optional<std::pair<std::int32_t, std::int32_t>>),
|
||||
GetDynamicPortRange, (), (override));
|
||||
};
|
||||
|
||||
MockAwdlMedium* awdl_medium_mock = nullptr;
|
||||
|
||||
namespace connections {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame;
|
||||
using ::location::nearby::connections::OfflineFrame;
|
||||
using ::location::nearby::connections::V1Frame;
|
||||
using ::location::nearby::proto::connections::OperationResultCode;
|
||||
using ::testing::_;
|
||||
using ::testing::ByMove;
|
||||
using ::protobuf_matchers::EqualsProto;
|
||||
using ::testing::MockFunction;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnRef;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
constexpr absl::string_view kServiceId{"service_id"};
|
||||
constexpr absl::string_view kEndpointId{"endpoint_id"};
|
||||
constexpr absl::string_view kServiceName{"awdl_srv"};
|
||||
constexpr absl::string_view kServiceType{"_awdl._tcp"};
|
||||
constexpr absl::string_view kPassword{"password123"};
|
||||
constexpr absl::string_view kChannelName{"channel_name"};
|
||||
|
||||
class AwdlBwuHandlerTest : public ::testing::Test {
|
||||
protected:
|
||||
AwdlBwuHandlerTest()
|
||||
: handler_(&mediums_.GetAwdl(),
|
||||
incoming_connection_callback_.AsStdFunction()) {}
|
||||
|
||||
void SetUp() override {
|
||||
// By default, network is connected.
|
||||
ON_CALL(*awdl_medium_mock, IsNetworkConnected())
|
||||
.WillByDefault(Return(true));
|
||||
}
|
||||
|
||||
Mediums mediums_;
|
||||
MockFunction<void(ClientProxy*,
|
||||
std::unique_ptr<BwuHandler::IncomingSocketConnection>)>
|
||||
incoming_connection_callback_;
|
||||
AwdlBwuHandler handler_;
|
||||
MockInputStream mock_input_stream_;
|
||||
MockOutputStream mock_output_stream_;
|
||||
};
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest,
|
||||
CreateUpgradedEndpointChannel_InvalidCredentials_Fails) {
|
||||
ClientProxy client;
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
||||
path_info.mutable_awdl_credentials(); // Empty credentials
|
||||
|
||||
auto result =
|
||||
static_cast<BwuHandler*>(&handler_)->CreateUpgradedEndpointChannel(
|
||||
&client, "service_id", "endpoint_id", path_info);
|
||||
|
||||
ASSERT_TRUE(result.has_error());
|
||||
EXPECT_EQ(result.error().operation_result_code().value(),
|
||||
OperationResultCode::CONNECTIVITY_AWDL_INVALID_CREDENTIAL);
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, CreateUpgradedEndpointChannel_Success) {
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
MockInputStream input_stream;
|
||||
MockOutputStream output_stream;
|
||||
auto awdl_socket = std::make_unique<MockAwdlSocket>();
|
||||
EXPECT_CALL(*awdl_socket, GetInputStream())
|
||||
.WillRepeatedly(ReturnRef(input_stream));
|
||||
EXPECT_CALL(*awdl_socket, GetOutputStream())
|
||||
.WillRepeatedly(ReturnRef(output_stream));
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, StartDiscovery(_, _))
|
||||
.WillOnce([](const std::string& service_type,
|
||||
api::AwdlMedium::DiscoveredServiceCallback callback) {
|
||||
NsdServiceInfo service_info;
|
||||
service_info.SetServiceName(std::string(kServiceName));
|
||||
service_info.SetServiceType(service_type);
|
||||
if (callback.service_discovered_cb) {
|
||||
NsdServiceInfo service_info_copy = service_info;
|
||||
callback.service_discovered_cb(service_info_copy);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
EXPECT_CALL(*awdl_medium_mock, StopDiscovery(_)).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*awdl_medium_mock, ConnectToService(_, _, _))
|
||||
.WillOnce(Return(ByMove(std::move(awdl_socket))));
|
||||
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
||||
auto* credentials = path_info.mutable_awdl_credentials();
|
||||
credentials->set_service_name(kServiceName);
|
||||
credentials->set_service_type(kServiceType);
|
||||
credentials->set_password(kPassword);
|
||||
|
||||
auto result =
|
||||
static_cast<BwuHandler*>(&handler_)->CreateUpgradedEndpointChannel(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId),
|
||||
path_info);
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest,
|
||||
InitializeUpgradedMediumForEndpoint_StartAcceptingConnectionsFails) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, ListenForService(_, 0))
|
||||
.WillOnce(Return(ByMove(nullptr)));
|
||||
|
||||
std::string result = handler_.InitializeUpgradedMediumForEndpoint(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId));
|
||||
|
||||
EXPECT_TRUE(result.empty());
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, InitializeUpgradedMediumForEndpoint_Success) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
// The reason for putting ClientProxy inside a C++ { } block so it destructs
|
||||
// before the simulated clock is restored. Otherwise, the simulated clock
|
||||
// would stopped before ClientProxy went out of scope, causing its destructor
|
||||
// to log the session duration using the real system clock. If 1 or more
|
||||
// real-world milliseconds elapsed between the test start and test end, this
|
||||
// duration evaluated to something > 0.
|
||||
{
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
auto awdl_server_socket = std::make_unique<MockAwdlServerSocket>();
|
||||
auto* awdl_server_socket_ptr = awdl_server_socket.get();
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, GetPort())
|
||||
.WillRepeatedly(Return(8080));
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Accept())
|
||||
.WillOnce(Return(ByMove(nullptr)));
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Close())
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, ListenForService(_, 0))
|
||||
.WillOnce(Return(ByMove(std::move(awdl_server_socket))));
|
||||
|
||||
std::string captured_service_name;
|
||||
std::string captured_service_type;
|
||||
EXPECT_CALL(*awdl_medium_mock, StartAdvertising(_))
|
||||
.WillOnce([&](const NsdServiceInfo& nsd_service_info) {
|
||||
captured_service_name = nsd_service_info.GetServiceName();
|
||||
captured_service_type = nsd_service_info.GetServiceType();
|
||||
return true;
|
||||
});
|
||||
|
||||
std::string result = handler_.InitializeUpgradedMediumForEndpoint(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId));
|
||||
|
||||
EXPECT_FALSE(result.empty());
|
||||
OfflineFrame expected_frame;
|
||||
expected_frame.set_version(OfflineFrame::V1);
|
||||
expected_frame.mutable_v1()->set_type(
|
||||
V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION);
|
||||
auto* bwu_frame =
|
||||
expected_frame.mutable_v1()->mutable_bandwidth_upgrade_negotiation();
|
||||
bwu_frame->set_event_type(
|
||||
BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE);
|
||||
auto* upgrade_path_info = bwu_frame->mutable_upgrade_path_info();
|
||||
upgrade_path_info->set_medium(
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo::AWDL);
|
||||
upgrade_path_info->set_supports_client_introduction_ack(true);
|
||||
upgrade_path_info->set_supports_disabling_encryption(true);
|
||||
auto* awdl_credentials = upgrade_path_info->mutable_awdl_credentials();
|
||||
awdl_credentials->set_service_name(captured_service_name);
|
||||
awdl_credentials->set_service_type(captured_service_type);
|
||||
|
||||
// The password is automatically generated and set in the handle start, we
|
||||
// can obtain it from the credential Since we mock StartAcceptingConnections
|
||||
// instead of using real awdl, GetPskInfo won't work perfectly. However
|
||||
// InitializeUpgradedMediumForEndpoint internally calls
|
||||
// parser::ForBwuAwdlPathAvailable which puts the generated password. We
|
||||
// will extract it from result directly to build expected frame.
|
||||
OfflineFrame result_frame;
|
||||
EXPECT_TRUE(result_frame.ParseFromString(result));
|
||||
awdl_credentials->set_password(result_frame.v1()
|
||||
.bandwidth_upgrade_negotiation()
|
||||
.upgrade_path_info()
|
||||
.awdl_credentials()
|
||||
.password());
|
||||
|
||||
EXPECT_THAT(result_frame, EqualsProto(expected_frame));
|
||||
|
||||
handler_.RevertInitiatorState();
|
||||
}
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, OnIncomingAwdlConnection_Success) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
auto awdl_server_socket = std::make_unique<MockAwdlServerSocket>();
|
||||
auto* awdl_server_socket_ptr = awdl_server_socket.get();
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Close())
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Accept())
|
||||
.WillOnce([this]() {
|
||||
auto awdl_socket = std::make_unique<MockAwdlSocket>();
|
||||
EXPECT_CALL(*awdl_socket, GetInputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_input_stream_));
|
||||
EXPECT_CALL(*awdl_socket, GetOutputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_output_stream_));
|
||||
return awdl_socket;
|
||||
})
|
||||
.WillRepeatedly([]() {
|
||||
absl::SleepFor(absl::Seconds(5));
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, ListenForService(_, 0))
|
||||
.WillOnce(Return(ByMove(std::move(awdl_server_socket))));
|
||||
EXPECT_CALL(*awdl_medium_mock, StartAdvertising(_)).WillOnce(Return(true));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
EXPECT_CALL(incoming_connection_callback_, Call(&client, _))
|
||||
.WillOnce([&latch](ClientProxy* client,
|
||||
std::unique_ptr<BwuHandler::IncomingSocketConnection>
|
||||
connection) { latch.CountDown(); });
|
||||
|
||||
std::string result = handler_.InitializeUpgradedMediumForEndpoint(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId));
|
||||
EXPECT_FALSE(result.empty());
|
||||
|
||||
auto await_result = latch.Await(absl::Seconds(5));
|
||||
EXPECT_TRUE(await_result.ok());
|
||||
|
||||
handler_.RevertInitiatorState();
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, AwdlIncomingSocket_ToStringAndClose) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
auto awdl_server_socket = std::make_unique<MockAwdlServerSocket>();
|
||||
auto* awdl_server_socket_ptr = awdl_server_socket.get();
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Close())
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Accept())
|
||||
.WillOnce([this]() {
|
||||
auto awdl_socket = std::make_unique<MockAwdlSocket>();
|
||||
EXPECT_CALL(*awdl_socket, GetInputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_input_stream_));
|
||||
EXPECT_CALL(*awdl_socket, GetOutputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_output_stream_));
|
||||
EXPECT_CALL(*awdl_socket, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
return awdl_socket;
|
||||
})
|
||||
.WillRepeatedly([]() {
|
||||
absl::SleepFor(absl::Seconds(5));
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, ListenForService(_, 0))
|
||||
.WillOnce(Return(ByMove(std::move(awdl_server_socket))));
|
||||
EXPECT_CALL(*awdl_medium_mock, StartAdvertising(_)).WillOnce(Return(true));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
EXPECT_CALL(incoming_connection_callback_, Call(&client, _))
|
||||
.WillOnce([&latch](ClientProxy* client,
|
||||
std::unique_ptr<BwuHandler::IncomingSocketConnection>
|
||||
connection) {
|
||||
EXPECT_FALSE(connection->socket->ToString().empty());
|
||||
connection->socket->Close();
|
||||
latch.CountDown();
|
||||
});
|
||||
|
||||
std::string result = handler_.InitializeUpgradedMediumForEndpoint(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId));
|
||||
EXPECT_FALSE(result.empty());
|
||||
|
||||
auto await_result = latch.Await(absl::Seconds(5));
|
||||
EXPECT_TRUE(await_result.ok());
|
||||
|
||||
handler_.RevertInitiatorState();
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, HandleRevertInitiatorStateForService_Success) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
auto awdl_server_socket = std::make_unique<MockAwdlServerSocket>();
|
||||
auto* awdl_server_socket_ptr = awdl_server_socket.get();
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Close())
|
||||
.WillRepeatedly(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(*awdl_server_socket_ptr, Accept()).WillRepeatedly([]() {
|
||||
absl::SleepFor(absl::Seconds(10));
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
EXPECT_CALL(*awdl_medium_mock, ListenForService(_, 0))
|
||||
.WillOnce(Return(ByMove(std::move(awdl_server_socket))));
|
||||
EXPECT_CALL(*awdl_medium_mock, StartAdvertising(_)).WillOnce(Return(true));
|
||||
EXPECT_CALL(*awdl_medium_mock, StopAdvertising(_)).WillOnce(Return(true));
|
||||
|
||||
handler_.InitializeUpgradedMediumForEndpoint(&client, std::string(kServiceId),
|
||||
std::string(kEndpointId));
|
||||
|
||||
handler_.RevertInitiatorState();
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, GetUpgradeMedium_ReturnsAwdl) {
|
||||
auto* bwu_handler = static_cast<BwuHandler*>(&handler_);
|
||||
EXPECT_EQ(bwu_handler->GetUpgradeMedium(),
|
||||
location::nearby::proto::connections::Medium::AWDL);
|
||||
}
|
||||
|
||||
TEST_F(AwdlBwuHandlerTest, OnEndpointDisconnect_DoesNotCrash) {
|
||||
ClientProxy client;
|
||||
auto* bwu_handler = static_cast<BwuHandler*>(&handler_);
|
||||
// This method is a no-op, just verifying it doesn't crash.
|
||||
bwu_handler->OnEndpointDisconnect(&client, std::string(kEndpointId));
|
||||
}
|
||||
|
||||
class AwdlEndpointChannelTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ON_CALL(*awdl_medium_mock, IsNetworkConnected())
|
||||
.WillByDefault(Return(true));
|
||||
mock_socket_ = std::make_unique<StrictMock<MockAwdlSocket>>();
|
||||
EXPECT_CALL(*mock_socket_, GetInputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_input_stream_));
|
||||
EXPECT_CALL(*mock_socket_, GetOutputStream())
|
||||
.WillRepeatedly(ReturnRef(mock_output_stream_));
|
||||
}
|
||||
|
||||
std::unique_ptr<StrictMock<MockAwdlSocket>> mock_socket_;
|
||||
StrictMock<MockInputStream> mock_input_stream_;
|
||||
StrictMock<MockOutputStream> mock_output_stream_;
|
||||
Awdl awdl_medium_;
|
||||
};
|
||||
|
||||
TEST_F(AwdlEndpointChannelTest, CloseImpl_StopsDiscoveryIfOutgoing) {
|
||||
EXPECT_CALL(*mock_socket_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(mock_input_stream_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(mock_output_stream_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(*awdl_medium_mock, StartDiscovery(_, _)).WillOnce(Return(true));
|
||||
EXPECT_CALL(*awdl_medium_mock, StopDiscovery(_)).WillOnce(Return(true));
|
||||
awdl_medium_.StartDiscovery(std::string(kServiceId), {});
|
||||
|
||||
AwdlEndpointChannel channel(
|
||||
std::string(kServiceId), std::string(kChannelName),
|
||||
AwdlSocket(std::move(mock_socket_)), &awdl_medium_,
|
||||
/*is_outgoing=*/true);
|
||||
|
||||
channel.Close(location::nearby::proto::connections::DisconnectionReason::
|
||||
UNKNOWN_DISCONNECTION_REASON);
|
||||
}
|
||||
|
||||
TEST_F(AwdlEndpointChannelTest, CloseImpl_DoesNotStopDiscoveryIfIncoming) {
|
||||
EXPECT_CALL(*mock_socket_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(mock_input_stream_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
EXPECT_CALL(mock_output_stream_, Close())
|
||||
.WillOnce(Return(Exception{Exception::kSuccess}));
|
||||
|
||||
AwdlEndpointChannel channel(
|
||||
std::string(kServiceId), std::string(kChannelName),
|
||||
AwdlSocket(std::move(mock_socket_)), &awdl_medium_,
|
||||
/*is_outgoing=*/false);
|
||||
|
||||
channel.Close(location::nearby::proto::connections::DisconnectionReason::
|
||||
UNKNOWN_DISCONNECTION_REASON);
|
||||
}
|
||||
|
||||
TEST_F(AwdlEndpointChannelTest, EnableMultiplexSocket_CallsSocket) {
|
||||
AwdlEndpointChannel channel(
|
||||
std::string(kServiceId), std::string(kChannelName),
|
||||
AwdlSocket(std::move(mock_socket_)), &awdl_medium_,
|
||||
/*is_outgoing=*/true);
|
||||
|
||||
EXPECT_TRUE(channel.EnableMultiplexSocket());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
namespace api {
|
||||
|
||||
std::unique_ptr<AwdlMedium> ImplementationPlatform::CreateAwdlMedium() {
|
||||
auto medium = std::make_unique<MockAwdlMedium>();
|
||||
awdl_medium_mock = medium.get();
|
||||
return medium;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace nearby
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/awdl_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/awdl_endpoint_channel.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
+4
-3
@@ -12,13 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_AWDL_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_AWDL_ENDPOINT_CHANNEL_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_AWDL_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_AWDL_ENDPOINT_CHANNEL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "connections/implementation/base_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "internal/platform/awdl.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -48,4 +49,4 @@ class AwdlEndpointChannel final : public BaseEndpointChannel {
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_AWDL_ENDPOINT_CHANNEL_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_AWDL_ENDPOINT_CHANNEL_H_
|
||||
@@ -70,7 +70,6 @@ cc_library(
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -207,22 +207,28 @@ Medium BleSocket::GetMediumLocked() const {
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BleSocket::DispatchPacket() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!ble_input_stream_) {
|
||||
return Exception::kFailed;
|
||||
std::shared_ptr<BleInputStream> input_stream;
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
if (!ble_input_stream_) {
|
||||
return Exception::kFailed;
|
||||
}
|
||||
input_stream = ble_input_stream_;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> read_bytes =
|
||||
ble_input_stream_->Read(BlePacket::kServiceIdHashLength);
|
||||
input_stream->Read(BlePacket::kServiceIdHashLength);
|
||||
while (read_bytes.ok()) {
|
||||
ByteArray read_bytes_result = read_bytes.result();
|
||||
if (BlePacket::IsControlPacketBytes(read_bytes_result)) {
|
||||
ExceptionOr<ByteArray> handle_result = ProcessBleControlPacketLocked();
|
||||
ExceptionOr<ByteArray> handle_result =
|
||||
ProcessBleControlPacket(input_stream);
|
||||
if (!handle_result.ok()) {
|
||||
return handle_result;
|
||||
}
|
||||
read_bytes = ble_input_stream_->Read(BlePacket::kServiceIdHashLength);
|
||||
read_bytes = input_stream->Read(BlePacket::kServiceIdHashLength);
|
||||
} else {
|
||||
MutexLock lock(&mutex_);
|
||||
if (read_bytes_result != service_id_hash_) {
|
||||
LOG(WARNING)
|
||||
<< "Received data packet with incorrect service ID hash. Expected: "
|
||||
@@ -239,20 +245,22 @@ ExceptionOr<ByteArray> BleSocket::DispatchPacket() {
|
||||
|
||||
ExceptionOr<std::int32_t> BleSocket::ReadPayloadLength() {
|
||||
int payload_length = 0;
|
||||
std::shared_ptr<BleInputStream> input_stream;
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
if (!ble_input_stream_) {
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> read_bytes =
|
||||
ble_input_stream_->Read(sizeof(std::int32_t));
|
||||
if (!read_bytes.ok()) {
|
||||
return read_bytes.exception();
|
||||
}
|
||||
|
||||
payload_length = byte_utils::BytesToInt(std::move(read_bytes.result()));
|
||||
input_stream = ble_input_stream_;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> read_bytes = input_stream->Read(sizeof(std::int32_t));
|
||||
if (!read_bytes.ok()) {
|
||||
return read_bytes.exception();
|
||||
}
|
||||
|
||||
payload_length = byte_utils::BytesToInt(std::move(read_bytes.result()));
|
||||
|
||||
Exception send_ack_result = SendPacketAcknowledgement(payload_length);
|
||||
if (!send_ack_result.Ok()) {
|
||||
LOG(WARNING) << "Failed to send packet acknowledgement.";
|
||||
@@ -268,9 +276,10 @@ Exception BleSocket::WritePayloadLength(int payload_length) {
|
||||
return ble_output_stream_->WritePayloadLength(payload_length);
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BleSocket::ProcessBleControlPacketLocked() {
|
||||
ExceptionOr<ByteArray> BleSocket::ProcessBleControlPacket(
|
||||
std::shared_ptr<BleInputStream> input_stream) {
|
||||
// Read the first 4 bytes (packet block 1).
|
||||
ExceptionOr<ByteArray> read_bytes = ble_input_stream_->Read(4);
|
||||
ExceptionOr<ByteArray> read_bytes = input_stream->Read(4);
|
||||
if (!read_bytes.ok()) {
|
||||
return read_bytes;
|
||||
}
|
||||
@@ -282,7 +291,7 @@ ExceptionOr<ByteArray> BleSocket::ProcessBleControlPacketLocked() {
|
||||
// Read the length from the 3rd byte of the packet block (0-indexed).
|
||||
int packet_block_2_size = packet_block_1.data()[3];
|
||||
// Read the left bytes for the packet block 2).
|
||||
read_bytes = ble_input_stream_->Read(packet_block_2_size);
|
||||
read_bytes = input_stream->Read(packet_block_2_size);
|
||||
if (!read_bytes.ok()) {
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
@@ -375,8 +375,8 @@ class BleSocket final {
|
||||
* payload, the `ByteArray` may be empty. Returns an `Exception` if a
|
||||
* protocol error occurs or the read operation fails.
|
||||
*/
|
||||
ExceptionOr<ByteArray> ProcessBleControlPacketLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
ExceptionOr<ByteArray> ProcessBleControlPacket(
|
||||
std::shared_ptr<BleInputStream> input_stream);
|
||||
|
||||
/**
|
||||
* Sends a raw L2CAP packet over the socket.
|
||||
@@ -407,9 +407,9 @@ class BleSocket final {
|
||||
SingleThreadExecutor serial_executor_;
|
||||
|
||||
const ByteArray service_id_hash_;
|
||||
std::unique_ptr<mediums::BleInputStream> ble_input_stream_
|
||||
std::shared_ptr<mediums::BleInputStream> ble_input_stream_
|
||||
ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
std::unique_ptr<mediums::BleOutputStream> ble_output_stream_
|
||||
std::shared_ptr<mediums::BleOutputStream> ble_output_stream_
|
||||
ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
nearby::BleSocket ble_socket_ ABSL_GUARDED_BY(mutex_) = nearby::BleSocket();
|
||||
nearby::BleL2capSocket l2cap_socket_ ABSL_GUARDED_BY(mutex_) =
|
||||
|
||||
@@ -228,6 +228,7 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked(
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<BleAdvertisement> advertisements_to_clear;
|
||||
for (const auto& hash : on_lost_advertisement->hashes()) {
|
||||
for (const auto& it : gatt_advertisement_infos_) {
|
||||
if (it.second.instant_on_lost_hash.string_data() == hash) {
|
||||
@@ -247,30 +248,25 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked(
|
||||
BlePeripheral lost_peripheral = it.second.peripheral;
|
||||
lost_peripheral.SetId(ByteArray(gatt_advertisement));
|
||||
if (gatt_advertisement.IsValid()) {
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableScanningForInstantOnLost)) {
|
||||
AddInstantLostAdvertisement(it.second.advertisement_header);
|
||||
discovery_cb_it->second.discovered_peripheral_callback
|
||||
.instant_lost_cb(lost_peripheral, it.second.service_id,
|
||||
gatt_advertisement.GetData(),
|
||||
gatt_advertisement.IsFastAdvertisement());
|
||||
} else {
|
||||
discovery_cb_it->second.discovered_peripheral_callback
|
||||
.peripheral_lost_cb(lost_peripheral, it.second.service_id,
|
||||
gatt_advertisement.GetData(),
|
||||
gatt_advertisement.IsFastAdvertisement());
|
||||
}
|
||||
AddInstantLostAdvertisement(it.second.advertisement_header);
|
||||
discovery_cb_it->second.discovered_peripheral_callback
|
||||
.instant_lost_cb(lost_peripheral, it.second.service_id,
|
||||
gatt_advertisement.GetData(),
|
||||
gatt_advertisement.IsFastAdvertisement());
|
||||
LOG(INFO) << __func__ << ": OnLost triggered for service_id "
|
||||
<< it.second.service_id;
|
||||
}
|
||||
|
||||
ClearGattAdvertisement(gatt_advertisement);
|
||||
advertisements_to_clear.push_back(gatt_advertisement);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& advertisement : advertisements_to_clear) {
|
||||
ClearGattAdvertisement(advertisement);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
@@ -53,7 +52,6 @@
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
#include "internal/test/fake_clock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -225,6 +223,42 @@ class DiscoveredPeripheralTrackerTest
|
||||
adapter_peripheral_->GetAddress().address());
|
||||
}
|
||||
|
||||
void SetupMultipleAdvertisementsState(
|
||||
const BleAdvertisementHeader& header,
|
||||
const BleAdvertisement& advertisement_1,
|
||||
const BleAdvertisement& advertisement_2) {
|
||||
MutexLock lock(&discovered_peripheral_tracker_->mutex_);
|
||||
ByteArray advertisement_bytes_1 = advertisement_1.ByteArrayWithExtraField();
|
||||
ByteArray advertisement_bytes_2 = advertisement_2.ByteArrayWithExtraField();
|
||||
std::vector<const ByteArray*> gatt_advertisement_bytes_list = {
|
||||
&advertisement_bytes_1, &advertisement_bytes_2};
|
||||
|
||||
discovered_peripheral_tracker_->HandleRawGattAdvertisements(
|
||||
CreateBlePeripheral(), header, gatt_advertisement_bytes_list,
|
||||
/*service_uuid=*/{});
|
||||
}
|
||||
|
||||
void RegisterServiceIdCallback(const std::string& service_id,
|
||||
CountDownLatch& lost_latch) {
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
service_id, /*include_dct_advertisement=*/false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.instant_lost_cb =
|
||||
[&lost_latch](
|
||||
BlePeripheral peripheral, const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) { lost_latch.CountDown(); },
|
||||
},
|
||||
/*fast_advertisement_service_uuid=*/{});
|
||||
}
|
||||
|
||||
bool CallHandleOnLostAdvertisementLocked(
|
||||
const api::ble::BleAdvertisementData& advertisement_data) {
|
||||
MutexLock lock(&discovered_peripheral_tracker_->mutex_);
|
||||
return discovered_peripheral_tracker_->HandleOnLostAdvertisementLocked(
|
||||
advertisement_data);
|
||||
}
|
||||
|
||||
// Simulates to see a fast advertisement.
|
||||
void FindFastAdvertisement(
|
||||
const api::ble::BleAdvertisementData& advertisement_data,
|
||||
@@ -1269,6 +1303,58 @@ TEST_P(DiscoveredPeripheralTrackerTest, InstantLostPeripheralForInstantOnLost) {
|
||||
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
InstantLostPeripheralForInstantOnLost_MultipleAdvertisements) {
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
BleAdvertisementHeader header(BleAdvertisementHeader::Version::kV2,
|
||||
/*extended_advertisement=*/false,
|
||||
/*num_slots=*/1, ByteArray{}, // bloom filter
|
||||
advertisement_hash,
|
||||
BleAdvertisementHeader::kDefaultPsmValue);
|
||||
|
||||
ByteArray advertisement_bytes_1 = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string(kData)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
ByteArray advertisement_bytes_2 = CreateBleAdvertisement(
|
||||
std::string(kServiceIdB), ByteArray(std::string(kData2)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
|
||||
auto adv_status_or_1 =
|
||||
BleAdvertisement::CreateBleAdvertisement(advertisement_bytes_1);
|
||||
ASSERT_OK(adv_status_or_1);
|
||||
BleAdvertisement advertisement_1 = adv_status_or_1.value();
|
||||
|
||||
auto adv_status_or_2 =
|
||||
BleAdvertisement::CreateBleAdvertisement(advertisement_bytes_2);
|
||||
ASSERT_OK(adv_status_or_2);
|
||||
BleAdvertisement advertisement_2 = adv_status_or_2.value();
|
||||
|
||||
// Register callbacks for both Service A and Service B.
|
||||
CountDownLatch lost_latch(2);
|
||||
RegisterServiceIdCallback(std::string(kServiceIdA), lost_latch);
|
||||
RegisterServiceIdCallback(std::string(kServiceIdB), lost_latch);
|
||||
|
||||
// Use helper method to set up state manually.
|
||||
SetupMultipleAdvertisementsState(header, advertisement_1, advertisement_2);
|
||||
|
||||
// Create OnLost advertisement for advertisement_1's hash.
|
||||
auto advertisement = InstantOnLostAdvertisement::CreateFromHashes(
|
||||
std::list<std::string>({std::string(bleutils::GenerateAdvertisementHash(
|
||||
advertisement_1.ByteArrayWithExtraField()))}));
|
||||
ASSERT_OK(advertisement);
|
||||
|
||||
api::ble::BleAdvertisementData loss_advertisement_data{};
|
||||
loss_advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, ByteArray(advertisement->ToBytes())});
|
||||
|
||||
// Call HandleOnLostAdvertisementLocked using helper.
|
||||
bool result = CallHandleOnLostAdvertisementLocked(loss_advertisement_data);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
// Verify that both are lost (callback triggered twice).
|
||||
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
IgnoreFoundAdvertisementForInstantOnLost) {
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
@@ -1628,9 +1714,6 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
OnlyGattAdvertisementReceivedOnDeviceWithExtended) {
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
@@ -1668,7 +1751,7 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
// 2. Receive GATT advertisement data again after 4 seconds, it should access
|
||||
// GATT server.
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
MediumEnvironment::Instance().FastForward(absl::Seconds(4));
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
@@ -1678,9 +1761,6 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest, SkipExpiredGattAdvertisement) {
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
@@ -1718,7 +1798,7 @@ TEST_P(DiscoveredPeripheralTrackerTest, SkipExpiredGattAdvertisement) {
|
||||
|
||||
// 2. The GATT advertisement is already queued and will be skipped.
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
(*fake_clock)->FastForward(absl::Seconds(20));
|
||||
MediumEnvironment::Instance().FastForward(absl::Seconds(20));
|
||||
discovered_peripheral_tracker_->StartFetchExecutorForTesting();
|
||||
|
||||
// We should not receive a client callback of a peripheral discovery.
|
||||
@@ -1729,9 +1809,6 @@ TEST_P(DiscoveredPeripheralTrackerTest, SkipExpiredGattAdvertisement) {
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
DiscoveredOnceWhenGattAndExtendedAdvertisementReceived) {
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
@@ -1756,7 +1833,7 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
MediumEnvironment::Instance().FastForward(absl::Seconds(4));
|
||||
discovered_peripheral_tracker_->StartFetchExecutorForTesting();
|
||||
|
||||
// 1. Received extended advertisement.
|
||||
@@ -1784,8 +1861,6 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
FindGattAdvertisementInHigherPriorityThanExtendedGattAdvertisement) {
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash_a = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_a =
|
||||
@@ -1823,7 +1898,7 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
MediumEnvironment::Instance().FastForward(absl::Seconds(4));
|
||||
discovered_peripheral_tracker_->StartFetchExecutorForTesting();
|
||||
|
||||
// 1. Find peripheral A with GATT advertisement.
|
||||
|
||||
@@ -206,10 +206,7 @@ bool InstantOnLostManager::StartInstantOnLostAdvertisement() {
|
||||
|
||||
StopOnLostAdvertising();
|
||||
|
||||
if (NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kDisableInstantOnLostOnBleWithoutExtended) &&
|
||||
!ble_medium_.IsExtendedAdvertisementsAvailable()) {
|
||||
if (!ble_medium_.IsExtendedAdvertisementsAvailable()) {
|
||||
LOG(WARNING)
|
||||
<< __func__
|
||||
<< ": Disabling instant on lost on BLE without extended advertising.";
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/ble_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/ble_endpoint_channel.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CONNECTIONS_IMPLEMENTATION_BLE_ENDPOINT_CHANNEL_H_
|
||||
#define CONNECTIONS_IMPLEMENTATION_BLE_ENDPOINT_CHANNEL_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_BLE_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_BLE_ENDPOINT_CHANNEL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -57,4 +57,4 @@ class BleEndpointChannel final : public BaseEndpointChannel {
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CONNECTIONS_IMPLEMENTATION_BLE_ENDPOINT_CHANNEL_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_BLE_ENDPOINT_CHANNEL_H_
|
||||
+2
-2
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/ble_l2cap_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/ble_l2cap_endpoint_channel.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -22,11 +22,11 @@
|
||||
#include "connections/implementation/base_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/ble/ble_socket.h"
|
||||
#include "internal/platform/ble.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -60,4 +60,4 @@ class BleL2capEndpointChannel final : public BaseEndpointChannel {
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_BLE_L2CAP_ENDPOINT_CHANNEL_H_
|
||||
+16
-9
@@ -12,22 +12,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/bluetooth_bwu_handler.h"
|
||||
#include "connections/implementation/mediums/bluetooth_bwu_handler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "connections/implementation/base_bwu_handler.h"
|
||||
#include "connections/implementation/bluetooth_endpoint_channel.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "connections/implementation/mediums/bluetooth_classic.h"
|
||||
#include "connections/implementation/mediums/bluetooth_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
@@ -44,9 +46,12 @@ using ::location::nearby::proto::connections::OperationResultCode;
|
||||
} // namespace
|
||||
|
||||
BluetoothBwuHandler::BluetoothBwuHandler(
|
||||
Mediums& mediums, IncomingConnectionCallback incoming_connection_callback)
|
||||
BluetoothRadio* absl_nonnull bluetooth_radio,
|
||||
BluetoothClassic* absl_nonnull bluetooth_medium,
|
||||
IncomingConnectionCallback incoming_connection_callback)
|
||||
: BaseBwuHandler(std::move(incoming_connection_callback)),
|
||||
mediums_(mediums) {}
|
||||
bluetooth_radio_(*bluetooth_radio),
|
||||
bluetooth_medium_(*bluetooth_medium) {}
|
||||
|
||||
// Called by BWU target. Retrieves a new medium info from incoming message,
|
||||
// and establishes connection over BT using this info.
|
||||
@@ -85,8 +90,10 @@ BluetoothBwuHandler::CreateUpgradedEndpointChannel(
|
||||
OperationResultCode::CONNECTIVITY_BLUETOOTH_DEVICE_OBTAIN_FAILURE)};
|
||||
}
|
||||
|
||||
ErrorOr<BluetoothSocket> socket_result = bluetooth_medium_.Connect(
|
||||
device, service_id, client->GetCancellationFlag(endpoint_id));
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag =
|
||||
client->GetCancellationFlag(endpoint_id);
|
||||
ErrorOr<BluetoothSocket> socket_result =
|
||||
bluetooth_medium_.Connect(device, service_name, cancellation_flag.get());
|
||||
if (socket_result.has_error()) {
|
||||
LOG(ERROR)
|
||||
<< "BluetoothBwuHandler failed to connect to the Bluetooth device ("
|
||||
@@ -116,7 +123,7 @@ BluetoothBwuHandler::CreateUpgradedEndpointChannel(
|
||||
return {std::move(channel)};
|
||||
}
|
||||
|
||||
ByteArray BluetoothBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string BluetoothBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) {
|
||||
MacAddress mac_address = bluetooth_medium_.GetAddress();
|
||||
+11
-11
@@ -12,21 +12,21 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_
|
||||
#define CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_BLUETOOTH_BWU_HANDLER_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_BLUETOOTH_BWU_HANDLER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "connections/implementation/base_bwu_handler.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/bluetooth_classic.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/expected.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -36,8 +36,9 @@ namespace connections {
|
||||
// per-Medium-specific operations needed to upgrade an EndpointChannel.
|
||||
class BluetoothBwuHandler : public BaseBwuHandler {
|
||||
public:
|
||||
explicit BluetoothBwuHandler(
|
||||
Mediums& mediums,
|
||||
BluetoothBwuHandler(
|
||||
BluetoothRadio* absl_nonnull bluetooth_radio,
|
||||
BluetoothClassic* absl_nonnull bluetooth_medium,
|
||||
IncomingConnectionCallback incoming_connection_callback);
|
||||
|
||||
private:
|
||||
@@ -66,7 +67,7 @@ class BluetoothBwuHandler : public BaseBwuHandler {
|
||||
const std::string& endpoint_id) final {}
|
||||
|
||||
// BaseBwuHandler implementation:
|
||||
ByteArray HandleInitializeUpgradedMediumForEndpoint(
|
||||
std::string HandleInitializeUpgradedMediumForEndpoint(
|
||||
ClientProxy* client, const std::string& upgrade_service_id,
|
||||
const std::string& endpoint_id) final;
|
||||
void HandleRevertInitiatorStateForService(
|
||||
@@ -76,12 +77,11 @@ class BluetoothBwuHandler : public BaseBwuHandler {
|
||||
const std::string& upgrade_service_id,
|
||||
BluetoothSocket socket);
|
||||
|
||||
Mediums& mediums_;
|
||||
BluetoothRadio& bluetooth_radio_{mediums_.GetBluetoothRadio()};
|
||||
BluetoothClassic& bluetooth_medium_{mediums_.GetBluetoothClassic()};
|
||||
BluetoothRadio& bluetooth_radio_;
|
||||
BluetoothClassic& bluetooth_medium_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_BLUETOOTH_BWU_HANDLER_H_
|
||||
+48
-16
@@ -12,18 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/mediums/bluetooth_bwu_handler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/bluetooth_bwu_handler.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/client_proxy.h"
|
||||
#include "connections/implementation/endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/expected.h"
|
||||
@@ -43,17 +44,27 @@ constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000);
|
||||
|
||||
class BluetoothBwuTest : public testing::Test {
|
||||
protected:
|
||||
BluetoothBwuTest() { env_.Start(); }
|
||||
~BluetoothBwuTest() override { env_.Stop(); }
|
||||
BluetoothBwuTest() {
|
||||
original_flags_ = FeatureFlags::GetInstance().GetFlags();
|
||||
env_.Start();
|
||||
}
|
||||
~BluetoothBwuTest() override {
|
||||
FeatureFlags::GetMutableInstanceForTesting().SetFlags(original_flags_);
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
void RunSTACreateEndpointChannelTest(bool enable_cancellation);
|
||||
|
||||
MediumEnvironment& env_{MediumEnvironment::Instance()};
|
||||
FeatureFlags::Flags original_flags_;
|
||||
};
|
||||
|
||||
TEST_F(BluetoothBwuTest, CanCreateBwuHandler) {
|
||||
ClientProxy client;
|
||||
Mediums mediums;
|
||||
|
||||
auto handler = std::make_unique<BluetoothBwuHandler>(mediums, nullptr);
|
||||
auto handler = std::make_unique<BluetoothBwuHandler>(
|
||||
&mediums.GetBluetoothRadio(), &mediums.GetBluetoothClassic(), nullptr);
|
||||
|
||||
handler->InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"B",
|
||||
/*endpoint_id=*/"2");
|
||||
@@ -62,7 +73,12 @@ TEST_F(BluetoothBwuTest, CanCreateBwuHandler) {
|
||||
handler.reset();
|
||||
}
|
||||
|
||||
TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
void BluetoothBwuTest::RunSTACreateEndpointChannelTest(
|
||||
bool enable_cancellation) {
|
||||
FeatureFlags::Flags flags = original_flags_;
|
||||
flags.enable_cancellation_flag = enable_cancellation;
|
||||
FeatureFlags::GetMutableInstanceForTesting().SetFlags(flags);
|
||||
|
||||
CountDownLatch start_latch(1);
|
||||
CountDownLatch accept_latch(1);
|
||||
CountDownLatch end_latch(1);
|
||||
@@ -71,10 +87,14 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
Mediums mediums_1, mediums_2;
|
||||
ExceptionOr<OfflineFrame> upgrade_frame;
|
||||
|
||||
EXPECT_TRUE(mediums_1.GetBluetoothRadio().Enable());
|
||||
EXPECT_TRUE(mediums_2.GetBluetoothRadio().Enable());
|
||||
|
||||
auto handler_1 = std::make_unique<BluetoothBwuHandler>(
|
||||
mediums_1, [&](ClientProxy* client,
|
||||
std::unique_ptr<BwuHandler::IncomingSocketConnection>
|
||||
mutable_connection) {
|
||||
&mediums_1.GetBluetoothRadio(), &mediums_1.GetBluetoothClassic(),
|
||||
[&](ClientProxy* client,
|
||||
std::unique_ptr<BwuHandler::IncomingSocketConnection>
|
||||
mutable_connection) {
|
||||
LOG(WARNING) << "Server socket connection accept call back";
|
||||
accept_latch.CountDown();
|
||||
EXPECT_TRUE(end_latch.Await(kWaitDuration).result());
|
||||
@@ -83,11 +103,11 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
// client_1 works as Bluetooth Server Device
|
||||
SingleThreadExecutor server_executor;
|
||||
server_executor.Execute([&]() {
|
||||
ByteArray upgrade_path_available_frame =
|
||||
std::string upgrade_path_available_frame =
|
||||
handler_1->InitializeUpgradedMediumForEndpoint(&client_1,
|
||||
/*service_id=*/"A",
|
||||
/*endpoint_id=*/"1");
|
||||
EXPECT_FALSE(upgrade_path_available_frame.Empty());
|
||||
EXPECT_FALSE(upgrade_path_available_frame.empty());
|
||||
|
||||
upgrade_frame = parser::FromBytes(upgrade_path_available_frame);
|
||||
start_latch.CountDown();
|
||||
@@ -98,7 +118,9 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
// Wait till client_1 started as Bluetooth and then connect to it
|
||||
EXPECT_TRUE(start_latch.Await(kWaitDuration).result());
|
||||
std::unique_ptr<BwuHandler> handler_2 =
|
||||
std::make_unique<BluetoothBwuHandler>(mediums_2, nullptr);
|
||||
std::make_unique<BluetoothBwuHandler>(
|
||||
&mediums_2.GetBluetoothRadio(), &mediums_2.GetBluetoothClassic(),
|
||||
nullptr);
|
||||
|
||||
client_executor.Execute([&]() {
|
||||
auto bwu_frame =
|
||||
@@ -108,7 +130,7 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
handler_2->CreateUpgradedEndpointChannel(&client_2, /*service_id=*/"A",
|
||||
/*endpoint_id=*/"1",
|
||||
bwu_frame.upgrade_path_info());
|
||||
if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) {
|
||||
if (!enable_cancellation) {
|
||||
ASSERT_TRUE(result.has_value());
|
||||
std::unique_ptr<EndpointChannel> new_channel = std::move(result.value());
|
||||
EXPECT_TRUE(accept_latch.Await(kWaitDuration).result());
|
||||
@@ -117,9 +139,9 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
} else {
|
||||
EXPECT_FALSE(result.has_value());
|
||||
EXPECT_TRUE(result.has_error());
|
||||
EXPECT_EQ(
|
||||
result.error().operation_result_code(),
|
||||
OperationResultCode::CONNECTIVITY_BLUETOOTH_DEVICE_OBTAIN_FAILURE);
|
||||
EXPECT_EQ(result.error().operation_result_code(),
|
||||
OperationResultCode::
|
||||
CLIENT_CANCELLATION_CANCEL_BT_OUTGOING_CONNECTION);
|
||||
accept_latch.CountDown();
|
||||
}
|
||||
EXPECT_TRUE(mediums_2.GetBluetoothClassic().GetAddress().IsSet());
|
||||
@@ -131,5 +153,15 @@ TEST_F(BluetoothBwuTest, SoftAPBWUInit_STACreateEndpointChannel) {
|
||||
EXPECT_TRUE(end_latch.Await(kWaitDuration).result());
|
||||
}
|
||||
|
||||
TEST_F(BluetoothBwuTest,
|
||||
SoftAPBWUInit_STACreateEndpointChannel_WithCancellation) {
|
||||
RunSTACreateEndpointChannelTest(true);
|
||||
}
|
||||
|
||||
TEST_F(BluetoothBwuTest,
|
||||
SoftAPBWUInit_STACreateEndpointChannel_NoCancellation) {
|
||||
RunSTACreateEndpointChannelTest(false);
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -18,11 +18,9 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "connections/implementation/mediums/bluetooth_bwu_handler.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
@@ -30,8 +28,6 @@
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/socket.h"
|
||||
#include "internal/platform/types.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -54,8 +50,6 @@ std::string ScanModeToString(BluetoothAdapter::ScanMode mode) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using MultiplexSocket = mediums::multiplex::MultiplexSocket;
|
||||
|
||||
BluetoothClassic::BluetoothClassic(BluetoothRadio& radio)
|
||||
: BluetoothClassic(radio, std::make_unique<BluetoothClassicMedium>(
|
||||
radio.GetBluetoothAdapter())) {}
|
||||
@@ -64,15 +58,7 @@ BluetoothClassic::BluetoothClassic(
|
||||
BluetoothRadio& radio, std::unique_ptr<BluetoothClassicMedium> medium)
|
||||
: radio_(radio),
|
||||
adapter_(radio_.GetBluetoothAdapter()),
|
||||
medium_(std::move(medium)) {
|
||||
is_multiplex_enabled_ =
|
||||
NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplex) &&
|
||||
NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableMultiplexBluetooth);
|
||||
}
|
||||
medium_(std::move(medium)) {}
|
||||
|
||||
BluetoothClassic::~BluetoothClassic() {
|
||||
// Destructor is not taking locks, but methods it is calling are.
|
||||
@@ -82,20 +68,6 @@ BluetoothClassic::~BluetoothClassic() {
|
||||
}
|
||||
TurnOffDiscoverability();
|
||||
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
LOG(INFO) << "Closing multiplex sockets for " << multiplex_sockets_.size()
|
||||
<< " devices";
|
||||
if (is_multiplex_enabled_) {
|
||||
for (auto& [bt_mac, multiplex_socket] : multiplex_sockets_) {
|
||||
LOG(INFO) << "Closing multiplex sockets for "
|
||||
<< GetRemoteDevice(bt_mac).GetName();
|
||||
multiplex_socket->Shutdown();
|
||||
}
|
||||
}
|
||||
multiplex_sockets_.clear();
|
||||
}
|
||||
|
||||
// All the AcceptLoopRunnable objects in here should already have gotten an
|
||||
// opportunity to shut themselves down cleanly in the calls to
|
||||
// StopAcceptingConnections() above.
|
||||
@@ -384,24 +356,13 @@ ErrorOr<bool> BluetoothClassic::StartAcceptingConnections(
|
||||
auto owned_socket =
|
||||
server_sockets_.emplace(service_id, std::move(socket)).first->second;
|
||||
|
||||
if (is_multiplex_enabled_) {
|
||||
MultiplexSocket::ListenForIncomingConnection(
|
||||
service_id, Medium::BLUETOOTH,
|
||||
[&callback](const std::string& listening_service_id,
|
||||
MediumSocket* virtual_socket) mutable {
|
||||
if (callback) {
|
||||
callback(listening_service_id,
|
||||
*(down_cast<BluetoothSocket*>(virtual_socket)));
|
||||
}
|
||||
});
|
||||
}
|
||||
// Start the accept loop on a dedicated thread - this stays alive and
|
||||
// listening for new incoming connections until StopAcceptingConnections()
|
||||
// is invoked.
|
||||
accept_loops_runner_.Execute("bt-accept", [callback = std::move(callback),
|
||||
server_socket =
|
||||
std::move(owned_socket),
|
||||
service_id, this]() mutable {
|
||||
service_id]() mutable {
|
||||
while (true) {
|
||||
BluetoothSocket client_socket = server_socket.Accept();
|
||||
if (!client_socket.IsValid()) {
|
||||
@@ -411,34 +372,6 @@ ErrorOr<bool> BluetoothClassic::StartAcceptingConnections(
|
||||
}
|
||||
LOG(INFO) << "Accepted connection for " << service_id;
|
||||
bool callback_called = false;
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
if (is_multiplex_enabled_) {
|
||||
BluetoothSocket client_socket_bak = client_socket;
|
||||
auto physical_socket_ptr =
|
||||
std::make_shared<BluetoothSocket>(client_socket_bak);
|
||||
MultiplexSocket* multiplex_socket =
|
||||
MultiplexSocket::CreateIncomingSocket(physical_socket_ptr,
|
||||
service_id, 0);
|
||||
|
||||
if (multiplex_socket != nullptr &&
|
||||
multiplex_socket->GetVirtualSocket(service_id)) {
|
||||
multiplex_sockets_.emplace(
|
||||
client_socket.GetRemoteDevice().GetAddress(),
|
||||
multiplex_socket);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(
|
||||
service_id, Medium::BLUETOOTH);
|
||||
LOG(INFO) << "Multiplex virtaul socket created for "
|
||||
<< client_socket.GetRemoteDevice().GetName();
|
||||
if (callback) {
|
||||
callback(service_id,
|
||||
*(down_cast<BluetoothSocket*>(
|
||||
multiplex_socket->GetVirtualSocket(service_id))));
|
||||
callback_called = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback && !callback_called) {
|
||||
LOG(INFO) << "Call back triggered for physical socket.";
|
||||
callback(service_id, std::move(client_socket));
|
||||
@@ -475,10 +408,6 @@ bool BluetoothClassic::StopAcceptingConnections(const std::string& service_id) {
|
||||
<< " because it was never started.";
|
||||
return false;
|
||||
}
|
||||
if (is_multiplex_enabled_) {
|
||||
MultiplexSocket::StopListeningForIncomingConnection(service_id,
|
||||
Medium::BLUETOOTH);
|
||||
}
|
||||
|
||||
// Closing the BluetoothServerSocket will kick off the suicide of the thread
|
||||
// in accept_loops_thread_pool_ that blocks on
|
||||
@@ -507,29 +436,6 @@ bool BluetoothClassic::StopAcceptingConnections(const std::string& service_id) {
|
||||
ErrorOr<BluetoothSocket> BluetoothClassic::Connect(
|
||||
BluetoothDevice& bluetooth_device, const std::string& service_id,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
if (is_multiplex_enabled_) {
|
||||
LOG(INFO) << "multiplex_sockets_ size:" << multiplex_sockets_.size();
|
||||
auto it = multiplex_sockets_.find(bluetooth_device.GetAddress());
|
||||
if (it != multiplex_sockets_.end()) {
|
||||
MultiplexSocket* multiplex_socket = it->second;
|
||||
if (multiplex_socket->IsEnabled()) {
|
||||
auto* virtual_socket =
|
||||
multiplex_socket->EstablishVirtualSocket(service_id);
|
||||
// Should not happen.
|
||||
auto* bluetooth_socket = down_cast<BluetoothSocket*>(virtual_socket);
|
||||
if (bluetooth_socket == nullptr) {
|
||||
LOG(INFO) << "Failed to cast to BluetoothSocket for " << service_id
|
||||
<< " with " << bluetooth_device.GetName();
|
||||
return {Error(OperationResultCode::
|
||||
NEARBY_BT_VIRTUAL_SOCKET_CREATION_FAILURE)};
|
||||
}
|
||||
return *bluetooth_socket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
service_id_to_connect_attempts_count_map_[service_id] = 1;
|
||||
while (service_id_to_connect_attempts_count_map_[service_id] <=
|
||||
kConnectAttemptsLimit) {
|
||||
@@ -605,29 +511,6 @@ ErrorOr<BluetoothSocket> BluetoothClassic::AttemptToConnect(
|
||||
return {Error(
|
||||
OperationResultCode::CONNECTIVITY_BT_CLIENT_SOCKET_CREATION_FAILURE)};
|
||||
}
|
||||
|
||||
if (is_multiplex_enabled_) {
|
||||
// New MultiplexSocket but default disabled, should be enabled after
|
||||
// negotiated
|
||||
auto physical_socket_ptr = std::make_shared<BluetoothSocket>(socket);
|
||||
MultiplexSocket* multiplex_socket = MultiplexSocket::CreateOutgoingSocket(
|
||||
std::move(physical_socket_ptr), service_id);
|
||||
|
||||
auto* virtual_socket = multiplex_socket->GetVirtualSocket(service_id);
|
||||
// Should not happen.
|
||||
auto* bluetooth_socket = down_cast<BluetoothSocket*>(virtual_socket);
|
||||
if (bluetooth_socket == nullptr) {
|
||||
LOG(INFO) << "Failed to cast to BluetoothSocket for " << service_id
|
||||
<< " with " << bluetooth_device.GetName();
|
||||
return {Error(
|
||||
OperationResultCode::NEARBY_BT_VIRTUAL_SOCKET_CREATION_FAILURE)};
|
||||
}
|
||||
LOG(INFO) << "Multiplex socket created for " << bluetooth_device.GetName();
|
||||
multiplex_sockets_.emplace(bluetooth_device.GetAddress(),
|
||||
multiplex_socket);
|
||||
return *bluetooth_socket;
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
@@ -684,5 +567,12 @@ std::string BluetoothClassic::GenerateUuidFromString(const std::string& data) {
|
||||
return std::string(Uuid(data));
|
||||
}
|
||||
|
||||
std::unique_ptr<BwuHandler> BluetoothClassic::CreateBwuHandler(
|
||||
BwuHandler::IncomingConnectionCallback incoming_connection_callback) {
|
||||
MutexLock lock(&mutex_);
|
||||
return std::make_unique<BluetoothBwuHandler>(
|
||||
&radio_, this, std::move(incoming_connection_callback));
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
@@ -22,10 +22,8 @@
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
@@ -129,6 +127,9 @@ class BluetoothClassic {
|
||||
bool IsDiscovering(const std::string& serviceId) const
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
std::unique_ptr<BwuHandler> CreateBwuHandler(
|
||||
BwuHandler::IncomingConnectionCallback incoming_connection_callback);
|
||||
|
||||
protected:
|
||||
// Use for unit tests only to inject a BluetoothClassicMedium.
|
||||
BluetoothClassic(BluetoothRadio& radio,
|
||||
@@ -234,14 +235,6 @@ class BluetoothClassic {
|
||||
mutable Mutex discovery_callbacks_mutex_;
|
||||
absl::flat_hash_map<std::string, DiscoveredDeviceCallback>
|
||||
discovery_callbacks_ ABSL_GUARDED_BY(discovery_callbacks_mutex_);
|
||||
|
||||
// Whether the multiplex feature is enabled.
|
||||
bool is_multiplex_enabled_ = NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::kEnableMultiplex);
|
||||
|
||||
// A map of Bluetooth MacAddress -> MultiplexSocket.
|
||||
absl::flat_hash_map<MacAddress, mediums::multiplex::MultiplexSocket*>
|
||||
multiplex_sockets_ ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/bluetooth_endpoint_channel.h"
|
||||
#include "connections/implementation/mediums/bluetooth_endpoint_channel.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -46,4 +46,4 @@ class BluetoothEndpointChannel final : public BaseEndpointChannel {
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
#endif // CORE_INTERNAL_MEDIUMS_BLUETOOTH_ENDPOINT_CHANNEL_H_
|
||||
@@ -14,10 +14,15 @@
|
||||
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "connections/implementation/mediums/ble.h"
|
||||
#include "connections/implementation/mediums/bluetooth_classic.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#ifndef NO_WEBRTC
|
||||
#include "connections/implementation/mediums/webrtc/webrtc_impl.h"
|
||||
#endif
|
||||
#include "connections/implementation/mediums/webrtc.h"
|
||||
#include "connections/implementation/mediums/wifi.h"
|
||||
#include "connections/implementation/mediums/wifi_direct.h"
|
||||
@@ -27,6 +32,14 @@
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
Mediums::Mediums() {
|
||||
#ifndef NO_WEBRTC
|
||||
webrtc_ = std::make_unique<mediums::WebRtcImpl>();
|
||||
#else
|
||||
webrtc_ = std::make_unique<mediums::WebRtc>();
|
||||
#endif
|
||||
}
|
||||
|
||||
BluetoothRadio& Mediums::GetBluetoothRadio() { return bluetooth_radio_; }
|
||||
|
||||
BluetoothClassic& Mediums::GetBluetoothClassic() { return bluetooth_classic_; }
|
||||
@@ -41,7 +54,7 @@ WifiHotspot& Mediums::GetWifiHotspot() { return wifi_hotspot_; }
|
||||
|
||||
WifiDirect& Mediums::GetWifiDirect() { return wifi_direct_; }
|
||||
|
||||
mediums::WebRtc& Mediums::GetWebRtc() { return webrtc_; }
|
||||
mediums::WebRtc& Mediums::GetWebRtc() { return *webrtc_; }
|
||||
|
||||
Awdl& Mediums::GetAwdl() { return awdl_; }
|
||||
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_MEDIUMS_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_MEDIUMS_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "connections/implementation/mediums/awdl.h"
|
||||
#include "connections/implementation/mediums/ble.h"
|
||||
#include "connections/implementation/mediums/bluetooth_classic.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#ifdef NO_WEBRTC
|
||||
#include "connections/implementation/mediums/webrtc_stub.h"
|
||||
#else
|
||||
#include "connections/implementation/mediums/webrtc.h"
|
||||
#endif
|
||||
#include "connections/implementation/mediums/wifi.h"
|
||||
#include "connections/implementation/mediums/wifi_direct.h"
|
||||
#include "connections/implementation/mediums/wifi_hotspot.h"
|
||||
@@ -35,7 +33,7 @@ namespace connections {
|
||||
// Facilitates convenient and reliable usage of various wireless mediums.
|
||||
class Mediums {
|
||||
public:
|
||||
Mediums() = default;
|
||||
Mediums();
|
||||
~Mediums() = default;
|
||||
|
||||
// Returns a handle to the Bluetooth radio.
|
||||
@@ -81,7 +79,7 @@ class Mediums {
|
||||
WifiLan wifi_lan_;
|
||||
WifiHotspot wifi_hotspot_;
|
||||
WifiDirect wifi_direct_;
|
||||
mediums::WebRtc webrtc_;
|
||||
std::unique_ptr<mediums::WebRtc> webrtc_;
|
||||
Awdl awdl_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
# 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.
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "multiplex",
|
||||
srcs = [
|
||||
"multiplex_frames.cc",
|
||||
"multiplex_output_stream.cc",
|
||||
"multiplex_socket.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"multiplex_frames.h",
|
||||
"multiplex_output_stream.h",
|
||||
"multiplex_socket.h",
|
||||
],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/mediums:utils",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"//proto/mediums:multiplex_frames_cc_proto",
|
||||
"@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/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "multiplex_test",
|
||||
srcs = [
|
||||
"multiplex_frames_test.cc",
|
||||
"multiplex_output_stream_test.cc",
|
||||
"multiplex_socket_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":multiplex",
|
||||
"//connections/implementation:internal",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # buildcleaner: keep
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"//proto/mediums:multiplex_frames_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@@ -1,215 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/mediums/utils.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
using ::location::nearby::mediums::ConnectionResponseFrame;
|
||||
using ::location::nearby::mediums::MultiplexControlFrame;
|
||||
using ::location::nearby::mediums::MultiplexFrame;
|
||||
|
||||
ByteArray GenerateServiceIdHash(const std::string& service_id) {
|
||||
return Utils::Sha256Hash(service_id, kServiceIdHashLength);
|
||||
}
|
||||
|
||||
ByteArray GenerateServiceIdHashWithSalt(const std::string& service_id,
|
||||
std::string salt) {
|
||||
if (salt.empty()) {
|
||||
return GenerateServiceIdHash(service_id);
|
||||
}
|
||||
|
||||
return Utils::Sha256Hash(service_id + salt, kServiceIdHashLength);
|
||||
}
|
||||
|
||||
std::string GenerateServiceIdHashKey(const ByteArray& service_id_hash) {
|
||||
return Base64Utils::Encode(service_id_hash);
|
||||
}
|
||||
|
||||
std::string GenerateServiceIdHashKey(const std::string& service_id) {
|
||||
return GenerateServiceIdHashKey(GenerateServiceIdHash(service_id));
|
||||
}
|
||||
|
||||
std::string GenerateServiceIdHashKeyWithSalt(const std::string& service_id,
|
||||
std::string salt) {
|
||||
return GenerateServiceIdHashKey(
|
||||
GenerateServiceIdHashWithSalt(service_id, salt));
|
||||
}
|
||||
|
||||
ByteArray ToBytes(MultiplexFrame&& frame) {
|
||||
ByteArray bytes(frame.ByteSizeLong());
|
||||
frame.SerializeToArray(bytes.data(), bytes.size());
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ByteArray ForConnectionRequest(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt) {
|
||||
MultiplexFrame frame;
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::CONTROL_FRAME);
|
||||
auto* header = frame.mutable_header();
|
||||
header->set_salted_service_id_hash(std::string(
|
||||
GenerateServiceIdHashWithSalt(service_id, service_id_hash_salt)));
|
||||
header->set_service_id_hash_salt(service_id_hash_salt);
|
||||
|
||||
auto* control_frame = frame.mutable_control_frame();
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::CONNECTION_REQUEST);
|
||||
|
||||
return ToBytes(std::move(frame));
|
||||
}
|
||||
|
||||
ByteArray ForConnectionResponse(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
ConnectionResponseFrame::ConnectionResponseCode response_code) {
|
||||
MultiplexFrame frame;
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::CONTROL_FRAME);
|
||||
auto* header = frame.mutable_header();
|
||||
header->set_salted_service_id_hash(std::string(salted_service_id_hash));
|
||||
header->set_service_id_hash_salt(service_id_hash_salt);
|
||||
|
||||
auto* control_frame = frame.mutable_control_frame();
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::CONNECTION_RESPONSE);
|
||||
|
||||
auto* response_frame = control_frame->mutable_connection_response_frame();
|
||||
response_frame->set_connection_response_code(response_code);
|
||||
|
||||
return ToBytes(std::move(frame));
|
||||
}
|
||||
|
||||
ByteArray ForDisconnection(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt) {
|
||||
MultiplexFrame frame;
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::CONTROL_FRAME);
|
||||
auto* header = frame.mutable_header();
|
||||
header->set_salted_service_id_hash(std::string(
|
||||
GenerateServiceIdHashWithSalt(service_id, service_id_hash_salt)));
|
||||
header->set_service_id_hash_salt(service_id_hash_salt);
|
||||
|
||||
auto* control_frame = frame.mutable_control_frame();
|
||||
control_frame->set_control_frame_type(MultiplexControlFrame::DISCONNECTION);
|
||||
|
||||
return ToBytes(std::move(frame));
|
||||
}
|
||||
|
||||
ByteArray ForData(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt,
|
||||
bool should_pass_salt, absl::string_view data) {
|
||||
MultiplexFrame frame;
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::DATA_FRAME);
|
||||
auto* header = frame.mutable_header();
|
||||
header->set_salted_service_id_hash(std::string(
|
||||
GenerateServiceIdHashWithSalt(service_id, service_id_hash_salt)));
|
||||
if (should_pass_salt) {
|
||||
header->set_service_id_hash_salt(service_id_hash_salt);
|
||||
}
|
||||
|
||||
auto* data_frame = frame.mutable_data_frame();
|
||||
data_frame->set_data(data);
|
||||
|
||||
return ToBytes(std::move(frame));
|
||||
}
|
||||
|
||||
ExceptionOr<MultiplexFrame> FromBytes(const ByteArray& multiplex_frame_bytes) {
|
||||
MultiplexFrame frame;
|
||||
|
||||
if (frame.ParseFromString(std::string(multiplex_frame_bytes))) {
|
||||
if (!IsValid(frame)) {
|
||||
return ExceptionOr<MultiplexFrame>(Exception::kInvalidProtocolBuffer);
|
||||
}
|
||||
return ExceptionOr<MultiplexFrame>(std::move(frame));
|
||||
} else {
|
||||
return ExceptionOr<MultiplexFrame>(Exception::kInvalidProtocolBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsControlFrame(MultiplexFrame::MultiplexFrameType frame_type) {
|
||||
return frame_type == MultiplexFrame::CONTROL_FRAME;
|
||||
}
|
||||
|
||||
bool IsDataFrame(MultiplexFrame::MultiplexFrameType frame_type) {
|
||||
return frame_type == MultiplexFrame::DATA_FRAME;
|
||||
}
|
||||
|
||||
bool IsValid(const MultiplexFrame& frame) {
|
||||
switch (frame.frame_type()) {
|
||||
case MultiplexFrame::CONTROL_FRAME:
|
||||
return IsValidControlFrame(frame);
|
||||
case MultiplexFrame::DATA_FRAME:
|
||||
return IsValidDataFrame(frame);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValidControlFrame(const MultiplexFrame& frame) {
|
||||
if (!frame.has_control_frame()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (frame.control_frame().control_frame_type()) {
|
||||
case MultiplexControlFrame::CONNECTION_REQUEST:
|
||||
case MultiplexControlFrame::CONNECTION_RESPONSE:
|
||||
case MultiplexControlFrame::DISCONNECTION:
|
||||
if (frame.header().salted_service_id_hash().size() ==
|
||||
kServiceIdHashLength) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsValidDataFrame(const MultiplexFrame& frame) {
|
||||
return frame.has_data_frame() &&
|
||||
frame.header().salted_service_id_hash().size() == kServiceIdHashLength;
|
||||
}
|
||||
|
||||
bool IsMultiplexFrame(const ByteArray& data) {
|
||||
ExceptionOr<MultiplexFrame> frame = FromBytes(data);
|
||||
if (!frame.ok()) {
|
||||
return false;
|
||||
} else {
|
||||
LOG(INFO) << "Checked data is a multiplex frame. Is Control ? "
|
||||
<< frame.result().has_control_frame() << ", is data ? "
|
||||
<< frame.result().has_data_frame();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
// 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 CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_FRAMES_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_FRAMES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "proto/mediums/multiplex_frames.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
constexpr int kServiceIdHashLength = 4;
|
||||
|
||||
// Serialize/Deserialize MultiplexFrame messages.
|
||||
|
||||
// Parses incoming MultiplexFrame message.
|
||||
// Returns MultiplexFrame if parser was able to understand it, or
|
||||
// Exception::kInvalidProtocolBuffer, if parser failed.
|
||||
|
||||
// Generates a service ID hash bytes with {@link
|
||||
// MultiplexFrames#SERVICE_ID_HASH_LENGTH}.
|
||||
ByteArray GenerateServiceIdHash(const std::string& service_id);
|
||||
|
||||
// Generates a service ID hash bytes with salt and {@link
|
||||
// MultiplexFrames#SERVICE_ID_HASH_LENGTH}.
|
||||
ByteArray GenerateServiceIdHashWithSalt(const std::string& service_id,
|
||||
std::string salt);
|
||||
|
||||
// Converts the service Id hash bytes to a Base64 encoded string to be used as a
|
||||
// {@code Map} key.
|
||||
std::string GenerateServiceIdHashKey(const ByteArray& service_id_hash);
|
||||
|
||||
// Generates a service ID hash bytes with {@link
|
||||
// MultiplexFrames#SERVICE_ID_HASH_LENGTH} and converts to a Base64 encoded
|
||||
// string to be used as a {@code Map} key.
|
||||
std::string GenerateServiceIdHashKey(const std::string& service_id);
|
||||
|
||||
// Generates a service ID hash bytes with salt and {@link
|
||||
// MultiplexFrames#SERVICE_ID_HASH_LENGTH} and converts to a Base64 encoded
|
||||
// string to be used as a { @code Map } key.
|
||||
std::string GenerateServiceIdHashKeyWithSalt(const std::string& service_id,
|
||||
std::string salt);
|
||||
|
||||
// Build a MultiplexFrame Connection Request frame Bytes stream.
|
||||
// @param service_id The service ID of the connection.
|
||||
// @param service_id_hash_salt The salt used to generate the service ID hash.
|
||||
ByteArray ForConnectionRequest(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt);
|
||||
|
||||
// Build a MultiplexFrame Connection Response frame Bytes stream.
|
||||
// @param salted_service_id_hash The salted service ID hash.
|
||||
// @param service_id_hash_salt The salt used to generate the service ID hash.
|
||||
// @param response_code The response code of the connection.
|
||||
ByteArray ForConnectionResponse(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
location::nearby::mediums::ConnectionResponseFrame::ConnectionResponseCode
|
||||
response_code);
|
||||
|
||||
// Build a MultiplexFrame Disconnection frame Bytes stream.
|
||||
// @param service_id The service ID of the connection.
|
||||
// @param service_id_hash_salt The salt used to generate the service ID hash.
|
||||
ByteArray ForDisconnection(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt);
|
||||
|
||||
// Build a MultiplexFrame Data frame Bytes stream.
|
||||
// @param service_id The service ID of the connection.
|
||||
// @param service_id_hash_salt The salt used to generate the service ID hash.
|
||||
// @param should_pass_salt Whether to pass the salt in the data frame.
|
||||
// @param data The data to send.
|
||||
ByteArray ForData(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt,
|
||||
bool should_pass_salt, absl::string_view data);
|
||||
|
||||
ExceptionOr<location::nearby::mediums::MultiplexFrame> FromBytes(
|
||||
const ByteArray& multiplex_frame_bytes);
|
||||
|
||||
bool IsControlFrame(
|
||||
location::nearby::mediums::MultiplexFrame::MultiplexFrameType frame_type);
|
||||
bool IsDataFrame(
|
||||
location::nearby::mediums::MultiplexFrame::MultiplexFrameType frame_type);
|
||||
bool IsValid(const location::nearby::mediums::MultiplexFrame& frame);
|
||||
bool IsValidControlFrame(
|
||||
const location::nearby::mediums::MultiplexFrame& frame);
|
||||
bool IsValidDataFrame(const location::nearby::mediums::MultiplexFrame& frame);
|
||||
bool IsMultiplexFrame(const ByteArray& data);
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_FRAMES_H_
|
||||
@@ -1,170 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
using ::location::nearby::mediums::MultiplexFrame;
|
||||
using ::location::nearby::mediums::MultiplexControlFrame;
|
||||
using ::location::nearby::mediums::ConnectionResponseFrame;
|
||||
|
||||
constexpr absl::string_view kServiceId_1 = "serviceId_1";
|
||||
constexpr absl::string_view kServiceId_2 = "serviceId_2";
|
||||
|
||||
TEST(MultiplexFrameTest, FrameValidation) {
|
||||
const ByteArray data("abcdefghijklmnopqrstuvwxyz");
|
||||
MultiplexFrame frame;
|
||||
EXPECT_FALSE(IsValid(frame));
|
||||
frame.set_frame_type(MultiplexFrame::CONTROL_FRAME);
|
||||
EXPECT_FALSE(IsValidControlFrame(frame));
|
||||
|
||||
auto* control_frame = frame.mutable_control_frame();
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::UNKNOWN_CONTROL_FRAME_TYPE);
|
||||
EXPECT_FALSE(IsValidControlFrame(frame));
|
||||
auto* header = frame.mutable_header();
|
||||
header->set_salted_service_id_hash(std::string(
|
||||
GenerateServiceIdHashWithSalt(std::string(kServiceId_1), "1234")));
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::CONNECTION_REQUEST);
|
||||
EXPECT_TRUE(IsValidControlFrame(frame));
|
||||
EXPECT_TRUE(IsValid(frame));
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::CONNECTION_RESPONSE);
|
||||
EXPECT_TRUE(IsValidControlFrame(frame));
|
||||
EXPECT_TRUE(IsValid(frame));
|
||||
control_frame->set_control_frame_type(
|
||||
MultiplexControlFrame::DISCONNECTION);
|
||||
EXPECT_TRUE(IsValidControlFrame(frame));
|
||||
EXPECT_TRUE(IsValid(frame));
|
||||
|
||||
EXPECT_FALSE(IsValidDataFrame(frame));
|
||||
frame.set_frame_type(MultiplexFrame::DATA_FRAME);
|
||||
auto* data_frame = frame.mutable_data_frame();
|
||||
data_frame->set_data(std::string(std::move(data)));
|
||||
EXPECT_TRUE(IsValidDataFrame(frame));
|
||||
EXPECT_TRUE(IsValid(frame));
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::UNKNOWN_FRAME_TYPE);
|
||||
EXPECT_FALSE(IsValid(frame));
|
||||
|
||||
frame.set_frame_type(MultiplexFrame::DATA_FRAME);
|
||||
auto serialized_bytes = ByteArray(frame.SerializeAsString());
|
||||
EXPECT_TRUE(IsMultiplexFrame(std::move(serialized_bytes)));
|
||||
|
||||
EXPECT_TRUE(IsControlFrame(MultiplexFrame::CONTROL_FRAME));
|
||||
EXPECT_FALSE(IsControlFrame(MultiplexFrame::DATA_FRAME));
|
||||
EXPECT_TRUE(IsDataFrame(MultiplexFrame::DATA_FRAME));
|
||||
EXPECT_FALSE(IsDataFrame(MultiplexFrame::UNKNOWN_FRAME_TYPE));
|
||||
}
|
||||
|
||||
TEST(MultiplexFrameTest, HashValidtion) {
|
||||
auto service_id_hash_1 = GenerateServiceIdHash(std::string(kServiceId_1));
|
||||
EXPECT_EQ(service_id_hash_1.size(), kServiceIdHashLength);
|
||||
auto service_id_hash_2 = GenerateServiceIdHash(std::string(kServiceId_2));
|
||||
EXPECT_NE(service_id_hash_1, service_id_hash_2);
|
||||
|
||||
auto hash_key_1 = GenerateServiceIdHashKey(service_id_hash_1);
|
||||
auto hash_key_2 = GenerateServiceIdHashKey(service_id_hash_2);
|
||||
EXPECT_NE(hash_key_1, hash_key_2);
|
||||
|
||||
auto service_id_hash_with_salt_1 =
|
||||
GenerateServiceIdHashWithSalt(std::string(kServiceId_1), "1234");
|
||||
EXPECT_EQ(service_id_hash_with_salt_1.size(), kServiceIdHashLength);
|
||||
auto service_id_hash_with_salt_2 =
|
||||
GenerateServiceIdHashWithSalt(std::string(kServiceId_2), "1234");
|
||||
EXPECT_NE(service_id_hash_with_salt_1, service_id_hash_with_salt_2);
|
||||
service_id_hash_with_salt_2 =
|
||||
GenerateServiceIdHashWithSalt(std::string(kServiceId_1), "abcd");
|
||||
EXPECT_NE(service_id_hash_with_salt_1, service_id_hash_with_salt_2);
|
||||
|
||||
auto hash_key_with_salt_1 =
|
||||
GenerateServiceIdHashKeyWithSalt(std::string(kServiceId_1), "1234");
|
||||
auto hash_key_with_salt_2 =
|
||||
GenerateServiceIdHashKeyWithSalt(std::string(kServiceId_2), "1234");
|
||||
EXPECT_NE(hash_key_with_salt_1, hash_key_with_salt_2);
|
||||
}
|
||||
|
||||
TEST(MultiplexFrameTest, CanGenerateConnectionRequest) {
|
||||
ByteArray bytes = ForConnectionRequest(std::string(kServiceId_1), "1234");
|
||||
auto request = FromBytes(bytes);
|
||||
ASSERT_TRUE(request.ok());
|
||||
auto frame = request.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::CONNECTION_REQUEST);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
"1234")));
|
||||
}
|
||||
|
||||
TEST(MultiplexFrameTest, CanGenerateConnectionRespons) {
|
||||
auto service_id_hash_with_salt_2 =
|
||||
GenerateServiceIdHashWithSalt(std::string(kServiceId_2), "1234");
|
||||
ByteArray bytes =
|
||||
ForConnectionResponse(service_id_hash_with_salt_2, "1234",
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED);
|
||||
auto response = FromBytes(bytes);
|
||||
ASSERT_TRUE(response.ok());
|
||||
auto frame = response.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::CONNECTION_RESPONSE);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(service_id_hash_with_salt_2));
|
||||
EXPECT_EQ(frame.control_frame()
|
||||
.connection_response_frame()
|
||||
.connection_response_code(),
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED);
|
||||
}
|
||||
|
||||
TEST(MultiplexFrameTest, CanGenerateDisconnection) {
|
||||
ByteArray bytes = ForDisconnection(std::string(kServiceId_1), "1234");
|
||||
auto response = FromBytes(bytes);
|
||||
ASSERT_TRUE(response.ok());
|
||||
auto frame = response.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::DISCONNECTION);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
"1234")));
|
||||
}
|
||||
|
||||
TEST(MultiplexFrameTest, CanGenerateData) {
|
||||
absl::string_view data = "abcdefghijklmnopqrstuvwxyz";
|
||||
ByteArray bytes =
|
||||
ForData(std::string(kServiceId_1), "1234", true, data);
|
||||
auto response = FromBytes(bytes);
|
||||
ASSERT_TRUE(response.ok());
|
||||
auto frame = response.result();
|
||||
EXPECT_EQ(frame.frame_type(), MultiplexFrame::DATA_FRAME);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
"1234")));
|
||||
EXPECT_EQ(frame.data_frame().data(),
|
||||
std::string("abcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,360 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_output_stream.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
#include "internal/platform/array_blocking_queue.h"
|
||||
#include "internal/platform/atomic_boolean.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
namespace {
|
||||
using ::location::nearby::mediums::ConnectionResponseFrame;
|
||||
|
||||
constexpr absl::string_view kFakeSalt = "RECEIVER_CONDIMENT";
|
||||
} // namespace
|
||||
|
||||
// Implementation for class MultiplexOutputStream
|
||||
MultiplexOutputStream::MultiplexOutputStream(OutputStream* physical_writer,
|
||||
AtomicBoolean& is_enabled)
|
||||
: is_enabled_(is_enabled),
|
||||
physical_writer_(physical_writer),
|
||||
multiplex_writer_{physical_writer} {}
|
||||
|
||||
Exception MultiplexOutputStream::WaitForResult(const std::string& method_name,
|
||||
Future<bool>* future) {
|
||||
if (!future) {
|
||||
LOG(INFO) << "No future to wait for; return with error.";
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
LOG(INFO) << "Waiting for future to complete: " << method_name;
|
||||
ExceptionOr<bool> result =
|
||||
future->Get(FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.mediums_frame_write_timeout_millis);
|
||||
if (!result.ok()) {
|
||||
LOG(INFO) << "Future:[" << method_name
|
||||
<< "] completed with exception:" << result.exception();
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
if (result.result()) {
|
||||
LOG(INFO) << "Future:[" << method_name << "] completed with success.";
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
LOG(INFO) << "Future:[" << method_name << "] completed with failure.";
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
bool MultiplexOutputStream::WriteConnectionRequestFrame(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
if (!is_enabled_.Get()) {
|
||||
return false;
|
||||
}
|
||||
Future<bool> future;
|
||||
multiplex_writer_.EnqueueToSend(
|
||||
&future, ForConnectionRequest(service_id, service_id_hash_salt),
|
||||
"MultiplexFrame::CONNECTION_REQUEST");
|
||||
if (WaitForResult("MultiplexFrame::CONNECTION_REQUEST", &future).Ok())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MultiplexOutputStream::WriteConnectionResponseFrame(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
ConnectionResponseFrame::ConnectionResponseCode response_code) {
|
||||
if (!is_enabled_.Get()) {
|
||||
return false;
|
||||
}
|
||||
Future<bool> future;
|
||||
multiplex_writer_.EnqueueToSend(
|
||||
&future,
|
||||
ForConnectionResponse(salted_service_id_hash, service_id_hash_salt,
|
||||
response_code),
|
||||
"MultiplexFrame::CONNECTION_RESPONSE");
|
||||
if (WaitForResult("MultiplexFrame::CONNECTION_RESPONSE", &future).Ok())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MultiplexOutputStream::Close(const std::string& service_id) {
|
||||
auto item = virtual_output_streams_.find(service_id);
|
||||
if (item == virtual_output_streams_.end()) {
|
||||
LOG(INFO) << "Don't need to close VirtualOutputStream(" << service_id
|
||||
<< ") because it's already gone.";
|
||||
return false;
|
||||
}
|
||||
|
||||
item->second->Close();
|
||||
if (is_enabled_.Get()) {
|
||||
Future<bool> future;
|
||||
multiplex_writer_.EnqueueToSend(
|
||||
&future,
|
||||
ForDisconnection(service_id, item->second->GetServiceIdHashSalt()),
|
||||
"MultiplexFrame::DISCONNECTION");
|
||||
WaitForResult("MultiplexFrame::DISCONNECTION", &future);
|
||||
}
|
||||
virtual_output_streams_.erase(service_id);
|
||||
if (virtual_output_streams_.empty()) {
|
||||
physical_writer_->Close();
|
||||
multiplex_writer_.Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::CloseAll() {
|
||||
for (auto& [service_id, virtual_output_stream] : virtual_output_streams_) {
|
||||
if (is_enabled_.Get()) {
|
||||
Future<bool> future;
|
||||
multiplex_writer_.EnqueueToSend(
|
||||
&future,
|
||||
ForDisconnection(service_id,
|
||||
virtual_output_stream->GetServiceIdHashSalt()),
|
||||
"MultiplexFrame::DISCONNECTION");
|
||||
WaitForResult("MultiplexFrame::DISCONNECTION", &future);
|
||||
}
|
||||
virtual_output_stream->Close();
|
||||
}
|
||||
virtual_output_streams_.clear();
|
||||
physical_writer_->Close();
|
||||
multiplex_writer_.Close();
|
||||
}
|
||||
|
||||
OutputStream*
|
||||
MultiplexOutputStream::CreateVirtualOutputStreamForFirstVirtualSocket(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
return virtual_output_streams_
|
||||
.emplace(service_id,
|
||||
std::make_unique<VirtualOutputStream>(
|
||||
service_id, service_id_hash_salt, physical_writer_,
|
||||
multiplex_writer_,
|
||||
VirtualOutputStreamType::kFirstVirtualSocket, *this))
|
||||
.first->second.get();
|
||||
}
|
||||
|
||||
OutputStream* MultiplexOutputStream::CreateVirtualOutputStream(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
return virtual_output_streams_
|
||||
.emplace(service_id,
|
||||
std::make_unique<VirtualOutputStream>(
|
||||
service_id, service_id_hash_salt, physical_writer_,
|
||||
multiplex_writer_,
|
||||
VirtualOutputStreamType::kNormalVirtualSocket, *this))
|
||||
.first->second.get();
|
||||
}
|
||||
|
||||
std::string MultiplexOutputStream::GetServiceIdHashSalt(
|
||||
const std::string& service_id) {
|
||||
auto item = virtual_output_streams_.find(service_id);
|
||||
if (item != virtual_output_streams_.end()) {
|
||||
return item->second->GetServiceIdHashSalt();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::Shutdown() {
|
||||
physical_writer_->Close();
|
||||
multiplex_writer_.Close();
|
||||
}
|
||||
|
||||
// Implementation for class MultiplexOutputStream::MultiplexWriter
|
||||
MultiplexOutputStream::MultiplexWriter::MultiplexWriter(
|
||||
OutputStream* physical_writer)
|
||||
: physical_writer_(physical_writer) {}
|
||||
|
||||
MultiplexOutputStream::MultiplexWriter::~MultiplexWriter() {
|
||||
Close();
|
||||
physical_writer_ = nullptr;
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::MultiplexWriter::EnqueueToSend(
|
||||
Future<bool>* future, const ByteArray& data,
|
||||
const std::string& frame_name) {
|
||||
MutexLock lock(&writing_mutex_);
|
||||
data_queue_.Put(EnqueuedFrame(future, data));
|
||||
|
||||
if (is_writing_) {
|
||||
return;
|
||||
}
|
||||
is_writing_ = true;
|
||||
is_writing_cond_.Notify();
|
||||
if (!is_write_loop_running_) {
|
||||
is_write_loop_running_ = true;
|
||||
writer_thread_.Execute("Start writing", [this] { StartWriting(); });
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::MultiplexWriter::StartWriting() {
|
||||
LOG(INFO) << "Writing loop started.";
|
||||
while (true) {
|
||||
auto enqueued_frame = data_queue_.TryTake();
|
||||
if (enqueued_frame != std::nullopt) {
|
||||
Write(enqueued_frame.value());
|
||||
continue;
|
||||
}
|
||||
{
|
||||
MutexLock lock(&writing_mutex_);
|
||||
if (data_queue_.Empty() && is_writing_ && !is_closed_) {
|
||||
is_writing_ = false;
|
||||
LOG(INFO) << "Waiting for data_queue_ has data.";
|
||||
Exception wait_succeeded = is_writing_cond_.Wait();
|
||||
if (!wait_succeeded.Ok()) {
|
||||
LOG(WARNING) << "Failure waiting to wait: " << wait_succeeded.value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (is_closed_) {
|
||||
LOG(INFO) << "Notify to close_writing_thread";
|
||||
MutexLock lock(&close_writing_thread_mutex_);
|
||||
close_writing_thread_cond_.Notify();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(INFO) << "Writing loop stopped.";
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::MultiplexWriter::Write(
|
||||
EnqueuedFrame& enqueued_frame) {
|
||||
MutexLock lock(&writer_mutex_);
|
||||
if (!Base64Utils::WriteInt(physical_writer_, enqueued_frame.data_.size())
|
||||
.Ok()) {
|
||||
enqueued_frame.future_->SetException({Exception::kIo});
|
||||
return;
|
||||
};
|
||||
if (!physical_writer_->Write(enqueued_frame.data_.AsStringView()).Ok()) {
|
||||
enqueued_frame.future_->SetException({Exception::kIo});
|
||||
return;
|
||||
};
|
||||
if (!physical_writer_->Flush().Ok()) {
|
||||
enqueued_frame.future_->SetException({Exception::kIo});
|
||||
return;
|
||||
};
|
||||
enqueued_frame.future_->Set(true);
|
||||
}
|
||||
|
||||
void MultiplexOutputStream::MultiplexWriter::Close() {
|
||||
if (is_closed_) {
|
||||
LOG(INFO) << "MultiplexWriter is already closed.";
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Stop writing loop and Shutdown writer thread.";
|
||||
{
|
||||
MutexLock lock(&writing_mutex_);
|
||||
is_closed_ = true;
|
||||
if (!is_write_loop_running_) {
|
||||
writer_thread_.Shutdown();
|
||||
return;
|
||||
}
|
||||
is_write_loop_running_ = false;
|
||||
is_writing_cond_.Notify();
|
||||
}
|
||||
LOG(INFO) << "Wait to close_writing_thread";
|
||||
{
|
||||
MutexLock lock(&close_writing_thread_mutex_);
|
||||
close_writing_thread_cond_.Wait(absl::Milliseconds(20));
|
||||
LOG(INFO) << "Shutdown writer thread.";
|
||||
writer_thread_.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
MultiplexOutputStream::VirtualOutputStream::VirtualOutputStream(
|
||||
std::string service_id, std::string service_id_hash_salt,
|
||||
OutputStream* physical_writer, MultiplexWriter& multiplex_writer,
|
||||
VirtualOutputStreamType virtual_output_stream_type,
|
||||
MultiplexOutputStream& multiplex_output_stream)
|
||||
: service_id_(service_id),
|
||||
service_id_hash_salt_(service_id_hash_salt),
|
||||
physical_writer_(physical_writer),
|
||||
multiplex_writer_(multiplex_writer),
|
||||
virtual_output_stream_type_(virtual_output_stream_type),
|
||||
multiplex_output_stream_(multiplex_output_stream) {}
|
||||
|
||||
Exception MultiplexOutputStream::VirtualOutputStream::Write(
|
||||
absl::string_view data) {
|
||||
if (is_closed_.Get()) {
|
||||
LOG(WARNING) << "Failed to write data because the VirtualOutputStream for "
|
||||
<< service_id_ << " closed";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
if (multiplex_output_stream_.is_enabled_.Get()) {
|
||||
bool should_pass_salt = false;
|
||||
if (IsFirstVirtualOutputStream()) {
|
||||
if (!first_frame_sent_for_first_virtual_output_stream_) {
|
||||
first_frame_sent_for_first_virtual_output_stream_ = true;
|
||||
should_pass_salt = true;
|
||||
}
|
||||
// Fixes b/290724590, b/290983930 which can't get the correct socket
|
||||
// from the virtualSockets map. NS receiver side will pass 2
|
||||
// DATA_FRAMEs continuously to the remote sender side but originally
|
||||
// impl will only consider the 1st one. Add below fix to handle 2nd
|
||||
// frame which the salt is still fake one and change shouldPassSalt to
|
||||
// true to let the remote handle correctly.
|
||||
if ((service_id_hash_salt_ == kFakeSalt) && !should_pass_salt) {
|
||||
should_pass_salt = true;
|
||||
LOG(INFO) << "service_idHashSalt is still a fake one and "
|
||||
"not changed yet; continue to pass salt.";
|
||||
}
|
||||
}
|
||||
ByteArray data_frame =
|
||||
ForData(service_id_, service_id_hash_salt_, should_pass_salt, data);
|
||||
Future<bool> future;
|
||||
multiplex_writer_.EnqueueToSend(&future, data_frame,
|
||||
"MultiplexFrame::DATA_FRAME");
|
||||
return multiplex_output_stream_.WaitForResult("MultiplexFrame::DATA_FRAME",
|
||||
&future);
|
||||
} else {
|
||||
if (!physical_writer_->Write(data).Ok()) {
|
||||
return {Exception::kIo};
|
||||
};
|
||||
if (!physical_writer_->Flush().Ok()) {
|
||||
return {Exception::kIo};
|
||||
};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception MultiplexOutputStream::VirtualOutputStream::Flush() {
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception MultiplexOutputStream::VirtualOutputStream::Close() {
|
||||
LOG(INFO) << "MultiplexOutputStream::VirtualOutputStream::Close";
|
||||
is_closed_.Set(true);
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,209 +0,0 @@
|
||||
// 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 CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_OUTPUT_STREAM_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_OUTPUT_STREAM_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/array_blocking_queue.h"
|
||||
#include "internal/platform/atomic_boolean.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
#include "proto/mediums/multiplex_frames.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
/**
|
||||
* A helper class to send out the {@code MultiplexControlFrame} and the outgoing
|
||||
* data from clients. It schedules control and data frames with priority below
|
||||
*
|
||||
* <p>{@link MultiplexControlFrameType#CONNECTION_REQUEST} and {@link
|
||||
* MultiplexControlFrameType#CONNECTION_RESPONSE} have the highest priority
|
||||
*
|
||||
* <p>All {@link MultiplexDataFrame} has the medium priority. If there's
|
||||
* multiple clients send data at the same time, should poll every client's
|
||||
* outgoing data in sequence. For example, client A and B send data at the same
|
||||
* time, the outgoing data sequence should like A-Frame-1, B-Frame-1, A-Frame-2,
|
||||
* B-Frame-2,...
|
||||
*
|
||||
* <p>{@link MultiplexControlFrameType#DISCONNECTION} has the same priority with
|
||||
* {@link MultiplexDataFrame} because the disconnect should not make the already
|
||||
* enqueued data failed to send out, so put it in the same priority queue with
|
||||
* the MultiplexDataFrame.
|
||||
*/
|
||||
class MultiplexOutputStream {
|
||||
public:
|
||||
enum class VirtualOutputStreamType {
|
||||
// The type of virtual socket established for the physical socket is
|
||||
// created.
|
||||
kFirstVirtualSocket = 0,
|
||||
// The others except FIRST_VIRTUAL_SCOKET type.
|
||||
kNormalVirtualSocket = 1,
|
||||
};
|
||||
|
||||
MultiplexOutputStream(OutputStream* physical_writer,
|
||||
AtomicBoolean& is_enabled);
|
||||
~MultiplexOutputStream() = default;
|
||||
|
||||
// Writes the connection request frame to the physical output stream.
|
||||
bool WriteConnectionRequestFrame(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt);
|
||||
|
||||
// Writes the connection response frame to the physical output stream.
|
||||
bool WriteConnectionResponseFrame(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
::location::nearby::mediums::ConnectionResponseFrame::
|
||||
ConnectionResponseCode response_code);
|
||||
|
||||
// Closes the virtual output stream.
|
||||
bool Close(const std::string& service_id);
|
||||
|
||||
// Closes all virtual output streams.
|
||||
void CloseAll();
|
||||
|
||||
// Waits for the result of the future.
|
||||
Exception WaitForResult(const std::string& method_name, Future<bool>* future);
|
||||
|
||||
// Creates the virtual output stream for the first virtual socket.
|
||||
OutputStream* CreateVirtualOutputStreamForFirstVirtualSocket(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt);
|
||||
|
||||
// Creates the virtual output stream.
|
||||
OutputStream* CreateVirtualOutputStream(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt);
|
||||
|
||||
// Gets the service id hash salt.
|
||||
std::string GetServiceIdHashSalt(const std::string& service_id);
|
||||
|
||||
// Shuts down the multiplex output stream.
|
||||
void Shutdown();
|
||||
|
||||
class EnqueuedFrame {
|
||||
public:
|
||||
EnqueuedFrame(Future<bool>* future, ByteArray data)
|
||||
: future_(future), data_(data) {}
|
||||
~EnqueuedFrame() = default;
|
||||
|
||||
Future<bool>* future_;
|
||||
ByteArray data_;
|
||||
};
|
||||
|
||||
class MultiplexWriter {
|
||||
public:
|
||||
explicit MultiplexWriter(OutputStream* physical_writer);
|
||||
~MultiplexWriter();
|
||||
|
||||
// Enqueues the frame to be sent out.
|
||||
void EnqueueToSend(Future<bool>* future, const ByteArray& data,
|
||||
const std::string& frame_name);
|
||||
// Closes the writer.
|
||||
void Close();
|
||||
|
||||
private:
|
||||
// Starts the writer thread.
|
||||
void StartWriting();
|
||||
|
||||
// Writes the enqueued frame.
|
||||
void Write(EnqueuedFrame& enqueued_frame);
|
||||
|
||||
Mutex writer_mutex_;
|
||||
OutputStream* physical_writer_ ABSL_PT_GUARDED_BY(writer_mutex_);
|
||||
|
||||
ArrayBlockingQueue<EnqueuedFrame> data_queue_{
|
||||
FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.multiplex_socket_middle_priority_queue_capacity};
|
||||
mutable Mutex writing_mutex_;
|
||||
ConditionVariable is_writing_cond_{&writing_mutex_};
|
||||
bool is_writing_ ABSL_GUARDED_BY(writing_mutex_) = false;
|
||||
bool is_closed_ = false;
|
||||
mutable Mutex close_writing_thread_mutex_;
|
||||
ConditionVariable close_writing_thread_cond_{&close_writing_thread_mutex_};
|
||||
|
||||
// The single thread to write all enqueued frames.
|
||||
SingleThreadExecutor writer_thread_;
|
||||
bool is_write_loop_running_ = false;
|
||||
};
|
||||
|
||||
class VirtualOutputStream : public OutputStream {
|
||||
public:
|
||||
VirtualOutputStream(std::string service_id,
|
||||
std::string service_id_hash_salt,
|
||||
OutputStream* physical_writer,
|
||||
MultiplexWriter& multiplex_writer,
|
||||
VirtualOutputStreamType virtual_output_stream_type,
|
||||
MultiplexOutputStream& multiplex_output_stream);
|
||||
~VirtualOutputStream() override = default;
|
||||
|
||||
// Returns true if the virtual output stream is the first virtual output
|
||||
// stream.
|
||||
bool IsFirstVirtualOutputStream() {
|
||||
return virtual_output_stream_type_ ==
|
||||
VirtualOutputStreamType::kFirstVirtualSocket;
|
||||
}
|
||||
|
||||
// Returns the service id hash salt.
|
||||
std::string GetServiceIdHashSalt() { return service_id_hash_salt_; }
|
||||
|
||||
// Sets the service id hash salt.
|
||||
void SetserviceIdHashSalt(std::string service_id_hash_salt) {
|
||||
service_id_hash_salt_ = service_id_hash_salt;
|
||||
}
|
||||
|
||||
// Writes the data to the physical output stream.
|
||||
Exception Write(absl::string_view data) override;
|
||||
// Flushes the physical output stream.
|
||||
Exception Flush() override;
|
||||
// Closes the virtual output stream.
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
AtomicBoolean is_closed_{false};
|
||||
|
||||
std::string service_id_;
|
||||
std::string service_id_hash_salt_;
|
||||
OutputStream* physical_writer_;
|
||||
MultiplexWriter& multiplex_writer_;
|
||||
VirtualOutputStreamType virtual_output_stream_type_;
|
||||
bool first_frame_sent_for_first_virtual_output_stream_ = false;
|
||||
MultiplexOutputStream& multiplex_output_stream_;
|
||||
};
|
||||
|
||||
private:
|
||||
AtomicBoolean& is_enabled_;
|
||||
OutputStream* physical_writer_;
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<VirtualOutputStream>>
|
||||
virtual_output_streams_;
|
||||
MultiplexWriter multiplex_writer_;
|
||||
};
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_OUTPUT_STREAM_H_
|
||||
@@ -1,253 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_output_stream.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
#include "internal/platform/atomic_boolean.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/multi_thread_executor.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/pipe.h"
|
||||
#include "proto/mediums/multiplex_frames.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
constexpr absl::string_view kServiceId_1 = "serviceId_1";
|
||||
constexpr absl::string_view kServiceId_2 = "serviceId_2";
|
||||
constexpr absl::string_view kNoSalt = "";
|
||||
constexpr absl::string_view kSalt_1 = "DNFG";
|
||||
constexpr absl::string_view kSalt_2 = "YFRT";
|
||||
|
||||
using ::location::nearby::mediums::ConnectionResponseFrame;
|
||||
using ::location::nearby::mediums::MultiplexControlFrame;
|
||||
using ::location::nearby::mediums::MultiplexFrame;
|
||||
|
||||
class MultiplexOutputStreamTest : public ::testing::Test {
|
||||
protected:
|
||||
ExceptionOr<MultiplexFrame> ReadFrame() {
|
||||
ExceptionOr<std::int32_t> read_int = Base64Utils::ReadInt(reader_.get());
|
||||
if (!read_int.ok()) return read_int.GetException();
|
||||
if (read_int.result() <= 0) return {Exception::kFailed};
|
||||
|
||||
ExceptionOr<ByteArray> received_data =
|
||||
reader_->ReadExactly(read_int.result());
|
||||
if (!received_data.ok()) return received_data.GetException();
|
||||
auto bytes = std::move(received_data.result());
|
||||
return FromBytes(bytes);
|
||||
}
|
||||
|
||||
AtomicBoolean enabled_{true};
|
||||
std::pair<std::unique_ptr<InputStream>, std::unique_ptr<OutputStream>> pipe_ =
|
||||
CreatePipe();
|
||||
|
||||
std::unique_ptr<InputStream> reader_ = std::move(pipe_.first);
|
||||
std::unique_ptr<OutputStream> writer_ = std::move(pipe_.second);
|
||||
std::unique_ptr<MultiplexOutputStream> multiplex_output_stream_;
|
||||
};
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, SendConnectionRequestFrame) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_TRUE(multiplex_output_stream_->WriteConnectionRequestFrame(
|
||||
std::string(kServiceId_1), std::string(kNoSalt)));
|
||||
|
||||
auto request = ReadFrame();
|
||||
ASSERT_TRUE(request.ok());
|
||||
auto frame = request.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::CONNECTION_REQUEST);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
std::string(kNoSalt))));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, SendConnectionRequestFrameDisabled) {
|
||||
enabled_.Set(false);
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_FALSE(multiplex_output_stream_->WriteConnectionRequestFrame(
|
||||
std::string(kServiceId_1), std::string(kNoSalt)));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, SendConnectionResponseFrame) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_TRUE(multiplex_output_stream_->WriteConnectionResponseFrame(
|
||||
GenerateServiceIdHash(std::string(kServiceId_1)), std::string(kNoSalt),
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED));
|
||||
|
||||
auto response = ReadFrame();
|
||||
ASSERT_TRUE(response.ok());
|
||||
auto frame = response.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::CONNECTION_RESPONSE);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
std::string(kNoSalt))));
|
||||
EXPECT_EQ(frame.control_frame()
|
||||
.connection_response_frame()
|
||||
.connection_response_code(),
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED);
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, SendConnectionResponseFrameDisabled) {
|
||||
enabled_.Set(false);
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_FALSE(multiplex_output_stream_->WriteConnectionResponseFrame(
|
||||
GenerateServiceIdHash(std::string(kServiceId_1)), std::string(kNoSalt),
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, CloseVirtualStreamFailed) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_FALSE(multiplex_output_stream_->Close(std::string(kServiceId_1)));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, CloseVirtualStreamSuccess) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
EXPECT_FALSE(multiplex_output_stream_->Close(std::string(kServiceId_1)));
|
||||
|
||||
multiplex_output_stream_->CreateVirtualOutputStream(std::string(kServiceId_1),
|
||||
std::string(kNoSalt));
|
||||
EXPECT_TRUE(multiplex_output_stream_->Close(std::string(kServiceId_1)));
|
||||
|
||||
auto request = ReadFrame();
|
||||
ASSERT_TRUE(request.ok());
|
||||
auto frame = request.result();
|
||||
EXPECT_EQ(frame.control_frame().control_frame_type(),
|
||||
MultiplexControlFrame::DISCONNECTION);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
std::string(kNoSalt))));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, CreateVirtualStream_SendData) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
|
||||
auto virtual_output_stream =
|
||||
multiplex_output_stream_->CreateVirtualOutputStream(
|
||||
std::string(kServiceId_1), std::string(kSalt_1));
|
||||
|
||||
absl::string_view data = "abcdefghijklmnopqrstuvwxyz";
|
||||
virtual_output_stream->Write(data);
|
||||
virtual_output_stream->Flush();
|
||||
auto frame_data = ReadFrame();
|
||||
ASSERT_TRUE(frame_data.ok());
|
||||
auto frame = frame_data.result();
|
||||
EXPECT_EQ(frame.frame_type(), MultiplexFrame::DATA_FRAME);
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
std::string(kSalt_1))));
|
||||
EXPECT_EQ(frame.data_frame().data(), std::string(data));
|
||||
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(MultiplexOutputStreamTest, CreateTwoVirtualStreams_SendData) {
|
||||
multiplex_output_stream_ =
|
||||
std::make_unique<MultiplexOutputStream>(writer_.get(), enabled_);
|
||||
|
||||
auto virtual_output_stream_1 =
|
||||
multiplex_output_stream_->CreateVirtualOutputStreamForFirstVirtualSocket(
|
||||
std::string(kServiceId_1), std::string(kSalt_1));
|
||||
auto virtual_output_stream_2 =
|
||||
multiplex_output_stream_->CreateVirtualOutputStreamForFirstVirtualSocket(
|
||||
std::string(kServiceId_2), std::string(kSalt_2));
|
||||
|
||||
absl::string_view data_1("abcdefg");
|
||||
absl::string_view data_2("hijklmn");
|
||||
MultiThreadExecutor executor(2);
|
||||
CountDownLatch latch(2);
|
||||
executor.Execute([&virtual_output_stream_1, &latch, &data_1]() {
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
virtual_output_stream_1->Write(data_1);
|
||||
virtual_output_stream_1->Flush();
|
||||
latch.CountDown();
|
||||
});
|
||||
executor.Execute([&virtual_output_stream_2, &latch, &data_2]() {
|
||||
virtual_output_stream_2->Write(data_2);
|
||||
virtual_output_stream_2->Flush();
|
||||
latch.CountDown();
|
||||
});
|
||||
EXPECT_TRUE(latch.Await(absl::Milliseconds(5000)).result());
|
||||
|
||||
auto frame_data = ReadFrame();
|
||||
ASSERT_TRUE(frame_data.ok());
|
||||
auto frame = frame_data.result();
|
||||
EXPECT_EQ(frame.frame_type(), MultiplexFrame::DATA_FRAME);
|
||||
bool first_frame_is_data_1 = true;
|
||||
if (frame.header().salted_service_id_hash() ==
|
||||
std::string(GenerateServiceIdHashWithSalt(std::string(kServiceId_1),
|
||||
std::string(kSalt_1)))) {
|
||||
EXPECT_EQ(frame.data_frame().data(), std::string(data_1));
|
||||
LOG(INFO) << "Read first virtual stream frame first.";
|
||||
} else {
|
||||
EXPECT_EQ(frame.header().salted_service_id_hash(),
|
||||
std::string(GenerateServiceIdHashWithSalt(
|
||||
std::string(kServiceId_2), std::string(kSalt_2))));
|
||||
EXPECT_EQ(frame.data_frame().data(), std::string(data_2));
|
||||
first_frame_is_data_1 = false;
|
||||
LOG(INFO) << "Read second virtual stream frame first.";
|
||||
}
|
||||
|
||||
frame_data = ReadFrame();
|
||||
ASSERT_TRUE(frame_data.ok());
|
||||
frame = frame_data.result();
|
||||
EXPECT_EQ(frame.frame_type(), MultiplexFrame::DATA_FRAME);
|
||||
if (first_frame_is_data_1) {
|
||||
EXPECT_EQ(frame.data_frame().data(), std::string(data_2));
|
||||
} else {
|
||||
EXPECT_EQ(frame.data_frame().data(), std::string(data_1));
|
||||
}
|
||||
multiplex_output_stream_->Shutdown();
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,807 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_output_stream.h"
|
||||
#include "connections/implementation/mediums/utils.h"
|
||||
#include "internal/platform/atomic_boolean.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/socket.h"
|
||||
#include "internal/platform/types.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
namespace {
|
||||
// It is defined for the receiver which send the first packet to the sender
|
||||
// without getting salt from it yet. The fake salt reminds sender to get the
|
||||
// correct socket from `virtualSockets` without remapping it.
|
||||
constexpr absl::string_view kFakeSalt = "RECEIVER_CONDIMENT";
|
||||
|
||||
// The max duration to wait for the reader thread to stop.
|
||||
constexpr absl::Duration kTimeoutForReaderThreadStop = absl::Milliseconds(100);
|
||||
|
||||
} // namespace
|
||||
|
||||
using ::location::nearby::mediums::ConnectionResponseFrame;
|
||||
using ::location::nearby::mediums::MultiplexControlFrame;
|
||||
using ::location::nearby::mediums::MultiplexDataFrame;
|
||||
using ::location::nearby::mediums::MultiplexFrame;
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::location::nearby::proto::connections::Medium_Name;
|
||||
using ConnectionResponseCode = ConnectionResponseFrame::ConnectionResponseCode;
|
||||
|
||||
// AtomicBoolean is trivial destructible, so it is safe to use it as a static
|
||||
// variable.
|
||||
AtomicBoolean MultiplexSocket::is_shutting_down_{false}; // NOLINT
|
||||
|
||||
void MultiplexSocket::ListenForIncomingConnection(
|
||||
const std::string& service_id, Medium type,
|
||||
MultiplexIncomingConnectionCb incoming_connection_cb) {
|
||||
GetIncomingConnectionCallbacks().emplace(
|
||||
std::pair<std::string, Medium>(service_id, type),
|
||||
std::move(incoming_connection_cb));
|
||||
}
|
||||
|
||||
void MultiplexSocket::StopListeningForIncomingConnection(
|
||||
const std::string& service_id, Medium type) {
|
||||
GetIncomingConnectionCallbacks().erase(
|
||||
std::pair<std::string, Medium>(service_id, type));
|
||||
}
|
||||
|
||||
MultiplexSocket::MultiplexSocket(std::shared_ptr<MediumSocket> physical_socket)
|
||||
: physical_socket_ptr_(physical_socket),
|
||||
multiplex_output_stream_{&physical_socket_ptr_->GetOutputStream(),
|
||||
enabled_},
|
||||
physical_reader_(&physical_socket_ptr_->GetInputStream()),
|
||||
medium_(physical_socket_ptr_->GetMedium()) {}
|
||||
|
||||
absl::flat_hash_map<std::pair<std::string, Medium>,
|
||||
MultiplexIncomingConnectionCb>&
|
||||
MultiplexSocket::GetIncomingConnectionCallbacks() {
|
||||
using MapType = absl::flat_hash_map<std::pair<std::string, Medium>,
|
||||
MultiplexIncomingConnectionCb>;
|
||||
alignas(MapType) static char storage[sizeof(MapType)];
|
||||
static MapType* incoming_connection_callbacks = new (&storage) MapType();
|
||||
|
||||
return *incoming_connection_callbacks;
|
||||
}
|
||||
|
||||
MultiplexSocket* MultiplexSocket::CreateIncomingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id, std::int32_t first_frame_len) {
|
||||
while (is_shutting_down_.Get()) {
|
||||
LOG(WARNING)
|
||||
<< "Shutting down is going on, wait for 2ms to create incoming socket";
|
||||
absl::SleepFor(absl::Milliseconds(2));
|
||||
}
|
||||
|
||||
MultiplexSocket* multiplex_incoming_socket = nullptr;
|
||||
static MultiplexSocket* multiplex_incoming_socket_bt = nullptr;
|
||||
static MultiplexSocket* multiplex_incoming_socket_wlan = nullptr;
|
||||
|
||||
switch (physical_socket->GetMedium()) {
|
||||
case Medium::BLUETOOTH:
|
||||
if (multiplex_incoming_socket_bt != nullptr) {
|
||||
LOG(INFO) << "Multiplex incoming socket already exists for BT";
|
||||
return multiplex_incoming_socket_bt;
|
||||
}
|
||||
alignas(MultiplexSocket) static char storage_bt[sizeof(MultiplexSocket)];
|
||||
multiplex_incoming_socket_bt =
|
||||
new (&storage_bt) MultiplexSocket(physical_socket);
|
||||
multiplex_incoming_socket = multiplex_incoming_socket_bt;
|
||||
break;
|
||||
case Medium::WIFI_LAN:
|
||||
case Medium::AWDL:
|
||||
if (multiplex_incoming_socket_wlan != nullptr) {
|
||||
LOG(INFO) << "Multiplex incoming socket already exists for WLAN";
|
||||
return multiplex_incoming_socket_wlan;
|
||||
}
|
||||
alignas(
|
||||
MultiplexSocket) static char storage_wlan[sizeof(MultiplexSocket)];
|
||||
multiplex_incoming_socket_wlan =
|
||||
new (&storage_wlan) MultiplexSocket(physical_socket);
|
||||
multiplex_incoming_socket = multiplex_incoming_socket_wlan;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << __func__
|
||||
<< "Unsupported medium: " << physical_socket->GetMedium();
|
||||
multiplex_incoming_socket = nullptr;
|
||||
return multiplex_incoming_socket;
|
||||
}
|
||||
LOG(INFO) << "CreateIncomingSocket with serviceId=" << service_id
|
||||
<< ", serviceIdHashSalt=" << kFakeSalt
|
||||
<< " for medium=" << Medium_Name(physical_socket->GetMedium());
|
||||
|
||||
multiplex_incoming_socket->CreateFirstVirtualSocket(service_id,
|
||||
(std::string)kFakeSalt);
|
||||
multiplex_incoming_socket->StartReaderThread(first_frame_len);
|
||||
|
||||
return multiplex_incoming_socket;
|
||||
}
|
||||
|
||||
MultiplexSocket* MultiplexSocket::CreateOutgoingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
while (is_shutting_down_.Get()) {
|
||||
LOG(WARNING)
|
||||
<< "Shutting down is going on, wait for 2ms to create outgoing socket";
|
||||
absl::SleepFor(absl::Milliseconds(2));
|
||||
}
|
||||
|
||||
MultiplexSocket* multiplex_outgoing_socket = nullptr;
|
||||
static MultiplexSocket* multiplex_outgoing_socket_bt = nullptr;
|
||||
static MultiplexSocket* multiplex_outgoing_socket_wlan = nullptr;
|
||||
|
||||
switch (physical_socket->GetMedium()) {
|
||||
case Medium::BLUETOOTH:
|
||||
if (multiplex_outgoing_socket_bt != nullptr) {
|
||||
LOG(INFO) << "Multiplex outgoing socket already exists for BT";
|
||||
return multiplex_outgoing_socket_bt;
|
||||
}
|
||||
alignas(MultiplexSocket) static char storage_bt[sizeof(MultiplexSocket)];
|
||||
multiplex_outgoing_socket_bt =
|
||||
new (&storage_bt) MultiplexSocket(physical_socket);
|
||||
multiplex_outgoing_socket = multiplex_outgoing_socket_bt;
|
||||
break;
|
||||
case Medium::WIFI_LAN:
|
||||
case Medium::AWDL:
|
||||
if (multiplex_outgoing_socket_wlan != nullptr) {
|
||||
LOG(INFO) << "Multiplex outgoing socket already exists for WLAN";
|
||||
return multiplex_outgoing_socket_wlan;
|
||||
}
|
||||
alignas(
|
||||
MultiplexSocket) static char storage_wlan[sizeof(MultiplexSocket)];
|
||||
multiplex_outgoing_socket_wlan =
|
||||
new (&storage_wlan) MultiplexSocket(physical_socket);
|
||||
multiplex_outgoing_socket = multiplex_outgoing_socket_wlan;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << __func__
|
||||
<< "Unsupported medium: " << physical_socket->GetMedium();
|
||||
multiplex_outgoing_socket = nullptr;
|
||||
return multiplex_outgoing_socket;
|
||||
}
|
||||
LOG(INFO) << "CreateOutgoingSocket with serviceId=" << service_id
|
||||
<< ", serviceIdHashSalt=" << service_id_hash_salt
|
||||
<< " for medium=" << Medium_Name(physical_socket->GetMedium());
|
||||
|
||||
multiplex_outgoing_socket->CreateFirstVirtualSocket(service_id,
|
||||
service_id_hash_salt);
|
||||
multiplex_outgoing_socket->StartReaderThread(0);
|
||||
return multiplex_outgoing_socket;
|
||||
}
|
||||
|
||||
MultiplexSocket* MultiplexSocket::CreateOutgoingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id) {
|
||||
return CreateOutgoingSocket(physical_socket, service_id,
|
||||
Utils::GenerateSalt());
|
||||
}
|
||||
|
||||
MediumSocket* MultiplexSocket::CreateFirstVirtualSocket(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
auto output_stream =
|
||||
multiplex_output_stream_.CreateVirtualOutputStreamForFirstVirtualSocket(
|
||||
service_id, service_id_hash_salt);
|
||||
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKeyWithSalt(service_id, service_id_hash_salt);
|
||||
LOG(INFO) << __func__ << " for service_id=" << service_id
|
||||
<< ", salt=" << service_id_hash_salt
|
||||
<< ", salted_service_id_hash_key=" << salted_service_id_hash_key;
|
||||
MediumSocket* virtual_socket = physical_socket_ptr_->CreateVirtualSocket(
|
||||
salted_service_id_hash_key, output_stream, medium_, &virtual_sockets_);
|
||||
|
||||
virtual_socket->AddOnSocketClosedListener(
|
||||
std::make_unique<absl::AnyInvocable<void()>>(
|
||||
[this, service_id]() { OnVirtualSocketClosed(service_id); }));
|
||||
|
||||
if (!IsEnabled()) {
|
||||
LOG(INFO) << __func__ << ": Register multiplex enabled callback";
|
||||
virtual_socket->RegisterMultiplexEnabledCallback(enable_cb_);
|
||||
}
|
||||
|
||||
return virtual_socket;
|
||||
}
|
||||
|
||||
MediumSocket* MultiplexSocket::CreateVirtualSocket(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt) {
|
||||
auto output_stream = multiplex_output_stream_.CreateVirtualOutputStream(
|
||||
service_id, service_id_hash_salt);
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKeyWithSalt(service_id, service_id_hash_salt);
|
||||
|
||||
LOG(INFO) << __func__ << "service_id=" << service_id
|
||||
<< ", salt=" << service_id_hash_salt
|
||||
<< ", salted_service_id_hash_key=" << salted_service_id_hash_key;
|
||||
|
||||
MediumSocket* virtual_socket = physical_socket_ptr_->CreateVirtualSocket(
|
||||
salted_service_id_hash_key, output_stream, medium_, &virtual_sockets_);
|
||||
|
||||
virtual_socket->AddOnSocketClosedListener(
|
||||
std::make_unique<absl::AnyInvocable<void()>>(
|
||||
[this, service_id]() { OnVirtualSocketClosed(service_id); }));
|
||||
|
||||
return virtual_socket;
|
||||
}
|
||||
|
||||
MediumSocket* MultiplexSocket::GetVirtualSocket(const std::string& service_id) {
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
LOG(INFO) << __func__ << " service_id=" << service_id << ", Salt="
|
||||
<< multiplex_output_stream_.GetServiceIdHashSalt(service_id)
|
||||
<< ", virtual_sockets_.size()=" << virtual_sockets_.size();
|
||||
auto item = virtual_sockets_.find(GenerateServiceIdHashKeyWithSalt(
|
||||
service_id, multiplex_output_stream_.GetServiceIdHashSalt(service_id)));
|
||||
if (item == virtual_sockets_.end()) {
|
||||
LOG(INFO) << "Not found!";
|
||||
return nullptr;
|
||||
}
|
||||
return item->second.get();
|
||||
}
|
||||
|
||||
int MultiplexSocket::GetVirtualSocketCount() {
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
return virtual_sockets_.size();
|
||||
}
|
||||
|
||||
void MultiplexSocket::ListVirtualSocket() {
|
||||
LOG(INFO) << __func__
|
||||
<< " virtual_sockets_.size()=" << virtual_sockets_.size();
|
||||
for (auto& [service_id_hash_key, virtual_socket] : virtual_sockets_) {
|
||||
LOG(INFO) << __func__ << " service_id_hash_key=" << service_id_hash_key
|
||||
<< ", virtual_socket=" << virtual_socket;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Future<ConnectionResponseCode>>
|
||||
MultiplexSocket::RegisterConnectionResponse(const std::string& service_id) {
|
||||
auto future = std::make_shared<Future<ConnectionResponseCode>>();
|
||||
connection_response_futures_.emplace(service_id, future);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
void MultiplexSocket::UnRegisterConnectionResponse(
|
||||
const std::string& service_id) {
|
||||
connection_response_futures_.erase(service_id);
|
||||
}
|
||||
|
||||
MediumSocket* MultiplexSocket::EstablishVirtualSocket(
|
||||
const std::string& service_id) {
|
||||
if (!IsEnabled()) {
|
||||
LOG(ERROR)
|
||||
<< "MultiplexSocket is disabled, cannot establish virtual socket.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string service_id_hash_salt = Utils::GenerateSalt();
|
||||
auto future = RegisterConnectionResponse(service_id);
|
||||
|
||||
multiplex_output_stream_.WriteConnectionRequestFrame(service_id,
|
||||
service_id_hash_salt);
|
||||
auto result =
|
||||
future->Get(FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.multiplex_socket_connection_response_timeout_millis);
|
||||
if (!result.ok()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< "EstablishVirtualSocket failed with response code="
|
||||
<< result.exception();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ConnectionResponseCode response_code = result.GetResult();
|
||||
switch (response_code) {
|
||||
case ConnectionResponseFrame::CONNECTION_ACCEPTED:
|
||||
LOG(INFO) << "EstablishVirtualSocket after remote response to"
|
||||
" accept the connection with service_id="
|
||||
<< service_id
|
||||
<< ", service_id_hash_salt=" << service_id_hash_salt;
|
||||
return CreateVirtualSocket(service_id, service_id_hash_salt);
|
||||
case ConnectionResponseFrame::NOT_LISTENING:
|
||||
LOG(ERROR) << "EstablishVirtualSocket failed for service_id="
|
||||
<< service_id
|
||||
<< ", service_id_hash_salt=" << service_id_hash_salt
|
||||
<< " with response code=NOT_LISTENING";
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "EstablishVirtualSocket failed for service_id="
|
||||
<< service_id
|
||||
<< ", service_id_hash_salt=" << service_id_hash_salt
|
||||
<< " with response code=UNKNOWN_RESPONSE_CODE";
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MultiplexSocket::StartReaderThread(std::int32_t first_frame_len) {
|
||||
if (is_shutdown_) {
|
||||
LOG(WARNING) << "Stop to start reader thread since socket is "
|
||||
"shutdown.";
|
||||
return;
|
||||
}
|
||||
reader_thread_shutdown_barrier_ = std::make_unique<CountDownLatch>(1);
|
||||
physical_reader_thread_.Execute([this, first_frame_len]() {
|
||||
LOG(INFO) << __func__ << " Reader thread starts.";
|
||||
auto first_frame_len_copy = first_frame_len;
|
||||
while (!is_shutdown_) {
|
||||
bool fail = false;
|
||||
ExceptionOr<ByteArray> bytes;
|
||||
ExceptionOr<std::int32_t> read_int;
|
||||
if (first_frame_len_copy > 0) {
|
||||
read_int = ExceptionOr<std::int32_t>(first_frame_len);
|
||||
first_frame_len_copy = 0;
|
||||
} else {
|
||||
read_int = Base64Utils::ReadInt(physical_reader_);
|
||||
}
|
||||
if (!read_int.ok()) {
|
||||
LOG(WARNING) << __func__
|
||||
<< "Failed to read. Exception:" << read_int.exception();
|
||||
fail = true;
|
||||
} else {
|
||||
auto length = read_int.result();
|
||||
VLOG(1) << __func__ << " length:" << length;
|
||||
|
||||
if (length < 0 || length > FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.connection_max_frame_length) {
|
||||
// Ignore the failure because not only one client use this
|
||||
// connection.
|
||||
LOG(WARNING) << __func__
|
||||
<< "Failed to read because received a invalid length "
|
||||
<< length << ", but continue to read.";
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes = physical_reader_->ReadExactly(length);
|
||||
if (!bytes.ok()) {
|
||||
LOG(WARNING) << __func__
|
||||
<< "Read data exception:" << bytes.exception();
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
if (fail) {
|
||||
reader_thread_shutdown_barrier_->CountDown();
|
||||
return;
|
||||
}
|
||||
|
||||
ExceptionOr<MultiplexFrame> frame_exc =
|
||||
multiplex::FromBytes(bytes.result());
|
||||
if (!frame_exc.ok()) {
|
||||
HandleOfflineFrame(bytes.result());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsEnabled()) {
|
||||
// The reader thread will only be enabled when local device
|
||||
// supports multiplex if we received a multiplex frame from
|
||||
// the remote, it means that the remote and the local both
|
||||
// support multiplex as well. So it is safe to just turn on
|
||||
// the feature at this point.
|
||||
LOG(INFO) << __func__
|
||||
<< " Received a multiplex frame while not enabled, enable "
|
||||
"multiplex.";
|
||||
Enable();
|
||||
}
|
||||
const auto& frame = frame_exc.result();
|
||||
auto salted_service_id_hash =
|
||||
ByteArray{std::move(frame.header().salted_service_id_hash())};
|
||||
auto service_id_hash_salt = frame.header().has_service_id_hash_salt()
|
||||
? frame.header().service_id_hash_salt()
|
||||
: "";
|
||||
switch (frame.frame_type()) {
|
||||
case MultiplexFrame::CONTROL_FRAME:
|
||||
HandleControlFrame(salted_service_id_hash, service_id_hash_salt,
|
||||
frame.control_frame());
|
||||
break;
|
||||
case MultiplexFrame::DATA_FRAME:
|
||||
VLOG(1) << "service_id_hash_salt: " << service_id_hash_salt;
|
||||
HandleDataFrame(salted_service_id_hash, service_id_hash_salt,
|
||||
frame.data_frame());
|
||||
break;
|
||||
default:
|
||||
LOG(WARNING) << __func__
|
||||
<< " Received MultiplexFrame with unknown frame type "
|
||||
<< frame.frame_type();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleOfflineFrame(const ByteArray& bytes) {
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
LOG(INFO) << __func__ << " Virtual_socket num:" << virtual_sockets_.size();
|
||||
if (virtual_sockets_.size() == 1) {
|
||||
auto item = virtual_sockets_.begin();
|
||||
if (item->second == nullptr) {
|
||||
LOG(WARNING) << "Expected one live socket, but found null.";
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << __func__ << "FeedIncomingData:" << std::string(bytes);
|
||||
item->second->FeedIncomingData(Base64Utils::IntToBytes(bytes.size()));
|
||||
item->second->FeedIncomingData(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleControlFrame(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const MultiplexControlFrame& frame) {
|
||||
switch (frame.control_frame_type()) {
|
||||
case MultiplexControlFrame::CONNECTION_REQUEST:
|
||||
RunOffloadThread("CONNECTION_REQUEST", [this, salted_service_id_hash,
|
||||
service_id_hash_salt] {
|
||||
HandleConnectionRequest(salted_service_id_hash, service_id_hash_salt);
|
||||
});
|
||||
break;
|
||||
case MultiplexControlFrame::CONNECTION_RESPONSE:
|
||||
LOG(INFO) << __func__ << "Received an CONNECTION_RESPONSE frame."
|
||||
<< " salted_service_id_hash: "
|
||||
<< std::string(salted_service_id_hash)
|
||||
<< ", service_id_hash_salt: " << service_id_hash_salt
|
||||
<< ", ConnectionResponseCode: "
|
||||
<< frame.connection_response_frame().connection_response_code();
|
||||
|
||||
RunOffloadThread("CONNECTION_RESPONSE", [this, salted_service_id_hash,
|
||||
service_id_hash_salt,
|
||||
frame = frame] {
|
||||
HandleConnectionResponse(salted_service_id_hash, service_id_hash_salt,
|
||||
frame.connection_response_frame());
|
||||
});
|
||||
break;
|
||||
case MultiplexControlFrame::DISCONNECTION:
|
||||
// The virtual socket will be closed in the offload thread, so don't run
|
||||
// the thread here.
|
||||
HandleDisconnection(salted_service_id_hash);
|
||||
break;
|
||||
default:
|
||||
LOG(WARNING) << __func__ << "Received an unknown frame type "
|
||||
<< frame.control_frame_type();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleConnectionRequest(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt) {
|
||||
if (!IsEnabled()) {
|
||||
LOG(WARNING) << "Received a CONNECTION_REQUEST frame on medium "
|
||||
<< Medium_Name(medium_)
|
||||
<< " but status is disabled, ignore it.";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKey(salted_service_id_hash);
|
||||
MultiplexIncomingConnectionCb* incoming_connection_callback = nullptr;
|
||||
std::string listening_service_id = "";
|
||||
for (auto& [service_id_medium_pair, callback] :
|
||||
GetIncomingConnectionCallbacks()) {
|
||||
if (GenerateServiceIdHashWithSalt(service_id_medium_pair.first,
|
||||
service_id_hash_salt) ==
|
||||
salted_service_id_hash) {
|
||||
incoming_connection_callback = &callback;
|
||||
listening_service_id = service_id_medium_pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
if (incoming_connection_callback == nullptr || listening_service_id.empty()) {
|
||||
LOG(INFO) << "There's no client listening for hash salt : "
|
||||
<< service_id_hash_salt
|
||||
<< ", hash key : " << salted_service_id_hash_key << " on medium "
|
||||
<< Medium_Name(medium_);
|
||||
|
||||
LOG(INFO) << "The size of incomingConnectionCallbacks : "
|
||||
<< GetIncomingConnectionCallbacks().size();
|
||||
if (!multiplex_output_stream_.WriteConnectionResponseFrame(
|
||||
salted_service_id_hash, service_id_hash_salt,
|
||||
ConnectionResponseFrame::NOT_LISTENING)) {
|
||||
LOG(INFO) << __func__ << "Failed to write NOT_LISTENING frame.";
|
||||
}
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Accept new virtual socket request service ID : "
|
||||
<< listening_service_id << ", hash salt : " << service_id_hash_salt
|
||||
<< ", hash key : " << salted_service_id_hash_key << " on medium "
|
||||
<< Medium_Name(medium_);
|
||||
|
||||
if (!multiplex_output_stream_.WriteConnectionResponseFrame(
|
||||
salted_service_id_hash, service_id_hash_salt,
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED)) {
|
||||
LOG(INFO) << "Failed to write CONNECTION_ACCEPTED frame.";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO)
|
||||
<< "EstablishVirtualSocket after local device accept the connection "
|
||||
"with serviceId="
|
||||
<< listening_service_id;
|
||||
MediumSocket* virtual_socket =
|
||||
CreateVirtualSocket(listening_service_id, service_id_hash_salt);
|
||||
(*incoming_connection_callback)(std::move(listening_service_id),
|
||||
virtual_socket);
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleConnectionResponse(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const ConnectionResponseFrame& frame) {
|
||||
LOG(INFO) << __func__
|
||||
<< "connection_response_code: " << frame.connection_response_code();
|
||||
for (auto& [service_id, future] : connection_response_futures_) {
|
||||
if (GenerateServiceIdHashWithSalt(service_id, service_id_hash_salt) ==
|
||||
salted_service_id_hash) {
|
||||
if (future != nullptr) {
|
||||
future->Set(frame.connection_response_code());
|
||||
LOG(INFO) << __func__ << "Set the future for serviceId=" << service_id
|
||||
<< ", serviceIdHashSalt=" << service_id_hash_salt
|
||||
<< " with response code=" << frame.connection_response_code();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG(WARNING)
|
||||
<< __func__
|
||||
<< "Received a CONNECTION_RESPONSE frame but no client waiting for "
|
||||
"service ID Hash Key"
|
||||
<< GenerateServiceIdHashKey(salted_service_id_hash);
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleDisconnection(
|
||||
const ByteArray& salted_service_id_hash) {
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKey(salted_service_id_hash);
|
||||
MediumSocket* virtual_socket_to_close = nullptr;
|
||||
{
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
auto item = virtual_sockets_.find(salted_service_id_hash_key);
|
||||
if (item != virtual_sockets_.end()) {
|
||||
LOG(INFO)
|
||||
<< "Received a DISCONNECTION frame to disconnect virtual socket for "
|
||||
"salted service ID Hash Key "
|
||||
<< salted_service_id_hash_key;
|
||||
virtual_socket_to_close = item->second.get();
|
||||
} else {
|
||||
LOG(WARNING)
|
||||
<< "Received a DISCONNECTION frame but there's no alive socket to "
|
||||
"disconnect for service ID Hash Key "
|
||||
<< salted_service_id_hash_key;
|
||||
}
|
||||
}
|
||||
// Close the virtual socket outside of the mutex lock because
|
||||
// OnVirtualSocketClosed will lock the mutex.
|
||||
if (virtual_socket_to_close != nullptr) {
|
||||
virtual_socket_to_close->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexSocket::HandleDataFrame(const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const MultiplexDataFrame& frame) {
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKey(salted_service_id_hash);
|
||||
MediumSocket* virtual_socket = nullptr;
|
||||
if (service_id_hash_salt.empty()) {
|
||||
{
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
auto item = virtual_sockets_.find(salted_service_id_hash_key);
|
||||
if (item != virtual_sockets_.end()) {
|
||||
virtual_socket = item->second.get();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
virtual_socket =
|
||||
ReMapAndGetVirtualSocket(salted_service_id_hash, service_id_hash_salt);
|
||||
}
|
||||
|
||||
if (virtual_socket != nullptr) {
|
||||
VLOG(1)
|
||||
<< "Received a DATA frame to feed virtual socket for salted service ID "
|
||||
"Hash Key "
|
||||
<< salted_service_id_hash_key;
|
||||
virtual_socket->FeedIncomingData(ByteArray(frame.data()));
|
||||
} else {
|
||||
LOG(WARNING)
|
||||
<< "Received a DATA frame but there's no alive socket to feed for "
|
||||
"salted service ID Hash Key "
|
||||
<< salted_service_id_hash_key;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexSocket::OnPhysicalSocketClosed() {
|
||||
RunOffloadThread("Shutdown", [this]() { Shutdown(); });
|
||||
}
|
||||
|
||||
void MultiplexSocket::OnVirtualSocketClosed(const std::string& service_id) {
|
||||
LOG(INFO) << __func__ << " for service_id:" << service_id;
|
||||
CountDownLatch latch(1);
|
||||
bool shutdown = false;
|
||||
RunOffloadThread(
|
||||
"VirtualSocketClosed", [this, service_id, &latch, &shutdown]() {
|
||||
LOG(INFO) << "Try to close Virtual socket: " << service_id;
|
||||
MediumSocket* virtual_socket = GetVirtualSocket(service_id);
|
||||
{
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
LOG(INFO) << "virtual_socket:" << virtual_socket;
|
||||
if (virtual_socket != nullptr) {
|
||||
auto salted_service_id_hash_key = GenerateServiceIdHashKeyWithSalt(
|
||||
service_id,
|
||||
multiplex_output_stream_.GetServiceIdHashSalt(service_id));
|
||||
multiplex_output_stream_.Close(service_id);
|
||||
virtual_sockets_.erase(salted_service_id_hash_key);
|
||||
LOG(INFO) << "Erase Virtual socket with service_id: " << service_id
|
||||
<< ", hash_key: " << salted_service_id_hash_key;
|
||||
ListVirtualSocket();
|
||||
|
||||
if (virtual_sockets_.empty()) {
|
||||
LOG(INFO) << "Close the physical socket because all virtual "
|
||||
"sockets disconnected.";
|
||||
is_shutting_down_.Set(true);
|
||||
Shutdown();
|
||||
shutdown = true;
|
||||
}
|
||||
} else {
|
||||
LOG(INFO) << "Virtual socket(" << service_id << ") not found";
|
||||
}
|
||||
}
|
||||
latch.CountDown();
|
||||
});
|
||||
|
||||
if (!latch.Await(absl::Milliseconds(1000)).result()) {
|
||||
LOG(ERROR) << "Timeout to close virtual socket";
|
||||
}
|
||||
|
||||
if (shutdown) {
|
||||
LOG(INFO)
|
||||
<< "Shutdown single_thread_offloader_ and physical_reader_thread_";
|
||||
single_thread_offloader_.Shutdown();
|
||||
physical_reader_thread_.Shutdown();
|
||||
is_shutting_down_.Set(false);
|
||||
}
|
||||
}
|
||||
|
||||
MediumSocket* MultiplexSocket::ReMapAndGetVirtualSocket(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt) {
|
||||
std::string salted_service_id_hash_key =
|
||||
GenerateServiceIdHashKey(salted_service_id_hash);
|
||||
VLOG(1) << "ReMapAndGetVirtualSocket with serviceIdHashSalt="
|
||||
<< service_id_hash_salt
|
||||
<< ", saltedServiceIdHashKey=" << salted_service_id_hash_key;
|
||||
{
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
for (auto& [hash_key, virtual_socket] : virtual_sockets_) {
|
||||
auto output_stream =
|
||||
down_cast<MultiplexOutputStream::VirtualOutputStream*>(
|
||||
&(virtual_socket->GetOutputStream()));
|
||||
if (output_stream == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (!output_stream->IsFirstVirtualOutputStream()) {
|
||||
continue;
|
||||
}
|
||||
if ((service_id_hash_salt == kFakeSalt) ||
|
||||
(hash_key == salted_service_id_hash_key)) {
|
||||
return virtual_socket.get();
|
||||
} else {
|
||||
LOG(INFO) << "Remap the virtualSockets.";
|
||||
output_stream->SetserviceIdHashSalt(service_id_hash_salt);
|
||||
auto virtual_socket_tmp = virtual_socket;
|
||||
LOG(INFO) << "virtual_socket before:" << virtual_socket;
|
||||
virtual_sockets_.erase(hash_key);
|
||||
virtual_sockets_[salted_service_id_hash_key] = virtual_socket_tmp;
|
||||
ListVirtualSocket();
|
||||
return virtual_socket_tmp.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Failed to remap the virtualSockets.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MultiplexSocket::RunOffloadThread(const std::string& name,
|
||||
absl::AnyInvocable<void()> runnable) {
|
||||
single_thread_offloader_.Execute(name, std::move(runnable));
|
||||
}
|
||||
|
||||
void MultiplexSocket::Shutdown() {
|
||||
LOG(INFO) << __func__ << " start";
|
||||
if (is_shutdown_) {
|
||||
LOG(INFO) << __func__ << " Already shutdown";
|
||||
return;
|
||||
}
|
||||
|
||||
multiplex_output_stream_.Shutdown();
|
||||
physical_socket_ptr_->Close();
|
||||
|
||||
if (reader_thread_shutdown_barrier_) {
|
||||
reader_thread_shutdown_barrier_->Await(kTimeoutForReaderThreadStop);
|
||||
}
|
||||
|
||||
GetIncomingConnectionCallbacks().clear();
|
||||
connection_response_futures_.clear();
|
||||
|
||||
is_shutdown_ = true;
|
||||
enabled_.Set(false);
|
||||
LOG(INFO) << __func__ << " end";
|
||||
}
|
||||
|
||||
void MultiplexSocket::ShutdownAll() {
|
||||
LOG(INFO) << __func__ << " start";
|
||||
if (is_shutdown_) {
|
||||
LOG(WARNING) << __func__ << " Already shutdown";
|
||||
return;
|
||||
}
|
||||
|
||||
CountDownLatch latch(1);
|
||||
RunOffloadThread("VirtualSocketClosed", [this, &latch]() {
|
||||
{
|
||||
MutexLock lock(&virtual_socket_mutex_);
|
||||
multiplex_output_stream_.CloseAll();
|
||||
virtual_sockets_.clear();
|
||||
|
||||
Shutdown();
|
||||
}
|
||||
latch.CountDown();
|
||||
});
|
||||
|
||||
if (!latch
|
||||
.Await(FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.mediums_frame_write_timeout_millis +
|
||||
absl::Milliseconds(100))
|
||||
.result()) {
|
||||
LOG(ERROR) << "Timeout to close virtual socket";
|
||||
}
|
||||
|
||||
LOG(INFO) << "Shutdown single_thread_offloader_ and physical_reader_thread_";
|
||||
single_thread_offloader_.Shutdown();
|
||||
physical_reader_thread_.Shutdown();
|
||||
LOG(INFO) << __func__ << " end";
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,222 +0,0 @@
|
||||
// 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 CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_SOCKET_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_SOCKET_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_output_stream.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "internal/platform/atomic_boolean.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
#include "internal/platform/socket.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
#include "proto/mediums/multiplex_frames.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
using MultiplexEnbaleCb = absl::AnyInvocable<void()>;
|
||||
using MultiplexIncomingConnectionCb = absl::AnyInvocable<void(
|
||||
const std::string& service_id, MediumSocket* socket)>;
|
||||
|
||||
class MultiplexSocket {
|
||||
public:
|
||||
MultiplexSocket(const MultiplexSocket&) = delete;
|
||||
MultiplexSocket& operator=(const MultiplexSocket&) = delete;
|
||||
~MultiplexSocket() { ShutdownAll(); };
|
||||
|
||||
// Creates a new incoming MultiplexSocket.
|
||||
static MultiplexSocket* CreateIncomingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id, std::int32_t first_frame_len);
|
||||
// Creates a new outgoing MultiplexSocket.
|
||||
static MultiplexSocket* CreateOutgoingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id, const std::string& service_id_hash_salt);
|
||||
|
||||
// Creates a new outgoing MultiplexSocket with default service_id_hash_salt.
|
||||
static MultiplexSocket* CreateOutgoingSocket(
|
||||
std::shared_ptr<MediumSocket> physical_socket,
|
||||
const std::string& service_id);
|
||||
|
||||
// A Table of service Id as row key, medium type as column key, and
|
||||
// MultiplexIncomingConnectionCb as value. Non-empty while the client starts
|
||||
// listening for incoming virtual socket. The MultiplexIncomingConnectionCb
|
||||
// will be called when the incoming virtual socket is established.
|
||||
static absl::flat_hash_map<
|
||||
std::pair<std::string, ::location::nearby::proto::connections::Medium>,
|
||||
MultiplexIncomingConnectionCb>&
|
||||
GetIncomingConnectionCallbacks();
|
||||
|
||||
// Listens for incoming connection through multiplex for specified {@code
|
||||
// service_id} on medium
|
||||
// {@code type}. Should register the callback before new the MultiplexSocket.
|
||||
static void ListenForIncomingConnection(
|
||||
const std::string& service_id,
|
||||
::location::nearby::proto::connections::Medium type,
|
||||
absl::AnyInvocable<void(const std::string& service_id,
|
||||
MediumSocket* socket)>
|
||||
incoming_connection_cb);
|
||||
|
||||
// Stops listening for incoming multiplex connection for {@code service_id} on
|
||||
// medium {@code type}.
|
||||
static void StopListeningForIncomingConnection(
|
||||
const std::string& service_id,
|
||||
::location::nearby::proto::connections::Medium type);
|
||||
|
||||
bool IsEnabled() { return enabled_.Get(); }
|
||||
void Enable() {
|
||||
LOG(INFO) << "Enable the Multiplex MediumSocket.";
|
||||
enabled_.Set(true);
|
||||
}
|
||||
|
||||
// Gets the virtual socket by service id.
|
||||
MediumSocket* GetVirtualSocket(const std::string& service_id);
|
||||
// Gets the virtual socket count.
|
||||
int GetVirtualSocketCount();
|
||||
|
||||
void ListVirtualSocket()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(virtual_socket_mutex_);
|
||||
|
||||
// Establishes the virtual socket by service id.
|
||||
MediumSocket* EstablishVirtualSocket(const std::string& service_id);
|
||||
// Shuts down the multiplex socket.
|
||||
void Shutdown();
|
||||
bool IsShutdown() { return is_shutdown_; }
|
||||
void SetShutdown(bool is_shutdown) { is_shutdown_ = is_shutdown; }
|
||||
void ShutdownAll();
|
||||
|
||||
private:
|
||||
explicit MultiplexSocket(std::shared_ptr<MediumSocket> physical_socket);
|
||||
|
||||
// Creates the first virtual socket for the service id. The first virtual
|
||||
// socket is created by the sender.
|
||||
MediumSocket* CreateFirstVirtualSocket(
|
||||
const std::string& service_id, const std::string& service_id_hash_salt);
|
||||
// Creates the virtual socket for the service id.
|
||||
MediumSocket* CreateVirtualSocket(const std::string& service_id,
|
||||
const std::string& service_id_hash_salt);
|
||||
// Registers the connection response future for the service id.
|
||||
std::shared_ptr<Future<::location::nearby::mediums::ConnectionResponseFrame::
|
||||
ConnectionResponseCode>>
|
||||
RegisterConnectionResponse(const std::string& service_id);
|
||||
// Unregisters the connection response future for the service id.
|
||||
void UnRegisterConnectionResponse(const std::string& service_id);
|
||||
// Starts the reader thread to read the incoming MultiplexFrame from the
|
||||
// physical socket.
|
||||
void StartReaderThread(std::int32_t first_frame_len);
|
||||
// Handles the offline frame from the physical socket.
|
||||
void HandleOfflineFrame(const ByteArray& bytes);
|
||||
// Handles the control frame from the physical socket.
|
||||
void HandleControlFrame(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const ::location::nearby::mediums::MultiplexControlFrame& frame);
|
||||
// Handles the connection request frame from the physical socket.
|
||||
void HandleConnectionRequest(const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt);
|
||||
// Handles the connection response frame from the physical socket.
|
||||
void HandleConnectionResponse(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const ::location::nearby::mediums::ConnectionResponseFrame& frame);
|
||||
// Handles the disconnection frame from the physical socket.
|
||||
void HandleDisconnection(const ByteArray& salted_service_id_hash);
|
||||
// Handles the data frame from the physical socket.
|
||||
void HandleDataFrame(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt,
|
||||
const ::location::nearby::mediums::MultiplexDataFrame& frame);
|
||||
// Handles the physical socket closed.
|
||||
void OnPhysicalSocketClosed();
|
||||
// Remaps and gets the virtual socket by service id hash.
|
||||
MediumSocket* ReMapAndGetVirtualSocket(
|
||||
const ByteArray& salted_service_id_hash,
|
||||
const std::string& service_id_hash_salt);
|
||||
// Handles the virtual socket closed.
|
||||
void OnVirtualSocketClosed(const std::string& service_id);
|
||||
// Runs the offload thread.
|
||||
void RunOffloadThread(const std::string& name,
|
||||
absl::AnyInvocable<void()> runnable);
|
||||
|
||||
// The physical socket connect to the remote device.
|
||||
std::shared_ptr<MediumSocket> physical_socket_ptr_;
|
||||
|
||||
// The output stream to manage all outgoing frames from all clients.
|
||||
MultiplexOutputStream multiplex_output_stream_;
|
||||
// The {@link InputStream} of the physical socket. It is used to read the
|
||||
// incoming MultiplexFrame from the physical socket.
|
||||
InputStream* physical_reader_;
|
||||
// The medium type of the physical socket.
|
||||
Medium medium_;
|
||||
|
||||
// The callback to enable the MultiplexSocket.
|
||||
std::shared_ptr<absl::AnyInvocable<void()>> enable_cb_ =
|
||||
std::make_shared<absl::AnyInvocable<void()>>([this]() { Enable(); });
|
||||
|
||||
// A map of service Id -> {@link SettableFuture} for waiting the
|
||||
// ConnectionResponse. Non-empty while requesting the virtual socket.
|
||||
absl::flat_hash_map<std::string,
|
||||
std::shared_ptr<Future<
|
||||
::location::nearby::mediums::ConnectionResponseFrame::
|
||||
ConnectionResponseCode>>>
|
||||
connection_response_futures_;
|
||||
|
||||
// A map of service Id hash key -> virtual socket. Non-empty while at least
|
||||
// one virtual socket alive. Class derived from "MediumSocket" should define a
|
||||
// pointer to the virtual sockets map. When here's any virtual socket
|
||||
// operation, it will be reflected in both derived MediumSocket class and
|
||||
// MultiplexSocket object
|
||||
mutable Mutex virtual_socket_mutex_;
|
||||
absl::flat_hash_map<std::string, std::shared_ptr<MediumSocket>>
|
||||
virtual_sockets_ ABSL_GUARDED_BY(virtual_socket_mutex_);
|
||||
|
||||
// The thread to receive incoming MultiplexFrame from the physical socket.
|
||||
SingleThreadExecutor physical_reader_thread_;
|
||||
// The single thread we throw the potentially blocking work on to.
|
||||
SingleThreadExecutor single_thread_offloader_;
|
||||
|
||||
// The status of the MultiplexSocket enabled or disabled, it depends on both
|
||||
// Sender and Receiver supports MultiplexSocket or not. Default disabled and
|
||||
// enable it once two devices negotiated finished.
|
||||
AtomicBoolean enabled_{false};
|
||||
|
||||
// If the socket is already shutdown and no longer in use.
|
||||
bool is_shutdown_ = false;
|
||||
static AtomicBoolean is_shutting_down_;
|
||||
std::unique_ptr<CountDownLatch> reader_thread_shutdown_barrier_;
|
||||
};
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_MEDIUMS_MULTIPLEX_MULTIPLEX_SOCKET_H_
|
||||
@@ -1,451 +0,0 @@
|
||||
// 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 "connections/implementation/mediums/multiplex/multiplex_socket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/mediums/multiplex/multiplex_frames.h"
|
||||
#include "connections/implementation/offline_frames.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/pipe.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
#include "internal/platform/socket.h"
|
||||
#include "proto/connections_enums.proto.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace multiplex {
|
||||
|
||||
constexpr absl::string_view SERVICE_ID_1 = "serviceId_1";
|
||||
constexpr absl::string_view SERVICE_ID_2 = "serviceId_2";
|
||||
|
||||
using location::nearby::mediums::ConnectionResponseFrame;
|
||||
using location::nearby::mediums::MultiplexControlFrame;
|
||||
using location::nearby::mediums::MultiplexFrame;
|
||||
using location::nearby::proto::connections::Medium;
|
||||
using location::nearby::proto::connections::Medium_Name;
|
||||
|
||||
// A fake socket for testing.
|
||||
class FakeSocket : public MediumSocket {
|
||||
public:
|
||||
explicit FakeSocket(Medium medium) : MediumSocket(medium) {
|
||||
pipe_1_ = CreatePipe();
|
||||
reader_1_ = std::move(pipe_1_.first);
|
||||
writer_1_ = std::move(pipe_1_.second);
|
||||
pipe_2_ = CreatePipe();
|
||||
reader_2_ = std::move(pipe_2_.first);
|
||||
writer_2_ = std::move(pipe_2_.second);
|
||||
LOG(WARNING) << "Physical Socket Medium:" << Medium_Name(GetMedium());
|
||||
};
|
||||
~FakeSocket() override = default;
|
||||
|
||||
FakeSocket(const FakeSocket&) = default;
|
||||
FakeSocket& operator=(const FakeSocket&) = default;
|
||||
|
||||
/**
|
||||
* The constructor for a virtual socket which own the virtual {@link
|
||||
* OutputStream} and {@link InputStream}.
|
||||
*/
|
||||
explicit FakeSocket(Medium medium, OutputStream* virtualOutputStream)
|
||||
: MediumSocket(medium),
|
||||
is_virtual_socket_(true),
|
||||
virtual_output_stream_(virtualOutputStream) {
|
||||
pipe_1_ = CreatePipe();
|
||||
reader_1_ = std::move(pipe_1_.first);
|
||||
writer_1_ = std::move(pipe_1_.second);
|
||||
pipe_2_ = CreatePipe();
|
||||
reader_2_ = std::move(pipe_2_.first);
|
||||
writer_2_ = std::move(pipe_2_.second);
|
||||
}
|
||||
|
||||
InputStream& GetInputStream() override { return *reader_1_; }
|
||||
OutputStream& GetOutputStream() override {
|
||||
return IsVirtualSocket() ? *virtual_output_stream_
|
||||
: *writer_2_;
|
||||
} Exception Close() override {
|
||||
if (IsVirtualSocket()) {
|
||||
LOG(INFO) << "Multiplex: Closing virtual socket: " << this;
|
||||
CloseLocal();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
LOG(INFO) << "Multiplex: Closing physical socket: " << this;
|
||||
reader_1_->Close();
|
||||
reader_2_->Close();
|
||||
writer_1_->Close();
|
||||
writer_2_->Close();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
MediumSocket* CreateVirtualSocket(
|
||||
const std::string& salted_service_id_hash_key, OutputStream* outputstream,
|
||||
Medium medium,
|
||||
absl::flat_hash_map<std::string, std::shared_ptr<MediumSocket>>*
|
||||
virtual_sockets_ptr) override {
|
||||
if (IsVirtualSocket()) {
|
||||
LOG(WARNING)
|
||||
<< "Creating the virtual socket on a virtual socket is not allowed.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto virtual_socket = std::make_shared<FakeSocket>(medium, outputstream);
|
||||
LOG(WARNING) << "Created the virtual socket for Medium: "
|
||||
<< Medium_Name(virtual_socket->GetMedium());
|
||||
|
||||
if (virtual_sockets_ptr_ == nullptr) {
|
||||
virtual_sockets_ptr_ = virtual_sockets_ptr;
|
||||
}
|
||||
|
||||
(*virtual_sockets_ptr_)[salted_service_id_hash_key] = virtual_socket;
|
||||
LOG(INFO) << "virtual_sockets_ size: " << virtual_sockets_ptr_->size();
|
||||
return virtual_socket.get();
|
||||
}
|
||||
|
||||
void FeedIncomingData(ByteArray data) override {
|
||||
bytes_read_future_.Set(data);
|
||||
LOG(INFO) << "FeedIncomingData. Size of receive data: " << data.size()
|
||||
<< ", bytes content:" << std::string(data);
|
||||
}
|
||||
|
||||
bool IsVirtualSocket() override { return is_virtual_socket_; }
|
||||
Future<ByteArray>& GetByteReadFuture() { return bytes_read_future_; }
|
||||
|
||||
std::pair<std::unique_ptr<InputStream>, std::unique_ptr<OutputStream>>
|
||||
pipe_1_;
|
||||
std::unique_ptr<InputStream> reader_1_;
|
||||
std::unique_ptr<OutputStream> writer_1_;
|
||||
std::pair<std::unique_ptr<InputStream>, std::unique_ptr<OutputStream>>
|
||||
pipe_2_;
|
||||
std::unique_ptr<InputStream> reader_2_;
|
||||
std::unique_ptr<OutputStream> writer_2_;
|
||||
|
||||
private:
|
||||
bool is_virtual_socket_ = false;
|
||||
Future<ByteArray> bytes_read_future_;
|
||||
absl::flat_hash_map<std::string, std::shared_ptr<MediumSocket>>*
|
||||
virtual_sockets_ptr_ = nullptr;
|
||||
OutputStream* virtual_output_stream_ = nullptr;
|
||||
};
|
||||
|
||||
TEST(MultiplexSocketTest, CreateIncomingSocketSuccess) {
|
||||
auto fake_socket_ptr = std::make_shared<FakeSocket>(Medium::BLUETOOTH);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_1),
|
||||
Medium::BLUETOOTH);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_2),
|
||||
Medium::BLUETOOTH);
|
||||
MultiplexSocket::ListenForIncomingConnection(
|
||||
std::string(SERVICE_ID_1), Medium::BLUETOOTH,
|
||||
[](const std::string& service_id, MediumSocket* socket) {
|
||||
LOG(INFO) << "Incoming connection for service_id: " << service_id;
|
||||
});
|
||||
MultiplexSocket::ListenForIncomingConnection(
|
||||
std::string(SERVICE_ID_2), Medium::BLUETOOTH,
|
||||
[](const std::string& service_id, MediumSocket* socket) {
|
||||
LOG(INFO) << "Incoming connection for service_id: " << service_id;
|
||||
});
|
||||
|
||||
MultiplexSocket* multiplex_socket_incoming =
|
||||
MultiplexSocket::CreateIncomingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_1), /*first_frame_len*/ 0);
|
||||
ASSERT_NE(multiplex_socket_incoming, nullptr);
|
||||
MultiplexSocket* multiplex_socket_incoming_2 =
|
||||
MultiplexSocket::CreateIncomingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_2), /*first_frame_len*/ 0);
|
||||
ASSERT_EQ(multiplex_socket_incoming_2, multiplex_socket_incoming);
|
||||
|
||||
FakeSocket* virtual_socket =
|
||||
(FakeSocket*)multiplex_socket_incoming->GetVirtualSocket(
|
||||
std::string(SERVICE_ID_1));
|
||||
if (virtual_socket == nullptr) {
|
||||
LOG(INFO) << "Virtual socket not found for " << SERVICE_ID_1;
|
||||
return;
|
||||
}
|
||||
|
||||
SingleThreadExecutor executor;
|
||||
FakeSocket* socket = fake_socket_ptr.get();
|
||||
executor.Execute([socket]() {
|
||||
ByteArray connection_req_frame = parser::ForConnectionRequestConnections(
|
||||
{}, {
|
||||
.local_endpoint_id = "endpoint1",
|
||||
.local_endpoint_info = ByteArray("endpoint1 info"),
|
||||
});
|
||||
auto& writer = socket->writer_1_;
|
||||
LOG(INFO) << "writer_1_ Write start";
|
||||
Base64Utils::WriteInt(writer.get(), connection_req_frame.size());
|
||||
writer->Write(connection_req_frame.AsStringView());
|
||||
writer->Flush();
|
||||
LOG(INFO) << "writer_1_ Write end";
|
||||
});
|
||||
|
||||
ExceptionOr<ByteArray> result = virtual_socket->GetByteReadFuture().Get();
|
||||
if (!result.ok()) {
|
||||
ADD_FAILURE() << "Read error: " << result.GetException().value;
|
||||
}
|
||||
ByteArray data = result.result();
|
||||
LOG(INFO) << "Received " << data.size() << " bytes of data.";
|
||||
EXPECT_NE(data.size(), 0);
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
|
||||
EXPECT_EQ(multiplex_socket_incoming->GetVirtualSocketCount(), 1);
|
||||
virtual_socket->Close();
|
||||
EXPECT_EQ(multiplex_socket_incoming->GetVirtualSocketCount(), 0);
|
||||
multiplex_socket_incoming->ShutdownAll();
|
||||
}
|
||||
|
||||
TEST(MultiplexSocketTest, CreateFail_MediumNotSupport) {
|
||||
auto fake_socket_ptr = std::make_shared<FakeSocket>(Medium::WEB_RTC);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_1),
|
||||
Medium::WEB_RTC);
|
||||
MultiplexSocket* multiplex_socket_incoming =
|
||||
MultiplexSocket::CreateIncomingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_1), /*first_frame_len*/ 0);
|
||||
|
||||
ASSERT_EQ(multiplex_socket_incoming, nullptr);
|
||||
}
|
||||
|
||||
TEST(MultiplexSocketTest, CreateIncomingVirtualSocketSuccess) {
|
||||
auto fake_socket_ptr = std::make_shared<FakeSocket>(Medium::WIFI_LAN);
|
||||
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_1),
|
||||
Medium::WIFI_LAN);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_2),
|
||||
Medium::WIFI_LAN);
|
||||
MultiplexSocket::ListenForIncomingConnection(
|
||||
std::string(SERVICE_ID_1), Medium::WIFI_LAN,
|
||||
[](const std::string& service_id, MediumSocket* socket) {
|
||||
LOG(INFO) << "Incoming connection for service_id: " << service_id;
|
||||
});
|
||||
MultiplexSocket::ListenForIncomingConnection(
|
||||
std::string(SERVICE_ID_2), Medium::WIFI_LAN,
|
||||
[](const std::string& service_id, MediumSocket* socket) {
|
||||
LOG(INFO) << "Incoming connection for service_id: " << service_id;
|
||||
});
|
||||
|
||||
MultiplexSocket* multiplex_socket_incoming =
|
||||
MultiplexSocket::CreateIncomingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_1), /*first_frame_len*/ 0);
|
||||
ASSERT_NE(multiplex_socket_incoming, nullptr);
|
||||
|
||||
FakeSocket* virtual_socket =
|
||||
(FakeSocket*)multiplex_socket_incoming->GetVirtualSocket(
|
||||
std::string(SERVICE_ID_1));
|
||||
if (virtual_socket == nullptr) {
|
||||
LOG(INFO) << "Virtual socket not found for " << SERVICE_ID_1;
|
||||
return;
|
||||
}
|
||||
|
||||
SingleThreadExecutor executor;
|
||||
FakeSocket* socket = fake_socket_ptr.get();
|
||||
executor.Execute([socket]() {
|
||||
ByteArray connection_req_frame = ForConnectionRequest(
|
||||
std::string(SERVICE_ID_2), "J7frzSmHK-VBTHjCKpf4ew");
|
||||
auto& writer = socket->writer_1_;
|
||||
LOG(INFO) << "writer_1_ Write start";
|
||||
Base64Utils::WriteInt(writer.get(), connection_req_frame.size());
|
||||
writer->Write(connection_req_frame.AsStringView());
|
||||
writer->Flush();
|
||||
LOG(INFO) << "writer_1_ Write end";
|
||||
});
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
|
||||
EXPECT_EQ(multiplex_socket_incoming->GetVirtualSocketCount(), 2);
|
||||
virtual_socket->Close();
|
||||
EXPECT_EQ(multiplex_socket_incoming->GetVirtualSocketCount(), 1);
|
||||
multiplex_socket_incoming->ShutdownAll();
|
||||
}
|
||||
|
||||
TEST(MultiplexSocketTest,
|
||||
EstablishVirtualSocket_Timeout_BecauseNoConnectionResponse) {
|
||||
auto fake_socket_ptr = std::make_shared<FakeSocket>(Medium::WIFI_LAN);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_1),
|
||||
Medium::WIFI_LAN);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_2),
|
||||
Medium::WIFI_LAN);
|
||||
MultiplexSocket* multiplex_socket = MultiplexSocket::CreateOutgoingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_1));
|
||||
ASSERT_NE(multiplex_socket, nullptr);
|
||||
MultiplexSocket* multiplex_socket_2 = MultiplexSocket::CreateOutgoingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_2));
|
||||
ASSERT_EQ(multiplex_socket_2, multiplex_socket);
|
||||
multiplex_socket->Enable();
|
||||
FakeSocket* virtual_socket = (FakeSocket*)multiplex_socket->GetVirtualSocket(
|
||||
std::string(SERVICE_ID_1));
|
||||
if (virtual_socket == nullptr) {
|
||||
LOG(INFO) << "Virtual socket not found for " << SERVICE_ID_1;
|
||||
return;
|
||||
}
|
||||
|
||||
SingleThreadExecutor establish_socket_executor;
|
||||
establish_socket_executor.Execute([&multiplex_socket]() {
|
||||
LOG(INFO) << "EstablishVirtualSocket";
|
||||
MediumSocket* socket =
|
||||
multiplex_socket->EstablishVirtualSocket(std::string(SERVICE_ID_2));
|
||||
LOG(INFO) << "EstablishVirtualSocket finished";
|
||||
EXPECT_EQ(socket, nullptr);
|
||||
});
|
||||
|
||||
SingleThreadExecutor read_executor;
|
||||
read_executor.Execute([&multiplex_socket, &fake_socket_ptr]() {
|
||||
auto reader = fake_socket_ptr->reader_2_.get();
|
||||
LOG(INFO) << "reader_2_ Read start";
|
||||
ExceptionOr<std::int32_t> read_int = Base64Utils::ReadInt(reader);
|
||||
if (!read_int.ok()) {
|
||||
ADD_FAILURE() << "Failed to read. Exception:" << read_int.exception();
|
||||
}
|
||||
auto length = read_int.result();
|
||||
LOG(INFO) << " length:" << length;
|
||||
EXPECT_GT(length, 0);
|
||||
EXPECT_EQ(multiplex_socket->GetVirtualSocket(std::string(SERVICE_ID_2)),
|
||||
nullptr);
|
||||
});
|
||||
|
||||
absl::SleepFor(absl::Milliseconds(300));
|
||||
EXPECT_EQ(multiplex_socket->GetVirtualSocketCount(), 1);
|
||||
virtual_socket->Close();
|
||||
EXPECT_EQ(multiplex_socket->GetVirtualSocketCount(), 0);
|
||||
multiplex_socket->ShutdownAll();
|
||||
}
|
||||
|
||||
TEST(MultiplexSocketTest, EstablishVirtualSocket_RemoteAccepted) {
|
||||
auto fake_socket_ptr = std::make_shared<FakeSocket>(Medium::BLUETOOTH);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_1),
|
||||
Medium::BLUETOOTH);
|
||||
MultiplexSocket::StopListeningForIncomingConnection(std::string(SERVICE_ID_2),
|
||||
Medium::BLUETOOTH);
|
||||
|
||||
MultiplexSocket* multiplex_socket = MultiplexSocket::CreateOutgoingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_1));
|
||||
ASSERT_NE(multiplex_socket, nullptr);
|
||||
MultiplexSocket* multiplex_socket_2 = MultiplexSocket::CreateOutgoingSocket(
|
||||
fake_socket_ptr, std::string(SERVICE_ID_2));
|
||||
ASSERT_EQ(multiplex_socket_2, multiplex_socket);
|
||||
|
||||
SingleThreadExecutor executor;
|
||||
CountDownLatch latch(1);
|
||||
executor.Execute([&multiplex_socket, &latch]() {
|
||||
LOG(INFO) << "EstablishVirtualSocket";
|
||||
MediumSocket* socket =
|
||||
multiplex_socket->EstablishVirtualSocket(std::string(SERVICE_ID_2));
|
||||
EXPECT_EQ(socket, nullptr);
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
|
||||
multiplex_socket->Enable();
|
||||
executor.Execute([&multiplex_socket]() {
|
||||
LOG(INFO) << "EstablishVirtualSocket";
|
||||
MediumSocket* socket =
|
||||
multiplex_socket->EstablishVirtualSocket(std::string(SERVICE_ID_2));
|
||||
EXPECT_NE(socket, nullptr);
|
||||
});
|
||||
|
||||
auto reader = fake_socket_ptr->reader_2_.get();
|
||||
LOG(INFO) << "reader_2_ Waiting for CONNECTION_REQUEST frame.";
|
||||
ExceptionOr<std::int32_t> read_int = Base64Utils::ReadInt(reader);
|
||||
if (!read_int.ok()) {
|
||||
ADD_FAILURE() << "Failed to read length.Exception:" << read_int.exception();
|
||||
}
|
||||
auto length = read_int.result();
|
||||
if (length < 0 ||
|
||||
length >
|
||||
FeatureFlags::GetInstance().GetFlags().connection_max_frame_length) {
|
||||
ADD_FAILURE() << "Invalid length:" << length;
|
||||
}
|
||||
|
||||
auto bytes = reader->ReadExactly(length);
|
||||
if (!bytes.ok()) {
|
||||
ADD_FAILURE() << "Failed to read frame. Exception:" << bytes.exception();
|
||||
}
|
||||
length = read_int.result();
|
||||
if (length < 0 ||
|
||||
length >
|
||||
FeatureFlags::GetInstance().GetFlags().connection_max_frame_length) {
|
||||
ADD_FAILURE() << "Invalid frame length:" << length;
|
||||
}
|
||||
|
||||
ExceptionOr<MultiplexFrame> frame_exc = multiplex::FromBytes(bytes.result());
|
||||
if (!frame_exc.ok()) {
|
||||
ADD_FAILURE() << "Failed to parse MultiplexFrame. Exception:"
|
||||
<< frame_exc.exception();
|
||||
}
|
||||
auto frame = frame_exc.result();
|
||||
auto salted_service_id_hash =
|
||||
ByteArray{std::move(frame.header().salted_service_id_hash())};
|
||||
auto service_id_hash_salt = frame.header().has_service_id_hash_salt()
|
||||
? frame.header().service_id_hash_salt()
|
||||
: "";
|
||||
ASSERT_EQ(frame.frame_type(), MultiplexFrame::CONTROL_FRAME);
|
||||
auto control_frame = frame.control_frame();
|
||||
ASSERT_EQ(control_frame.control_frame_type(),
|
||||
MultiplexControlFrame::CONNECTION_REQUEST);
|
||||
LOG(INFO) << "Recieved MultiplexControlFrame::CONNECTION_REQUEST "
|
||||
"frame, now send CONNECTION_RESPONSE frame.";
|
||||
|
||||
ByteArray connection_response_frame =
|
||||
ForConnectionResponse(salted_service_id_hash, service_id_hash_salt,
|
||||
ConnectionResponseFrame::CONNECTION_ACCEPTED);
|
||||
auto& writer = fake_socket_ptr->writer_1_;
|
||||
LOG(INFO) << "writer_1_ Write start";
|
||||
Base64Utils::WriteInt(writer.get(), connection_response_frame.size());
|
||||
writer->Write(connection_response_frame.AsStringView());
|
||||
writer->Flush();
|
||||
LOG(INFO) << "writer_1_ Write end";
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
EXPECT_NE(multiplex_socket->GetVirtualSocket(std::string(SERVICE_ID_2)),
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(multiplex_socket->GetVirtualSocketCount(), 2);
|
||||
|
||||
LOG(INFO) << "Send Data frame on virtual socket for SERVICE_ID_2.";
|
||||
ByteArray data_frame =
|
||||
ForData(std::string(SERVICE_ID_2), service_id_hash_salt,
|
||||
/*should_pass_salt=*/true, absl::string_view("data"));
|
||||
Base64Utils::WriteInt(writer.get(), data_frame.size());
|
||||
writer->Write(data_frame.AsStringView());
|
||||
writer->Flush();
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
|
||||
LOG(INFO) << "Send disconnection frame on virtual socket for SERVICE_ID_2.";
|
||||
ByteArray disconnect_frame =
|
||||
ForDisconnection(std::string(SERVICE_ID_2), service_id_hash_salt);
|
||||
Base64Utils::WriteInt(writer.get(), disconnect_frame.size());
|
||||
writer->Write(disconnect_frame.AsStringView());
|
||||
writer->Flush();
|
||||
absl::SleepFor(absl::Milliseconds(100));
|
||||
EXPECT_EQ(multiplex_socket->GetVirtualSocketCount(), 1);
|
||||
|
||||
multiplex_socket->ShutdownAll();
|
||||
}
|
||||
|
||||
} // namespace multiplex
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -1,788 +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 NO_WEBRTC
|
||||
|
||||
#include "connections/implementation/mediums/webrtc.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/mediums/webrtc/connection_flow.h"
|
||||
#include "connections/implementation/mediums/webrtc/session_description_wrapper.h"
|
||||
#include "connections/implementation/mediums/webrtc/signaling_frames.h"
|
||||
#include "connections/implementation/mediums/webrtc_peer_id.h"
|
||||
#include "connections/implementation/mediums/webrtc_socket.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancelable_alarm.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/feature_flags.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
#include "internal/platform/webrtc.h"
|
||||
#include "webrtc/api/jsep.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
|
||||
namespace {
|
||||
using ::location::nearby::connections::LocationHint;
|
||||
using ::location::nearby::proto::connections::OperationResultCode;
|
||||
|
||||
// The maximum amount of time to wait to connect to a data channel via WebRTC.
|
||||
constexpr absl::Duration kDataChannelTimeout = absl::Seconds(10);
|
||||
|
||||
// Delay between restarting signaling messenger to receive messages.
|
||||
constexpr absl::Duration kRestartReceiveMessagesDuration = absl::Seconds(60);
|
||||
|
||||
} // namespace
|
||||
|
||||
WebRtc::WebRtc() : WebRtc(std::make_unique<WebRtcMedium>()) {}
|
||||
|
||||
WebRtc::WebRtc(std::unique_ptr<WebRtcMedium> medium)
|
||||
: medium_(std::move(medium)) {}
|
||||
|
||||
WebRtc::~WebRtc() {
|
||||
// This ensures that all pending callbacks are run before we reset the medium
|
||||
// and we are not accepting new runnables.
|
||||
single_thread_executor_.Shutdown();
|
||||
|
||||
// Stop accepting all connections
|
||||
absl::flat_hash_set<std::string> service_ids;
|
||||
for (auto& item : accepting_connections_info_) {
|
||||
service_ids.emplace(item.first);
|
||||
}
|
||||
for (const auto& service_id : service_ids) {
|
||||
StopAcceptingConnections(service_id);
|
||||
}
|
||||
}
|
||||
|
||||
std::string WebRtc::GetDefaultCountryCode() {
|
||||
return medium_->GetDefaultCountryCode();
|
||||
}
|
||||
|
||||
bool WebRtc::IsAvailable() { return medium_->IsValid(); }
|
||||
|
||||
bool WebRtc::IsAcceptingConnections(const std::string& service_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
return IsAcceptingConnectionsLocked(service_id);
|
||||
}
|
||||
|
||||
bool WebRtc::IsAcceptingConnectionsLocked(const std::string& service_id) {
|
||||
return accepting_connections_info_.contains(service_id);
|
||||
}
|
||||
|
||||
bool WebRtc::StartAcceptingConnections(const std::string& service_id,
|
||||
const WebrtcPeerId& self_peer_id,
|
||||
const LocationHint& location_hint,
|
||||
AcceptedConnectionCallback callback,
|
||||
bool non_cellular) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!IsAvailable()) {
|
||||
LOG(WARNING) << "Cannot start accepting WebRTC connections because "
|
||||
"WebRTC is not available.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsAcceptingConnectionsLocked(service_id)) {
|
||||
LOG(WARNING) << "Cannot start accepting WebRTC connections because service "
|
||||
<< service_id << "is already accepting WebRTC connections.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We'll track our state here, so that we're separated from the other services
|
||||
// who may be also using WebRTC.
|
||||
AcceptingConnectionsInfo info = AcceptingConnectionsInfo();
|
||||
info.self_peer_id = self_peer_id;
|
||||
info.accepted_connection_callback = std::move(callback);
|
||||
|
||||
medium_->SetNonCellular(non_cellular);
|
||||
|
||||
// Create a new SignalingMessenger so that we can communicate w/ Tachyon.
|
||||
info.signaling_messenger =
|
||||
medium_->GetSignalingMessenger(self_peer_id.GetId(), location_hint);
|
||||
if (!info.signaling_messenger->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This registers ourselves w/ Tachyon, creating a room from the PeerId.
|
||||
// This allows a remote device to message us over Tachyon.
|
||||
if (!info.signaling_messenger->StartReceivingMessages(
|
||||
absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id),
|
||||
absl::bind_front(&WebRtc::OnSignalingComplete, this, service_id))) {
|
||||
info.signaling_messenger.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
// We'll automatically disconnect from Tachyon after 60sec. When this alarm
|
||||
// fires, we'll recreate our room so we continue to receive messages.
|
||||
info.restart_tachyon_receive_messages_alarm =
|
||||
std::make_unique<CancelableAlarm>(
|
||||
"restart_receiving_messages_webrtc",
|
||||
std::bind(&WebRtc::ProcessRestartTachyonReceiveMessages, this,
|
||||
service_id),
|
||||
kRestartReceiveMessagesDuration, &single_thread_executor_);
|
||||
|
||||
// Now that we're set up to receive messages, we'll save our state and return
|
||||
// a successful result.
|
||||
accepting_connections_info_.emplace(service_id, std::move(info));
|
||||
LOG(INFO) << "Started listening for WebRTC connections as "
|
||||
<< self_peer_id.GetId() << " on service " << service_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebRtc::StopAcceptingConnections(const std::string& service_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!IsAcceptingConnectionsLocked(service_id)) {
|
||||
LOG(WARNING) << "Cannot stop accepting WebRTC connections because service "
|
||||
<< service_id << "is not accepting WebRTC connections.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab our info from the map.
|
||||
auto& info = accepting_connections_info_.find(service_id)->second;
|
||||
|
||||
// Stop receiving messages from Tachyon.
|
||||
info.signaling_messenger->StopReceivingMessages();
|
||||
info.signaling_messenger.reset();
|
||||
|
||||
// Cancel the scheduled alarm.
|
||||
if (info.restart_tachyon_receive_messages_alarm &&
|
||||
info.restart_tachyon_receive_messages_alarm->IsValid()) {
|
||||
info.restart_tachyon_receive_messages_alarm->Cancel();
|
||||
info.restart_tachyon_receive_messages_alarm.reset();
|
||||
}
|
||||
|
||||
// If we had any in-progress connections that haven't materialized into full
|
||||
// DataChannels yet, it's time to shut them down since they can't reach us
|
||||
// anymore.
|
||||
absl::flat_hash_set<std::string> peer_ids;
|
||||
for (auto& item : connection_flows_) {
|
||||
peer_ids.emplace(item.first);
|
||||
}
|
||||
for (const auto& peer_id : peer_ids) {
|
||||
const auto& entry = connection_flows_.find(peer_id);
|
||||
// Skip outgoing connections in this step. Start/StopAcceptingConnections
|
||||
// only deals with incoming connections.
|
||||
if (requesting_connections_info_.contains(peer_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip fully connected connections in this step. If the connection was
|
||||
// formed while we were accepting connections, then it will stay alive until
|
||||
// it's explicitly closed.
|
||||
if (!entry->second->CloseIfNotConnected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
connection_flows_.erase(peer_id);
|
||||
}
|
||||
|
||||
// Clean up our state. We're now no longer listening for connections.
|
||||
accepting_connections_info_.erase(service_id);
|
||||
LOG(INFO) << "Stopped listening for WebRTC connections for service "
|
||||
<< service_id;
|
||||
}
|
||||
|
||||
ErrorOr<WebRtcSocketWrapper> WebRtc::Connect(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id,
|
||||
const LocationHint& location_hint, CancellationFlag* cancellation_flag,
|
||||
bool non_cellular) {
|
||||
service_id_to_connect_attempts_count_map_[service_id] = 1;
|
||||
medium_->SetNonCellular(non_cellular);
|
||||
ErrorOr<WebRtcSocketWrapper> wrapper_result = {
|
||||
Error(OperationResultCode::DETAIL_UNKNOWN)};
|
||||
while (service_id_to_connect_attempts_count_map_[service_id] <=
|
||||
kConnectAttemptsLimit) {
|
||||
if (cancellation_flag->Cancelled()) {
|
||||
LOG(WARNING) << "Attempt #"
|
||||
<< service_id_to_connect_attempts_count_map_[service_id]
|
||||
<< ": Cannot Connect with WebRtc due to cancel.";
|
||||
return {
|
||||
Error(OperationResultCode::
|
||||
CLIENT_CANCELLATION_CANCEL_WEB_RTC_OUTGOING_CONNECTION)};
|
||||
}
|
||||
|
||||
LOG(INFO) << "Attempt #"
|
||||
<< service_id_to_connect_attempts_count_map_[service_id]
|
||||
<< ": Beginning connection.";
|
||||
wrapper_result = AttemptToConnect(service_id, remote_peer_id, location_hint,
|
||||
cancellation_flag);
|
||||
if (wrapper_result.has_value()) {
|
||||
return std::move(wrapper_result.value());
|
||||
}
|
||||
|
||||
service_id_to_connect_attempts_count_map_[service_id]++;
|
||||
}
|
||||
|
||||
LOG(WARNING) << "Giving up after " << kConnectAttemptsLimit << " attempts";
|
||||
return {Error(wrapper_result.error().operation_result_code().value())};
|
||||
}
|
||||
|
||||
ErrorOr<WebRtcSocketWrapper> WebRtc::AttemptToConnect(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id,
|
||||
const LocationHint& location_hint, CancellationFlag* cancellation_flag) {
|
||||
ConnectionRequestInfo info = ConnectionRequestInfo();
|
||||
info.self_peer_id = WebrtcPeerId::FromRandom();
|
||||
Future<WebRtcSocketWrapper> socket_future = info.socket_future;
|
||||
|
||||
// `listener` will go out of scope at the end of `AttemptToConnect`, and this
|
||||
// is expected. This `listener` is tied to `socket_future` which we block on
|
||||
// within this stack call, and will not go out of scope until the attempt
|
||||
// is complete.
|
||||
CancellationFlagListener listener(
|
||||
cancellation_flag, [this, &service_id, &socket_future]() {
|
||||
LOG(WARNING) << "Attempt # "
|
||||
<< service_id_to_connect_attempts_count_map_[service_id]
|
||||
<< " to connect with WebRtc stopped due to cancel.";
|
||||
socket_future.SetException({Exception::kFailed});
|
||||
});
|
||||
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
if (!IsAvailable()) {
|
||||
LOG(WARNING) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId()
|
||||
<< " because WebRTC is not available.";
|
||||
return {
|
||||
Error(OperationResultCode::MEDIUM_UNAVAILABLE_WEB_RTC_NOT_AVAILABLE)};
|
||||
}
|
||||
|
||||
// Create a new ConnectionFlow for this connection attempt.
|
||||
std::unique_ptr<ConnectionFlow> connection_flow =
|
||||
CreateConnectionFlow(service_id, remote_peer_id);
|
||||
if (!connection_flow) {
|
||||
LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId()
|
||||
<< " because we failed to create a ConnectionFlow.";
|
||||
return {Error(OperationResultCode::NEARBY_WEB_RTC_CONNECTION_FLOW_NULL)};
|
||||
}
|
||||
|
||||
// Create a new SignalingMessenger so that we can communicate over Tachyon.
|
||||
info.signaling_messenger = medium_->GetSignalingMessenger(
|
||||
info.self_peer_id.GetId(), location_hint);
|
||||
if (!info.signaling_messenger->IsValid()) {
|
||||
LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId()
|
||||
<< " because we failed to create a SignalingMessenger.";
|
||||
return {
|
||||
Error(OperationResultCode::
|
||||
MISCELLEANEOUS_WEB_RTC_TACHYON_SIGNALING_MESSENGER_NULL)};
|
||||
}
|
||||
|
||||
// This registers ourselves w/ Tachyon, creating a room from the PeerId.
|
||||
// This allows a remote device to message us over Tachyon.
|
||||
auto signaling_complete_callback = [socket_future](bool success) mutable {
|
||||
if (!success) {
|
||||
socket_future.SetException({Exception::kFailed});
|
||||
}
|
||||
};
|
||||
if (!info.signaling_messenger->StartReceivingMessages(
|
||||
absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id),
|
||||
signaling_complete_callback)) {
|
||||
LOG(INFO)
|
||||
<< "Cannot connect to WebRTC peer " << remote_peer_id.GetId()
|
||||
<< " because we failed to start receiving messages over Tachyon.";
|
||||
info.signaling_messenger.reset();
|
||||
return {Error(OperationResultCode::
|
||||
MISCELLEANEOUS_WEB_RTC_FAILED_TO_RECEIVE_MESSAGE)};
|
||||
}
|
||||
|
||||
// Poke the remote device. This will cause them to send us an Offer.
|
||||
if (!info.signaling_messenger->SendMessage(
|
||||
remote_peer_id.GetId(),
|
||||
webrtc_frames::EncodeReadyForSignalingPoke(info.self_peer_id))) {
|
||||
LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId()
|
||||
<< " because we failed to poke the peer over Tachyon.";
|
||||
info.signaling_messenger.reset();
|
||||
return {Error(OperationResultCode::
|
||||
CONNECTIVITY_WEB_RTC_CONNECT_TO_TACHYON_FAILURE)};
|
||||
}
|
||||
|
||||
// Create a new ConnectionRequest entry. This map will be used later to look
|
||||
// up state as we negotiate the connection over Tachyon.
|
||||
requesting_connections_info_.emplace(remote_peer_id.GetId(),
|
||||
std::move(info));
|
||||
connection_flows_.emplace(remote_peer_id.GetId(),
|
||||
std::move(connection_flow));
|
||||
}
|
||||
|
||||
// Wait for the connection to go through. Don't hold the mutex here so that
|
||||
// we're not blocking necessary operations.
|
||||
ExceptionOr<WebRtcSocketWrapper> socket_result =
|
||||
socket_future.Get(kDataChannelTimeout);
|
||||
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
// Reclaim our info, since we had released ownership while talking to
|
||||
// Tachyon.
|
||||
auto& info =
|
||||
requesting_connections_info_.find(remote_peer_id.GetId())->second;
|
||||
|
||||
// Verify that the connection went through.
|
||||
if (!socket_result.ok()) {
|
||||
LOG(INFO) << "Failed to connect to WebRTC peer "
|
||||
<< remote_peer_id.GetId();
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
info.signaling_messenger.reset();
|
||||
requesting_connections_info_.erase(remote_peer_id.GetId());
|
||||
return {Error(OperationResultCode::
|
||||
CONNECTIVITY_WEB_RTC_CLIENT_SOCKET_CREATION_FAILURE)};
|
||||
}
|
||||
|
||||
// Clean up our ConnectionRequest.
|
||||
info.signaling_messenger.reset();
|
||||
requesting_connections_info_.erase(remote_peer_id.GetId());
|
||||
|
||||
// Return the result.
|
||||
return socket_result.GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtc::ProcessLocalIceCandidate(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id,
|
||||
const location::nearby::mediums::IceCandidate ice_candidate) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
// Check first if we have an outgoing request w/ this peer. As this request is
|
||||
// tied to a specific peer, it takes precedence.
|
||||
const auto& connection_request_entry =
|
||||
requesting_connections_info_.find(remote_peer_id.GetId());
|
||||
if (connection_request_entry != requesting_connections_info_.end()) {
|
||||
// Pass the ice candidate to the remote side.
|
||||
if (!connection_request_entry->second.signaling_messenger->SendMessage(
|
||||
remote_peer_id.GetId(),
|
||||
webrtc_frames::EncodeIceCandidates(
|
||||
connection_request_entry->second.self_peer_id,
|
||||
{ice_candidate}))) {
|
||||
LOG(INFO) << "Failed to send ice candidate to " << remote_peer_id.GetId();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Sent ice candidate to " << remote_peer_id.GetId();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check next if we're expecting incoming connection requests.
|
||||
const auto& accepting_connection_entry =
|
||||
accepting_connections_info_.find(service_id);
|
||||
if (accepting_connection_entry != accepting_connections_info_.end()) {
|
||||
// Pass the ice candidate to the remote side.
|
||||
// TODO(xlythe) Consider not blocking here, since this can eat into the
|
||||
// connection time
|
||||
if (!accepting_connection_entry->second.signaling_messenger->SendMessage(
|
||||
remote_peer_id.GetId(),
|
||||
webrtc_frames::EncodeIceCandidates(
|
||||
accepting_connection_entry->second.self_peer_id,
|
||||
{ice_candidate}))) {
|
||||
LOG(INFO) << "Failed to send ice candidate to " << remote_peer_id.GetId();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Sent ice candidate to " << remote_peer_id.GetId();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Skipping restart listening for tachyon inbox messages "
|
||||
"since we are not accepting connections for service "
|
||||
<< service_id;
|
||||
}
|
||||
|
||||
void WebRtc::OnSignalingMessage(const std::string& service_id,
|
||||
const ByteArray& message) {
|
||||
OffloadFromThread("rtc-on-signaling-message", [this, service_id, message]() {
|
||||
ProcessTachyonInboxMessage(service_id, message);
|
||||
});
|
||||
}
|
||||
|
||||
void WebRtc::OnSignalingComplete(const std::string& service_id, bool success) {
|
||||
LOG(INFO) << "Signaling completed with status: " << success;
|
||||
if (success) {
|
||||
return;
|
||||
}
|
||||
|
||||
OffloadFromThread("rtc-on-signaling-complete", [this, service_id]() {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& info_entry = accepting_connections_info_.find(service_id);
|
||||
if (info_entry == accepting_connections_info_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info_entry->second.restart_accept_connections_count <
|
||||
kRestartAcceptConnectionsLimit) {
|
||||
++info_entry->second.restart_accept_connections_count;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
RestartTachyonReceiveMessages(service_id);
|
||||
});
|
||||
}
|
||||
|
||||
void WebRtc::ProcessTachyonInboxMessage(const std::string& service_id,
|
||||
const ByteArray& message) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
// Attempt to parse the incoming message as a WebRtcSignalingFrame.
|
||||
location::nearby::mediums::WebRtcSignalingFrame frame;
|
||||
if (!frame.ParseFromString(std::string(message))) {
|
||||
LOG(WARNING) << "Failed to parse signaling message.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that the frame is valid (no missing fields).
|
||||
if (!frame.has_sender_id()) {
|
||||
LOG(WARNING) << "Invalid WebRTC frame: Sender ID is missing.";
|
||||
return;
|
||||
}
|
||||
WebrtcPeerId remote_peer_id = WebrtcPeerId(frame.sender_id().id());
|
||||
|
||||
// Depending on the message type, we'll respond as appropriate.
|
||||
if (requesting_connections_info_.contains(remote_peer_id.GetId())) {
|
||||
// This is from a peer we have an outgoing connection request with, so we'll
|
||||
// only process the Answer path.
|
||||
if (frame.has_offer()) {
|
||||
ReceiveOffer(remote_peer_id,
|
||||
SessionDescriptionWrapper(
|
||||
webrtc_frames::DecodeOffer(frame).release()));
|
||||
SendAnswer(remote_peer_id);
|
||||
} else if (frame.has_ice_candidates()) {
|
||||
ReceiveIceCandidates(remote_peer_id,
|
||||
webrtc_frames::DecodeIceCandidates(frame));
|
||||
} else {
|
||||
LOG(INFO) << "Received unknown WebRTC frame: ignoring.";
|
||||
}
|
||||
} else if (IsAcceptingConnectionsLocked(service_id)) {
|
||||
// We don't have an outgoing connection request with this peer, but we are
|
||||
// accepting incoming requests so we'll only process the Offer path.
|
||||
if (frame.has_ready_for_signaling_poke()) {
|
||||
SendOffer(service_id, remote_peer_id);
|
||||
} else if (frame.has_answer()) {
|
||||
ReceiveAnswer(remote_peer_id,
|
||||
SessionDescriptionWrapper(
|
||||
webrtc_frames::DecodeAnswer(frame).release()));
|
||||
} else if (frame.has_ice_candidates()) {
|
||||
ReceiveIceCandidates(remote_peer_id,
|
||||
webrtc_frames::DecodeIceCandidates(frame));
|
||||
} else {
|
||||
LOG(INFO) << "Received unknown WebRTC frame: ignoring.";
|
||||
}
|
||||
} else {
|
||||
LOG(INFO)
|
||||
<< "Ignoring Tachyon message since we are not accepting connections.";
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtc::SendOffer(const std::string& service_id,
|
||||
const WebrtcPeerId& remote_peer_id) {
|
||||
std::unique_ptr<ConnectionFlow> connection_flow =
|
||||
CreateConnectionFlow(service_id, remote_peer_id);
|
||||
if (!connection_flow) {
|
||||
LOG(INFO) << "Unable to send offer. Failed to create a ConnectionFlow.";
|
||||
return;
|
||||
}
|
||||
|
||||
SessionDescriptionWrapper offer = connection_flow->CreateOffer();
|
||||
if (!offer.IsValid()) {
|
||||
LOG(INFO) << "Unable to send offer. Failed to create our offer locally.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
const webrtc::SessionDescriptionInterface& sdp = offer.GetSdp();
|
||||
if (!connection_flow->SetLocalSessionDescription(offer)) {
|
||||
LOG(INFO) << "Unable to send offer. Failed to register our offer locally.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab our info from the map.
|
||||
auto& info = accepting_connections_info_.find(service_id)->second;
|
||||
|
||||
// Pass the offer to the remote side.
|
||||
if (!info.signaling_messenger->SendMessage(
|
||||
remote_peer_id.GetId(),
|
||||
webrtc_frames::EncodeOffer(info.self_peer_id, sdp))) {
|
||||
LOG(INFO)
|
||||
<< "Unable to send offer. Failed to write the offer to the remote peer "
|
||||
<< remote_peer_id.GetId();
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the ConnectionFlow so that other methods can use it later.
|
||||
connection_flows_.emplace(remote_peer_id.GetId(), std::move(connection_flow));
|
||||
LOG(INFO) << "Sent offer to " << remote_peer_id.GetId();
|
||||
}
|
||||
|
||||
void WebRtc::ReceiveOffer(const WebrtcPeerId& remote_peer_id,
|
||||
SessionDescriptionWrapper offer) {
|
||||
const auto& entry = connection_flows_.find(remote_peer_id.GetId());
|
||||
if (entry == connection_flows_.end()) {
|
||||
LOG(INFO) << "Unable to receive offer. Failed to create a ConnectionFlow.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entry->second->OnOfferReceived(offer)) {
|
||||
LOG(INFO) << "Unable to receive offer. Failed to process the offer.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtc::SendAnswer(const WebrtcPeerId& remote_peer_id) {
|
||||
const auto& entry = connection_flows_.find(remote_peer_id.GetId());
|
||||
if (entry == connection_flows_.end()) {
|
||||
LOG(INFO) << "Unable to send answer. Failed to create a ConnectionFlow.";
|
||||
return;
|
||||
}
|
||||
|
||||
SessionDescriptionWrapper answer = entry->second->CreateAnswer();
|
||||
if (!answer.IsValid()) {
|
||||
LOG(INFO) << "Unable to send answer. Failed to create our answer locally.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
const webrtc::SessionDescriptionInterface& sdp = answer.GetSdp();
|
||||
if (!entry->second->SetLocalSessionDescription(answer)) {
|
||||
LOG(INFO)
|
||||
<< "Unable to send answer. Failed to register our answer locally.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab our info from the map.
|
||||
const auto& connection_request_entry =
|
||||
requesting_connections_info_.find(remote_peer_id.GetId());
|
||||
if (connection_request_entry == requesting_connections_info_.end()) {
|
||||
LOG(INFO) << "Unable to send answer. Failed to find an outgoing "
|
||||
"connection request.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the answer to the remote side.
|
||||
if (!connection_request_entry->second.signaling_messenger->SendMessage(
|
||||
remote_peer_id.GetId(),
|
||||
webrtc_frames::EncodeAnswer(
|
||||
connection_request_entry->second.self_peer_id, sdp))) {
|
||||
LOG(INFO)
|
||||
<< "Unable to send answer. Failed to write the answer to the remote "
|
||||
"peer "
|
||||
<< remote_peer_id.GetId();
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Sent answer to " << remote_peer_id.GetId();
|
||||
}
|
||||
|
||||
void WebRtc::ReceiveAnswer(const WebrtcPeerId& remote_peer_id,
|
||||
SessionDescriptionWrapper answer) {
|
||||
const auto& entry = connection_flows_.find(remote_peer_id.GetId());
|
||||
if (entry == connection_flows_.end()) {
|
||||
LOG(INFO) << "Unable to receive answer. Failed to create a ConnectionFlow.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entry->second->OnAnswerReceived(answer)) {
|
||||
LOG(INFO) << "Unable to receive answer. Failed to process the answer.";
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtc::ReceiveIceCandidates(
|
||||
const WebrtcPeerId& remote_peer_id,
|
||||
std::vector<std::unique_ptr<webrtc::IceCandidate>> ice_candidates) {
|
||||
const auto& entry = connection_flows_.find(remote_peer_id.GetId());
|
||||
if (entry == connection_flows_.end()) {
|
||||
LOG(INFO) << "Unable to receive ice candidates. Failed to create a "
|
||||
"ConnectionFlow.";
|
||||
return;
|
||||
}
|
||||
|
||||
entry->second->OnRemoteIceCandidatesReceived(std::move(ice_candidates));
|
||||
}
|
||||
|
||||
void WebRtc::ProcessRestartTachyonReceiveMessages(
|
||||
const std::string& service_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
RestartTachyonReceiveMessages(service_id);
|
||||
}
|
||||
|
||||
void WebRtc::RestartTachyonReceiveMessages(const std::string& service_id) {
|
||||
if (!IsAcceptingConnectionsLocked(service_id)) {
|
||||
LOG(INFO)
|
||||
<< "Skipping restart listening for tachyon inbox messages since we are "
|
||||
"not accepting connections for service "
|
||||
<< service_id;
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab our info from the map.
|
||||
auto& info = accepting_connections_info_.find(service_id)->second;
|
||||
|
||||
// Ensure we've disconnected from Tachyon.
|
||||
info.signaling_messenger->StopReceivingMessages();
|
||||
|
||||
// Attempt to re-register.
|
||||
if (!info.signaling_messenger->StartReceivingMessages(
|
||||
absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id),
|
||||
absl::bind_front(&WebRtc::OnSignalingComplete, this, service_id))) {
|
||||
LOG(WARNING)
|
||||
<< "Failed to restart listening for tachyon inbox messages for "
|
||||
"service "
|
||||
<< service_id << " since we failed to reach Tachyon.";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully restarted listening for tachyon inbox "
|
||||
"messages on service "
|
||||
<< service_id;
|
||||
}
|
||||
|
||||
void WebRtc::ProcessDataChannelOpen(const std::string& service_id,
|
||||
const WebrtcPeerId& remote_peer_id,
|
||||
WebRtcSocketWrapper socket_wrapper) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
// Notify the client of the newly formed socket.
|
||||
const auto& connection_request_entry =
|
||||
requesting_connections_info_.find(remote_peer_id.GetId());
|
||||
if (connection_request_entry != requesting_connections_info_.end()) {
|
||||
connection_request_entry->second.socket_future.Set(socket_wrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& accepting_connection_entry =
|
||||
accepting_connections_info_.find(service_id);
|
||||
if (accepting_connection_entry != accepting_connections_info_.end() &&
|
||||
accepting_connection_entry->second.accepted_connection_callback) {
|
||||
accepting_connection_entry->second.accepted_connection_callback(
|
||||
service_id, socket_wrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
// No one to handle the newly created DataChannel, so we'll just close it.
|
||||
socket_wrapper.Close();
|
||||
LOG(INFO) << "Ignoring new DataChannel because we are not accepting "
|
||||
"connections for service "
|
||||
<< service_id;
|
||||
}
|
||||
|
||||
void WebRtc::ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
LOG(INFO) << "Data channel has closed, removing connection flow for peer "
|
||||
<< remote_peer_id.GetId();
|
||||
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
}
|
||||
|
||||
std::unique_ptr<ConnectionFlow> WebRtc::CreateConnectionFlow(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id) {
|
||||
RemoveConnectionFlow(remote_peer_id);
|
||||
|
||||
return ConnectionFlow::Create(
|
||||
{.local_ice_candidate_found_cb =
|
||||
{[this, service_id,
|
||||
remote_peer_id](const webrtc::IceCandidate* ice_candidate) {
|
||||
// Note: We need to encode the ice candidate here, before we jump
|
||||
// off the thread. Otherwise, it gets destroyed and we can't read
|
||||
// it later.
|
||||
location::nearby::mediums::IceCandidate encoded_ice_candidate =
|
||||
webrtc_frames::EncodeIceCandidate(*ice_candidate);
|
||||
OffloadFromThread(
|
||||
"rtc-ice-candidates",
|
||||
[this, service_id, remote_peer_id, encoded_ice_candidate]() {
|
||||
ProcessLocalIceCandidate(service_id, remote_peer_id,
|
||||
encoded_ice_candidate);
|
||||
});
|
||||
}}},
|
||||
{
|
||||
.data_channel_open_cb = {[this, service_id, remote_peer_id](
|
||||
WebRtcSocketWrapper socket_wrapper) {
|
||||
OffloadFromThread(
|
||||
"rtc-channel-created",
|
||||
[this, service_id, remote_peer_id, socket_wrapper]() {
|
||||
ProcessDataChannelOpen(service_id, remote_peer_id,
|
||||
socket_wrapper);
|
||||
});
|
||||
}},
|
||||
.data_channel_closed_cb = {[this, remote_peer_id]() {
|
||||
OffloadFromThread("rtc-channel-closed", [this, remote_peer_id]() {
|
||||
ProcessDataChannelClosed(remote_peer_id);
|
||||
});
|
||||
}},
|
||||
},
|
||||
{
|
||||
.adapter_type_changed_cb = {[this](webrtc::AdapterType adapter_type) {
|
||||
OffloadFromThread("rtc-adapter-type-changed",
|
||||
[this, adapter_type]() {
|
||||
if (FeatureFlags::GetInstance()
|
||||
.GetFlags()
|
||||
.support_web_rtc_non_cellular_medium) {
|
||||
AdapterTypeChangedHandler(adapter_type);
|
||||
}
|
||||
});
|
||||
}},
|
||||
},
|
||||
*medium_);
|
||||
}
|
||||
|
||||
void WebRtc::AdapterTypeChangedHandler(webrtc::AdapterType adapter_type) {
|
||||
MutexLock lock(&mutex_);
|
||||
is_using_cellular_ = adapter_type == webrtc::ADAPTER_TYPE_CELLULAR ||
|
||||
adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_2G ||
|
||||
adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_3G ||
|
||||
adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_4G ||
|
||||
adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_5G;
|
||||
}
|
||||
|
||||
void WebRtc::RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id) {
|
||||
if (!connection_flows_.erase(remote_peer_id.GetId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we had an outgoing connection request w/ this peer, report the failure
|
||||
// to the future that's being waited on.
|
||||
const auto& connection_request_entry =
|
||||
requesting_connections_info_.find(remote_peer_id.GetId());
|
||||
if (connection_request_entry != requesting_connections_info_.end()) {
|
||||
connection_request_entry->second.socket_future.SetException(
|
||||
{Exception::kFailed});
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtc::OffloadFromThread(const std::string& name, Runnable runnable) {
|
||||
single_thread_executor_.Execute(name, std::move(runnable));
|
||||
}
|
||||
|
||||
bool WebRtc::IsUsingCellular() {
|
||||
MutexLock lock(&mutex_);
|
||||
return is_using_cellular_;
|
||||
}
|
||||
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
@@ -15,262 +15,76 @@
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_WEBRTC_H_
|
||||
|
||||
#ifndef NO_WEBRTC
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "connections/implementation/mediums/webrtc/connection_flow.h"
|
||||
#include "connections/implementation/mediums/webrtc/session_description_wrapper.h"
|
||||
#include "connections/implementation/bwu_handler.h"
|
||||
#include "connections/implementation/mediums/webrtc_peer_id.h"
|
||||
#include "connections/implementation/mediums/webrtc_socket.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancelable_alarm.h"
|
||||
#include "connections/implementation/proto/offline_wire_formats.pb.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/expected.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/runnable.h"
|
||||
#include "internal/platform/scheduled_executor.h"
|
||||
#include "internal/platform/webrtc.h"
|
||||
#include "proto/mediums/web_rtc_signaling_frames.pb.h"
|
||||
#include "webrtc/api/jsep.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
|
||||
// Entry point for connecting a data channel between two devices via WebRtc.
|
||||
// A non-working base implementation for connecting a data channel between two
|
||||
// devices via WebRtc.
|
||||
class WebRtc {
|
||||
public:
|
||||
// Callback that is invoked when a new connection is accepted.
|
||||
using AcceptedConnectionCallback = absl::AnyInvocable<void(
|
||||
const std::string& service_id, WebRtcSocketWrapper socket)>;
|
||||
const std::string& service_id, std::shared_ptr<WebRtcSocket> socket)>;
|
||||
|
||||
WebRtc();
|
||||
~WebRtc();
|
||||
|
||||
// Gets the default two-letter country code associated with current locale.
|
||||
// For example, en_US locale resolves to "US".
|
||||
std::string GetDefaultCountryCode();
|
||||
virtual ~WebRtc() = default;
|
||||
|
||||
// Returns if WebRtc is available as a medium for nearby to transport data.
|
||||
// Runs on @MainThread.
|
||||
bool IsAvailable();
|
||||
virtual bool IsAvailable() { return false; }
|
||||
|
||||
// Returns if the device is accepting connection with specific service id.
|
||||
// Runs on @MainThread.
|
||||
bool IsAcceptingConnections(const std::string& service_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual bool IsAcceptingConnections(const std::string& service_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepares the device to accept incoming WebRtc connections. Returns a
|
||||
// boolean value indicating if the device has started accepting connections.
|
||||
// Runs on @MainThread.
|
||||
bool StartAcceptingConnections(
|
||||
virtual bool StartAcceptingConnections(
|
||||
const std::string& service_id, const WebrtcPeerId& self_peer_id,
|
||||
const location::nearby::connections::LocationHint& location_hint,
|
||||
AcceptedConnectionCallback callback, bool non_cellular)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
AcceptedConnectionCallback callback, bool non_cellular) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to stop (accepting) the specific connection with provided service id.
|
||||
// Runs on @MainThread
|
||||
void StopAcceptingConnections(const std::string& service_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual void StopAcceptingConnections(const std::string& service_id) {}
|
||||
|
||||
// Initiates a WebRtc connection with peer device identified by |peer_id|
|
||||
// with internal retry for maximum attempts of kConnectAttemptsLimit.
|
||||
// Runs on @MainThread.
|
||||
ErrorOr<WebRtcSocketWrapper> Connect(
|
||||
virtual ErrorOr<std::shared_ptr<WebRtcSocket>> Connect(
|
||||
const std::string& service_id, const WebrtcPeerId& peer_id,
|
||||
const location::nearby::connections::LocationHint& location_hint,
|
||||
CancellationFlag* cancellation_flag, bool non_cellular)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
CancellationFlag* cancellation_flag, bool non_cellular) {
|
||||
return {Error(location::nearby::proto::connections::OperationResultCode::
|
||||
DETAIL_UNKNOWN)};
|
||||
}
|
||||
|
||||
bool IsUsingCellular() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
virtual bool IsUsingCellular() { return false; }
|
||||
|
||||
protected:
|
||||
// Use for unit tests only to inject a WebRtcMedium.
|
||||
explicit WebRtc(std::unique_ptr<WebRtcMedium> medium);
|
||||
|
||||
// Used in unit tests to determine how many calls to `AttemptToConnect`
|
||||
// occured during a call to `Connect`, per service id.
|
||||
std::map<std::string, int> service_id_to_connect_attempts_count_map_;
|
||||
|
||||
private:
|
||||
static constexpr int kConnectAttemptsLimit = 3;
|
||||
static constexpr int kRestartAcceptConnectionsLimit = 3;
|
||||
|
||||
enum class Role {
|
||||
kNone = 0,
|
||||
kOfferer = 1,
|
||||
kAnswerer = 2,
|
||||
};
|
||||
|
||||
struct AcceptingConnectionsInfo {
|
||||
// The self_peer_id is generated from the BT/WiFi advertisements and allows
|
||||
// the scanner to message us over Tachyon.
|
||||
WebrtcPeerId self_peer_id;
|
||||
|
||||
// The registered callback. When there's an incoming connection, this
|
||||
// callback is notified.
|
||||
AcceptedConnectionCallback accepted_connection_callback;
|
||||
|
||||
// Allows us to communicate with the Tachyon web server.
|
||||
std::unique_ptr<WebRtcSignalingMessenger> signaling_messenger;
|
||||
|
||||
// Restarts the tachyon inbox receives messages streaming rpc if the
|
||||
// streaming rpc times out. The streaming rpc times out after 60s while
|
||||
// advertising. Non-null when listening for WebRTC connections as an
|
||||
// offerer.
|
||||
std::unique_ptr<CancelableAlarm> restart_tachyon_receive_messages_alarm;
|
||||
|
||||
// Tracks the number of times we've restarted receiving messages after a
|
||||
// failure. We limit the number to prevent endless restarts if we are
|
||||
// repeatedly unable to communicate with Tachyon.
|
||||
int restart_accept_connections_count = 0;
|
||||
};
|
||||
|
||||
struct ConnectionRequestInfo {
|
||||
// The self_peer_id is randomly generated and allows the advertiser to
|
||||
// message us over Tachyon.
|
||||
WebrtcPeerId self_peer_id;
|
||||
|
||||
// Allows us to communicate with the Tachyon web server.
|
||||
std::unique_ptr<WebRtcSignalingMessenger> signaling_messenger;
|
||||
|
||||
// The pending DataChannel future. Our client will be blocked on this while
|
||||
// they wait for us to set up the channel over Tachyon.
|
||||
Future<WebRtcSocketWrapper> socket_future;
|
||||
};
|
||||
|
||||
// Attempt to initiates a WebRtc connection with peer device identified by
|
||||
// |peer_id|.
|
||||
// Runs on @MainThread.
|
||||
ErrorOr<WebRtcSocketWrapper> AttemptToConnect(
|
||||
const std::string& service_id, const WebrtcPeerId& peer_id,
|
||||
const location::nearby::connections::LocationHint& location_hint,
|
||||
CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns if the device is accepting connection with specific service id.
|
||||
// Runs on @MainThread.
|
||||
bool IsAcceptingConnectionsLocked(const std::string& service_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Receives a message from the signaling messenger.
|
||||
void OnSignalingMessage(const std::string& service_id,
|
||||
const ByteArray& message);
|
||||
|
||||
// Decides whether to restart receiving messages.
|
||||
void OnSignalingComplete(const std::string& service_id, bool success);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ProcessTachyonInboxMessage(const std::string& service_id,
|
||||
const ByteArray& message)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void SendOffer(const std::string& service_id,
|
||||
const WebrtcPeerId& remote_peer_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ReceiveOffer(const WebrtcPeerId& remote_peer_id,
|
||||
SessionDescriptionWrapper offer)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void SendAnswer(const WebrtcPeerId& remote_peer_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ReceiveAnswer(const WebrtcPeerId& remote_peer_id,
|
||||
SessionDescriptionWrapper answer)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ReceiveIceCandidates(
|
||||
const WebrtcPeerId& remote_peer_id,
|
||||
std::vector<std::unique_ptr<webrtc::IceCandidate>> ice_candidates)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
std::unique_ptr<ConnectionFlow> CreateConnectionFlow(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
std::unique_ptr<ConnectionFlow> GetConnectionFlow(
|
||||
const WebrtcPeerId& remote_peer_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ProcessDataChannelOpen(const std::string& service_id,
|
||||
const WebrtcPeerId& remote_peer_id,
|
||||
WebRtcSocketWrapper socket_wrapper)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ProcessLocalIceCandidate(
|
||||
const std::string& service_id, const WebrtcPeerId& remote_peer_id,
|
||||
const location::nearby::mediums::IceCandidate ice_candidate)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void ProcessRestartTachyonReceiveMessages(const std::string& service_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void RestartTachyonReceiveMessages(const std::string& service_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Runs on |single_thread_executor_|.
|
||||
void AdapterTypeChangedHandler(webrtc::AdapterType adapter_type)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void OffloadFromThread(const std::string& name, Runnable runnable);
|
||||
|
||||
Mutex mutex_;
|
||||
|
||||
std::unique_ptr<WebRtcMedium> medium_;
|
||||
|
||||
// The single thread we throw the potentially blocking work on to.
|
||||
ScheduledExecutor single_thread_executor_;
|
||||
|
||||
// A map of ServiceID -> State for all services that are listening for
|
||||
// incoming connections.
|
||||
absl::flat_hash_map<std::string, AcceptingConnectionsInfo>
|
||||
accepting_connections_info_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// A map of a remote PeerId -> State for pending connection requests. As
|
||||
// messages from Tachyon come in, this lets us look up the connection request
|
||||
// info to handle the interaction.
|
||||
absl::flat_hash_map<std::string, ConnectionRequestInfo>
|
||||
requesting_connections_info_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// A map of a remote PeerId -> ConnectionFlow. For each connection, we create
|
||||
// a unique ConnectionFlow.
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<ConnectionFlow>>
|
||||
connection_flows_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
bool is_using_cellular_ ABSL_GUARDED_BY(mutex_) = true;
|
||||
virtual std::unique_ptr<BwuHandler> CreateBwuHandler(
|
||||
BwuHandler::IncomingConnectionCallback incoming_connection_callback) {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_H_
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
# 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.
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "webrtc",
|
||||
srcs = [
|
||||
"connection_flow.cc",
|
||||
"signaling_frames.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"connection_flow.h",
|
||||
"data_channel_listener.h",
|
||||
"local_ice_candidate_listener.h",
|
||||
"session_description_wrapper.h",
|
||||
"signaling_frames.h",
|
||||
],
|
||||
copts = [
|
||||
"-DCORE_ADAPTER_DLL",
|
||||
"-DNO_WEBRTC",
|
||||
],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":data_types",
|
||||
"//connections:core_types",
|
||||
"//connections/implementation/mediums:webrtc_utils",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//proto/mediums:web_rtc_signaling_frames_cc_proto",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:create_peerconnection_factory", # buildcleaner: keep
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:jsep",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:peer_connection_interface",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "data_types",
|
||||
srcs = [
|
||||
"webrtc_socket_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"webrtc_socket_impl.h",
|
||||
],
|
||||
copts = [
|
||||
"-DCORE_ADAPTER_DLL",
|
||||
"-DNO_WEBRTC",
|
||||
],
|
||||
visibility = [
|
||||
"//connections/implementation:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "webrtc_test",
|
||||
timeout = "short",
|
||||
srcs = [
|
||||
"connection_flow_test.cc",
|
||||
"signaling_frames_test.cc",
|
||||
"webrtc_socket_impl_test.cc",
|
||||
],
|
||||
tags = [
|
||||
"notsan", # NOTE(b/139734036): known data race in usrsctplib.
|
||||
"requires-net:external",
|
||||
],
|
||||
deps = [
|
||||
":data_types",
|
||||
":webrtc",
|
||||
"//connections/implementation/mediums:webrtc_utils",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # buildcleaner: keep
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:jsep",
|
||||
# "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@com_google_protobuf//:protobuf",
|
||||
],
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user