Start initial Swift SDK by creating a lightweight Objective-C wrapper

PiperOrigin-RevId: 466681084
This commit is contained in:
Nick Bourdakos
2022-08-10 07:44:26 -07:00
committed by Copybara-Service
parent 55f20775d2
commit 63b4f0760c
46 changed files with 2460 additions and 12 deletions
+58 -12
View File
@@ -6,10 +6,14 @@ let package = Package(
name: "NearbyConnections",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "NearbyCoreAdapter",
targets: ["NearbyCoreAdapter"]
),
.library(
name: "NearbyConnections",
targets: ["NearbyConnections"]
)
),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
@@ -360,7 +364,7 @@ let package = Package(
]
),
.target(
name: "NearbyConnections",
name: "NearbyCoreAdapter",
dependencies: [
"google-toolbox-for-mac",
"smhasher",
@@ -373,6 +377,10 @@ let package = Package(
"presence",
"embedded",
"connections/clients/windows",
"connections/clients/ios",
"connections/clients/swift/NearbyConnections",
"connections/clients/swift/NearbyCoreAdapter/BUILD",
"connections/clients/swift/NearbyCoreAdapter/Tests",
"connections/samples",
"docs",
"internal/platform/implementation/g3",
@@ -385,7 +393,6 @@ let package = Package(
"README.md",
"WORKSPACE",
// build files
"connections/clients/ios/BUILD",
"connections/implementation/analytics/BUILD",
"connections/implementation/proto/BUILD",
"connections/implementation/proto/CMakeLists.txt",
@@ -412,7 +419,6 @@ let package = Package(
// tests
"connections/listeners_test.cc",
"connections/strategy_test.cc",
"connections/clients/ios/BuildTests",
"connections/implementation/offline_frames_test.cc",
"connections/implementation/offline_service_controller_test.cc",
"connections/implementation/encryption_runner_test.cc",
@@ -428,7 +434,6 @@ let package = Package(
"connections/implementation/analytics/analytics_recorder_test.cc",
"connections/implementation/mediums/ble_v2_test.cc",
"connections/implementation/mediums/ble_v2/bloom_filter_test.cc",
"connections/implementation/mediums/ble_v2/ble_peripheral_test.cc",
"connections/implementation/mediums/ble_v2/ble_packet_test.cc",
"connections/implementation/mediums/ble_v2/ble_advertisement_test.cc",
"connections/implementation/mediums/ble_v2/advertisement_read_result_test.cc",
@@ -537,23 +542,64 @@ let package = Package(
"internal",
"proto",
],
publicHeadersPath: "connections/clients/ios/Public",
publicHeadersPath: "connections/clients/swift/NearbyCoreAdapter/Sources/Public",
cSettings: [
.headerSearchPath("./"),
.headerSearchPath("compiled_proto/"),
.define("NO_WEBRTC"),
.define("NEARBY_SWIFTPM"),
]
),
.target(
name: "NearbyConnections",
dependencies: ["NearbyCoreAdapter"],
path: ".",
exclude: [
"compiled_proto",
"connections/clients/windows",
"connections/clients/ios",
"connections/clients/swift/NearbyCoreAdapter",
"connections/clients/swift/NearbyConnections/BUILD",
"connections/clients/swift/NearbyConnections/Tests",
"connections/BUILD",
"connections/discovery_options.cc",
"connections/status.cc",
"connections/listeners_test.cc",
"connections/advertising_options.cc",
"connections/payload.cc",
"connections/strategy_test.cc",
"connections/connection_options.cc",
"connections/core_test.cc",
"connections/status_test.cc",
"connections/core.cc",
"connections/strategy.cc",
"connections/payload_test.cc",
"connections/implementation",
"connections/samples",
"docs",
"embedded",
"internal",
"presence",
"proto",
"third_party",
"CONTRIBUTING.md",
"LICENSE",
"README.md",
"WORKSPACE",
],
linkerSettings: [
.linkedLibrary("c++"),
.linkedFramework("CoreBluetooth"),
.linkedFramework("CoreFoundation"),
sources: [
"connections/clients/swift/NearbyConnections/Sources"
]
),
.testTarget(
name: "BuildTests",
name: "NearbyCoreAdapterTests",
dependencies: ["NearbyCoreAdapter"],
path: "connections/clients/swift/NearbyCoreAdapter/Tests"
),
.testTarget(
name: "NearbyConnectionsTests",
dependencies: ["NearbyConnections"],
path: "connections/clients/ios/BuildTests"
path: "connections/clients/swift/NearbyConnections/Tests"
),
],
cLanguageStandard: .c99,
+3
View File
@@ -11,6 +11,9 @@
# 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.
# TODO(b/240046236): Rename this package as `objc`.
load("//tools/build_defs/apple:ios.bzl", "ios_static_framework", "ios_unit_test")
load("//tools/build_defs/swift:swift.bzl", "swift_library")
@@ -0,0 +1,48 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
load("//tools/build_defs/swift:swift.bzl", "swift_library")
licenses(["notice"])
package(default_visibility = ["//visibility:public"])
swift_library(
name = "NearbyConnections",
srcs = glob(["Sources/**/*.swift"]),
module_name = "NearbyConnections",
deps = [
"//connections/clients/swift/NearbyCoreAdapter",
],
)
swift_library(
name = "TestsLib",
testonly = 1,
srcs = ["Tests/BuildTests.swift"],
deps = [
":NearbyConnections",
"//third_party/apple_frameworks:XCTest",
],
)
ios_unit_test(
name = "Tests",
minimum_os_version = "12.0",
runner = "//testing/utp/ios:IOS_12",
deps = [
":TestsLib",
],
)
@@ -0,0 +1,17 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import NearbyCoreAdapter
public class Advertiser {}
@@ -0,0 +1,17 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import NearbyCoreAdapter
public class Connection {}
@@ -0,0 +1,17 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import NearbyCoreAdapter
public class Discoverer {}
@@ -0,0 +1,8 @@
import NearbyConnections
import XCTest
class BuildTests: XCTestCase {
func testBuild() {
// At least one test case is needed.
}
}
@@ -0,0 +1,58 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
load("//tools/build_defs/swift:swift.bzl", "swift_library")
licenses(["notice"])
package(default_visibility = ["//visibility:public"])
objc_library(
name = "NearbyCoreAdapter",
srcs = glob([
"Sources/*.mm",
"Sources/*.m",
"Sources/*.h",
]),
hdrs = glob(["Sources/Public/**/*.h"]),
features = ["-layering_check"],
module_name = "NearbyCoreAdapter",
deps = [
"//third_party/apple_frameworks:Foundation",
"//connections:core",
"//connections:core_types",
"//internal/platform:base",
"//internal/platform/implementation/ios:Platform", # buildcleaner: keep
],
)
swift_library(
name = "TestsLib",
testonly = 1,
srcs = ["Tests/BuildTests.swift"],
deps = [
":NearbyCoreAdapter",
"//third_party/apple_frameworks:XCTest",
],
)
ios_unit_test(
name = "Tests",
minimum_os_version = "12.0",
runner = "//testing/utp/ios:IOS_12",
deps = [
":TestsLib",
],
)
@@ -0,0 +1,50 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#ifdef __cplusplus
namespace location {
namespace nearby {
class InputStream;
}
} // namespace location
#endif
@interface CPPInputStreamBinding : NSObject
/**
* Creates and attaches a @c CPPInputStreamBinding object to the provided stream as an associated
* object.
*
* This association makes it possible for a c++ pointer to live as long as the original user
* provided @c NSInputStream object.
*
* @param stream The stream to become associated with.
*/
+ (void)bindToStream:(NSInputStream *)stream;
#ifdef __cplusplus
/**
* Retreives a reference to the c++ pointer associated to the provided stream.
*
* CPPInputStreamBinding::bindToStream: must be called on the this stream before calling this
* function.
*
* @param stream The stream that has a c++ pointer associated with it.
*/
+ (location::nearby::InputStream &)getRefFromStream:(NSInputStream *)stream;
#endif
@end
@@ -0,0 +1,90 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/CPPInputStreamBinding.h"
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#include <memory>
#include <vector>
// TODO(b/239758418): Change this to the non-internal version when available.
#include "internal/platform/input_stream.h"
using ::location::nearby::ByteArray;
using ::location::nearby::Exception;
using ::location::nearby::ExceptionOr;
using ::location::nearby::InputStream;
class CPPInputStream : public InputStream {
public:
explicit CPPInputStream(NSInputStream *iStream) : iStream_(iStream) { [iStream_ open]; }
~CPPInputStream() override { Close(); }
ExceptionOr<ByteArray> Read(std::int64_t size) override {
std::vector<uint8_t> buffer;
buffer.reserve(size);
NSInteger numberOfBytesRead = [iStream_ read:buffer.data() maxLength:size];
if (numberOfBytesRead == 0) {
return ExceptionOr<ByteArray>();
}
if (numberOfBytesRead < 0) {
return ExceptionOr<ByteArray>(Exception::kIo);
}
return ExceptionOr<ByteArray>(ByteArray((const char *)buffer.data(), numberOfBytesRead));
}
Exception Close() override {
[iStream_ close];
return Exception{Exception::kSuccess};
}
private:
// Prevent a retain cycle since NSInputStream will have a strong reference to this object.
__weak NSInputStream *iStream_;
};
// Wrap a c++ InputStream subclass in objective-c so it can be associated with the original
// NSInputStream object. The association makes it possible for the unique_ptr to live as long as
// the original user provided NSInputStream.
@implementation CPPInputStreamBinding {
@public
std::unique_ptr<CPPInputStream> _cppStream;
}
// This field's address is used as a unique identifier.
static char gAssociatedStreamKey;
- (instancetype)initWithStream:(NSInputStream *)stream {
self = [super init];
if (self) {
_cppStream = std::make_unique<CPPInputStream>(stream);
}
return self;
}
+ (void)bindToStream:(NSInputStream *)stream {
CPPInputStreamBinding *binding = [[CPPInputStreamBinding alloc] initWithStream:stream];
objc_setAssociatedObject(stream, &gAssociatedStreamKey, binding,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (InputStream &)getRefFromStream:(NSInputStream *)stream {
CPPInputStreamBinding *binding = objc_getAssociatedObject(stream, &gAssociatedStreamKey);
return *binding->_cppStream;
}
@end
@@ -0,0 +1,35 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCAdvertisingOptions.h"
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class AdvertisingOptions;
}
} // namespace nearby
} // namespace location
#endif
@interface GNCAdvertisingOptions (CppConversions)
#ifdef __cplusplus
- (location::nearby::connections::AdvertisingOptions)toCpp;
#endif
@end
@@ -0,0 +1,35 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCAdvertisingOptions.h"
#import <Foundation/Foundation.h>
#include "connections/advertising_options.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCAdvertisingOptions+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCStrategy+Internal.h"
using ::location::nearby::connections::AdvertisingOptions;
using ::location::nearby::connections::CppStrategyFromGNCStrategy;
@implementation GNCAdvertisingOptions (CppConversions)
- (AdvertisingOptions)toCpp {
AdvertisingOptions advertising_options;
advertising_options.strategy = CppStrategyFromGNCStrategy(self.strategy);
return advertising_options;
}
@end
@@ -0,0 +1,31 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCAdvertisingOptions.h"
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCStrategy.h"
@implementation GNCAdvertisingOptions
- (instancetype)initWithStrategy:(GNCStrategy)strategy {
self = [super init];
if (self) {
_strategy = strategy;
}
return self;
}
@end
@@ -0,0 +1,35 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCConnectionOptions.h"
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class ConnectionOptions;
}
} // namespace nearby
} // namespace location
#endif
@interface GNCConnectionOptions (CppConversions)
#ifdef __cplusplus
- (location::nearby::connections::ConnectionOptions)toCpp;
#endif
@end
@@ -0,0 +1,31 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCConnectionOptions.h"
#import <Foundation/Foundation.h>
#include "connections/connection_options.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCConnectionOptions+CppConversions.h"
using ::location::nearby::connections::ConnectionOptions;
@implementation GNCConnectionOptions (CppConversions)
- (ConnectionOptions)toCpp {
return ConnectionOptions{};
}
@end
@@ -0,0 +1,21 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCConnectionOptions.h"
#import <Foundation/Foundation.h>
@implementation GNCConnectionOptions
@end
@@ -0,0 +1,417 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCCoreAdapter.h"
#import <Foundation/Foundation.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "connections/core.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCAdvertisingOptions+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCConnectionOptions+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCDiscoveryOptions+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCError+Internal.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCPayload+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCAdvertisingOptions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCConnectionDelegate.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCConnectionOptions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCDiscoveryDelegate.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCDiscoveryOptions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCError.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCPayload.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCPayloadDelegate.h"
using ::location::nearby::ByteArray;
using ::location::nearby::connections::AdvertisingOptions;
using ::location::nearby::connections::ConnectionListener;
using ::location::nearby::connections::ConnectionOptions;
using ::location::nearby::connections::ConnectionRequestInfo;
using ::location::nearby::connections::ConnectionResponseInfo;
using ::location::nearby::connections::Core;
using ::location::nearby::connections::DiscoveryListener;
using ::location::nearby::connections::DiscoveryOptions;
using ::location::nearby::connections::Payload;
using ::location::nearby::connections::PayloadListener;
using ::location::nearby::connections::PayloadProgressInfo;
using ResultListener = ::location::nearby::connections::ResultCallback;
using ::location::nearby::connections::ServiceControllerRouter;
using ::location::nearby::connections::Status;
GNCStatus GNCStatusFromCppStatus(Status status) {
switch (status.value) {
case Status::kSuccess:
return GNCStatusSuccess;
case Status::kError:
return GNCStatusError;
case Status::kOutOfOrderApiCall:
return GNCStatusOutOfOrderApiCall;
case Status::kAlreadyHaveActiveStrategy:
return GNCStatusAlreadyHaveActiveStrategy;
case Status::kAlreadyAdvertising:
return GNCStatusAlreadyAdvertising;
case Status::kAlreadyDiscovering:
return GNCStatusAlreadyDiscovering;
case Status::kEndpointIoError:
return GNCStatusEndpointIoError;
case Status::kEndpointUnknown:
return GNCStatusEndpointUnknown;
case Status::kConnectionRejected:
return GNCStatusConnectionRejected;
case Status::kAlreadyConnectedToEndpoint:
return GNCStatusAlreadyConnectedToEndpoint;
case Status::kNotConnectedToEndpoint:
return GNCStatusNotConnectedToEndpoint;
case Status::kBluetoothError:
return GNCStatusBluetoothError;
case Status::kBleError:
return GNCStatusBleError;
case Status::kWifiLanError:
return GNCStatusWifiLanError;
case Status::kPayloadUnknown:
return GNCStatusPayloadUnknown;
}
}
@interface GNCCoreAdapter () {
std::unique_ptr<Core> _core;
std::unique_ptr<ServiceControllerRouter> _serviceControllerRouter;
}
@end
@implementation GNCCoreAdapter
+ (GNCCoreAdapter *)shared {
static dispatch_once_t onceToken;
static GNCCoreAdapter *shared = nil;
dispatch_once(&onceToken, ^{
shared = [[GNCCoreAdapter alloc] init];
});
return shared;
}
- (instancetype)init {
self = [super init];
if (self) {
_serviceControllerRouter = std::make_unique<ServiceControllerRouter>();
_core = std::make_unique<Core>(_serviceControllerRouter.get());
}
return self;
}
- (void)dealloc {
// Make sure Core is deleted before ServiceControllerRouter.
_core.reset();
_serviceControllerRouter.reset();
}
- (void)startAdvertisingAsService:(NSString *)serviceID
endpointInfo:(NSData *)endpointInfo
options:(GNCAdvertisingOptions *)advertisingOptions
delegate:(id<GNCConnectionDelegate>)delegate
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string service_id = [serviceID cStringUsingEncoding:[NSString defaultCStringEncoding]];
AdvertisingOptions advertising_options = [advertisingOptions toCpp];
ConnectionListener listener;
listener.initiated_cb = ^(const std::string &endpoint_id, const ConnectionResponseInfo &info) {
NSString *endpointID = @(endpoint_id.c_str());
NSData *endpointInfo = [NSData dataWithBytes:info.remote_endpoint_info.data()
length:info.remote_endpoint_info.size()];
NSString *authenticationToken = @(info.authentication_token.c_str());
[delegate connectedToEndpoint:endpointID
withEndpointInfo:endpointInfo
authenticationToken:authenticationToken];
};
listener.accepted_cb = ^(const std::string &endpoint_id) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate acceptedConnectionToEndpoint:endpointID];
};
listener.rejected_cb = ^(const std::string &endpoint_id, Status status) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate rejectedConnectionToEndpoint:endpointID withStatus:GNCStatusFromCppStatus(status)];
};
listener.disconnected_cb = ^(const std::string &endpoint_id) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate disconnectedFromEndpoint:endpointID];
};
ConnectionRequestInfo connection_request_info;
connection_request_info.endpoint_info =
ByteArray((const char *)endpointInfo.bytes, endpointInfo.length);
connection_request_info.listener = std::move(listener);
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->StartAdvertising(service_id, advertising_options, connection_request_info, result);
}
- (void)stopAdvertisingWithCompletionHandler:(void (^)(NSError *error))completionHandler {
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->StopAdvertising(result);
}
- (void)startDiscoveryAsService:(NSString *)serviceID
options:(GNCDiscoveryOptions *)discoveryOptions
delegate:(id<GNCDiscoveryDelegate>)delegate
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string service_id = [serviceID cStringUsingEncoding:[NSString defaultCStringEncoding]];
DiscoveryOptions discovery_options = [discoveryOptions toCpp];
DiscoveryListener listener;
listener.endpoint_found_cb = ^(const std::string &endpoint_id, const ByteArray &endpoint_info,
const std::string &service_id) {
NSString *endpointID = @(endpoint_id.c_str());
NSData *info = [NSData dataWithBytes:endpoint_info.data() length:endpoint_info.size()];
[delegate foundEndpoint:endpointID withEndpointInfo:info];
};
listener.endpoint_lost_cb = ^(const std::string &endpoint_id) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate lostEndpoint:endpointID];
};
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->StartDiscovery(service_id, discovery_options, std::move(listener), result);
}
- (void)stopDiscoveryWithCompletionHandler:(void (^)(NSError *error))completionHandler {
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->StopDiscovery(result);
}
- (void)requestConnectionToEndpoint:(NSString *)endpointID
endpointInfo:(NSData *)endpointInfo
options:(GNCConnectionOptions *)connectionOptions
delegate:(id<GNCConnectionDelegate>)delegate
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
ConnectionListener listener;
listener.initiated_cb = ^(const std::string &endpoint_id, const ConnectionResponseInfo &info) {
NSString *endpointID = @(endpoint_id.c_str());
NSData *endpointInfo = [NSData dataWithBytes:info.remote_endpoint_info.data()
length:info.remote_endpoint_info.size()];
NSString *authenticationToken = @(info.authentication_token.c_str());
[delegate connectedToEndpoint:endpointID
withEndpointInfo:endpointInfo
authenticationToken:authenticationToken];
};
listener.accepted_cb = ^(const std::string &endpoint_id) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate acceptedConnectionToEndpoint:endpointID];
};
listener.rejected_cb = ^(const std::string &endpoint_id, Status status) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate rejectedConnectionToEndpoint:endpointID withStatus:GNCStatusFromCppStatus(status)];
};
listener.disconnected_cb = ^(const std::string &endpoint_id) {
NSString *endpointID = @(endpoint_id.c_str());
[delegate disconnectedFromEndpoint:endpointID];
};
ConnectionRequestInfo connection_request_info;
connection_request_info.endpoint_info =
ByteArray((const char *)endpointInfo.bytes, endpointInfo.length);
connection_request_info.listener = std::move(listener);
ConnectionOptions connection_options = [connectionOptions toCpp];
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->RequestConnection(endpoint_id, connection_request_info, connection_options, result);
}
- (void)acceptConnectionRequestFromEndpoint:(NSString *)endpointID
delegate:(id<GNCPayloadDelegate>)delegate
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
PayloadListener listener;
listener.payload_cb = ^(const std::string &endpoint_id, Payload payload) {
NSString *endpointID = @(endpoint_id.c_str());
GNCPayload *gncPayload = [GNCPayload fromCpp:std::move(payload)];
[delegate receivedPayload:gncPayload fromEndpoint:endpointID];
};
listener.payload_progress_cb =
^(const std::string &endpoint_id, const PayloadProgressInfo &info) {
NSString *endpointID = @(endpoint_id.c_str());
GNCPayloadStatus status;
switch (info.status) {
case PayloadProgressInfo::Status::kSuccess:
status = GNCPayloadStatusSuccess;
break;
case PayloadProgressInfo::Status::kFailure:
status = GNCPayloadStatusFailure;
break;
case PayloadProgressInfo::Status::kInProgress:
status = GNCPayloadStatusInProgress;
break;
case PayloadProgressInfo::Status::kCanceled:
status = GNCPayloadStatusCanceled;
break;
}
[delegate receivedProgressUpdateForPayload:info.payload_id
withStatus:status
fromEndpoint:endpointID
bytesTransfered:info.bytes_transferred
totalBytes:info.total_bytes];
};
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->AcceptConnection(endpoint_id, std::move(listener), result);
}
- (void)rejectConnectionRequestFromEndpoint:(NSString *)endpointID
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->RejectConnection(endpoint_id, result);
}
- (void)sendPayload:(GNCPayload *)payload
toEndpoints:(NSArray<NSString *> *)endpointIDs
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::vector<std::string> endpoint_ids;
endpoint_ids.reserve([endpointIDs count]);
for (NSString *endpointID in endpointIDs) {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
endpoint_ids.push_back(endpoint_id);
}
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->SendPayload(endpoint_ids, [payload toCpp], result);
}
- (void)cancelPayload:(int64_t)payloadID
withCompletionHandler:(void (^)(NSError *error))completionHandler {
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->CancelPayload(payloadID, result);
}
- (void)disconnectFromEndpoint:(NSString *)endpointID
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->DisconnectFromEndpoint(endpoint_id, result);
}
- (void)stopAllEndpointsWithCompletionHandler:(void (^)(NSError *error))completionHandler {
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->StopAllEndpoints(result);
}
- (void)initiateBandwidthUpgrade:(NSString *)endpointID
withCompletionHandler:(void (^)(NSError *error))completionHandler {
std::string endpoint_id = [endpointID cStringUsingEncoding:[NSString defaultCStringEncoding]];
ResultListener result;
result.result_cb = ^(Status status) {
NSError *err = NSErrorFromCppStatus(status);
if (completionHandler) {
completionHandler(err);
}
};
_core->InitiateBandwidthUpgrade(endpoint_id, result);
}
- (NSString *)localEndpointID {
std::string endpoint_id = _core->GetLocalEndpointId();
return @(endpoint_id.c_str());
}
@end
@@ -0,0 +1,35 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCDiscoveryOptions.h"
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class DiscoveryOptions;
}
} // namespace nearby
} // namespace location
#endif
@interface GNCDiscoveryOptions (CppConversions)
#ifdef __cplusplus
- (location::nearby::connections::DiscoveryOptions)toCpp;
#endif
@end
@@ -0,0 +1,35 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCDiscoveryOptions.h"
#import <Foundation/Foundation.h>
#include "connections/discovery_options.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCDiscoveryOptions+CppConversions.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCStrategy+Internal.h"
using ::location::nearby::connections::CppStrategyFromGNCStrategy;
using ::location::nearby::connections::DiscoveryOptions;
@implementation GNCDiscoveryOptions (CppConversions)
- (DiscoveryOptions)toCpp {
DiscoveryOptions discovery_options;
discovery_options.strategy = CppStrategyFromGNCStrategy(self.strategy);
return discovery_options;
}
@end
@@ -0,0 +1,31 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCDiscoveryOptions.h"
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCStrategy.h"
@implementation GNCDiscoveryOptions
- (instancetype)initWithStrategy:(GNCStrategy)strategy {
self = [super init];
if (self) {
_strategy = strategy;
}
return self;
}
@end
@@ -0,0 +1,26 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class Status;
NSError *NSErrorFromCppStatus(Status status);
} // namespace connections
} // namespace nearby
} // namespace location
#endif
@@ -0,0 +1,72 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCError.h"
#import <Foundation/Foundation.h>
#include "connections/status.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCError+Internal.h"
extern NSErrorDomain const GNCErrorDomain = @"com.google.nearby.connections.error";
namespace location {
namespace nearby {
namespace connections {
NSError *NSErrorFromCppStatus(Status status) {
switch (status.value) {
case Status::kSuccess:
return nil;
case Status::kError:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorUnknown userInfo:nil];
case Status::kOutOfOrderApiCall:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorOutOfOrderApiCall userInfo:nil];
case Status::kAlreadyHaveActiveStrategy:
return [NSError errorWithDomain:GNCErrorDomain
code:GNCErrorAlreadyHaveActiveStrategy
userInfo:nil];
case Status::kAlreadyAdvertising:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorAlreadyAdvertising userInfo:nil];
case Status::kAlreadyDiscovering:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorAlreadyDiscovering userInfo:nil];
case Status::kEndpointIoError:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorEndpointIoError userInfo:nil];
case Status::kEndpointUnknown:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorEndpointUnknown userInfo:nil];
case Status::kConnectionRejected:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorConnectionRejected userInfo:nil];
case Status::kAlreadyConnectedToEndpoint:
return [NSError errorWithDomain:GNCErrorDomain
code:GNCErrorAlreadyConnectedToEndpoint
userInfo:nil];
case Status::kNotConnectedToEndpoint:
return [NSError errorWithDomain:GNCErrorDomain
code:GNCErrorNotConnectedToEndpoint
userInfo:nil];
case Status::kBluetoothError:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorBluetoothError userInfo:nil];
case Status::kBleError:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorBleError userInfo:nil];
case Status::kWifiLanError:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorWifiLanError userInfo:nil];
case Status::kPayloadUnknown:
return [NSError errorWithDomain:GNCErrorDomain code:GNCErrorPayloadUnknown userInfo:nil];
}
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,26 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#ifdef __cplusplus
namespace location {
namespace nearby {
class Exception;
namespace connections {
NSError *NSErrorFromCppException(Exception exception);
} // namespace connections
} // namespace nearby
} // namespace location
#endif
@@ -0,0 +1,57 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCException.h"
#import <Foundation/Foundation.h>
// TODO(b/239758418): Change this to the non-internal version when available.
#include "internal/platform/exception.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCException+Internal.h"
extern NSErrorDomain const GNCExceptionDomain = @"com.google.nearby.connections.exception";
namespace location {
namespace nearby {
namespace connections {
NSError *NSErrorFromCppException(Exception exception) {
switch (exception.value) {
case Exception::kSuccess:
return nil;
case Exception::kFailed:
return [NSError errorWithDomain:GNCExceptionDomain code:GNCExceptionUnknown userInfo:nil];
case Exception::kIo:
return [NSError errorWithDomain:GNCExceptionDomain code:GNCExceptionIO userInfo:nil];
case Exception::kInterrupted:
return [NSError errorWithDomain:GNCExceptionDomain code:GNCExceptionInterrupted userInfo:nil];
case Exception::kInvalidProtocolBuffer:
return [NSError errorWithDomain:GNCExceptionDomain
code:GNCExceptionInvalidProtocolBuffer
userInfo:nil];
case Exception::kExecution:
return [NSError errorWithDomain:GNCExceptionDomain code:GNCExceptionExecution userInfo:nil];
case Exception::kTimeout:
return [NSError errorWithDomain:GNCExceptionDomain code:GNCExceptionTimeout userInfo:nil];
case Exception::kIllegalCharacters:
return [NSError errorWithDomain:GNCExceptionDomain
code:GNCExceptionIllegalCharacters
userInfo:nil];
}
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,36 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#ifdef __cplusplus
namespace location {
namespace nearby {
class InputStream;
}
} // namespace location
#endif
@interface GNCInputStream : NSInputStream <NSStreamDelegate>
- (nonnull instancetype)initWithData:(nonnull NSData *)data NS_UNAVAILABLE;
- (nonnull instancetype)initWithURL:(nonnull NSURL *)url NS_UNAVAILABLE;
#ifdef __cplusplus
- (nonnull instancetype)initWithCppInputStream:(nonnull location::nearby::InputStream *)stream
NS_DESIGNATED_INITIALIZER;
#endif
@end
@@ -0,0 +1,124 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCInputStream.h"
#import <Foundation/Foundation.h>
#include <algorithm>
// TODO(b/239758418): Change this to the non-internal version when available.
#include "internal/platform/input_stream.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCException+Internal.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCException.h"
using ::location::nearby::ByteArray;
using ::location::nearby::ExceptionOr;
using ::location::nearby::InputStream;
using ::location::nearby::connections::NSErrorFromCppException;
@implementation GNCInputStream {
NSStreamStatus _streamStatus;
NSError *_streamError;
id<NSStreamDelegate> _delegate;
InputStream *_stream;
}
- (instancetype)initWithCppInputStream:(InputStream *)stream {
// Init with empty data because init is not a designated initializer.
self = [super initWithData:[[NSData alloc] init]];
if (self) {
_streamStatus = NSStreamStatusNotOpen;
_delegate = self;
_stream = stream;
}
return self;
}
- (BOOL)hasBytesAvailable {
return _streamStatus == NSStreamStatusOpen;
}
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)maxLen {
ExceptionOr<ByteArray> readResult = _stream->Read(maxLen);
if (!readResult.ok()) {
_streamError = NSErrorFromCppException(readResult.GetException());
_streamStatus = NSStreamStatusError;
return -1;
}
ByteArray byteArray = readResult.GetResult();
if (byteArray.size() == 0) {
_streamStatus = NSStreamStatusAtEnd;
return 0;
}
memcpy(buffer, byteArray.data(), std::min(maxLen, byteArray.size()));
return byteArray.size();
}
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)length {
return NO;
}
- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode {
}
- (void)removeFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode {
}
- (void)open {
_streamStatus = NSStreamStatusOpen;
}
- (void)close {
_streamStatus = NSStreamStatusClosed;
_stream->Close();
}
- (NSStreamStatus)streamStatus {
return _streamStatus;
}
- (NSError *)streamError {
return _streamError;
}
- (id<NSStreamDelegate>)delegate {
return _delegate;
}
- (void)setDelegate:(id<NSStreamDelegate>)delegate {
// By default, a stream is its own delegate, and subclasses of NSInputStream and NSOutputStream
// must maintain this contract. Since we override this method in our subclass, we must
// restore the receiver as its own delegate when passed nil.
if (delegate) {
_delegate = delegate;
} else {
_delegate = self;
}
}
- (id)propertyForKey:(NSStreamPropertyKey)key {
return nil;
}
- (BOOL)setProperty:(id)property forKey:(NSStreamPropertyKey)key {
return NO;
}
@end
@@ -0,0 +1,39 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCPayload.h"
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class Payload;
}
} // namespace nearby
} // namespace location
#endif
@interface GNCPayload (CppConversions)
#ifdef __cplusplus
+ (nonnull GNCPayload *)fromCpp:(location::nearby::connections::Payload)payload;
#endif
#ifdef __cplusplus
- (location::nearby::connections::Payload)toCpp;
#endif
@end
@@ -0,0 +1,98 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCPayload.h"
#import <Foundation/Foundation.h>
#include <string>
#include "connections/payload.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/CPPInputStreamBinding.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCInputStream.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCPayload+CppConversions.h"
using ::location::nearby::ByteArray;
using ::location::nearby::InputFile;
using ::location::nearby::InputStream;
using ::location::nearby::connections::Payload;
@implementation GNCPayload (CppConversions)
+ (GNCPayload *)fromCpp:(Payload)payload {
int64_t payloadId = payload.GetId();
switch (payload.GetType()) {
case location::nearby::connections::PayloadType::kBytes: {
ByteArray bytes = payload.AsBytes();
NSData *payloadData = [NSData dataWithBytes:bytes.data() length:bytes.size()];
return [[GNCBytesPayload alloc] initWithData:payloadData identifier:payloadId];
}
case location::nearby::connections::PayloadType::kFile: {
InputFile *inputFile = payload.AsFile();
NSString *filePath = @(inputFile->GetFilePath().c_str());
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
return [[GNCFilePayload alloc] initWithFileURL:fileURL identifier:payloadId];
}
case location::nearby::connections::PayloadType::kStream: {
GNCInputStream *stream = [[GNCInputStream alloc] initWithCppInputStream:payload.AsStream()];
return [[GNCStreamPayload alloc] initWithStream:stream identifier:payloadId];
}
case location::nearby::connections::PayloadType::kUnknown:
return nil;
}
}
- (Payload)toCpp {
return Payload();
}
@end
@implementation GNCBytesPayload (CppConversions)
- (Payload)toCpp {
return Payload(self.identifier, ByteArray((const char *)self.data.bytes, self.data.length));
}
@end
@implementation GNCStreamPayload (CppConversions)
- (Payload)toCpp {
// GNCStreamPayload will most likely be destroyed almost immediately, so a weak self would be
// useless and a strong self will cause a retain cycle. This is why we are keeping a weak
// reference of the stream instead. The input stream should be kept alive by a strong reference
// on the user end.
__weak NSInputStream *stream = self.stream;
return Payload(self.identifier, [stream]() -> InputStream & {
return [CPPInputStreamBinding getRefFromStream:stream];
});
}
@end
@implementation GNCFilePayload (CppConversions)
- (Payload)toCpp {
NSNumber *fileSize;
BOOL result = [self.fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil];
if (!result) {
fileSize = [NSNumber numberWithInt:-1];
}
std::string path = [self.fileURL.path cStringUsingEncoding:[NSString defaultCStringEncoding]];
return Payload(self.identifier, InputFile(path, fileSize.longLongValue));
}
@end
@@ -0,0 +1,86 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCPayload.h"
#import <Foundation/Foundation.h>
#include <string>
#include "connections/payload.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/CPPInputStreamBinding.h"
using ::location::nearby::connections::Payload;
@implementation GNCPayload
- (instancetype)initWithIdentifier:(int64_t)identifier {
self = [super init];
if (self) {
_identifier = identifier;
}
return self;
}
@end
@implementation GNCBytesPayload
- (instancetype)initWithData:(NSData *)data identifier:(int64_t)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
_data = [data copy];
}
return self;
}
- (instancetype)initWithData:(NSData *)data {
return [self initWithData:data identifier:Payload::GenerateId()];
}
@end
@implementation GNCStreamPayload
- (instancetype)initWithStream:(NSInputStream *)stream identifier:(int64_t)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
_stream = stream;
[CPPInputStreamBinding bindToStream:stream];
}
return self;
}
- (instancetype)initWithStream:(NSInputStream *)stream {
return [self initWithStream:stream identifier:Payload::GenerateId()];
}
@end
@implementation GNCFilePayload
- (instancetype)initWithFileURL:(NSURL *)fileURL identifier:(int64_t)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
_fileURL = [fileURL copy];
}
return self;
}
- (instancetype)initWithFileURL:(NSURL *)fileURL {
return [self initWithFileURL:fileURL identifier:Payload::GenerateId()];
}
@end
@@ -0,0 +1,28 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, GNCStrategy);
#ifdef __cplusplus
namespace location {
namespace nearby {
namespace connections {
class Strategy;
Strategy CppStrategyFromGNCStrategy(GNCStrategy strategy);
} // namespace connections
} // namespace nearby
} // namespace location
#endif
@@ -0,0 +1,40 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "connections/clients/swift/NearbyCoreAdapter/Sources/Public/NearbyCoreAdapter/GNCStrategy.h"
#import <Foundation/Foundation.h>
#include "connections/strategy.h"
#import "connections/clients/swift/NearbyCoreAdapter/Sources/GNCStrategy+Internal.h"
namespace location {
namespace nearby {
namespace connections {
Strategy CppStrategyFromGNCStrategy(GNCStrategy strategy) {
switch (strategy) {
case GNCStrategyCluster:
return Strategy::kP2pCluster;
case GNCStrategyStar:
return Strategy::kP2pStar;
case GNCStrategyPointToPoint:
return Strategy::kP2pPointToPoint;
}
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,44 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, GNCStrategy);
// TODO(b/239609583): Current sdk only exposes `strategy`, but we should add full support.
/**
* A @c GNCAdvertisingOptions object represents the configuration for local endpoint advertisement.
*/
@interface GNCAdvertisingOptions : NSObject
/**
* The connection strategy.
*/
@property(nonatomic, readonly) GNCStrategy strategy;
/**
* @remark init is not an available initializer.
*/
- (nonnull instancetype)init NS_UNAVAILABLE;
/**
* Creates an advertising options object.
*
* @param strategy The connection strategy.
*
* @return The initialized options object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithStrategy:(GNCStrategy)strategy NS_DESIGNATED_INITIALIZER;
@end
@@ -0,0 +1,95 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* Indicates the status of a connection.
*/
typedef NS_ENUM(NSInteger, GNCStatus) {
GNCStatusSuccess,
GNCStatusError,
GNCStatusOutOfOrderApiCall,
GNCStatusAlreadyHaveActiveStrategy,
GNCStatusAlreadyAdvertising,
GNCStatusAlreadyDiscovering,
GNCStatusEndpointIoError,
GNCStatusEndpointUnknown,
GNCStatusConnectionRejected,
GNCStatusAlreadyConnectedToEndpoint,
GNCStatusNotConnectedToEndpoint,
GNCStatusBluetoothError,
GNCStatusBleError,
GNCStatusWifiLanError,
GNCStatusPayloadUnknown,
};
/**
* The @c GNCConnectionDelegate protocol defines methods that a delegate can implement to handle
* connection-related events.
*/
@protocol GNCConnectionDelegate
/**
* A basic encrypted channel has been created between you and the endpoint. Both sides are now
* asked if they wish to accept or reject the connection before any data can be sent over this
* channel.
*
* This is your chance, before you accept the connection, to confirm that you connected to the
* correct device. Both devices are given an identical token; it's up to you to decide how to
* verify it before proceeding. Typically this involves showing the token on both devices and
* having the users manually compare and confirm; however, this is only required if you desire a
* secure connection between the devices.
*
* Whichever route you decide to take (including not authenticating the other device), call
* GNCCoreAdapter::acceptConnectionRequestFromEndpoint:delegate: when you're ready to talk, or
* GNCCoreAdapter::rejectConnectionRequestFromEndpoint:withCompletionHandler: to close the
* connection.
*
* @param endpointID The identifier for the remote endpoint.
* @param info Other relevant information about the connection.
* @param authenticationToken The token to be verified.
*/
- (void)connectedToEndpoint:(nonnull NSString *)endpointID
withEndpointInfo:(nonnull NSData *)info
authenticationToken:(nonnull NSString *)authenticationToken;
/**
* Called after both sides have accepted the connection. Both sides may now send Payloads to each
* other.
*
* @param endpointID The identifier for the remote endpoint.
*/
- (void)acceptedConnectionToEndpoint:(nonnull NSString *)endpointID;
/**
* Called when either side rejected the connection. Payloads can not be exchaged. Call
* GNCCoreAdapter::disconnectFromEndpoint:withCompletionHandler: to terminate the connection.
*
* @param endpointID The identifier for the remote endpoint.
* @param status The reason for rejection.
*/
- (void)rejectedConnectionToEndpoint:(nonnull NSString *)endpointID withStatus:(GNCStatus)status;
/**
* Called when a remote endpoint is disconnected or has become unreachable. At this point service
* (re-)discovery may start again.
*
* @param endpointID The identifier for the remote endpoint.
*/
- (void)disconnectedFromEndpoint:(nonnull NSString *)endpointID;
// TODO(b/239832442): Add OnBandwidthChanged(const std::string &endpoint_id, Medium medium).
@end
@@ -0,0 +1,23 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
// TODO(b/239610255): Current sdk doesn't expose anything, but we should add full support.
/**
* A @c GNCConnectionOptions object represents the configuration for connecting to remote endpoints.
*/
@interface GNCConnectionOptions : NSObject
@end
@@ -0,0 +1,194 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
@class GNCAdvertisingOptions;
@class GNCConnectionOptions;
@class GNCDiscoveryOptions;
@class GNCPayload;
@protocol GNCConnectionDelegate;
@protocol GNCDiscoveryDelegate;
@protocol GNCPayloadDelegate;
/**
* This class defines the API of the Nearby Connections Core library.
*/
@interface GNCCoreAdapter : NSObject
/**
* A @c GNCCoreAdapter singleton.
*/
@property(nonnull, nonatomic, class, readonly) GNCCoreAdapter *shared;
/**
* Starts advertising an endpoint for a local app.
*
* @param serviceID 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.
* @param endpointInfo Arbitrary bytes of additional data that can be read and used by remote
* endpoints. A good default is a utf-8 encoded string to represent a local
* endpoint name.
* @param advertisingOptions The options for advertising.
* @param delegate A delegate to handle notifications about connection events.
* @param completionHandler Access the status of the operation when available.
*/
- (void)startAdvertisingAsService:(nonnull NSString *)serviceID
endpointInfo:(nonnull NSData *)endpointInfo
options:(nonnull GNCAdvertisingOptions *)advertisingOptions
delegate:(nullable id<GNCConnectionDelegate>)delegate
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Stops advertising a local endpoint. Should be called after calling
* startAdvertisingAsService:endpointInfo:options:delegate:withCompletionHandler:, 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.
*
* @param completionHandler Access the status of the operation when available.
*/
- (void)stopAdvertisingWithCompletionHandler:
(nullable void (^)(NSError *_Nonnull error))completionHandler;
/**
* Starts discovery for remote endpoints with the specified service ID.
*
* @param serviceID The ID for the service to be discovered, as specified in the corresponding call
* to start advertising.
* @param discoveryOptions The options for discovery.
* @param delegate A delegate to handle notifications about endpoint discovery events.
* @param completionHandler Access the status of the operation when available.
*/
- (void)startDiscoveryAsService:(nonnull NSString *)serviceID
options:(nonnull GNCDiscoveryOptions *)discoveryOptions
delegate:(nullable id<GNCDiscoveryDelegate>)delegate
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Stops discovery for remote endpoints, after a previous call to
* startDiscoveryAsService:options:delegate:withCompletionHandler:, when the client no longer needs
* to discover endpoints or goes inactive. Payloads can still be sent to connected endpoints after
* discovery ends.
*
* @param completionHandler Access the status of the operation when available.
*/
- (void)stopDiscoveryWithCompletionHandler:
(nullable void (^)(NSError *_Nonnull error))completionHandler;
/**
* Sends a request to connect to a remote endpoint.
*
* @param endpointID The identifier for the remote endpoint to which a connection request will be
* sent. Should match the endpointID provided by the
* GNCDiscoveryDelegate::foundEndpoint:withEndpointInfo: delegate method.
* @param endpointInfo Arbitrary bytes of additional data that can be read and used by remote
* endpoints. A good default is a utf-8 encoded string to represent a local
* endpoint name.
* @param connectionOptions The options for connecting.
* @param delegate A delegate to handle notifications about connection events.
* @param completionHandler Access the status of the operation when available.
*/
- (void)requestConnectionToEndpoint:(nonnull NSString *)endpointID
endpointInfo:(nonnull NSData *)endpointInfo
options:(nonnull GNCConnectionOptions *)connectionOptions
delegate:(nullable id<GNCConnectionDelegate>)delegate
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Accepts a connection to a remote endpoint. This method must be called before payloads can be
* exchanged with the remote endpoint.
* @param endpointID The identifier for the remote endpoint. Should match the endpointID provided by
* the
* GNCConnectionDelegate::connectedToEndpoint:withEndpointInfo:authenticationToken: delegate method.
* @param delegate A delegate to handle notifications about incoming payload events.
* @param completionHandler Access the status of the operation when available.
*/
- (void)acceptConnectionRequestFromEndpoint:(nonnull NSString *)endpointID
delegate:(nullable id<GNCPayloadDelegate>)delegate
withCompletionHandler:
(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Rejects a connection to a remote endpoint.
*
* @param endpointID The identifier for the remote endpoint. Should match the endpointID provided by
* the
* GNCConnectionDelegate::connectedToEndpoint:withEndpointInfo:authenticationToken: delegate method.
* @param completionHandler Access the status of the operation when available.
*/
- (void)rejectConnectionRequestFromEndpoint:(nonnull NSString *)endpointID
withCompletionHandler:
(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Sends a payload to a list of remote endpoints. Payloads can only be sent to remote endpoints once
* a notice of connection acceptance has been delivered via
* GNCConnectionDelegate::acceptedConnectionToEndpoint:.
*
* @param payload The Payload to be sent.
* @param endpointIDs List of remote endpoint identifiers to which the payload should be sent.
* @param completionHandler Access the status of the operation when available.
*/
- (void)sendPayload:(nonnull GNCPayload *)payload
toEndpoints:(nonnull NSArray<NSString *> *)endpointIDs
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Cancels a payload currently in-flight to or from remote endpoint(s).
*
* @param payloadID The identifier for the Payload to be canceled.
* @param completionHandler Access the status of the operation when available.
*/
- (void)cancelPayload:(int64_t)payloadID
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Disconnects from a remote endpoint. Payloads can no longer be sent to or received from the
* endpoint after this method is called.
*
* @param endpointID The identifier for the remote endpoint to disconnect from.
* @param completionHandler Access the status of the operation when available.
*/
- (void)disconnectFromEndpoint:(nonnull NSString *)endpointID
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Disconnects from, and removes all traces of, all connected and/or discovered endpoints. This call
* is expected to be preceded by a call to stop advertising or discovery as needed. After calling
* stopAllEndpointsWithCompletionHandler:, no further operations with remote endpoints will be
* possible until a new call to start advertising or discovery.
*
* @param completionHandler Access the status of the operation when available.
*/
- (void)stopAllEndpointsWithCompletionHandler:
(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* Sends a request to initiate connection bandwidth upgrade.
*
* @param endpointID The identifier for the remote endpoint which will be switching to a higher
* connection data rate and possibly different wireless protocol.
* @param completionHandler Access the status of the operation when available.
*/
- (void)initiateBandwidthUpgrade:(nonnull NSString *)endpointID
withCompletionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
/**
* The local endpoint indentifier generated by Nearby Connections.
*/
@property(nonnull, nonatomic, readonly, copy) NSString *localEndpointID;
@end
@@ -0,0 +1,38 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* The @c GNCDiscoveryDelegate protocol defines methods that a delegate can implement to handle
* discovery-related events.
*/
@protocol GNCDiscoveryDelegate
/**
* Called when a remote endpoint is discovered.
*
* @param endpointID The ID of the remote endpoint that was discovered.
* @param info The info of the remote endpoint represented by bytes.
*/
- (void)foundEndpoint:(nonnull NSString *)endpointID withEndpointInfo:(nonnull NSData *)info;
/**
* Called when a remote endpoint is no longer discoverable.
*
* @param endpointID The ID of the remote endpoint that was lost.
*/
- (void)lostEndpoint:(nonnull NSString *)endpointID;
@end
@@ -0,0 +1,44 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, GNCStrategy);
// TODO(b/239610253): Current sdk only exposes `strategy`, but we should add full support.
/**
* A @c GNCDiscoveryOptions object represents the configuration for remote endpoint discovery.
*/
@interface GNCDiscoveryOptions : NSObject
/**
* The connection strategy.
*/
@property(nonatomic, readonly) GNCStrategy strategy;
/**
* @remark init is not an available initializer.
*/
- (nonnull instancetype)init NS_UNAVAILABLE;
/**
* Creates a discovery options object.
*
* @param strategy The connection strategy.
*
* @return The initialized options object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithStrategy:(GNCStrategy)strategy NS_DESIGNATED_INITIALIZER;
@end
@@ -0,0 +1,40 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* The domain for @c NSErrors raised by Nearby Connections.
*/
extern NSErrorDomain const GNCErrorDomain;
/**
* Nearby Connections error codes.
*/
typedef NS_ERROR_ENUM(GNCErrorDomain, GNCErrorCode){
GNCErrorUnknown,
GNCErrorOutOfOrderApiCall,
GNCErrorAlreadyHaveActiveStrategy,
GNCErrorAlreadyAdvertising,
GNCErrorAlreadyDiscovering,
GNCErrorEndpointIoError,
GNCErrorEndpointUnknown,
GNCErrorConnectionRejected,
GNCErrorAlreadyConnectedToEndpoint,
GNCErrorNotConnectedToEndpoint,
GNCErrorBluetoothError,
GNCErrorBleError,
GNCErrorWifiLanError,
GNCErrorPayloadUnknown,
} NS_SWIFT_NAME(NearbyError);
@@ -0,0 +1,30 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* The domain for @c NSErrors raised by Nearby Connections as exceptions.
*/
extern NSErrorDomain const GNCExceptionDomain;
/**
* Nearby Connections exception codes.
*/
typedef NS_ERROR_ENUM(GNCExceptionDomain, GNCExceptionCode){
GNCExceptionUnknown, GNCExceptionIO,
GNCExceptionInterrupted, GNCExceptionInvalidProtocolBuffer,
GNCExceptionExecution, GNCExceptionTimeout,
GNCExceptionIllegalCharacters,
} NS_SWIFT_NAME(NearbyException);
@@ -0,0 +1,128 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* A @c GNCPayload object represents the data being sent to or received from a remote device.
*/
@interface GNCPayload : NSObject
/**
* The unique identifier for this payload.
*/
@property(nonatomic, readonly) int64_t identifier;
/**
* @remark init is not an available initializer.
*/
- (nonnull instancetype)init NS_UNAVAILABLE;
@end
/**
* A @c GNCBytesPayload object represents a payload that holds simple bytes.
*/
@interface GNCBytesPayload : GNCPayload
/**
* The byte data for this payload.
*/
@property(nonnull, nonatomic, readonly, copy) NSData *data;
/**
* Creates a bytes payload object with identifier.
*
* @param data An instance containing the message to send.
* @param identifier A unique identifier for the payload.
*
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithData:(nonnull NSData *)data
identifier:(int64_t)identifier NS_DESIGNATED_INITIALIZER;
/**
* Creates a bytes payload object.
*
* @param data An instance containing the message to send.
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithData:(nonnull NSData *)data;
@end
/**
* A @c GNCStreamPayload object represents a payload holds an open stream that can be read from by
* remote endpoints.
*/
@interface GNCStreamPayload : GNCPayload
/**
* The open stream for this payload.
*/
@property(nonnull, nonatomic, readonly) NSInputStream *stream;
/**
* Creates a stream payload object with identifier.
*
* @param stream An input stream instance.
* @param identifier A unique identifier for the payload.
*
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithStream:(nonnull NSInputStream *)stream
identifier:(int64_t)identifier NS_DESIGNATED_INITIALIZER;
/**
* Creates a stream payload object.
*
* @param stream An input stream instance.
*
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithStream:(nonnull NSInputStream *)stream;
@end
/**
* A @c GNCFilePayload object represents a payload that holds a file.
*/
@interface GNCFilePayload : GNCPayload
/**
* The URL of the file associated with this payload.
*/
@property(nonnull, nonatomic, readonly, copy) NSURL *fileURL;
/**
* Creates a file payload object with identifier.
*
* @param fileURL A file URL.
* @param identifier A unique identifier for the payload.
*
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithFileURL:(nonnull NSURL *)fileURL
identifier:(int64_t)identifier NS_DESIGNATED_INITIALIZER;
/**
* Creates a file payload object.
*
* @param fileURL A file URL.
*
* @return The initialized payload object, or nil if an error occurs.
*/
- (nonnull instancetype)initWithFileURL:(nonnull NSURL *)fileURL;
@end
@@ -0,0 +1,60 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
@class GNCPayload;
/**
* Indicates the status of a payload transfer.
*/
typedef NS_ENUM(NSInteger, GNCPayloadStatus) {
GNCPayloadStatusSuccess,
GNCPayloadStatusFailure,
GNCPayloadStatusInProgress,
GNCPayloadStatusCanceled,
};
/**
* The @c GNCPayloadDelegate protocol defines methods that a delegate can implement to handle
* payload-related events.
*/
@protocol GNCPayloadDelegate
/**
* Called when a payload is received from a remote endpoint. Depending on the type of the payload,
* all of the data may or may not have been received at the time of this call.
*
* @param payload The Payload object received.
* @param endpointID The identifier for the remote endpoint that sent the payload.
*/
- (void)receivedPayload:(nonnull GNCPayload *)payload fromEndpoint:(nonnull NSString *)endpointID;
/**
* Called with progress information about an active payload transfer, either incoming or outgoing.
*
* @param payloadID The identifier the sent or received payload.
* @param status The status of the payload transfer.
* @param endpointID The identifier for the remote endpoint that is sending or receiving this
* payload.
* @param bytesTransfered The number of bytes transfered so far.
* @param totalBytes The total bytes of the transfer.
*/
- (void)receivedProgressUpdateForPayload:(int64_t)payloadID
withStatus:(GNCPayloadStatus)status
fromEndpoint:(nonnull NSString *)endpointID
bytesTransfered:(int64_t)bytesTransfered
totalBytes:(int64_t)totalBytes;
@end
@@ -0,0 +1,24 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
/**
* Indicates the strategy or advertisement or discovery.
*/
typedef NS_ENUM(NSInteger, GNCStrategy) {
GNCStrategyCluster, // M-to-N
GNCStrategyStar, // 1-to-N
GNCStrategyPointToPoint, // 1-to-1
} NS_SWIFT_NAME(Strategy);
@@ -0,0 +1,24 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "GNCAdvertisingOptions.h"
#import "GNCConnectionDelegate.h"
#import "GNCConnectionOptions.h"
#import "GNCCoreAdapter.h"
#import "GNCDiscoveryDelegate.h"
#import "GNCDiscoveryOptions.h"
#import "GNCError.h"
#import "GNCPayload.h"
#import "GNCPayloadDelegate.h"
#import "GNCStrategy.h"
@@ -0,0 +1,8 @@
import NearbyCoreAdapter
import XCTest
class BuildTests: XCTestCase {
func testBuild() {
// At least one test case is needed.
}
}
+3
View File
@@ -11,6 +11,9 @@
# 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.
# TODO(b/240046236): Refactor this into a new `cpp` package.
load("//third_party/lexan/build_defs:lexan.bzl", "lexan")
load(
"expand_version_template.bzl",
@@ -15,6 +15,7 @@ licenses(["notice"])
package(default_visibility = [
"//connections/clients/ios:__subpackages__",
"//connections/clients/swift:__subpackages__",
"//internal/platform/implementation/ios:__subpackages__",
])