зеркало из https://github.com/nextcloud/talk-ios.git
130 строки
3.8 KiB
Objective-C
130 строки
3.8 KiB
Objective-C
// From https://github.com/react-native-webrtc/react-native-webrtc (MIT License)
|
|
// SPDX-FileCopyrightText: 2023 React-Native-WebRTC authors
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
|
|
#import "SocketConnection.h"
|
|
|
|
@interface SocketConnection ()
|
|
|
|
@property(nonatomic, assign) int serverSocket;
|
|
@property(nonatomic, strong) dispatch_source_t listeningSource;
|
|
|
|
@property(nonatomic, strong) NSInputStream *inputStream;
|
|
@property(nonatomic, strong) NSOutputStream *outputStream;
|
|
|
|
@end
|
|
|
|
@implementation SocketConnection
|
|
|
|
- (instancetype)initWithFilePath:(nonnull NSString *)filePath {
|
|
self = [super init];
|
|
|
|
self.serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
if (self.serverSocket < 0) {
|
|
NSLog(@"failure creating socket");
|
|
return nil;
|
|
}
|
|
|
|
if (![self setupSocketWithFileAtPath:filePath]) {
|
|
close(self.serverSocket);
|
|
return nil;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)openWithStreamDelegate:(id<NSStreamDelegate>)streamDelegate {
|
|
int status = listen(self.serverSocket, 10);
|
|
if (status < 0) {
|
|
NSLog(@"failure: socket listening");
|
|
return;
|
|
}
|
|
|
|
dispatch_source_t listeningSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self.serverSocket, 0, NULL);
|
|
dispatch_source_set_event_handler(listeningSource, ^{
|
|
int clientSocket = accept(self.serverSocket, NULL, NULL);
|
|
if (clientSocket < 0) {
|
|
NSLog(@"failure accepting connection");
|
|
return;
|
|
}
|
|
|
|
CFReadStreamRef readStream;
|
|
CFWriteStreamRef writeStream;
|
|
|
|
CFStreamCreatePairWithSocket(kCFAllocatorDefault, clientSocket, &readStream, &writeStream);
|
|
|
|
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
|
|
self.inputStream.delegate = streamDelegate;
|
|
[self.inputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
|
|
|
|
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
|
|
[self.outputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self scheduleStreams];
|
|
|
|
[self.inputStream open];
|
|
[self.outputStream open];
|
|
});
|
|
});
|
|
|
|
self.listeningSource = listeningSource;
|
|
dispatch_resume(listeningSource);
|
|
}
|
|
|
|
- (void)close {
|
|
//[self performSelector:@selector(unscheduleStreams) onThread:self.networkThread withObject:nil waitUntilDone:false];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self unscheduleStreams];
|
|
|
|
self.inputStream.delegate = nil;
|
|
self.outputStream.delegate = nil;
|
|
|
|
[self.inputStream close];
|
|
[self.outputStream close];
|
|
|
|
dispatch_source_cancel(self.listeningSource);
|
|
close(self.serverSocket);
|
|
});
|
|
}
|
|
|
|
// MARK: - Private Methods
|
|
|
|
- (BOOL)setupSocketWithFileAtPath:(NSString *)filePath {
|
|
struct sockaddr_un addr;
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
if (filePath.length > sizeof(addr.sun_path)) {
|
|
NSLog(@"failure: path too long");
|
|
return false;
|
|
}
|
|
|
|
unlink(filePath.UTF8String);
|
|
strncpy(addr.sun_path, filePath.UTF8String, sizeof(addr.sun_path) - 1);
|
|
|
|
int status = bind(self.serverSocket, (struct sockaddr *)&addr, sizeof(addr));
|
|
if (status < 0) {
|
|
NSLog(@"failure: socket binding");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
- (void)scheduleStreams {
|
|
[self.inputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
|
|
[self.outputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
|
|
}
|
|
|
|
- (void)unscheduleStreams {
|
|
[self.inputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
|
|
[self.outputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
|
|
}
|
|
|
|
@end
|