mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Move Server Socket and its dependencies to their own files
PiperOrigin-RevId: 551330682
This commit is contained in:
committed by
Copybara-Service
parent
2145ccce69
commit
a42cdc7346
@@ -570,6 +570,11 @@ let package = Package(
|
||||
"connections/implementation/mediums/webrtc",
|
||||
// This breaks the build, but seems to work fine without it?
|
||||
"internal/platform/medium_environment.cc",
|
||||
// Temporarily ignore BLEv2 source files.
|
||||
// TODO(b/293283024): Stop ignoring these files when BLEv2 migration is complete.
|
||||
"internal/platform/implementation/apple/ble_peripheral.mm",
|
||||
"internal/platform/implementation/apple/ble_server_socket.mm",
|
||||
"internal/platform/implementation/apple/ble_socket.mm",
|
||||
],
|
||||
sources: [
|
||||
"compiled_proto",
|
||||
|
||||
@@ -104,6 +104,36 @@ objc_library(
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "ble_v2",
|
||||
srcs = [
|
||||
"ble_peripheral.mm",
|
||||
"ble_server_socket.mm",
|
||||
"ble_socket.mm",
|
||||
"ble_utils.mm",
|
||||
"utils.mm",
|
||||
],
|
||||
hdrs = [
|
||||
"ble_peripheral.h",
|
||||
"ble_server_socket.h",
|
||||
"ble_socket.h",
|
||||
"ble_utils.h",
|
||||
"utils.h",
|
||||
],
|
||||
# Prevent Objective-C++ headers from being pulled into swift.
|
||||
aspect_hints = ["//tools/build_defs/swift:no_module"],
|
||||
deps = [
|
||||
"//internal/platform:base",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation/apple/Mediums",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "Shared",
|
||||
srcs = [
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Note: File language is detected using heuristics. Many Objective-C++ headers are incorrectly
|
||||
// classified as C++ resulting in invalid linter errors. The use of "NSArray" and other Foundation
|
||||
// classes like "NSData", "NSDictionary" and "NSUUID" are highly weighted for Objective-C and
|
||||
// Objective-C++ scores. Oddly, "#import <Foundation/Foundation.h>" does not contribute any points.
|
||||
// This comment alone should be enough to trick the IDE in to believing this is actually some sort
|
||||
// of Objective-C file. See: cs/google3/devtools/search/lang/recognize_language_classifiers_data
|
||||
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
// Opaque wrapper over a CoreBluetooth peripheral. This can be used to uniquely
|
||||
// identify a peripheral and connect to its GATT server.
|
||||
class BlePeripheral : public api::ble_v2::BlePeripheral {
|
||||
public:
|
||||
explicit BlePeripheral(CBPeripheral *peripheral);
|
||||
~BlePeripheral() override = default;
|
||||
|
||||
// Returns the hardware address of this peripheral.
|
||||
//
|
||||
// For example, "00:11:22:AA:BB:CC".
|
||||
std::string GetAddress() const override;
|
||||
|
||||
// Returns an immutable unique identifier. The identifier does not change when
|
||||
// the peripheral's address is rotated.
|
||||
api::ble_v2::BlePeripheral::UniqueId GetUniqueId() const override;
|
||||
|
||||
private:
|
||||
CBPeripheral *peripheral_;
|
||||
api::ble_v2::BlePeripheral::UniqueId unique_id_;
|
||||
};
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "internal/platform/implementation/apple/ble_peripheral.h"
|
||||
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/prng.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
BlePeripheral::BlePeripheral(CBPeripheral *peripheral)
|
||||
: peripheral_(peripheral), unique_id_(Prng().NextInt64()) {}
|
||||
|
||||
std::string BlePeripheral::GetAddress() const {
|
||||
return peripheral_.identifier.UUIDString.UTF8String;
|
||||
}
|
||||
|
||||
api::ble_v2::BlePeripheral::UniqueId BlePeripheral::GetUniqueId() const { return unique_id_; }
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Note: File language is detected using heuristics. Many Objective-C++ headers are incorrectly
|
||||
// classified as C++ resulting in invalid linter errors. The use of "NSArray" and other Foundation
|
||||
// classes like "NSData", "NSDictionary" and "NSUUID" are highly weighted for Objective-C and
|
||||
// Objective-C++ scores. Oddly, "#import <Foundation/Foundation.h>" does not contribute any points.
|
||||
// This comment alone should be enough to trick the IDE in to believing this is actually some sort
|
||||
// of Objective-C file. See: cs/google3/devtools/search/lang/recognize_language_classifiers_data
|
||||
|
||||
// TODO(b/293336684): Remove this file when shared Weave is complete.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
#import "internal/platform/implementation/apple/ble_socket.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
// A BLE server socket for listening for incoming Weave sockets.
|
||||
class BleServerSocket : public api::ble_v2::BleServerSocket {
|
||||
public:
|
||||
BleServerSocket() = default;
|
||||
~BleServerSocket() override;
|
||||
|
||||
// Wait for an available socket.
|
||||
//
|
||||
// Blocks until either:
|
||||
// - at least one incoming connection request is available, or
|
||||
// - ServerSocket is closed.
|
||||
//
|
||||
// On success, returns connected socket, ready to exchange data or nullptr on
|
||||
// error. Once error is reported, it is permanent, and ServerSocket must be
|
||||
// closed.
|
||||
std::unique_ptr<api::ble_v2::BleSocket> Accept() override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Close the server socket.
|
||||
//
|
||||
// Returns Exception::kIo on error, otherwise Exception::kSuccess.
|
||||
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool Connect(std::unique_ptr<BleSocket> socket) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void SetCloseNotifier(absl::AnyInvocable<void()> notifier)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
Exception DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
mutable absl::Mutex mutex_;
|
||||
absl::CondVar cond_;
|
||||
absl::flat_hash_set<std::unique_ptr<BleSocket>> pending_sockets_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
absl::AnyInvocable<void()> close_notifier_ ABSL_GUARDED_BY(mutex_);
|
||||
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
};
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// TODO(b/293336684): Remove this file when shared Weave is complete.
|
||||
|
||||
#import "internal/platform/implementation/apple/ble_server_socket.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
BleServerSocket::~BleServerSocket() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleSocket> BleServerSocket::Accept() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
while (!closed_ && pending_sockets_.empty()) {
|
||||
cond_.Wait(&mutex_);
|
||||
}
|
||||
if (closed_) return {};
|
||||
|
||||
std::unique_ptr<BleSocket> remote_socket =
|
||||
std::move(pending_sockets_.extract(pending_sockets_.begin()).value());
|
||||
return std::move(remote_socket);
|
||||
}
|
||||
|
||||
bool BleServerSocket::Connect(std::unique_ptr<BleSocket> socket) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (closed_) {
|
||||
return false;
|
||||
}
|
||||
pending_sockets_.insert(std::move(socket));
|
||||
cond_.SignalAll();
|
||||
return !closed_;
|
||||
}
|
||||
|
||||
void BleServerSocket::SetCloseNotifier(absl::AnyInvocable<void()> notifier) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
close_notifier_ = std::move(notifier);
|
||||
}
|
||||
|
||||
Exception BleServerSocket::Close() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return DoClose();
|
||||
}
|
||||
|
||||
Exception BleServerSocket::DoClose() {
|
||||
bool should_notify = !closed_;
|
||||
closed_ = true;
|
||||
if (should_notify) {
|
||||
cond_.SignalAll();
|
||||
if (close_notifier_) {
|
||||
auto notifier = std::move(close_notifier_);
|
||||
mutex_.Unlock();
|
||||
// Notifier may contain calls to public API, and may cause deadlock, if
|
||||
// mutex_ is held during the call.
|
||||
notifier();
|
||||
mutex_.Lock();
|
||||
}
|
||||
}
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,130 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Note: File language is detected using heuristics. Many Objective-C++ headers are incorrectly
|
||||
// classified as C++ resulting in invalid linter errors. The use of "NSArray" and other Foundation
|
||||
// classes like "NSData", "NSDictionary" and "NSUUID" are highly weighted for Objective-C and
|
||||
// Objective-C++ scores. Oddly, "#import <Foundation/Foundation.h>" does not contribute any points.
|
||||
// This comment alone should be enough to trick the IDE in to believing this is actually some sort
|
||||
// of Objective-C file. See: cs/google3/devtools/search/lang/recognize_language_classifiers_data
|
||||
|
||||
// TODO(b/293336684): Remove this file when shared Weave is complete.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
#import "internal/platform/implementation/apple/ble_peripheral.h"
|
||||
|
||||
@class GNCMConnectionHandlers;
|
||||
@protocol GNCMConnection;
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
// A readable stream of bytes.
|
||||
class BleInputStream : public InputStream {
|
||||
public:
|
||||
BleInputStream();
|
||||
~BleInputStream() override;
|
||||
|
||||
// Reads at most `size` bytes from the input stream.
|
||||
//
|
||||
// Returns an empty byte array on end of file, or Exception::kIo on error.
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
|
||||
// Closes the stream preventing further reads.
|
||||
//
|
||||
// Returns Exception::kIo on error, otherwise Exception::kSuccess.
|
||||
Exception Close() override;
|
||||
|
||||
GNCMConnectionHandlers *GetConnectionHandlers() { return connectionHandlers_; }
|
||||
|
||||
private:
|
||||
GNCMConnectionHandlers *connectionHandlers_;
|
||||
NSMutableArray<NSData *> *newDataPackets_;
|
||||
NSMutableData *accumulatedData_;
|
||||
NSCondition *condition_;
|
||||
};
|
||||
|
||||
// A writable stream of bytes.
|
||||
class BleOutputStream : public OutputStream {
|
||||
public:
|
||||
explicit BleOutputStream(id<GNCMConnection> connection)
|
||||
: connection_(connection), condition_([[NSCondition alloc] init]) {}
|
||||
~BleOutputStream() override;
|
||||
|
||||
// Write the provided bytes to the output stream.
|
||||
//
|
||||
// Returns Exception::kIo on error, otherwise Exception::kSuccess.
|
||||
Exception Write(const ByteArray &data) override;
|
||||
|
||||
// no-op
|
||||
//
|
||||
// Always returns Exception::kSuccess.
|
||||
Exception Flush() override;
|
||||
|
||||
// Closes the stream preventing further writes.
|
||||
//
|
||||
// Returns Exception::kIo on error, otherwise Exception::kSuccess.
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
id<GNCMConnection> connection_;
|
||||
NSCondition *condition_;
|
||||
};
|
||||
|
||||
// A BLE Weave socket.
|
||||
class BleSocket : public api::ble_v2::BleSocket {
|
||||
public:
|
||||
BleSocket(id<GNCMConnection> connection, BlePeripheral *peripheral);
|
||||
~BleSocket() override;
|
||||
|
||||
// Returns the InputStream of the BleSocket.
|
||||
// On error, returned stream will report Exception::kIo on any operation.
|
||||
//
|
||||
// The returned object is not owned by the caller, and can be invalidated once
|
||||
// the BleSocket object is destroyed.
|
||||
InputStream &GetInputStream() override { return *input_stream_; }
|
||||
|
||||
// Returns the OutputStream of the BleSocket.
|
||||
// On error, returned stream will report Exception::kIo on any operation.
|
||||
//
|
||||
// The returned object is not owned by the caller, and can be invalidated once
|
||||
// the BleSocket object is destroyed.
|
||||
OutputStream &GetOutputStream() override { return *output_stream_; }
|
||||
|
||||
// Returns Exception::kIo on error, otherwise Exception::kSuccess.
|
||||
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns valid BlePeripheral pointer if there is a connection, and
|
||||
// nullptr otherwise.
|
||||
BlePeripheral *GetRemotePeripheral() override { return peripheral_; }
|
||||
|
||||
bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
void DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
mutable absl::Mutex mutex_;
|
||||
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
std::unique_ptr<BleInputStream> input_stream_;
|
||||
std::unique_ptr<BleOutputStream> output_stream_;
|
||||
BlePeripheral *peripheral_;
|
||||
};
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "internal/platform/implementation/apple/ble_socket.h"
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/Ble/GNCMBleConnection.h"
|
||||
#import "internal/platform/implementation/apple/ble_peripheral.h"
|
||||
#import "internal/platform/implementation/apple/ble_utils.h"
|
||||
#import "internal/platform/implementation/apple/utils.h"
|
||||
|
||||
// TODO(b/293336684): Remove this file when shared Weave is complete.
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
|
||||
#pragma mark - BleInputStream
|
||||
|
||||
BleInputStream::BleInputStream()
|
||||
: newDataPackets_([NSMutableArray array]),
|
||||
accumulatedData_([NSMutableData data]),
|
||||
condition_([[NSCondition alloc] init]) {
|
||||
// Create the handlers of incoming data from the remote endpoint.
|
||||
connectionHandlers_ = [GNCMConnectionHandlers
|
||||
payloadHandler:^(NSData *data) {
|
||||
[condition_ lock];
|
||||
// Add the incoming data to the data packet array to be processed in read() below.
|
||||
[newDataPackets_ addObject:data];
|
||||
[condition_ broadcast];
|
||||
[condition_ unlock];
|
||||
}
|
||||
disconnectedHandler:^{
|
||||
[condition_ lock];
|
||||
// Release the data packet array, meaning the stream has been closed or severed.
|
||||
newDataPackets_ = nil;
|
||||
[condition_ broadcast];
|
||||
[condition_ unlock];
|
||||
}];
|
||||
}
|
||||
|
||||
BleInputStream::~BleInputStream() {
|
||||
NSCAssert(!newDataPackets_, @"BleInputStream not closed before destruction");
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BleInputStream::Read(std::int64_t size) {
|
||||
// Block until either (a) the connection has been closed, (b) we have enough data to return.
|
||||
NSData *dataToReturn;
|
||||
[condition_ lock];
|
||||
while (true) {
|
||||
// Check if the stream has been closed or severed.
|
||||
if (!newDataPackets_) break;
|
||||
|
||||
if (newDataPackets_.count > 0) {
|
||||
// Add the packet data to the accumulated data.
|
||||
for (NSData *data in newDataPackets_) {
|
||||
if (data.length > 0) {
|
||||
[accumulatedData_ appendData:data];
|
||||
}
|
||||
}
|
||||
[newDataPackets_ removeAllObjects];
|
||||
}
|
||||
|
||||
if ((size == -1) && (accumulatedData_.length > 0)) {
|
||||
// Return all of the data.
|
||||
dataToReturn = accumulatedData_;
|
||||
accumulatedData_ = [NSMutableData data];
|
||||
break;
|
||||
} else if (accumulatedData_.length > 0) {
|
||||
// Return up to |size| bytes of the data.
|
||||
std::int64_t sizeToReturn = (accumulatedData_.length < size) ? accumulatedData_.length : size;
|
||||
NSRange range = NSMakeRange(0, (NSUInteger)sizeToReturn);
|
||||
dataToReturn = [accumulatedData_ subdataWithRange:range];
|
||||
[accumulatedData_ replaceBytesInRange:range withBytes:nil length:0];
|
||||
break;
|
||||
}
|
||||
|
||||
[condition_ wait];
|
||||
}
|
||||
[condition_ unlock];
|
||||
|
||||
if (dataToReturn) {
|
||||
NSLog(@"[NEARBY] Input stream: Received data of size: %lu", (unsigned long)dataToReturn.length);
|
||||
return ExceptionOr<ByteArray>(ByteArrayFromNSData(dataToReturn));
|
||||
} else {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception BleInputStream::Close() {
|
||||
// Unblock pending read operation.
|
||||
[condition_ lock];
|
||||
newDataPackets_ = nil;
|
||||
[condition_ broadcast];
|
||||
[condition_ unlock];
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
#pragma mark - BleOutputStream
|
||||
|
||||
BleOutputStream::~BleOutputStream() {
|
||||
NSCAssert(!connection_, @"BleOutputStream not closed before destruction");
|
||||
}
|
||||
|
||||
Exception BleOutputStream::Write(const ByteArray &data) {
|
||||
[condition_ lock];
|
||||
NSLog(@"[NEARBY] Sending data of size: %lu", NSDataFromByteArray(data).length);
|
||||
|
||||
if (!connection_) {
|
||||
[condition_ unlock];
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
NSMutableData *packet = [NSMutableData dataWithData:NSDataFromByteArray(data)];
|
||||
|
||||
// Send the data, blocking until the completion handler is called.
|
||||
__block bool isComplete = NO;
|
||||
__block GNCMPayloadResult sendResult = GNCMPayloadResultFailure;
|
||||
NSCondition *condition = condition_; // don't capture |this| in completion
|
||||
|
||||
[connection_ sendData:packet
|
||||
progressHandler:^(size_t count) {
|
||||
}
|
||||
completion:^(GNCMPayloadResult result) {
|
||||
[condition lock];
|
||||
// Make sure we haven't already reported completion before. This prevents a crash
|
||||
// where we try leaving a dispatch group more times than we entered it.
|
||||
// b/79095653.
|
||||
if (isComplete) {
|
||||
[condition unlock];
|
||||
return;
|
||||
}
|
||||
isComplete = YES;
|
||||
sendResult = result;
|
||||
[condition broadcast];
|
||||
[condition unlock];
|
||||
}];
|
||||
|
||||
while (connection_ && !isComplete) {
|
||||
[condition_ wait];
|
||||
}
|
||||
|
||||
if (sendResult == GNCMPayloadResultSuccess) {
|
||||
[condition_ unlock];
|
||||
return {Exception::kSuccess};
|
||||
} else {
|
||||
[condition_ unlock];
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception BleOutputStream::Flush() {
|
||||
// The write() function blocks until the data is received by the remote endpoint, so there's
|
||||
// nothing to do here.
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BleOutputStream::Close() {
|
||||
// Unblock pending write operation.
|
||||
[condition_ lock];
|
||||
connection_ = nil;
|
||||
[condition_ broadcast];
|
||||
[condition_ unlock];
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
#pragma mark - BleSocket
|
||||
|
||||
BleSocket::BleSocket(id<GNCMConnection> connection, BlePeripheral *peripheral)
|
||||
: input_stream_(new BleInputStream()),
|
||||
output_stream_(new BleOutputStream(connection)),
|
||||
peripheral_(peripheral) {}
|
||||
|
||||
BleSocket::~BleSocket() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
}
|
||||
|
||||
bool BleSocket::IsClosed() const {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return closed_;
|
||||
}
|
||||
|
||||
Exception BleSocket::Close() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
void BleSocket::DoClose() {
|
||||
if (!closed_) {
|
||||
input_stream_->Close();
|
||||
output_stream_->Close();
|
||||
closed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace apple
|
||||
} // namespace nearby
|
||||
Reference in New Issue
Block a user