mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
Add implementation for Wi-Fi LAN sockets that use the Network framework
PiperOrigin-RevId: 507922710
This commit is contained in:
committed by
Copybara-Service
parent
aa95be4ff4
commit
fc3bf91485
@@ -28,6 +28,7 @@ objc_library(
|
||||
"WifiLan/GNCMBonjourConnection.m",
|
||||
"WifiLan/GNCMBonjourService.m",
|
||||
"WifiLan/GNCMBonjourUtils.m",
|
||||
"WifiLanV2/GNCWiFiLANSocket.m",
|
||||
],
|
||||
hdrs = [
|
||||
"Ble/GNCMBleCentral.h",
|
||||
@@ -40,6 +41,7 @@ objc_library(
|
||||
"WifiLan/GNCMBonjourConnection.h",
|
||||
"WifiLan/GNCMBonjourService.h",
|
||||
"WifiLan/GNCMBonjourUtils.h",
|
||||
"WifiLanV2/GNCWiFiLANSocket.h",
|
||||
],
|
||||
deps = [
|
||||
"//internal/platform/implementation/apple:Shared",
|
||||
@@ -49,7 +51,7 @@ objc_library(
|
||||
"//proto/mediums:ble_frames_cc_proto",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"//third_party/apple_frameworks:Network",
|
||||
"//third_party/objective_c/google_toolbox_for_mac:GTM_Logger",
|
||||
"@com_google_absl//absl/numeric:int128",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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 <Foundation/Foundation.h>
|
||||
#import <Network/Network.h>
|
||||
|
||||
@interface GNCWiFiLANSocket : NSObject
|
||||
|
||||
/**
|
||||
* @remark init is not an available initializer.
|
||||
*/
|
||||
- (nonnull instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates a socket that allows reading/writing for a given connection.
|
||||
*
|
||||
* @param connection A bidirectional data connection between a local and remote endpoint. It is the
|
||||
* responsibility of the caller to maintain a strong reference to the connection
|
||||
* object.
|
||||
*/
|
||||
- (nonnull instancetype)initWithConnection:(nonnull nw_connection_t)connection
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Reads the requested amount of bytes from the connection.
|
||||
*
|
||||
* Blocks execution until the bytes have been read or an error occurs.
|
||||
*
|
||||
* @param length The number of bytes to read.
|
||||
* @param[out] error Error that will be populated on failure. A read may return non-nil data along
|
||||
* with an error. This normally happens if the data read is shorter than the
|
||||
* requested length.
|
||||
*/
|
||||
- (nullable NSData *)readMaxLength:(NSUInteger)length error:(NSError **_Nullable)error;
|
||||
|
||||
/**
|
||||
* Writes the given data to the connection.
|
||||
*
|
||||
* Blocks execution until the bytes have been successfully written or an error occurs.
|
||||
*
|
||||
* @param data The data to write.
|
||||
* @param[out] error Error that will be populated on failure.
|
||||
*/
|
||||
- (BOOL)write:(NSData *)data error:(NSError **_Nullable)error;
|
||||
|
||||
/**
|
||||
* Gracefully closes the connection to remote endpoint.
|
||||
*
|
||||
* If a read or write is in progress, they will be unblocked with an error.
|
||||
*/
|
||||
- (void)close;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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/Mediums/WifiLanV2/GNCWiFiLANSocket.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Network/Network.h>
|
||||
|
||||
#import "GoogleToolboxForMac/GTMLogger.h"
|
||||
|
||||
@interface GNCWiFiLANSocket ()
|
||||
|
||||
@property(nonatomic, weak, readonly) nw_connection_t connection;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GNCWiFiLANSocket {
|
||||
}
|
||||
|
||||
- (instancetype)initWithConnection:(nw_connection_t)connection {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_connection = connection;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSData *)readMaxLength:(NSUInteger)length error:(NSError **)error {
|
||||
__strong nw_connection_t connection = self.connection;
|
||||
if (connection == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSCondition *condition = [[NSCondition alloc] init];
|
||||
[condition lock];
|
||||
|
||||
__block NSData *blockResult = nil;
|
||||
__block NSError *blockError = nil;
|
||||
|
||||
nw_connection_receive(
|
||||
connection, length, length,
|
||||
^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t error) {
|
||||
[condition lock];
|
||||
if (error != nil) {
|
||||
blockError = (__bridge_transfer NSError *)nw_error_copy_cf_error(error);
|
||||
}
|
||||
#if __LP64__
|
||||
// This cast is only safe in a 64-bit runtime.
|
||||
blockResult = (NSData *)content;
|
||||
#else
|
||||
blockResult = nil;
|
||||
#endif
|
||||
[condition signal];
|
||||
[condition unlock];
|
||||
});
|
||||
|
||||
[condition wait];
|
||||
[condition unlock];
|
||||
|
||||
if (error != nil) {
|
||||
*error = blockError;
|
||||
}
|
||||
return blockResult;
|
||||
}
|
||||
|
||||
- (BOOL)write:(NSData *)data error:(NSError **)error {
|
||||
__strong nw_connection_t connection = self.connection;
|
||||
if (connection == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSCondition *condition = [[NSCondition alloc] init];
|
||||
[condition lock];
|
||||
|
||||
__block BOOL blockResult = NO;
|
||||
__block NSError *blockError = nil;
|
||||
|
||||
dispatch_data_t dispatchData =
|
||||
dispatch_data_create(data.bytes, data.length, dispatch_get_main_queue(),
|
||||
^{
|
||||
// Since we block until the send is complete, `data` should stay
|
||||
// alive when needed and released at the end of this method.
|
||||
});
|
||||
|
||||
nw_connection_send(connection, dispatchData, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, false,
|
||||
^(nw_error_t error) {
|
||||
[condition lock];
|
||||
blockResult = error == nil;
|
||||
if (error != nil) {
|
||||
blockError = (__bridge_transfer NSError *)nw_error_copy_cf_error(error);
|
||||
}
|
||||
[condition signal];
|
||||
[condition unlock];
|
||||
});
|
||||
|
||||
[condition wait];
|
||||
[condition unlock];
|
||||
|
||||
if (error != nil) {
|
||||
*error = blockError;
|
||||
}
|
||||
return blockResult;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
__strong nw_connection_t connection = self.connection;
|
||||
if (connection == nil) {
|
||||
return;
|
||||
}
|
||||
nw_connection_cancel(connection);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user