SocketConnection.m 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // From https://github.com/react-native-webrtc/react-native-webrtc (MIT License)
  2. // SPDX-FileCopyrightText: 2023 React-Native-WebRTC authors
  3. // SPDX-License-Identifier: MIT
  4. #include <sys/socket.h>
  5. #include <sys/un.h>
  6. #import "SocketConnection.h"
  7. @interface SocketConnection ()
  8. @property(nonatomic, assign) int serverSocket;
  9. @property(nonatomic, strong) dispatch_source_t listeningSource;
  10. @property(nonatomic, strong) NSInputStream *inputStream;
  11. @property(nonatomic, strong) NSOutputStream *outputStream;
  12. @end
  13. @implementation SocketConnection
  14. - (instancetype)initWithFilePath:(nonnull NSString *)filePath {
  15. self = [super init];
  16. self.serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
  17. if (self.serverSocket < 0) {
  18. NSLog(@"failure creating socket");
  19. return nil;
  20. }
  21. if (![self setupSocketWithFileAtPath:filePath]) {
  22. close(self.serverSocket);
  23. return nil;
  24. }
  25. return self;
  26. }
  27. - (void)openWithStreamDelegate:(id<NSStreamDelegate>)streamDelegate {
  28. int status = listen(self.serverSocket, 10);
  29. if (status < 0) {
  30. NSLog(@"failure: socket listening");
  31. return;
  32. }
  33. dispatch_source_t listeningSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self.serverSocket, 0, NULL);
  34. dispatch_source_set_event_handler(listeningSource, ^{
  35. int clientSocket = accept(self.serverSocket, NULL, NULL);
  36. if (clientSocket < 0) {
  37. NSLog(@"failure accepting connection");
  38. return;
  39. }
  40. CFReadStreamRef readStream;
  41. CFWriteStreamRef writeStream;
  42. CFStreamCreatePairWithSocket(kCFAllocatorDefault, clientSocket, &readStream, &writeStream);
  43. self.inputStream = (__bridge_transfer NSInputStream *)readStream;
  44. self.inputStream.delegate = streamDelegate;
  45. [self.inputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
  46. self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
  47. [self.outputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
  48. dispatch_async(dispatch_get_main_queue(), ^{
  49. [self scheduleStreams];
  50. [self.inputStream open];
  51. [self.outputStream open];
  52. });
  53. });
  54. self.listeningSource = listeningSource;
  55. dispatch_resume(listeningSource);
  56. }
  57. - (void)close {
  58. //[self performSelector:@selector(unscheduleStreams) onThread:self.networkThread withObject:nil waitUntilDone:false];
  59. dispatch_async(dispatch_get_main_queue(), ^{
  60. [self unscheduleStreams];
  61. self.inputStream.delegate = nil;
  62. self.outputStream.delegate = nil;
  63. [self.inputStream close];
  64. [self.outputStream close];
  65. dispatch_source_cancel(self.listeningSource);
  66. close(self.serverSocket);
  67. });
  68. }
  69. // MARK: - Private Methods
  70. - (BOOL)setupSocketWithFileAtPath:(NSString *)filePath {
  71. struct sockaddr_un addr;
  72. memset(&addr, 0, sizeof(addr));
  73. addr.sun_family = AF_UNIX;
  74. if (filePath.length > sizeof(addr.sun_path)) {
  75. NSLog(@"failure: path too long");
  76. return false;
  77. }
  78. unlink(filePath.UTF8String);
  79. strncpy(addr.sun_path, filePath.UTF8String, sizeof(addr.sun_path) - 1);
  80. int status = bind(self.serverSocket, (struct sockaddr *)&addr, sizeof(addr));
  81. if (status < 0) {
  82. NSLog(@"failure: socket binding");
  83. return false;
  84. }
  85. return true;
  86. }
  87. - (void)scheduleStreams {
  88. [self.inputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
  89. [self.outputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
  90. }
  91. - (void)unscheduleStreams {
  92. [self.inputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
  93. [self.outputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
  94. }
  95. @end