1// Copyright 2015-present 650 Industries. All rights reserved. 2 3/** 4 * This file is compiled without ARC - the memory needs to be managed by hand. 5 */ 6 7#import <EXDevLauncher/RCTPackagerConnection+EXDevLauncherPackagerConnectionInterceptor.h> 8 9#import <React/RCTReconnectingWebSocket.h> 10 11#import <objc/runtime.h> 12#import <mutex> 13 14#if RCT_DEV 15 16static RCTReconnectingWebSocket *createSocketForURL(NSURL * url) 17{ 18 NSURLComponents *const components = [NSURLComponents new]; 19 components.host = [url host]; 20 components.scheme = @"http"; 21 components.port = [url port]; 22 components.path = @"/message"; 23 components.queryItems = @[[NSURLQueryItem queryItemWithName:@"role" value:@"ios"]]; 24 static dispatch_queue_t queue; 25 static dispatch_once_t onceToken; 26 dispatch_once(&onceToken, ^{ 27 queue = dispatch_queue_create("com.facebook.RCTPackagerConnectionQueue", DISPATCH_QUEUE_SERIAL); 28 }); 29 30 RCTReconnectingWebSocket *webSocket = [[RCTReconnectingWebSocket alloc] initWithURL:components.URL queue:queue]; 31 [components release]; 32 return [webSocket autorelease]; // adds to ARC 33} 34 35@implementation RCTPackagerConnection (EXDevLauncherPackagerConnectionInterceptor) 36 37/** 38 * Sets the WebSocket URL. 39 */ 40- (void)setSocketConnectionURL:(NSURL *)url 41{ 42 // Mutex isn't an objective-c object - [self valueForKey:@"_mutex"] will fail. 43 // The other solution requires `object_getInstanceVariable` which doesn't work with ARC. 44 // That's the only solution to get private variables that comes from cpp. 45 Ivar mutexVar = object_getInstanceVariable(self, "_mutex", NULL); 46 ptrdiff_t mutexOffset = ivar_getOffset(mutexVar); 47 unsigned char* selfPtr = (unsigned char *)(__bridge void*)self; 48 std::mutex *mutex = (std::mutex *)(selfPtr + mutexOffset); 49 50 RCTReconnectingWebSocket *oldSocket = (RCTReconnectingWebSocket *)[self valueForKey:@"_socket"]; 51 52 std::lock_guard<std::mutex> l(*mutex); 53 if (oldSocket == nil) { 54 return; // already stopped 55 } 56 57 oldSocket.delegate = nil; 58 [oldSocket stop]; 59 60 RCTReconnectingWebSocket *newSocket = createSocketForURL(url); 61 newSocket.delegate = (id<RCTReconnectingWebSocketDelegate>)self; 62 [newSocket start]; 63 64 @try { 65 // _serverHostForSocket was removed in RN 0.64 66 [self setValue:url.absoluteString forKey:@"_serverHostForSocket"]; 67 } @catch(id exception) {} 68 [self setValue:newSocket forKey:@"_socket"]; 69} 70 71@end 72 73#endif 74