From cd29ab51ac4bb5fbacdea03620b77936333968be Mon Sep 17 00:00:00 2001 From: eidenkim Date: Fri, 15 Oct 2021 12:26:38 -0700 Subject: [PATCH] Implemented StartAdvertising() API for Dart Wrappers. PiperOrigin-RevId: 403438989 --- windows/BUILD | 25 +++ windows/core_adapter.h | 1 + windows/dart/core_adapter_dart.cc | 315 ++++++++++++++++++++++++++++++ windows/dart/core_adapter_dart.h | 138 +++++++++++++ 4 files changed, 479 insertions(+) create mode 100644 windows/dart/core_adapter_dart.cc create mode 100644 windows/dart/core_adapter_dart.h diff --git a/windows/BUILD b/windows/BUILD index 1fe8ad6d..f7906412 100644 --- a/windows/BUILD +++ b/windows/BUILD @@ -25,6 +25,31 @@ cc_windows_dll( tags = ["windows-dll"], deps = [ "//absl/strings", + "//third_party/dart_lang/v2:dart_api_dl", + "//core", + "//platform/impl/windows", + "//webrtc/api:create_peerconnection_factory", + ], +) + +# Build with --config=lexan +# TODO(b/203019344) Move this configuration under dart folder and create a BUILD there. +cc_windows_dll( + name = "core_adapter_dart", + srcs = [ + "core_adapter.cc", + "dart/core_adapter_dart.cc", + ], + hdrs = [ + "core_adapter.h", + "dart/core_adapter_dart.h", + ], + copts = ["-DCORE_ADAPTER_DART_BUILD_DLL -DCORE_ADAPTER_DLL -DCOMPILING_CORE"], + defines = ["CORE_ADAPTER_DART_DLL"], + tags = ["windows-dll"], + deps = [ + "//absl/strings", + "//third_party/dart_lang/v2:dart_api_dl", "//core", "//platform/impl/windows", "//webrtc/api:create_peerconnection_factory", diff --git a/windows/core_adapter.h b/windows/core_adapter.h index ff1175b5..8d048f84 100644 --- a/windows/core_adapter.h +++ b/windows/core_adapter.h @@ -20,6 +20,7 @@ // todo(jfcarroll) This cannot remain. It exposes stuff the client doesn't need. #include "core/internal/offline_service_controller.h" +#define DLL_API extern "C" __declspec(dllexport) namespace location { namespace nearby { namespace connections { diff --git a/windows/dart/core_adapter_dart.cc b/windows/dart/core_adapter_dart.cc new file mode 100644 index 00000000..58ec364c --- /dev/null +++ b/windows/dart/core_adapter_dart.cc @@ -0,0 +1,315 @@ +// Copyright 2021 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 "absl/strings/string_view.h" +#include "absl/types/span.h" +#include "core/core.h" +#include "core/internal/client_proxy.h" +#include "core/internal/offline_service_controller.h" +#include "core/internal/service_controller.h" +#include "core/internal/service_controller_router.h" +#include "core/listeners.h" +#include "core/options.h" +#include "core/params.h" +#include "third_party/dart_lang/v2/runtime/include/dart_api_dl.h" +#include "third_party/nearby_connections/windows/core_adapter.h" +#include "third_party/nearby_connections/windows/dart/core_adapter_dart.h" +#include "absl/strings/str_format.h" + +namespace location { +namespace nearby { +namespace connections { + +ConnectionOptions g_discovery_connection_options; +ConnectionOptions g_advertising_connection_options; +ABSL_CONST_INIT absl::Mutex callback_mutex(absl::kConstInit); +std::queue callback_queue; + +Strategy GetStrategy(StrategyDart strategy) { + switch (strategy) { + case StrategyDart::P2P_CLUSTER: + return Strategy::kP2pCluster; + case StrategyDart::P2P_POINT_TO_POINT: + return Strategy::kP2pPointToPoint; + case StrategyDart::P2P_STAR: + return Strategy::kP2pStar; + } + return Strategy::kNone; +} + +ByteArray ConvertBluetoothMacAddress(absl::string_view address) { + return ByteArray(); +} + +void StartAdvertisingDart(Core* pCore, + const char* service_id, + StrategyDart strategy, + const char* endpoint_info, + int auto_upgrade_bandwidth, + int enforce_topology_constraints, + int enable_bluetooth, + int enable_ble, + int advertise_nearby_notifications_beacon, + int use_low_power_mode, + int discover_fast_advertisements, + int enable_wifi_lan, + int enable_nfc, + int enable_wifi_aware, + int enable_web_rtc, + Dart_Port initiated_cb, + Dart_Port accepted_cb, + Dart_Port rejected_cb, + Dart_Port disconnected_cb, + Dart_Port bandwidth_changed_cb, + Dart_Port result_cb) +{ + if (pCore) { + ConnectionOptions options; + options.strategy = GetStrategy(strategy); + options.auto_upgrade_bandwidth = + auto_upgrade_bandwidth; + options.enforce_topology_constraints = + enforce_topology_constraints; + options.allowed.bluetooth = enable_bluetooth; + options.allowed.ble = enable_ble; + // options.nearby_notificatios_beacon ?? + options.low_power = use_low_power_mode; + options.fast_advertisement_service_uuid = + discover_fast_advertisements ? "0000FE2C-0000-1000-8000-00805F9B34FB" : ""; + options.allowed.wifi_lan = enable_wifi_lan; + // options.allowed.nfc > no nfc + // options.allowed.wifi_aware = enable_wifi_aware; + options.allowed.web_rtc = enable_web_rtc; + + ConnectionRequestInfo info; + info.endpoint_info = ByteArray(endpoint_info); + info.listener.initiated_cb = [initiated_cb](const std::string& endpoint_id, + const ConnectionResponseInfo& connection_info) { + NEARBY_LOG(INFO, "Advertising initiated: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_initiated; + dart_object_initiated.type = Dart_CObject_kString; + dart_object_initiated.value.as_string = + (char *)connection_info.remote_endpoint_info.data(); + const bool result = + Dart_PostCObject_DL(initiated_cb, + &dart_object_initiated); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + info.listener.accepted_cb = [accepted_cb](const std::string& endpoint_id) { + NEARBY_LOG(INFO, "Advertising accepted: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_accepted; + dart_object_accepted.type = Dart_CObject_kString; + dart_object_accepted.value.as_string = + (char *)endpoint_id.c_str(); + const bool result = + Dart_PostCObject_DL(accepted_cb, + &dart_object_accepted); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + info.listener.rejected_cb = [rejected_cb](const std::string& endpoint_id, + Status status) { + NEARBY_LOG(INFO, "Advertising rejected: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_rejected; + dart_object_rejected.type = Dart_CObject_kString; + dart_object_rejected.value.as_string = + (char *)endpoint_id.c_str(); + const bool result = + Dart_PostCObject_DL(rejected_cb, + &dart_object_rejected); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + info.listener.disconnected_cb = [disconnected_cb]( + const std::string& endpoint_id) { + NEARBY_LOG(INFO, "Advertising disconnected: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_disconnected; + dart_object_disconnected.type = Dart_CObject_kString; + dart_object_disconnected.value.as_string = + (char *)endpoint_id.c_str(); + const bool result = + Dart_PostCObject_DL(disconnected_cb, + &dart_object_disconnected); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + info.listener.bandwidth_changed_cb = [bandwidth_changed_cb]( + const std::string& endpoint_id, Medium medium) { + NEARBY_LOG(INFO, "Advertising bandwidth changed: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_bandwidth_changed; + + dart_object_bandwidth_changed.type = Dart_CObject_kString; + dart_object_bandwidth_changed.value.as_string = + (char *)endpoint_id.c_str(); + const bool result = + Dart_PostCObject_DL(bandwidth_changed_cb, + &dart_object_bandwidth_changed); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + + ResultCallback callback; + callback.result_cb = [result_cb](Status status) { + NEARBY_LOG(INFO, "Result callback called. %d.", status.value); + Dart_CObject dart_object_result_callback; + dart_object_result_callback.type = Dart_CObject_kInt64; + dart_object_result_callback.value.as_int64 = status.value; + const bool result = Dart_PostCObject_DL(result_cb, + &dart_object_result_callback); + if (!result) { + NEARBY_LOG(INFO, "Posting message to port failed."); + } + }; + + StartAdvertising(pCore, service_id, options, info, callback); + } +} + +void StopAdvertisingDart(Core* pCore, Dart_Port result_cb) { + if (pCore) { + ResultCallback callback; + pCore->StopAdvertising(callback); + } +} + +void StartDiscoveryDart(Core* pCore, + const char* service_id, + StrategyDart strategy, + int forward_unrecognized_bluetooth_devices, + int enable_bluetooth, + int enable_ble, + int use_low_power_mode, + int discover_fast_advertisements, + int enable_wifi_lan, + int enable_nfc, + int enable_wifi_aware, + Dart_Port found_cb, + Dart_Port lost_cb, + Dart_Port distance_changed_cb, + Dart_Port result_cb) { + if (pCore) { + ConnectionOptions options; + options.strategy = GetStrategy(strategy); + options.allowed.bluetooth = enable_bluetooth; + options.allowed.ble = enable_ble; + options.allowed.wifi_lan = enable_wifi_lan; + options.allowed.web_rtc = false; + options.low_power = use_low_power_mode; + options.enable_bluetooth_listening = + enable_bluetooth; + options.enforce_topology_constraints = true; + options.fast_advertisement_service_uuid = + discover_fast_advertisements ? "0000FE2C-0000-1000-8000-00805F9B34FB" : ""; + + DiscoveryListener listener; + listener.endpoint_found_cb = + [found_cb](const std::string& endpoint_id, + const ByteArray& endpoint_info, + const std::string& str_service_id) { + NEARBY_LOG(INFO, "Device discovered: id=%s", + endpoint_id.c_str()); + NEARBY_LOG(INFO, "Device discovered: service_id=%s", + str_service_id.c_str()); + NEARBY_LOG(INFO, "Device discovered: info=%s", + ((string)endpoint_info).c_str()); + Dart_CObject dart_object_found; + dart_object_found.type = Dart_CObject_kString; + dart_object_found.value.as_string = + (char *)endpoint_info.data(); + const bool result = + Dart_PostCObject_DL(found_cb, + &dart_object_found); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + listener.endpoint_lost_cb = + [lost_cb](const std::string& endpoint_id) { + NEARBY_LOG(INFO, "Device lost: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_lost; + dart_object_lost.type = Dart_CObject_kString; + dart_object_lost.value.as_string = + (char *)endpoint_id.c_str(); + const bool result = + Dart_PostCObject_DL(lost_cb, &dart_object_lost); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + listener.endpoint_distance_changed_cb = + [distance_changed_cb](const std::string& endpoint_id, + DistanceInfo info) { + NEARBY_LOG(INFO, "Device distance changed: id=%s", + endpoint_id.c_str()); + Dart_CObject dart_object_distance_changed; + dart_object_distance_changed.type = + Dart_CObject_kString; + dart_object_distance_changed.value.as_string = + (char *)(endpoint_id.c_str()); + const bool result = + Dart_PostCObject_DL(distance_changed_cb, + &dart_object_distance_changed); + if (!result) { + NEARBY_LOG(INFO, + "Posting message to port failed."); + } + }; + + ResultCallback callback; + callback.result_cb = [result_cb](Status status) { + NEARBY_LOG(INFO, "Result callback called. %d.", status.value); + Dart_CObject dart_object_result_callback; + dart_object_result_callback.type = Dart_CObject_kInt64; + dart_object_result_callback.value.as_int64 = status.value; + const bool result = Dart_PostCObject_DL(result_cb, + &dart_object_result_callback); + if (!result) { + NEARBY_LOG(INFO, "Posting message to port failed."); + } + }; + + StartDiscovery(pCore, service_id, options, + listener, callback); + } +} + +void StopDiscoveryDart(Core* pCore, Dart_Port result_cb) { + if (pCore) { + ResultCallback callback; + StopDiscovery(pCore, callback); + } +} + +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/windows/dart/core_adapter_dart.h b/windows/dart/core_adapter_dart.h new file mode 100644 index 00000000..9aa02c4d --- /dev/null +++ b/windows/dart/core_adapter_dart.h @@ -0,0 +1,138 @@ +// Copyright 2021 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 LOCATION_NEARBY_CONNECTIONS_WINDOWS_DART_CORE_ADAPTER_DART_H_ +#define LOCATION_NEARBY_CONNECTIONS_WINDOWS_DART_CORE_ADAPTER_DART_H_ + +#define DLL_API extern "C" __declspec(dllexport) +namespace location { +namespace nearby { +namespace connections { + +enum StrategyDart { + P2P_CLUSTER = 0, + P2P_STAR, + P2P_POINT_TO_POINT, +}; + +// TODO(b/203093770) Replace below with the one that defined in common +struct DartConnectionOptions { + std::string strategy; + bool auto_upgrade_bandwidth; + bool enforce_topology_constraints; + bool low_power; + bool enable_bluetooth_listening; + bool enable_webrtc_listening; + // Whether this is intended to be used in conjunction with InjectEndpoint(). + bool is_out_of_band_connection = false; + ByteArray remote_bluetooth_mac_address; + std::string fast_advertisement_service_uuid; + int keep_alive_interval_millis = 0; + int keep_alive_timeout_millis = 0; +}; + +// Starts advertising an endpoint for a local app. +// +// service_id - An identifier to advertise your app to other endpoints. +// This can be an arbitrary string, so long as it uniquely +// identifies your service. A good default is to use your +// app's package name. +// endpoint_info - A human readable name for this endpoint, to appear on +// other devices. +// initiated_cb, accepted_cb, rejected_cb, disconnected_cb, +// bandwidth_changed_cb - A callback notified when remote +// endpoints request a connection to this endpoint. +// result_cb - to access the status of the operation when available. +// Possible status codes include: +// Status::STATUS_OK if advertising started successfully. +// Status::STATUS_ALREADY_ADVERTISING if the app is already advertising. +// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently +// connected to remote endpoints; call StopAllEndpoints first. +DLL_API void __stdcall StartAdvertisingDart(Core* pCore, + const char* service_id, + StrategyDart strategy, + const char* endpoint_info, + int auto_upgrade_bandwidth, + int enforce_topology_constraints, + int enable_bluetooth, + int enable_ble, + int advertise_nearby_notifications_beacon, + int use_low_power_mode, + int discover_fast_advertisements, + int enable_wifi_lan, + int enable_nfc, + int enable_wifi_aware, + int enable_web_rtc, + Dart_Port initiated_cb, + Dart_Port accepted_cb, + Dart_Port rejected_cb, + Dart_Port disconnected_cb, + Dart_Port bandwidth_changed_cb, + Dart_Port result_cb); + +// Stops advertising a local endpoint. Should be called after calling +// StartAdvertising, as soon as the application no longer needs to advertise +// itself or goes inactive. Payloads can still be sent to connected +// endpoints after advertising ends. +// +// result_cb - to access the status of the operation when available. +// Possible status codes include: +// Status::STATUS_OK if none of the above errors occurred. +DLL_API void __stdcall StopAdvertisingDart(Core* pCore, + Dart_Port result_cb); + +// Starts discovery for remote endpoints with the specified service ID. +// +// service_id - The ID for the service to be discovered, as specified in +// the corresponding call to StartAdvertising. +// found_cb, lost_cb, distance_changed_cb - A callback notified when a remote +// endpoint is discovered. +// result_cb - to access the status of the operation when available. +// Possible status codes include: +// Status::STATUS_OK if discovery started successfully. +// Status::STATUS_ALREADY_DISCOVERING if the app is already +// discovering the specified service. +// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently +// connected to remote endpoints; call StopAllEndpoints first. +DLL_API void __stdcall StartDiscoveryDart(Core* pCore, + const char* service_id, + StrategyDart strategy, + int forward_unrecognized_bluetooth_devices, + int enable_bluetooth, + int enable_ble, + int use_low_power_mode, + int discover_fast_advertisements, + int enable_wifi_lan, + int enable_nfc, + int enable_wifi_aware, + Dart_Port found_cb, + Dart_Port lost_cb, + Dart_Port distance_changed_cb, + Dart_Port result_cb); + +// Stops discovery for remote endpoints, after a previous call to +// StartDiscovery, when the client no longer needs to discover endpoints or +// goes inactive. Payloads can still be sent to connected endpoints after +// discovery ends. +// +// result_cb - to access the status of the operation when available. +// Possible status codes include: +// Status::STATUS_OK if none of the above errors occurred. +DLL_API void __stdcall StopDiscoveryDart(Core* pCore, + Dart_Port result_cb); +} // namespace connections +} // namespace nearby +} // namespace location + +#endif // LOCATION_NEARBY_CONNECTIONS_WINDOWS_CORE_ADAPTER_DART_H_