diff --git a/connections/dart/BUILD b/connections/dart/BUILD index a986b182..ac3bdef5 100644 --- a/connections/dart/BUILD +++ b/connections/dart/BUILD @@ -42,10 +42,13 @@ lexan.cc_windows_dll( name = "nc_windows_dart", srcs = [ "nc_adapter_dart.cc", + "nearby_connections_client_state.cc", ], hdrs = [ "nc_adapter_dart.h", "nc_adapter_def.h", + "nc_adapter_types.h", + "nearby_connections_client_state.h", ], copts = ["-DNC_DART_DLL"], tags = ["windows-dll"], @@ -55,6 +58,9 @@ lexan.cc_windows_dll( "//internal/platform:types", "//internal/platform/implementation/windows", "//third_party/dart_lang/v2:dart_api_dl", + "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/synchronization", ], ) diff --git a/connections/dart/nc_adapter_dart.cc b/connections/dart/nc_adapter_dart.cc index 57e63af2..30f71bc1 100644 --- a/connections/dart/nc_adapter_dart.cc +++ b/connections/dart/nc_adapter_dart.cc @@ -19,27 +19,29 @@ #include #include #include +#include +#include #include #include #include +#include "absl/base/no_destructor.h" #include "absl/strings/string_view.h" #include "third_party/dart_lang/v2/runtime/include/dart_api.h" #include "third_party/dart_lang/v2/runtime/include/dart_api_dl.h" #include "third_party/dart_lang/v2/runtime/include/dart_native_api.h" #include "connections/c/nc.h" #include "connections/c/nc_types.h" +#include "connections/dart/nearby_connections_client_state.h" #include "internal/platform/byte_array.h" -#include "internal/platform/count_down_latch.h" #include "internal/platform/logging.h" #include "internal/platform/prng.h" -static nearby::CountDownLatch *adapter_finished; +using nearby::connections::dart::NearbyConnectionsClientState; +using NearbyConnectionsApi = nearby::connections::dart:: + NearbyConnectionsClientState::NearbyConnectionsApi; -static Dart_Port port; -static DiscoveryListenerDart current_discovery_listener_dart; -static ConnectionListenerDart current_connection_listener_dart; -static PayloadListenerDart current_payload_listener_dart; +static absl::NoDestructor kClientState; NC_STRATEGY_TYPE GetStrategy(StrategyDart strategy) { switch (strategy) { @@ -61,17 +63,20 @@ nearby::ByteArray ConvertBluetoothMacAddress(absl::string_view address) { NC_PAYLOAD_ID GeneratePayloadId() { return nearby::Prng().NextInt64(); } -void ResultCB(NC_STATUS status) { - NEARBY_LOG(INFO, "ResultCB is called."); +void ResultCB(std::optional port, NC_STATUS status) { (void)status; // Avoid unused parameter warning + if (!port.has_value()) { + NEARBY_LOGS(ERROR) << "ResultCB called with invalid port."; + return; + } + Dart_CObject dart_object_result_callback; dart_object_result_callback.type = Dart_CObject_kInt64; dart_object_result_callback.value.as_int64 = static_cast(status); - const bool result = Dart_PostCObject_DL(port, &dart_object_result_callback); + const bool result = Dart_PostCObject_DL(*port, &dart_object_result_callback); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } - adapter_finished->CountDown(); } void ListenerInitiatedCB( @@ -99,9 +104,9 @@ void ListenerInitiatedCB( dart_object_initiated.value.as_array.length = 2; dart_object_initiated.value.as_array.values = elements; - const bool result = - Dart_PostCObject_DL(current_connection_listener_dart.initiated_dart_port, - &dart_object_initiated); + const bool result = Dart_PostCObject_DL( + kClientState->GetConnectionListenerDart()->initiated_dart_port, + &dart_object_initiated); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -112,9 +117,9 @@ void ListenerAcceptedCB(const char *endpoint_id) { Dart_CObject dart_object_accepted; dart_object_accepted.type = Dart_CObject_kString; dart_object_accepted.value.as_string = const_cast(endpoint_id); - const bool result = - Dart_PostCObject_DL(current_connection_listener_dart.accepted_dart_port, - &dart_object_accepted); + const bool result = Dart_PostCObject_DL( + kClientState->GetConnectionListenerDart()->accepted_dart_port, + &dart_object_accepted); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -125,9 +130,9 @@ void ListenerRejectedCB(const char *endpoint_id, NC_STATUS status) { Dart_CObject dart_object_rejected; dart_object_rejected.type = Dart_CObject_kString; dart_object_rejected.value.as_string = const_cast(endpoint_id); - const bool result = - Dart_PostCObject_DL(current_connection_listener_dart.rejected_dart_port, - &dart_object_rejected); + const bool result = Dart_PostCObject_DL( + kClientState->GetConnectionListenerDart()->rejected_dart_port, + &dart_object_rejected); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -139,7 +144,7 @@ void ListenerDisconnectedCB(const char *endpoint_id) { dart_object_disconnected.type = Dart_CObject_kString; dart_object_disconnected.value.as_string = const_cast(endpoint_id); const bool result = Dart_PostCObject_DL( - current_connection_listener_dart.disconnected_dart_port, + kClientState->GetConnectionListenerDart()->disconnected_dart_port, &dart_object_disconnected); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); @@ -154,7 +159,7 @@ void ListenerBandwidthChangedCB(const char *endpoint_id, NC_MEDIUM medium) { dart_object_bandwidth_changed.value.as_string = const_cast(endpoint_id); const bool result = Dart_PostCObject_DL( - current_connection_listener_dart.bandwidth_changed_dart_port, + kClientState->GetConnectionListenerDart()->bandwidth_changed_dart_port, &dart_object_bandwidth_changed); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); @@ -186,7 +191,8 @@ void ListenerEndpointFoundCB(const char *endpoint_id, dart_object_found.value.as_array.length = 2; dart_object_found.value.as_array.values = elements; const bool result = Dart_PostCObject_DL( - current_discovery_listener_dart.found_dart_port, &dart_object_found); + kClientState->GetDiscoveryListenerDart()->found_dart_port, + &dart_object_found); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -198,7 +204,8 @@ void ListenerEndpointLostCB(const char *endpoint_id) { dart_object_lost.type = Dart_CObject_kString; dart_object_lost.value.as_string = const_cast(endpoint_id); const bool result = Dart_PostCObject_DL( - current_discovery_listener_dart.lost_dart_port, &dart_object_lost); + kClientState->GetDiscoveryListenerDart()->lost_dart_port, + &dart_object_lost); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -213,7 +220,7 @@ void ListenerEndpointDistanceChangedCB(const char *endpoint_id, dart_object_distance_changed.value.as_string = const_cast(endpoint_id); const bool result = Dart_PostCObject_DL( - current_discovery_listener_dart.distance_changed_dart_port, + kClientState->GetDiscoveryListenerDart()->distance_changed_dart_port, &dart_object_distance_changed); if (!result) { NEARBY_LOG(INFO, "Posting message to port failed."); @@ -263,7 +270,7 @@ void ListenerPayloadCB(const char *endpoint_id, const NC_PAYLOAD &payload) { dart_object_payload.value.as_array.length = 3; dart_object_payload.value.as_array.values = elements; if (!Dart_PostCObject_DL( - current_payload_listener_dart.initial_byte_info_port, + kClientState->GetPayloadListenerDart()->initial_byte_info_port, &dart_object_payload)) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -280,7 +287,7 @@ void ListenerPayloadCB(const char *endpoint_id, const NC_PAYLOAD &payload) { dart_object_payload.value.as_array.length = 2; dart_object_payload.value.as_array.values = elements; if (!Dart_PostCObject_DL( - current_payload_listener_dart.initial_stream_info_port, + kClientState->GetPayloadListenerDart()->initial_stream_info_port, &dart_object_payload)) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -308,7 +315,7 @@ void ListenerPayloadCB(const char *endpoint_id, const NC_PAYLOAD &payload) { dart_object_payload.value.as_array.length = 4; dart_object_payload.value.as_array.values = elements; if (!Dart_PostCObject_DL( - current_payload_listener_dart.initial_file_info_port, + kClientState->GetPayloadListenerDart()->initial_file_info_port, &dart_object_payload)) { NEARBY_LOG(INFO, "Posting message to port failed."); } @@ -363,14 +370,13 @@ void ListenerPayloadProgressCB( dart_object_payload_progress.value.as_array.values = elements; if (!Dart_PostCObject_DL( - current_payload_listener_dart.payload_progress_dart_port, + kClientState->GetPayloadListenerDart()->payload_progress_dart_port, &dart_object_payload_progress)) { NEARBY_LOG(INFO, "Posting message to port failed."); } } void PostResult(Dart_Port &result_cb, NC_STATUS value) { - port = result_cb; Dart_CObject dart_object_result_callback; dart_object_result_callback.type = Dart_CObject_kInt64; dart_object_result_callback.value.as_int64 = static_cast(value); @@ -381,9 +387,20 @@ void PostResult(Dart_Port &result_cb, NC_STATUS value) { } } -NC_INSTANCE OpenServiceDart() { return NcOpenService(); } +NC_INSTANCE OpenServiceDart() { + NC_INSTANCE instance = kClientState->GetOpennedService(); + if (instance == nullptr) { + instance = NcOpenService(); + kClientState->SetOpennedService(instance); + } -void CloseServiceDart(NC_INSTANCE instance) { NcCloseService(instance); } + return instance; +} + +void CloseServiceDart(NC_INSTANCE instance) { + NcCloseService(instance); + kClientState->reset(); +} char *GetLocalEndpointIdDart(NC_INSTANCE instance) { return NcGetLocalEndpointId(instance); @@ -391,11 +408,13 @@ char *GetLocalEndpointIdDart(NC_INSTANCE instance) { void EnableBleV2Dart(NC_INSTANCE instance, int64_t enable, Dart_Port result_cb) { - port = result_cb; - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcEnableBleV2(instance, enable, [](NC_STATUS status) { ResultCB(status); }); - finished.Await(); + kClientState->PushNearbyConnectionsApiPort(NearbyConnectionsApi::kEnableBleV2, + result_cb); + NcEnableBleV2(instance, enable, [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kEnableBleV2), + status); + }); NEARBY_LOGS(INFO) << "EnableBleV2Dart callback is called with enable=" << enable; } @@ -409,8 +428,10 @@ void StartAdvertisingDart(NC_INSTANCE instance, const char *service_id, return; } - port = result_cb; - current_connection_listener_dart = info_dart.connection_listener; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kStartAdvertising, result_cb); + kClientState->SetConnectionListenerDart( + std::make_unique(info_dart.connection_listener)); NC_ADVERTISING_OPTIONS advertising_options{}; advertising_options.common_options.strategy.type = @@ -447,15 +468,12 @@ void StartAdvertisingDart(NC_INSTANCE instance, const char *service_id, request_info.disconnected_callback = ListenerDisconnectedCB; request_info.bandwidth_changed_callback = ListenerBandwidthChangedCB; - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcStartAdvertising(instance, service_id, advertising_options, request_info, [](NC_STATUS status) { - ResultCB(status); + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kStartAdvertising), + status); }); - - finished.Await(); } void StopAdvertisingDart(NC_INSTANCE instance, Dart_Port result_cb) { @@ -464,14 +482,15 @@ void StopAdvertisingDart(NC_INSTANCE instance, Dart_Port result_cb) { return; } - port = result_cb; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kStopAdvertising, result_cb); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - - NcStopAdvertising(instance, [](NC_STATUS status) { ResultCB(status); }); - - finished.Await(); + NcStopAdvertising(instance, [](NC_STATUS status) { + kClientState->SetConnectionListenerDart(nullptr); + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kStopAdvertising), + status); + }); } void StartDiscoveryDart(NC_INSTANCE instance, const char *service_id, @@ -483,8 +502,10 @@ void StartDiscoveryDart(NC_INSTANCE instance, const char *service_id, return; } - port = result_cb; - current_discovery_listener_dart = listener_dart; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kStartAdvertising, result_cb); + kClientState->SetDiscoveryListenerDart( + std::make_unique(listener_dart)); NC_DISCOVERY_OPTIONS discovery_options{}; discovery_options.common_options.strategy.type = @@ -516,15 +537,12 @@ void StartDiscoveryDart(NC_INSTANCE instance, const char *service_id, listener.endpoint_found_callback = ListenerEndpointFoundCB; listener.endpoint_lost_callback = ListenerEndpointLostCB; - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcStartDiscovery(instance, service_id, discovery_options, listener, [](NC_STATUS status) { - ResultCB(status); + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kStartDiscovery), + status); }); - - finished.Await(); } void StopDiscoveryDart(NC_INSTANCE instance, Dart_Port result_cb) { @@ -533,13 +551,15 @@ void StopDiscoveryDart(NC_INSTANCE instance, Dart_Port result_cb) { return; } - port = result_cb; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kStopDiscovery, result_cb); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - - NcStopDiscovery(instance, [](NC_STATUS status) { ResultCB(status); }); - adapter_finished->Await(); + NcStopDiscovery(instance, [](NC_STATUS status) { + kClientState->SetDiscoveryListenerDart(nullptr); + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kStopDiscovery), + status); + }); } void RequestConnectionDart(NC_INSTANCE instance, const char *endpoint_id, @@ -551,8 +571,10 @@ void RequestConnectionDart(NC_INSTANCE instance, const char *endpoint_id, return; } - port = result_cb; - current_connection_listener_dart = info_dart.connection_listener; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kRequestConnection, result_cb); + kClientState->SetConnectionListenerDart( + std::make_unique(info_dart.connection_listener)); NC_CONNECTION_OPTIONS connection_options; connection_options.enforce_topology_constraints = @@ -591,13 +613,12 @@ void RequestConnectionDart(NC_INSTANCE instance, const char *endpoint_id, request_info.disconnected_callback = ListenerDisconnectedCB; request_info.bandwidth_changed_callback = ListenerBandwidthChangedCB; - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcRequestConnection(instance, endpoint_id, request_info, connection_options, - [](NC_STATUS status) { ResultCB(status); }); - - adapter_finished->Await(); + [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kRequestConnection), + status); + }); } void AcceptConnectionDart(NC_INSTANCE instance, const char *endpoint_id, @@ -608,20 +629,20 @@ void AcceptConnectionDart(NC_INSTANCE instance, const char *endpoint_id, return; } - port = result_cb; - current_payload_listener_dart = listener_dart; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kAcceptConnection, result_cb); + kClientState->SetPayloadListenerDart( + std::make_unique(listener_dart)); NC_PAYLOAD_LISTENER listener{}; listener.received_callback = ListenerPayloadCB; listener.progress_updated_callback = ListenerPayloadProgressCB; - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - - NcAcceptConnection(instance, endpoint_id, listener, - [](NC_STATUS status) { ResultCB(status); }); - - finished.Await(); + NcAcceptConnection(instance, endpoint_id, listener, [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kAcceptConnection), + status); + }); } void RejectConnectionDart(NC_INSTANCE instance, const char *endpoint_id, @@ -631,15 +652,14 @@ void RejectConnectionDart(NC_INSTANCE instance, const char *endpoint_id, return; } - port = result_cb; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kRejectConnection, result_cb); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - - NcRejectConnection(instance, endpoint_id, - [](NC_STATUS status) { ResultCB(status); }); - - finished.Await(); + NcRejectConnection(instance, endpoint_id, [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kRejectConnection), + status); + }); } void DisconnectFromEndpointDart(NC_INSTANCE instance, char *endpoint_id, @@ -649,15 +669,14 @@ void DisconnectFromEndpointDart(NC_INSTANCE instance, char *endpoint_id, return; } - port = result_cb; + kClientState->PushNearbyConnectionsApiPort( + NearbyConnectionsApi::kDisconnectFromEndpoint, result_cb); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - - NcDisconnectFromEndpoint(instance, endpoint_id, - [](NC_STATUS status) { ResultCB(status); }); - - finished.Await(); + NcDisconnectFromEndpoint(instance, endpoint_id, [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kDisconnectFromEndpoint), + status); + }); } void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, @@ -667,8 +686,8 @@ void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, return; } - port = result_cb; - + kClientState->PushNearbyConnectionsApiPort(NearbyConnectionsApi::kSendPayload, + result_cb); std::vector endpoint_ids = {std::string(endpoint_id)}; NEARBY_LOG(INFO, "Payload type: %d", payload_dart.type); @@ -676,7 +695,7 @@ void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, case PAYLOAD_TYPE_UNKNOWN: case PAYLOAD_TYPE_STREAM: NEARBY_LOG(INFO, "Payload type not supported yet"); - PostResult(port, NC_STATUS_PAYLOADUNKNOWN); + PostResult(result_cb, NC_STATUS_PAYLOADUNKNOWN); break; case PAYLOAD_TYPE_BYTE: { NC_PAYLOAD payload{}; @@ -696,14 +715,12 @@ void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, return pc; }); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcSendPayload(instance, c_string_array.size(), c_string_array.data(), - std::move(payload), - [](NC_STATUS status) { ResultCB(status); }); - - adapter_finished->Await(); + std::move(payload), [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kSendPayload), + status); + }); break; } case PAYLOAD_TYPE_FILE: @@ -729,14 +746,12 @@ void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, return pc; }); - nearby::CountDownLatch finished(1); - adapter_finished = &finished; - NcSendPayload(instance, c_string_array.size(), c_string_array.data(), - std::move(payload), - [](NC_STATUS status) { ResultCB(status); }); - - adapter_finished->Await(); + std::move(payload), [](NC_STATUS status) { + ResultCB(kClientState->PopNearbyConnectionsApiPort( + NearbyConnectionsApi::kSendPayload), + status); + }); break; } diff --git a/connections/dart/nc_adapter_dart.h b/connections/dart/nc_adapter_dart.h index b7318abb..d21f4eb4 100644 --- a/connections/dart/nc_adapter_dart.h +++ b/connections/dart/nc_adapter_dart.h @@ -20,138 +20,12 @@ #include "connections/c/nc.h" #include "connections/c/nc_types.h" #include "connections/dart/nc_adapter_def.h" +#include "connections/dart/nc_adapter_types.h" #ifdef __cplusplus extern "C" { #endif -enum StrategyDart { - // LINT.IfChange - STRATEGY_UNKNOWN = -1, - STRATEGY_P2P_CLUSTER = 0, - STRATEGY_P2P_STAR, - STRATEGY_P2P_POINT_TO_POINT, - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/strategy.dart) -}; - -enum PayloadTypeDart { - // LINT.IfChange - PAYLOAD_TYPE_UNKNOWN = 0, - PAYLOAD_TYPE_BYTE, - PAYLOAD_TYPE_STREAM, - PAYLOAD_TYPE_FILE, - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload.dart) -}; - -struct MediumsDart { - // LINT.IfChange - int64_t bluetooth; - int64_t ble; - int64_t wifi_lan; - int64_t wifi_hotspot; - int64_t web_rtc; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/mediums.dart) -}; - -struct AdvertisingOptionsDart { - // LINT.IfChange - StrategyDart strategy; - int64_t auto_upgrade_bandwidth; - int64_t enforce_topology_constraints; - int64_t low_power; - - // Whether this is intended to be used in conjunction with InjectEndpoint(). - int64_t is_out_of_band_connection = false; - const char *fast_advertisement_service_uuid; - - // The information about this device (eg. name, device type), - // to appear on the remote device. - // Defined by client/application. - const char *device_info; - - MediumsDart mediums; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/advertising_options.dart) -}; - -struct ConnectionOptionsDart { - // LINT.IfChange - StrategyDart strategy; - - // Whether this is intended to be used in conjunction with InjectEndpoint(). - int64_t auto_upgrade_bandwidth; - int64_t enforce_topology_constraints; - int64_t low_power; - - // Whether this is intended to be used in conjunction with InjectEndpoint(). - int64_t is_out_of_band_connection = false; - char *remote_bluetooth_mac_address; - char *fast_advertisement_service_uuid; - int64_t keep_alive_interval_millis; - int64_t keep_alive_timeout_millis; - - MediumsDart mediums; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_options.dart) -}; - -struct DiscoveryOptionsDart { - // LINT.IfChange - StrategyDart strategy; - int64_t auto_upgrade_bandwidth; - int64_t enforce_topology_constraints; - - // Whether this is intended to be used in conjunction with InjectEndpoint(). - int64_t is_out_of_band_connection = false; - const char *fast_advertisement_service_uuid; - const char *remote_bluetooth_mac_address; - - MediumsDart mediums; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/discovery_options.dart) -}; - -struct DiscoveryListenerDart { - // LINT.IfChange - int64_t found_dart_port; - int64_t lost_dart_port; - int64_t distance_changed_dart_port; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/discovery_listener.dart) -}; - -struct PayloadListenerDart { - // LINT.IfChange - int64_t initial_byte_info_port; - int64_t initial_stream_info_port; - int64_t initial_file_info_port; - int64_t payload_progress_dart_port; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload_listener.dart) -}; - -struct ConnectionListenerDart { - // LINT.IfChange - int64_t initiated_dart_port; - int64_t accepted_dart_port; - int64_t rejected_dart_port; - int64_t disconnected_dart_port; - int64_t bandwidth_changed_dart_port; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_listener.dart) -}; - -struct ConnectionRequestInfoDart { - // LINT.IfChange - int endpoint_info_size; - char *endpoint_info; - ConnectionListenerDart connection_listener; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_request_info.dart) -}; - -struct PayloadDart { - // LINT.IfChange - int64_t id; - PayloadTypeDart type; - int64_t size; - char *data; - // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload.dart) -}; - static void ResultCB(NC_STATUS status); static void ListenerInitiatedCB( @@ -177,10 +51,10 @@ static void ListenerPayloadProgressCB( DART_API NC_INSTANCE OpenServiceDart(); DART_API void CloseServiceDart(NC_INSTANCE instance); -DART_API char* GetLocalEndpointIdDart(NC_INSTANCE instance); +DART_API char *GetLocalEndpointIdDart(NC_INSTANCE instance); DART_API void EnableBleV2Dart(NC_INSTANCE instance, int64_t enable, - Dart_Port result_cb); + Dart_Port result_cb); // Starts advertising an endpoint for a local app. // @@ -197,10 +71,10 @@ DART_API void EnableBleV2Dart(NC_INSTANCE instance, int64_t enable, // 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. -DART_API void StartAdvertisingDart( - NC_INSTANCE instance, const char *service_id, - AdvertisingOptionsDart options_dart, ConnectionRequestInfoDart info_dart, - Dart_Port result_cb); +DART_API void StartAdvertisingDart(NC_INSTANCE instance, const char *service_id, + AdvertisingOptionsDart options_dart, + ConnectionRequestInfoDart info_dart, + 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 @@ -210,8 +84,7 @@ DART_API void StartAdvertisingDart( // 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. -DART_API void StopAdvertisingDart(NC_INSTANCE instance, - Dart_Port result_cb); +DART_API void StopAdvertisingDart(NC_INSTANCE instance, Dart_Port result_cb); // Starts discovery for remote endpoints with the specified service ID. // @@ -226,11 +99,10 @@ DART_API void StopAdvertisingDart(NC_INSTANCE instance, // discovering the specified service. // Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently // connected to remote endpoints; call StopAllEndpoints first. -DART_API void StartDiscoveryDart(NC_INSTANCE instance, - const char *service_id, - DiscoveryOptionsDart options_dart, - DiscoveryListenerDart listener_dart, - Dart_Port result_cb); +DART_API void StartDiscoveryDart(NC_INSTANCE instance, const char *service_id, + DiscoveryOptionsDart options_dart, + DiscoveryListenerDart listener_dart, + 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 @@ -240,8 +112,7 @@ DART_API void StartDiscoveryDart(NC_INSTANCE instance, // 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. -DART_API void StopDiscoveryDart(NC_INSTANCE instance, - Dart_Port result_cb); +DART_API void StopDiscoveryDart(NC_INSTANCE instance, Dart_Port result_cb); // Sends a request to connect to a remote endpoint. // @@ -263,10 +134,11 @@ DART_API void StopDiscoveryDart(NC_INSTANCE instance, // Status::STATUS_RADIO_ERROR if we failed to connect because of an // issue with Bluetooth/WiFi. // Status::STATUS_ERROR if we failed to connect for any other reason. -DART_API void RequestConnectionDart( - NC_INSTANCE instance, const char *endpoint_id, - ConnectionOptionsDart options_dart, ConnectionRequestInfoDart info_dart, - Dart_Port result_cb); +DART_API void RequestConnectionDart(NC_INSTANCE instance, + const char *endpoint_id, + ConnectionOptionsDart options_dart, + ConnectionRequestInfoDart info_dart, + Dart_Port result_cb); // Accepts a connection to a remote endpoint. This method must be called // before Payloads can be exchanged with the remote endpoint. @@ -281,13 +153,13 @@ DART_API void RequestConnectionDart( // Status::STATUS_ALREADY_CONNECTED_TO_ENDPOINT if the app already. // has a connection to the specified endpoint. DART_API void AcceptConnectionDart(NC_INSTANCE instance, - const char *endpoint_id, - PayloadListenerDart listener_dart, - Dart_Port result_cb); + const char *endpoint_id, + PayloadListenerDart listener_dart, + Dart_Port result_cb); DART_API void RejectConnectionDart(NC_INSTANCE instance, - const char *endpoint_id, - Dart_Port result_cb); + const char *endpoint_id, + Dart_Port result_cb); // Disconnects from a remote endpoint. {@link Payload}s can no longer be sent // to or received from the endpoint after this method is called. @@ -296,8 +168,8 @@ DART_API void RejectConnectionDart(NC_INSTANCE instance, // Possible status codes include: // Status::STATUS_OK - finished successfully. DART_API void DisconnectFromEndpointDart(NC_INSTANCE instance, - char *endpoint_id, - Dart_Port result_cb); + char *endpoint_id, + Dart_Port result_cb); // Sends a Payload to a remote endpoint. Payloads can only be sent to remote // endpoints once a notice of connection acceptance has been delivered via @@ -318,10 +190,8 @@ DART_API void DisconnectFromEndpointDart(NC_INSTANCE instance, // still occur during transmission (and at different times for // different endpoints), and will be delivered via // PayloadCallback#onPayloadTransferUpdate. -DART_API void SendPayloadDart(NC_INSTANCE instance, - const char *endpoint_id, - PayloadDart payload_dart, - Dart_Port result_cb); +DART_API void SendPayloadDart(NC_INSTANCE instance, const char *endpoint_id, + PayloadDart payload_dart, Dart_Port result_cb); #ifdef __cplusplus } // extern "C" diff --git a/connections/dart/nc_adapter_types.h b/connections/dart/nc_adapter_types.h new file mode 100644 index 00000000..bd4795b4 --- /dev/null +++ b/connections/dart/nc_adapter_types.h @@ -0,0 +1,153 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_NEARBY_CONNECTIONS_DART_NC_ADAPTER_TYPES_H_ +#define THIRD_PARTY_NEARBY_CONNECTIONS_DART_NC_ADAPTER_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum StrategyDart { + // LINT.IfChange + STRATEGY_UNKNOWN = -1, + STRATEGY_P2P_CLUSTER = 0, + STRATEGY_P2P_STAR, + STRATEGY_P2P_POINT_TO_POINT, + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/strategy.dart) +}; + +enum PayloadTypeDart { + // LINT.IfChange + PAYLOAD_TYPE_UNKNOWN = 0, + PAYLOAD_TYPE_BYTE, + PAYLOAD_TYPE_STREAM, + PAYLOAD_TYPE_FILE, + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload.dart) +}; + +struct MediumsDart { + // LINT.IfChange + int64_t bluetooth; + int64_t ble; + int64_t wifi_lan; + int64_t wifi_hotspot; + int64_t web_rtc; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/mediums.dart) +}; + +struct AdvertisingOptionsDart { + // LINT.IfChange + StrategyDart strategy; + int64_t auto_upgrade_bandwidth; + int64_t enforce_topology_constraints; + int64_t low_power; + + // Whether this is intended to be used in conjunction with InjectEndpoint(). + int64_t is_out_of_band_connection = false; + const char *fast_advertisement_service_uuid; + + // The information about this device (eg. name, device type), + // to appear on the remote device. + // Defined by client/application. + const char *device_info; + + MediumsDart mediums; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/advertising_options.dart) +}; + +struct ConnectionOptionsDart { + // LINT.IfChange + StrategyDart strategy; + + // Whether this is intended to be used in conjunction with InjectEndpoint(). + int64_t auto_upgrade_bandwidth; + int64_t enforce_topology_constraints; + int64_t low_power; + + // Whether this is intended to be used in conjunction with InjectEndpoint(). + int64_t is_out_of_band_connection = false; + char *remote_bluetooth_mac_address; + char *fast_advertisement_service_uuid; + int64_t keep_alive_interval_millis; + int64_t keep_alive_timeout_millis; + + MediumsDart mediums; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_options.dart) +}; + +struct DiscoveryOptionsDart { + // LINT.IfChange + StrategyDart strategy; + int64_t auto_upgrade_bandwidth; + int64_t enforce_topology_constraints; + + // Whether this is intended to be used in conjunction with InjectEndpoint(). + int64_t is_out_of_band_connection = false; + const char *fast_advertisement_service_uuid; + const char *remote_bluetooth_mac_address; + + MediumsDart mediums; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/discovery_options.dart) +}; + +struct DiscoveryListenerDart { + // LINT.IfChange + int64_t found_dart_port; + int64_t lost_dart_port; + int64_t distance_changed_dart_port; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/discovery_listener.dart) +}; + +struct PayloadListenerDart { + // LINT.IfChange + int64_t initial_byte_info_port; + int64_t initial_stream_info_port; + int64_t initial_file_info_port; + int64_t payload_progress_dart_port; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload_listener.dart) +}; + +struct ConnectionListenerDart { + // LINT.IfChange + int64_t initiated_dart_port; + int64_t accepted_dart_port; + int64_t rejected_dart_port; + int64_t disconnected_dart_port; + int64_t bandwidth_changed_dart_port; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_listener.dart) +}; + +struct ConnectionRequestInfoDart { + // LINT.IfChange + int endpoint_info_size; + char *endpoint_info; + ConnectionListenerDart connection_listener; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/connection_request_info.dart) +}; + +struct PayloadDart { + // LINT.IfChange + int64_t id; + PayloadTypeDart type; + int64_t size; + char *data; + // LINT.ThenChange(//depot/google3/location/nearby/apps/helloconnections/plugins/nearby_connections/platform/lib/types/payload.dart) +}; + +#ifdef __cplusplus +} +#endif + +#endif // THIRD_PARTY_NEARBY_CONNECTIONS_DART_NC_ADAPTER_TYPES_H_ diff --git a/connections/dart/nearby_connections_client_state.cc b/connections/dart/nearby_connections_client_state.cc new file mode 100644 index 00000000..2aef752b --- /dev/null +++ b/connections/dart/nearby_connections_client_state.cc @@ -0,0 +1,104 @@ +// 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/dart/nearby_connections_client_state.h" + +#include +#include +#include +#include + +#include "absl/synchronization/mutex.h" +#include "third_party/dart_lang/v2/runtime/include/dart_api.h" +#include "connections/c/nc_types.h" +#include "connections/dart/nc_adapter_types.h" + +namespace nearby::connections::dart { + +NC_INSTANCE NearbyConnectionsClientState::GetOpennedService() const { + absl::MutexLock lock(&mutex_); + return opened_instance_; +} + +void NearbyConnectionsClientState::SetOpennedService(NC_INSTANCE nc_instance) { + absl::MutexLock lock(&mutex_); + opened_instance_ = nc_instance; +} + +DiscoveryListenerDart* +NearbyConnectionsClientState::GetDiscoveryListenerDart() { + absl::MutexLock lock(&mutex_); + return discovery_listener_dart_.get(); +} + +void NearbyConnectionsClientState::SetDiscoveryListenerDart( + std::unique_ptr discovery_listener_dart) { + absl::MutexLock lock(&mutex_); + discovery_listener_dart_ = std::move(discovery_listener_dart); +} + +ConnectionListenerDart* +NearbyConnectionsClientState::GetConnectionListenerDart() { + absl::MutexLock lock(&mutex_); + return connection_listener_dart_.get(); +} + +void NearbyConnectionsClientState::SetConnectionListenerDart( + std::unique_ptr connection_listener_dart) { + absl::MutexLock lock(&mutex_); + connection_listener_dart_ = std::move(connection_listener_dart); +} + +PayloadListenerDart* NearbyConnectionsClientState::GetPayloadListenerDart() { + absl::MutexLock lock(&mutex_); + return payload_listener_dart_.get(); +} + +void NearbyConnectionsClientState::SetPayloadListenerDart( + std::unique_ptr payload_listener_dart) { + absl::MutexLock lock(&mutex_); + payload_listener_dart_ = std::move(payload_listener_dart); +} + +std::optional +NearbyConnectionsClientState::PopNearbyConnectionsApiPort( + NearbyConnectionsApi api) { + absl::MutexLock lock(&mutex_); + std::deque& port_list = nearby_connections_api_ports_[api]; + if (port_list.empty()) { + return std::nullopt; + } + + Dart_Port port = port_list.front(); + port_list.pop_front(); + return port; +} + +void NearbyConnectionsClientState::PushNearbyConnectionsApiPort( + NearbyConnectionsApi api, Dart_Port dart_port) { + absl::MutexLock lock(&mutex_); + std::deque& port_list = nearby_connections_api_ports_[api]; + port_list.push_back(dart_port); +} + +void NearbyConnectionsClientState::reset() { + absl::MutexLock lock(&mutex_); + opened_instance_ = nullptr; + nearby_connections_api_ports_.clear(); + discovery_listener_dart_.reset(); + connection_listener_dart_.reset(); + payload_listener_dart_.reset(); +} + +} // namespace nearby::connections::dart diff --git a/connections/dart/nearby_connections_client_state.h b/connections/dart/nearby_connections_client_state.h new file mode 100644 index 00000000..5d846853 --- /dev/null +++ b/connections/dart/nearby_connections_client_state.h @@ -0,0 +1,95 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_NEARBY_CONNECTIONS_DART_NEARBY_CONNECTIONS_CLIENT_STATE_H_ +#define THIRD_PARTY_NEARBY_CONNECTIONS_DART_NEARBY_CONNECTIONS_CLIENT_STATE_H_ + +#include +#include +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/synchronization/mutex.h" +#include "third_party/dart_lang/v2/runtime/include/dart_api.h" +#include "connections/c/nc.h" +#include "connections/dart/nc_adapter_types.h" + +namespace nearby::connections::dart { + +// This class maintains the client state of Nearby Connections. An applicaiton +// should only maintain one client. +class NearbyConnectionsClientState { + public: + enum class NearbyConnectionsApi { + kStartAdvertising, + kStopAdvertising, + kStartDiscovery, + kStopDiscovery, + kRequestConnection, + kAcceptConnection, + kRejectConnection, + kDisconnectFromEndpoint, + kSendPayload, + kEnableBleV2 + }; + + NearbyConnectionsClientState() = default; + NearbyConnectionsClientState(const NearbyConnectionsClientState&) = delete; + NearbyConnectionsClientState& operator=(const NearbyConnectionsClientState&) = + delete; + + NC_INSTANCE GetOpennedService() const ABSL_LOCKS_EXCLUDED(mutex_); + void SetOpennedService(NC_INSTANCE nc_instance) ABSL_LOCKS_EXCLUDED(mutex_); + + DiscoveryListenerDart* GetDiscoveryListenerDart() ABSL_LOCKS_EXCLUDED(mutex_); + void SetDiscoveryListenerDart( + std::unique_ptr discovery_listener_dart) + ABSL_LOCKS_EXCLUDED(mutex_); + + ConnectionListenerDart* GetConnectionListenerDart() + ABSL_LOCKS_EXCLUDED(mutex_); + void SetConnectionListenerDart( + std::unique_ptr connection_listener_dart) + ABSL_LOCKS_EXCLUDED(mutex_); + + PayloadListenerDart* GetPayloadListenerDart() ABSL_LOCKS_EXCLUDED(mutex_); + void SetPayloadListenerDart( + std::unique_ptr payload_listener_dart) + ABSL_LOCKS_EXCLUDED(mutex_); + + std::optional PopNearbyConnectionsApiPort(NearbyConnectionsApi api) + ABSL_LOCKS_EXCLUDED(mutex_); + void PushNearbyConnectionsApiPort(NearbyConnectionsApi api, + Dart_Port dart_port) + ABSL_LOCKS_EXCLUDED(mutex_); + + void reset() ABSL_LOCKS_EXCLUDED(mutex_); + + private: + mutable absl::Mutex mutex_; + + NC_INSTANCE opened_instance_ ABSL_GUARDED_BY(mutex_) = nullptr; + absl::flat_hash_map> + nearby_connections_api_ports_ ABSL_GUARDED_BY(mutex_); + std::unique_ptr discovery_listener_dart_ + ABSL_GUARDED_BY(mutex_); + std::unique_ptr connection_listener_dart_ + ABSL_GUARDED_BY(mutex_); + std::unique_ptr payload_listener_dart_ + ABSL_GUARDED_BY(mutex_); +}; + +} // namespace nearby::connections::dart + +#endif // THIRD_PARTY_NEARBY_CONNECTIONS_DART_NEARBY_CONNECTIONS_CLIENT_STATE_H_