Implemented a C wrapper for Nearby Connections.

PiperOrigin-RevId: 601133946
This commit is contained in:
Guogang Li
2024-01-24 08:50:30 -08:00
committed by Copybara-Service
parent 10c4f5ede4
commit 6f58a4d111
5 changed files with 1107 additions and 0 deletions
+43
View File
@@ -111,6 +111,49 @@ lexan.cc_windows_dll(
],
)
cc_library(
name = "nc_types",
hdrs = [
"nc.h",
"nc_def.h",
"nc_types.h",
],
compatible_with = ["//buildenv/target:non_prod"],
)
cc_library(
name = "nc",
srcs = [
"nc.cc",
],
compatible_with = ["//buildenv/target:non_prod"],
copts = ["-DNC_DLL"],
deps = [
":nc_types",
"//connections:core",
"//connections:core_types",
"//internal/platform:base",
"//internal/platform:types",
"//proto:connections_enums_cc_proto",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:span",
],
)
lexan.cc_windows_dll(
name = "nc_windows",
srcs = [],
compatible_with = ["//buildenv/target:non_prod"],
copts = ["-DNC_DLL"],
tags = ["windows-dll"],
deps = [
":nc",
"//internal/platform/implementation/windows",
"@com_google_absl//absl/strings",
],
)
cc_test(
name = "connections_test",
size = "small",
+572
View File
@@ -0,0 +1,572 @@
// 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/c/nc.h"
#include <stddef.h>
#include <sys/stat.h>
#include <cstdint>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "connections/advertising_options.h"
#include "connections/c/nc_types.h"
#include "connections/connection_options.h"
#include "connections/core.h"
#include "connections/discovery_options.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/params.h"
#include "connections/payload.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/platform/bluetooth_utils.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/file.h"
#include "internal/platform/logging.h"
namespace nearby::connections {
class Core;
class ServiceController;
class ServiceControllerRouter;
class OfflineServiceController;
} // namespace nearby::connections
typedef struct NcContext {
nearby::connections::ServiceControllerRouter* router = nullptr;
nearby::connections::Core* core = nullptr;
} NcContext;
static NcContext kNcContext;
int64_t getFileSize(const char* filename) {
struct stat file_status;
if (stat(filename, &file_status) < 0) {
return -1;
}
return file_status.st_size;
}
nearby::connections::ConnectionRequestInfo GetCppConnectionRequestInfo(
const NC_CONNECTION_REQUEST_INFO& connection_request_info) {
nearby::connections::ConnectionRequestInfo cpp_connection_request_info;
cpp_connection_request_info.endpoint_info =
nearby::ByteArray(connection_request_info.endpoint_info.data,
connection_request_info.endpoint_info.size);
nearby::connections::ConnectionListener cpp_connection_listener;
cpp_connection_listener.accepted_cb = [=](const std::string& endpoint_id) {
connection_request_info.accepted_callback(endpoint_id.c_str());
};
cpp_connection_listener.bandwidth_changed_cb =
[=](const std::string& endpoint_id, nearby::connections::Medium medium) {
connection_request_info.bandwidth_changed_callback(
endpoint_id.c_str(), static_cast<NC_MEDIUM>(medium));
};
cpp_connection_listener.disconnected_cb =
[=](const std::string& endpoint_id) {
connection_request_info.disconnected_callback(endpoint_id.c_str());
};
cpp_connection_listener.initiated_cb =
[=](const std::string& endpoint_id,
const nearby::connections::ConnectionResponseInfo& info) {
NC_CONNECTION_RESPONSE_INFO connection_response_info;
connection_response_info.is_connection_verified =
info.is_connection_verified;
connection_response_info.is_incoming_connection =
info.is_incoming_connection;
connection_response_info.remote_endpoint_info.data =
(char*)info.remote_endpoint_info.data();
connection_response_info.remote_endpoint_info.size =
info.remote_endpoint_info.size();
connection_response_info.authentication_token.data =
(char*)info.authentication_token.data();
connection_response_info.authentication_token.size =
info.authentication_token.size();
connection_response_info.raw_authentication_token.data =
(char*)info.raw_authentication_token.data();
connection_response_info.raw_authentication_token.size =
info.raw_authentication_token.size();
connection_request_info.initiated_callback(endpoint_id.c_str(),
connection_response_info);
};
cpp_connection_listener.rejected_cb =
[=](const std::string& endpoint_id, nearby::connections::Status status) {
connection_request_info.rejected_callback(
endpoint_id.c_str(), static_cast<NC_STATUS>(status.value));
};
cpp_connection_request_info.listener = std::move(cpp_connection_listener);
return cpp_connection_request_info;
}
NC_INSTANCE NcOpenService() {
if (kNcContext.core == nullptr) {
kNcContext.router = new nearby::connections::ServiceControllerRouter();
kNcContext.core = new nearby::connections::Core(kNcContext.router);
}
return kNcContext.core;
}
void NcCloseService(NC_INSTANCE instance) {
if (kNcContext.core == nullptr) {
return;
}
kNcContext.core->StopAllEndpoints([](nearby::connections::Status status) {
NEARBY_LOGS(INFO) << "Stopping all endpoints with status "
<< status.ToString();
});
delete kNcContext.router;
delete kNcContext.core;
kNcContext.router = nullptr;
kNcContext.core = nullptr;
}
void NcStartAdvertising(
NC_INSTANCE instance, const char* service_id,
const NC_ADVERTISING_OPTIONS& advertising_options,
const NC_CONNECTION_REQUEST_INFO& connection_request_info,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
nearby::connections::ConnectionRequestInfo cpp_connection_request_info =
GetCppConnectionRequestInfo(connection_request_info);
nearby::connections::AdvertisingOptions cpp_advertising_options;
cpp_advertising_options.allowed.ble =
advertising_options.common_options.allowed_mediums[NC_MEDIUM_BLE];
cpp_advertising_options.allowed.bluetooth =
advertising_options.common_options.allowed_mediums[NC_MEDIUM_BLUETOOTH];
cpp_advertising_options.allowed.wifi_lan =
advertising_options.common_options.allowed_mediums[NC_MEDIUM_WIFI_LAN];
cpp_advertising_options.allowed.wifi_direct =
advertising_options.common_options.allowed_mediums[NC_MEDIUM_WIFI_DIRECT];
cpp_advertising_options.allowed.wifi_hotspot =
advertising_options.common_options
.allowed_mediums[NC_MEDIUM_WIFI_HOTSPOT];
cpp_advertising_options.allowed.web_rtc =
advertising_options.common_options.allowed_mediums[NC_MEDIUM_WEB_RTC];
cpp_advertising_options.enable_bluetooth_listening =
advertising_options.enable_bluetooth_listening;
cpp_advertising_options.enable_webrtc_listening =
advertising_options.enable_webrtc_listening;
cpp_advertising_options.auto_upgrade_bandwidth =
advertising_options.auto_upgrade_bandwidth;
cpp_advertising_options.enforce_topology_constraints =
advertising_options.enforce_topology_constraints;
if (advertising_options.fast_advertisement_service_uuid.size > 0) {
cpp_advertising_options.fast_advertisement_service_uuid =
std::string(advertising_options.fast_advertisement_service_uuid.data,
advertising_options.fast_advertisement_service_uuid.size);
}
cpp_advertising_options.is_out_of_band_connection =
advertising_options.is_out_of_band_connection;
cpp_advertising_options.low_power = advertising_options.low_power;
if (advertising_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_NONE) {
cpp_advertising_options.strategy = nearby::connections::Strategy::kNone;
}
if (advertising_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_CLUSTER)
cpp_advertising_options.strategy =
nearby::connections::Strategy::kP2pCluster;
if (advertising_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_POINT_TO_POINT)
cpp_advertising_options.strategy =
nearby::connections::Strategy::kP2pPointToPoint;
if (advertising_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_STAR)
cpp_advertising_options.strategy = nearby::connections::Strategy::kP2pStar;
kNcContext.core->StartAdvertising(
service_id, std::move(cpp_advertising_options),
std::move(cpp_connection_request_info),
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcStopAdvertising(NC_INSTANCE instance, NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->StopAdvertising([=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcStartDiscovery(NC_INSTANCE instance, const char* service_id,
const NC_DISCOVERY_OPTIONS& discovery_options,
const NC_DISCOVERY_LISTENER& discovery_listener,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
nearby::connections::DiscoveryOptions cpp_discovery_options;
if (discovery_options.common_options.strategy.type == NC_STRATEGY_TYPE_NONE)
cpp_discovery_options.strategy = nearby::connections::Strategy::kNone;
if (discovery_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_CLUSTER)
cpp_discovery_options.strategy = nearby::connections::Strategy::kP2pCluster;
if (discovery_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_POINT_TO_POINT)
cpp_discovery_options.strategy =
nearby::connections::Strategy::kP2pPointToPoint;
if (discovery_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_STAR)
cpp_discovery_options.strategy = nearby::connections::Strategy::kP2pStar;
cpp_discovery_options.auto_upgrade_bandwidth =
discovery_options.auto_upgrade_bandwidth;
cpp_discovery_options.enforce_topology_constraints =
discovery_options.enforce_topology_constraints;
cpp_discovery_options.is_out_of_band_connection =
discovery_options.is_out_of_band_connection;
if (discovery_options.fast_advertisement_service_uuid.size > 0) {
cpp_discovery_options.fast_advertisement_service_uuid =
std::string(discovery_options.fast_advertisement_service_uuid.data,
discovery_options.fast_advertisement_service_uuid.size);
}
cpp_discovery_options.allowed.bluetooth =
discovery_options.common_options.allowed_mediums[NC_MEDIUM_BLUETOOTH];
cpp_discovery_options.allowed.ble =
discovery_options.common_options.allowed_mediums[NC_MEDIUM_BLE];
cpp_discovery_options.allowed.wifi_lan =
discovery_options.common_options.allowed_mediums[NC_MEDIUM_WIFI_LAN];
cpp_discovery_options.allowed.wifi_hotspot =
discovery_options.common_options.allowed_mediums[NC_MEDIUM_WIFI_HOTSPOT];
cpp_discovery_options.allowed.web_rtc =
discovery_options.common_options.allowed_mediums[NC_MEDIUM_WEB_RTC];
nearby::connections::DiscoveryListener listener;
listener.endpoint_distance_changed_cb =
[=](const std::string& endpoint_id,
nearby::connections::DistanceInfo info) {
discovery_listener.endpoint_distance_changed_callback(
endpoint_id.c_str(), static_cast<NC_DISTANCE_INFO>(info));
};
listener.endpoint_found_cb = [=](const std::string& endpoint_id,
const nearby::ByteArray& endpoint_info,
const std::string& service_id) {
discovery_listener.endpoint_found_callback(
endpoint_id.c_str(),
NC_DATA{.size = endpoint_info.size(),
.data = (char*)endpoint_info.data()},
service_id.c_str());
};
listener.endpoint_lost_cb = [=](const std::string& endpoint_id) {
discovery_listener.endpoint_lost_callback(endpoint_id.c_str());
};
kNcContext.core->StartDiscovery(
service_id, std::move(cpp_discovery_options), std::move(listener),
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcStopDiscovery(NC_INSTANCE instance, NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->StopDiscovery([=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcInjectEndpoint(NC_INSTANCE instance, const char* service_id,
const NC_OUT_OF_BAND_CONNECTION_METADATA& metadata,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
nearby::connections::OutOfBandConnectionMetadata
cpp_out_of_band_connection_metadata;
cpp_out_of_band_connection_metadata.endpoint_id = metadata.endpoint_id;
cpp_out_of_band_connection_metadata.endpoint_info = {
metadata.endpoint_info.data, metadata.endpoint_info.size};
cpp_out_of_band_connection_metadata.medium =
static_cast<nearby::connections::Medium>(metadata.medium);
cpp_out_of_band_connection_metadata.remote_bluetooth_mac_address = {
metadata.remote_bluetooth_mac_address.data,
metadata.remote_bluetooth_mac_address.size};
kNcContext.core->InjectEndpoint(
service_id, cpp_out_of_band_connection_metadata,
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcRequestConnection(
NC_INSTANCE instance, const char* endpoint_id,
const NC_CONNECTION_REQUEST_INFO& connection_request_info,
const NC_CONNECTION_OPTIONS& connection_options,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
nearby::connections::ConnectionRequestInfo cpp_connection_request_info =
GetCppConnectionRequestInfo(connection_request_info);
nearby::connections::ConnectionOptions cpp_connection_options;
cpp_connection_options.allowed.ble =
connection_options.common_options.allowed_mediums[NC_MEDIUM_BLE];
cpp_connection_options.allowed.bluetooth =
connection_options.common_options.allowed_mediums[NC_MEDIUM_BLUETOOTH];
cpp_connection_options.allowed.web_rtc =
connection_options.common_options.allowed_mediums[NC_MEDIUM_WEB_RTC];
cpp_connection_options.allowed.wifi_lan =
connection_options.common_options.allowed_mediums[NC_MEDIUM_WIFI_LAN];
cpp_connection_options.auto_upgrade_bandwidth =
connection_options.auto_upgrade_bandwidth;
cpp_connection_options.enforce_topology_constraints =
connection_options.enforce_topology_constraints;
if (connection_options.fast_advertisement_service_uuid.size > 0) {
cpp_connection_options.fast_advertisement_service_uuid =
std::string(connection_options.fast_advertisement_service_uuid.data,
connection_options.fast_advertisement_service_uuid.size);
}
cpp_connection_options.is_out_of_band_connection =
connection_options.is_out_of_band_connection;
cpp_connection_options.keep_alive_interval_millis =
connection_options.keep_alive_interval_millis;
cpp_connection_options.keep_alive_timeout_millis =
connection_options.keep_alive_timeout_millis;
cpp_connection_options.low_power = connection_options.low_power;
if (connection_options.remote_bluetooth_mac_address.size > 0) {
cpp_connection_options.remote_bluetooth_mac_address =
nearby::BluetoothUtils::FromString(
std::string(connection_options.remote_bluetooth_mac_address.data,
connection_options.remote_bluetooth_mac_address.size));
}
if (connection_options.common_options.strategy.type == NC_STRATEGY_TYPE_NONE)
cpp_connection_options.strategy = nearby::connections::Strategy::kNone;
if (connection_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_CLUSTER)
cpp_connection_options.strategy =
nearby::connections::Strategy::kP2pCluster;
if (connection_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_POINT_TO_POINT)
cpp_connection_options.strategy =
nearby::connections::Strategy::kP2pPointToPoint;
if (connection_options.common_options.strategy.type ==
NC_STRATEGY_TYPE_P2P_STAR)
cpp_connection_options.strategy = nearby::connections::Strategy::kP2pStar;
kNcContext.core->RequestConnection(
endpoint_id, std::move(cpp_connection_request_info),
std::move(cpp_connection_options),
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcAcceptConnection(NC_INSTANCE instance, const char* endpoint_id,
NC_PAYLOAD_LISTENER payload_listener,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
nearby::connections::PayloadListener cpp_payload_listener;
cpp_payload_listener.payload_cb = [=](absl::string_view endpoint_id,
nearby::connections::Payload payload) {
NC_PAYLOAD nc_payload;
nc_payload.id = payload.GetId();
nc_payload.direction = NC_PAYLOAD_DIRECTION_INCOMING;
nc_payload.type = static_cast<NC_PAYLOAD_TYPE>(payload.GetType());
if (nc_payload.type == NC_PAYLOAD_TYPE_BYTES) {
nearby::ByteArray bytes = payload.AsBytes();
nc_payload.content.bytes.content.data = bytes.data();
nc_payload.content.bytes.content.size = bytes.size();
} else if (nc_payload.type == NC_PAYLOAD_TYPE_FILE) {
nc_payload.content.file.file_name = (char*)payload.GetFileName().c_str();
nc_payload.content.file.parent_folder =
(char*)payload.GetParentFolder().c_str();
} else if (nc_payload.type == NC_PAYLOAD_TYPE_STREAM) {
// TODO(guogang): support stream later.
}
payload_listener.received_callback(std::string(endpoint_id).c_str(),
nc_payload);
};
cpp_payload_listener.payload_progress_cb =
[=](absl::string_view endpoint_id,
const nearby::connections::PayloadProgressInfo& progress) {
NC_PAYLOAD_PROGRESS_INFO nc_payload_progress_info;
nc_payload_progress_info.id = progress.payload_id;
nc_payload_progress_info.bytes_transferred = progress.bytes_transferred;
nc_payload_progress_info.total_bytes = progress.total_bytes;
nc_payload_progress_info.status =
static_cast<NC_PAYLOAD_PROGRESS_INFO_STATUS>(progress.status);
payload_listener.progress_updated_callback(
std::string(endpoint_id).c_str(), nc_payload_progress_info);
};
kNcContext.core->AcceptConnection(
endpoint_id, std::move(cpp_payload_listener),
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcRejectConnection(NC_INSTANCE instance, const char* endpoint_id,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->RejectConnection(
endpoint_id, [=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcSendPayload(NC_INSTANCE instance, size_t endpoint_ids_size,
const char** endpoint_ids, const NC_PAYLOAD& payload,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
std::vector<std::string> endpoint_ids_vector;
for (size_t i = 0; i < endpoint_ids_size; ++i) {
endpoint_ids_vector.push_back(std::string(endpoint_ids[i]));
}
absl::Span<const std::string> endpoint_ids_span(endpoint_ids_vector.data(),
endpoint_ids_size);
nearby::connections::Payload cpp_payload;
if (payload.type == NC_PAYLOAD_TYPE_BYTES) {
cpp_payload = nearby::connections::Payload(
payload.id, nearby::ByteArray(payload.content.bytes.content.data,
payload.content.bytes.content.size));
} else if (payload.type == NC_PAYLOAD_TYPE_FILE) {
// get file size
std::string full_file_name = "";
if (payload.content.file.parent_folder == nullptr) {
full_file_name = payload.content.file.file_name;
} else {
full_file_name = absl::StrCat(payload.content.file.parent_folder, "/",
payload.content.file.file_name);
}
nearby::InputFile input_file(full_file_name,
getFileSize(full_file_name.c_str()));
cpp_payload =
nearby::connections::Payload(payload.id, std::move(input_file));
} else if (payload.type == NC_PAYLOAD_TYPE_STREAM) {
// TODO(guogang): support stream later.
}
kNcContext.core->SendPayload(
endpoint_ids_span, std::move(cpp_payload),
[=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcCancelPayload(NC_INSTANCE instance, NC_PAYLOAD_ID payload_id,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->CancelPayload(
payload_id, [=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcDisconnectFromEndpoint(NC_INSTANCE instance, const char* endpoint_id,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->DisconnectFromEndpoint(
endpoint_id, [=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcStopAllEndpoints(NC_INSTANCE instance,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->StopAllEndpoints([=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
void NcInitiateBandwidthUpgrade(NC_INSTANCE instance, const char* endpoint_id,
NcCallbackResult result_callback) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
result_callback(NC_STATUS_ERROR);
return;
}
kNcContext.core->InitiateBandwidthUpgrade(
endpoint_id, [=](nearby::connections::Status status) {
result_callback(static_cast<NC_STATUS>(status.value));
});
}
char* NcGetLocalEndpointId(NC_INSTANCE instance) {
if (kNcContext.core == nullptr || instance != kNcContext.core) {
return nullptr;
}
std::string endpoint_id = kNcContext.core->GetLocalEndpointId();
char* result = new char[endpoint_id.length() + 1];
absl::SNPrintF(result, endpoint_id.length() + 1, "%s", endpoint_id);
return result;
}
+172
View File
@@ -0,0 +1,172 @@
// 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_C_NC_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_H_
#include <stddef.h>
#include "connections/c/nc_def.h"
#include "connections/c/nc_types.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Opens Nearby Connections service. If service is opened already, it will
// return opened instance.
NC_API NC_INSTANCE NcOpenService();
NC_API void NcCloseService(NC_INSTANCE instance);
// Starts adververtising an endpoint using Nearby Connections.
//
// instance - The returned instance by NcOpenService.
// service_id - The ID for the service to be advertised.
// advertising_options - The options for advertising.
// connection_request_info - Connection parameters, including endpoint info
// and listeners.
// result_callback - The result of the API operation.
NC_API void NcStartAdvertising(
NC_INSTANCE instance, const char* service_id,
const NC_ADVERTISING_OPTIONS& advertising_options,
const NC_CONNECTION_REQUEST_INFO& connection_request_info,
NcCallbackResult result_callback);
// Stops advertising a local endpoint. It should be called after calling
// StartAdvertising.
//
// instance - The instance is used to start advertising.
// result_callback - The result of the API operation.
NC_API void NcStopAdvertising(NC_INSTANCE instance,
NcCallbackResult result_callback);
// Starts to discover for remote endpoints with the specified service ID.
//
// instance - The returned instance by NcOpenService.
// service_id - The ID for the service to be discovered.
// discovery_options - The options for discovery.
// discovery_listener - The callbacks notified when a remote endpoint is
// reported.
// result_callback - The result of the API operation.
NC_API void NcStartDiscovery(NC_INSTANCE instance, const char* service_id,
const NC_DISCOVERY_OPTIONS& discovery_options,
const NC_DISCOVERY_LISTENER& discovery_listener,
NcCallbackResult result_callback);
// Stops discovering for a running discovery.
//
// instance - The instance is used to start discovery.
// result_callback - The result of the API operation.
NC_API void NcStopDiscovery(NC_INSTANCE instance,
NcCallbackResult result_callback);
// Invokes the discovery callback from a previous call to NcStartDiscovery()
// with the given endpoint info. The previous call to NcStartDiscovery() must
// have been passed ConnectionOptions with is_out_of_band_connection == true.
//
// instance - The instance is used to start discovery.
// service_id - The ID for the service to be discovered, as specified in the
// corresponding call to NcStartDiscovery().
// metadata - Metadata used in order to inject the endpoint.
// result_callback - The result of the API operation.
NC_API void NcInjectEndpoint(NC_INSTANCE instance, const char* service_id,
const NC_OUT_OF_BAND_CONNECTION_METADATA& metadata,
NcCallbackResult result_callback);
// Sends a request to connect to a remote endpoint.
//
// instance - The returned instance by NcOpenService.
// endpoint_id - The identifier for the remote endpoint to which a
// connection request will be sent.
// connection_request_info - Connection parameters.
// connection_options - Options to connect.
// result_callback - The result of the API operation.
NC_API void NcRequestConnection(
NC_INSTANCE instance, const char* endpoint_id,
const NC_CONNECTION_REQUEST_INFO& connection_request_info,
const NC_CONNECTION_OPTIONS& connection_options,
NcCallbackResult result_callback);
// Accepts a connection to a remote endpoint.
//
// instance - The returned instance by NcOpenService.
// endpoint_id - The identifier for the remote endpoint.
// payload_listener - A callback for payloads exchanged with the remote
// endpoint.
// result_callback - The result of the API operation.
NC_API void NcAcceptConnection(NC_INSTANCE instance, const char* endpoint_id,
NC_PAYLOAD_LISTENER payload_listener,
NcCallbackResult result_callback);
// Rejects a connection from a remote endpoint.
//
// instance - The returned instance by NcOpenService.
// endpoint_id - The identifier for the remote endpoint.
// result_callback - The result of the API operation.
NC_API void NcRejectConnection(NC_INSTANCE instance, const char* endpoint_id,
NcCallbackResult result_callback);
// Sends a Payload to a remote endpoint.
//
// instance - The returned instance by NcOpenService.
// endpoint_ids_size - The endpoint number to receive the payload.
// endpoint_ids - The endpoint ID array.
// payload - the payload will be sent.
// result_callback - The result of the API operation.
NC_API void NcSendPayload(NC_INSTANCE instance, size_t endpoint_ids_size,
const char** endpoint_ids, const NC_PAYLOAD& payload,
NcCallbackResult result_callback);
// Cancels a Payload currently in-flight to or from remote endpoint(s).
//
// instance - The Nearby Connections instance is called by NcSendPayload.
// payload_id - The payload ID of payload to cancel.
// result_callback - The result of the API operation.
NC_API void NcCancelPayload(NC_INSTANCE instance, NC_PAYLOAD_ID payload_id,
NcCallbackResult result_callback);
// Disconnects from a remote endpoint.
//
// instance - The returned instance by NcOpenService.
// endpoint_id - The endpoint ID of remote device to disconnect.
// result_callback - The result of the API operation.
NC_API void NcDisconnectFromEndpoint(NC_INSTANCE instance,
const char* endpoint_id,
NcCallbackResult result_callback);
// Disconnects from, and removes all traces of, all connected and/or
// discovered endpoints.
//
// instance - The returned instance by NcOpenService.
// result_callback - The result of the API operation.
NC_API void NcStopAllEndpoints(NC_INSTANCE instance,
NcCallbackResult result_callback);
// Sends a request to initiate connection bandwidth upgrade.
//
// instance - The returned instance by NcOpenService.
// endpoint_id - Requested to upgrade on the remote device with the endpoint ID.
// result_callback - The result of the API operation.
NC_API void NcInitiateBandwidthUpgrade(NC_INSTANCE instance,
const char* endpoint_id,
NcCallbackResult result_callback);
// Gets the local endpoint generated by Nearby Connections.
NC_API char* NcGetLocalEndpointId(NC_INSTANCE instance);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_H_
+39
View File
@@ -0,0 +1,39 @@
// 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_C_NC_DEF_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_DEF_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifdef _WIN32 // These storage class specifiers only matter to win32 dll
// builds.
#ifdef NC_DLL
// If we're building the core, we're exporting.
#define NC_API __declspec(dllexport)
#else // !NC_DLL
// If we're not building the core, we're importing.
#define NC_API __declspec(dllimport)
#endif // NC_DLL
#else // !_WIN32
#define NC_API // We're not building a win32 dll, leave the source unchanged.
#endif // _WIN32
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_DEF_H_
+281
View File
@@ -0,0 +1,281 @@
// 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_C_NC_TYPES_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_TYPES_H_
#include <stddef.h>
#include <stdint.h>
#include <cstddef>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef void* NC_INSTANCE;
typedef int64_t NC_PAYLOAD_ID;
// NC_DATA is used to define a byte array. Its last byte is not zero.
typedef struct NC_DATA {
size_t size;
char* data;
} NC_DATA, *PNC_DATA;
// Supported mediums by Nearby Connections.
typedef enum NC_MEDIUM {
NC_MEDIUM_UNKNOWN = 0,
NC_MEDIUM_MDNS = 1, // deprecated
NC_MEDIUM_BLUETOOTH = 2,
NC_MEDIUM_WIFI_HOTSPOT = 3,
NC_MEDIUM_BLE = 4,
NC_MEDIUM_WIFI_LAN = 5,
NC_MEDIUM_WIFI_AWARE = 6,
NC_MEDIUM_NFC = 7,
NC_MEDIUM_WIFI_DIRECT = 8,
NC_MEDIUM_WEB_RTC = 9,
NC_MEDIUM_BLE_L2CAP = 10,
NC_MEDIUM_USB = 11,
NC_MEDIUM_MAX = 12
} NC_MEDIUM;
typedef enum NC_CONNECTION_TYPE {
NC_CONNECTION_TYPE_NONE = 0,
NC_CONNECTION_TYPE_POINT_TO_POINT = 1,
} NC_CONNECTION_TYPE;
typedef enum NC_TOPOLOGY_TYPE {
NC_TOPOLOGY_TYPE_UNKNOWN = 0,
NC_TOPOLOGY_TYPE_ONE_TO_ONE = 1,
NC_TOPOLOGY_TYPE_ONE_TO_MANY = 2,
NC_TOPOLOGY_TYPE_MANY_TO_MANY = 3,
} NC_TOPOLOGY_TYPE;
typedef enum NC_STRATEGY_TYPE {
NC_STRATEGY_TYPE_NONE,
NC_STRATEGY_TYPE_P2P_CLUSTER,
NC_STRATEGY_TYPE_P2P_STAR,
NC_STRATEGY_TYPE_P2P_POINT_TO_POINT
} NC_STRATEGY_TYPE;
typedef enum NC_DISTANCE_INFO {
NC_DISTANCE_INFO_UNKNOWN = 1,
NC_DISTANCE_INFO_VERYCLOSE = 2,
NC_DISTANCE_INFO_CLOSE = 3,
NC_DISTANCE_INFO_FAR = 4,
} NC_DISTANCE_INFO;
typedef enum NC_STATUS {
NC_STATUS_SUCCESS,
NC_STATUS_ERROR,
NC_STATUS_OUTOFORDERAPICALL,
NC_STATUS_ALREADYHAVEACTIVESTRATEGY,
NC_STATUS_ALREADYADVERTISING,
NC_STATUS_ALREADYDISCOVERING,
NC_STATUS_ALREADYLISTENING,
NC_STATUS_ENDPOINTIOERROR,
NC_STATUS_ENDPOINTUNKNOWN,
NC_STATUS_CONNECTIONREJECTED,
NC_STATUS_ALREADYCONNECTEDTOENDPOINT,
NC_STATUS_NOTCONNECTEDTOENDPOINT,
NC_STATUS_BLUETOOTHERROR,
NC_STATUS_BLEERROR,
NC_STATUS_WIFILANERROR,
NC_STATUS_PAYLOADUNKNOWN,
NC_STATUS_RESET,
NC_STATUS_TIMEOUT,
NC_STATUS_UNKNOWN,
NC_STATUS_NEXTVALUE,
} NC_STATUS;
typedef enum NC_PAYLOAD_TYPE {
NC_PAYLOAD_TYPE_UNKNOWN = 0,
NC_PAYLOAD_TYPE_BYTES = 1,
NC_PAYLOAD_TYPE_STREAM = 2,
NC_PAYLOAD_TYPE_FILE = 3
} NC_PAYLOAD_TYPE;
typedef enum NC_PAYLOAD_DIRECTION {
NC_PAYLOAD_DIRECTION_UNKNOWN = 0,
NC_PAYLOAD_DIRECTION_INCOMING = 1,
NC_PAYLOAD_DIRECTION_OUTGOING = 2,
} NC_PAYLOAD_DIRECTION;
// Defines struct types in Nearby connections.
typedef struct NC_STRATEGY {
NC_STRATEGY_TYPE type;
NC_CONNECTION_TYPE connection_type;
NC_TOPOLOGY_TYPE topology_type;
} NC_STRATEGY;
typedef struct NC_COMMON_OPTIONS {
NC_STRATEGY strategy;
bool allowed_mediums[NC_MEDIUM_MAX];
} NC_COMMON_OPTIONS;
typedef struct NC_ADVERTISING_OPTIONS {
NC_COMMON_OPTIONS common_options;
bool auto_upgrade_bandwidth;
bool enforce_topology_constraints;
bool enable_bluetooth_listening;
bool enable_webrtc_listening;
bool low_power;
bool is_out_of_band_connection;
NC_DATA fast_advertisement_service_uuid;
NC_DATA device_info;
} NC_ADVERTISING_OPTIONS, *PNC_ADVERTISING_OPTIONS;
typedef struct NC_CONNECTION_OPTIONS {
NC_COMMON_OPTIONS common_options;
bool auto_upgrade_bandwidth = true;
bool enforce_topology_constraints;
bool low_power;
bool is_out_of_band_connection = false;
NC_DATA remote_bluetooth_mac_address;
NC_DATA fast_advertisement_service_uuid;
int keep_alive_interval_millis = 0;
int keep_alive_timeout_millis = 0;
} NC_CONNECTION_OPTIONS, *PNC_CONNECTION_OPTIONS;
typedef struct NC_DISCOVERY_OPTIONS {
NC_COMMON_OPTIONS common_options;
bool auto_upgrade_bandwidth = true;
bool enforce_topology_constraints;
// Whether this is intended to be used in conjunction with InjectEndpoint().
bool is_out_of_band_connection = false;
NC_DATA fast_advertisement_service_uuid;
} NC_DISCOVERY_OPTIONS, *PNC_DISCOVERY_OPTIONS;
typedef struct NC_CONNECTION_RESPONSE_INFO {
NC_DATA remote_endpoint_info;
NC_DATA authentication_token;
NC_DATA raw_authentication_token;
bool is_incoming_connection = false;
bool is_connection_verified = false;
} NC_CONNECTION_RESPONSE_INFO, *PNC_CONNECTION_RESPONSE_INFO;
// Defines callbacks in Nearby Connections.
typedef void (*NcCallbackResult)(NC_STATUS status);
typedef void (*NcCallbackConnectionInitiated)(
const char* endpoint_id, const NC_CONNECTION_RESPONSE_INFO& info);
typedef void (*NcCallbackConnectionAccepted)(const char* endpoint_id);
typedef void (*NcCallbackConnectionRejected)(const char* endpoint_id,
NC_STATUS status);
typedef void (*NcCallbackConnectionDisconnected)(const char* endpoint_id);
typedef void (*NcCallbackConnectionBandwidthChanged)(const char* endpoint_id,
NC_MEDIUM medium);
typedef struct NC_CONNECTION_REQUEST_INFO {
NC_DATA endpoint_info;
NcCallbackConnectionInitiated initiated_callback;
NcCallbackConnectionAccepted accepted_callback;
NcCallbackConnectionRejected rejected_callback;
NcCallbackConnectionDisconnected disconnected_callback;
NcCallbackConnectionBandwidthChanged bandwidth_changed_callback;
} NC_CONNECTION_REQUEST_INFO;
typedef void (*NcCallbackDiscoveryEndpointFound)(const char* endpoint_id,
const NC_DATA& endpoint_info,
const char* service_id);
typedef void (*NcCallbackDiscoveryEndpointLost)(const char* endpoint_id);
typedef void (*NcCallbackDiscoveryEndpointDistanceChanged)(
const char* endpoint_id, NC_DISTANCE_INFO info);
typedef struct NC_DISCOVERY_LISTENER {
NcCallbackDiscoveryEndpointFound endpoint_found_callback;
NcCallbackDiscoveryEndpointLost endpoint_lost_callback;
NcCallbackDiscoveryEndpointDistanceChanged endpoint_distance_changed_callback;
} NC_DISCOVERY_LISTENER;
typedef struct NC_BYTES_PAYLOAD {
NC_DATA content;
} NC_BYTES_PAYLOAD;
typedef struct NC_STREAM_PAYLOAD {
NC_DATA data;
} NC_STREAM_PAYLOAD;
typedef struct NC_FILE_PAYLOAD {
char* file_name;
char* parent_folder;
} NC_FILE_PAYLOAD;
typedef union NC_PAYLOAD_CONTENT {
NC_BYTES_PAYLOAD bytes;
NC_STREAM_PAYLOAD stream;
NC_FILE_PAYLOAD file;
} NC_PAYLOAD_CONTENT;
typedef struct NC_PAYLOAD {
NC_PAYLOAD_ID id;
NC_PAYLOAD_TYPE type;
NC_PAYLOAD_DIRECTION direction;
NC_PAYLOAD_CONTENT content;
} NC_PAYLOAD;
typedef enum NC_PAYLOAD_PROGRESS_INFO_STATUS {
NC_PAYLOAD_PROGRESS_INFO_STATUS_SUCCESS,
NC_PAYLOAD_PROGRESS_INFO_STATUS_FAILURE,
NC_PAYLOAD_PROGRESS_INFO_STATUS_INPROGRESS,
NC_PAYLOAD_PROGRESS_INFO_STATUS_CANCELED,
} NC_PAYLOAD_PROGRESS_INFO_STATUS;
typedef struct NC_PAYLOAD_PROGRESS_INFO {
NC_PAYLOAD_ID id;
NC_PAYLOAD_PROGRESS_INFO_STATUS status;
size_t total_bytes;
size_t bytes_transferred;
} NC_PAYLOAD_PROGRESS_INFO;
typedef void (*NcCallbackPayloadReceived)(const char* endpoint_id,
const NC_PAYLOAD& payload);
typedef void (*NcCallbackPayloadProgressUpdated)(
const char* endpoint_id, const NC_PAYLOAD_PROGRESS_INFO& info);
typedef struct NC_PAYLOAD_LISTENER {
NcCallbackPayloadReceived received_callback;
NcCallbackPayloadProgressUpdated progress_updated_callback;
} NC_PAYLOAD_LISTENER;
typedef struct NC_OUT_OF_BAND_CONNECTION_METADATA {
// Medium to use for the out-of-band connection.
NC_MEDIUM medium;
// Endpoint ID to use for the injected connection; will be included in the
// endpoint_found_cb callback. Must be exactly 4 bytes and should be randomly-
// generated such that no two IDs are identical.
char* endpoint_id;
// Endpoint info to use for the injected connection; will be included in the
// endpoint_found_cb callback. Should uniquely identify the InjectEndpoint()
// call so that the client which made the call can verify the endpoint
// that was found is the one that was injected.
//
// Cannot be empty, and must be <131 bytes.
NC_DATA endpoint_info;
// Used for Bluetooth connections.
NC_DATA remote_bluetooth_mac_address;
} NC_OUT_OF_BAND_CONNECTION_METADATA, *PNC_OUT_OF_BAND_CONNECTION_METADATA;
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_C_NC_TYPES_H_