From cac09d14aa934fc5918652debd84c16ade709546 Mon Sep 17 00:00:00 2001 From: Lorenzo Blasa Date: Thu, 26 Aug 2021 09:01:17 -0700 Subject: [PATCH] FlipperWebSocket Summary: Contains the implementation of FlipperWebSocket with any necessary changes to use it but without switching it on. About SocketRocket and Cocoapods A decision had to be made about whether to define different sub-specs, one for RSocket and another for SocketRocket. I've opted to keep the podspec as is because: - Keeps pod consumption as is. - Makes easier to switch implementations using GK. - There's no intention to keep RSocket going into the future. So, there's no point in creating a sub-spec only to remove it in the future. - SocketRocket is a relatively small library so is not contributing to a significant increase in binary size. If, as reviewer, you consider a subspec makes more sense, then feel free to reach out to discuss. Reviewed By: fabiomassimo Differential Revision: D30371791 fbshipit-source-id: 225c5b1de76aff1a6e36640a41765b963aaa2796 --- FlipperKit.podspec | 3 +- iOS/FlipperKit/FlipperClient.mm | 7 + iOS/FlipperKit/FlipperPlatformWebSocket.h | 49 +++++ iOS/FlipperKit/FlipperPlatformWebSocket.mm | 215 ++++++++++++++++++ iOS/FlipperKit/FlipperWebSocket.h | 89 ++++++++ iOS/FlipperKit/FlipperWebSocket.mm | 242 +++++++++++++++++++++ iOS/Podfile | 1 + iOS/Podfile.lock | 66 +++--- iOS/Sample/Podfile | 2 + iOS/Sample/Podfile.lock | 9 +- 10 files changed, 650 insertions(+), 33 deletions(-) create mode 100644 iOS/FlipperKit/FlipperPlatformWebSocket.h create mode 100644 iOS/FlipperKit/FlipperPlatformWebSocket.mm create mode 100644 iOS/FlipperKit/FlipperWebSocket.h create mode 100644 iOS/FlipperKit/FlipperWebSocket.mm diff --git a/FlipperKit.podspec b/FlipperKit.podspec index 2d6bb1ecc..e4a0d34d8 100644 --- a/FlipperKit.podspec +++ b/FlipperKit.podspec @@ -77,10 +77,11 @@ Pod::Spec.new do |spec| ss.dependency 'FlipperKit/CppBridge' ss.dependency 'FlipperKit/FKPortForwarding' ss.dependency 'Flipper', '~>'+flipperkit_version + ss.dependency 'SocketRocket', '~> 0.6.0' ss.compiler_flags = folly_compiler_flags ss.source_files = 'iOS/FlipperKit/*.{h,m,mm}', 'iOS/FlipperKit/CppBridge/*.{h,mm}' ss.public_header_files = 'iOS/FlipperKit/**/{FlipperDiagnosticsViewController,FlipperStateUpdateListener,FlipperClient,FlipperPlugin,FlipperConnection,FlipperResponder,SKMacros,FlipperKitCertificateProvider}.h' - header_search_paths = "\"$(PODS_ROOT)/FlipperKit/iOS/FlipperKit/\" \"$(PODS_ROOT)/Headers/Private/FlipperKit/\" \"$(PODS_ROOT)/Flipper-Boost-iOSX\" \"$(PODS_ROOT)/libevent/include\"" + header_search_paths = "\"$(PODS_ROOT)/FlipperKit/iOS/FlipperKit/\" \"$(PODS_ROOT)/Headers/Private/FlipperKit/\" \"$(PODS_ROOT)/Flipper-Boost-iOSX\" \"$(PODS_ROOT)/SocketRocket\" \"$(PODS_ROOT)/libevent/include\"" ss.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "ONLY_ACTIVE_ARCH": "YES", "DEFINES_MODULE" => "YES", diff --git a/iOS/FlipperKit/FlipperClient.mm b/iOS/FlipperKit/FlipperClient.mm index f25f60272..f19d22752 100644 --- a/iOS/FlipperKit/FlipperClient.mm +++ b/iOS/FlipperKit/FlipperClient.mm @@ -10,12 +10,14 @@ #import "FlipperClient.h" #import #import +#import #include #include #include #import "FlipperClient+Testing.h" #import "FlipperCppWrapperPlugin.h" #import "FlipperKitCertificateProvider.h" +#import "FlipperWebSocket.h" #import "SKEnvironmentVariables.h" #include "SKStateUpdateCPPWrapper.h" @@ -101,6 +103,11 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin; [SKEnvironmentVariables getInsecurePort], [SKEnvironmentVariables getSecurePort]}); _cppClient = facebook::flipper::FlipperClient::instance(); + + // To switch to a websocket provider, uncomment the line below. + // facebook::flipper::FlipperSocketProvider::setDefaultProvider( + // std::make_unique()); + } catch (const std::system_error& e) { // Probably ran out of disk space. return nil; diff --git a/iOS/FlipperKit/FlipperPlatformWebSocket.h b/iOS/FlipperKit/FlipperPlatformWebSocket.h new file mode 100644 index 000000000..c2332996e --- /dev/null +++ b/iOS/FlipperKit/FlipperPlatformWebSocket.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Defines a WebSocket transport to be used by Flipper. It just acts as a +/// wrapper on top of a WebSocket connection mainly used to abstract the actual +/// used implementation. +@interface FlipperPlatformWebSocket : NSObject + +/// An event handler used to dispatch socket events to the caller. +@property(nonatomic) facebook::flipper::SocketEventHandler eventHandler; + +/// A message handler used to dispatch messages received from the server. +@property(nonatomic) facebook::flipper::SocketMessageHandler messageHandler; + +/// A certificate provider used to obtain the client certificate used for +/// authentication. +@property(nonatomic) + facebook::flipper::SocketCertificateProvider certificateProvider; + +/// Initializes an instance of FliperWebSocketTransport with an endpoint URL. +/// @param url Endpoint URL used to establish the connection. +- (instancetype)initWithURL:(NSURL* _Nonnull)url; + +/// Connect to the endpoint. +- (void)connect; + +/// Disconnects from the endpoint. +- (void)disconnect; + +/// Send a message to the endpoint. +/// @param message The message as text to be sent to the endpoint. +/// @param error A pointer to variable for an `NSError` object. +/// If an error occurs, the pointer is set to an `NSError` object containing +/// information about the error. You may specify `nil` to ignore the error +/// information. +- (void)send:(NSString*)message error:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS/FlipperKit/FlipperPlatformWebSocket.mm b/iOS/FlipperKit/FlipperPlatformWebSocket.mm new file mode 100644 index 000000000..10e315701 --- /dev/null +++ b/iOS/FlipperKit/FlipperPlatformWebSocket.mm @@ -0,0 +1,215 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FlipperPlatformWebSocket.h" +#import +#import + +static constexpr int connectionKeepaliveSeconds = 10; + +#pragma mark - FlipperClientCertificateSecurityPolicy + +@interface FlipperClientCertificateSecurityPolicy : SRSecurityPolicy + +@property(nonatomic) + facebook::flipper::SocketCertificateProvider certificateProvider; + +- (id)initWithCertificateProvider: + (facebook::flipper::SocketCertificateProvider)certificateProvider; + +@end + +@implementation FlipperClientCertificateSecurityPolicy + +- (id)initWithCertificateProvider: + (facebook::flipper::SocketCertificateProvider)certificateProvider { + self = [super init]; + + if (self) { + _certificateProvider = certificateProvider; + } + + return self; +} + +/** + Updates all the security options for output streams, used for client + certificate authentication. + + @param stream Stream to update the options in. + */ +- (void)updateSecurityOptionsInStream:(NSStream*)stream { + if (!_certificateProvider || ![stream isKindOfClass:[NSOutputStream class]]) { + return; + } + + NSMutableDictionary* SSLOptions = [[NSMutableDictionary alloc] init]; + [stream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL + forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel]; + + char PASSWORD[512] = {}; + auto certificatePath = _certificateProvider(&PASSWORD[0], 512); + + NSString* certificatePathObjC = + [NSString stringWithUTF8String:certificatePath.c_str()]; + NSData* certificateData = [NSData dataWithContentsOfFile:certificatePathObjC]; + + NSString* password = [NSString stringWithUTF8String:PASSWORD]; + NSDictionary* optionsDictionary = [NSDictionary + dictionaryWithObject:password + forKey:(__bridge id)kSecImportExportPassphrase]; + + CFArrayRef items = NULL; + OSStatus status = SecPKCS12Import( + (__bridge CFDataRef)certificateData, + (__bridge CFDictionaryRef)optionsDictionary, + &items); + if (status != noErr) { + return; + } + + CFDictionaryRef identityDictionary = + (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0); + SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue( + identityDictionary, kSecImportItemIdentity); + + SecCertificateRef certificate = NULL; + status = SecIdentityCopyCertificate(identity, &certificate); + + if (status != noErr) { + return; + } + + NSArray* certificates = [[NSArray alloc] + initWithObjects:(__bridge id)identity, (__bridge id)certificate, nil]; + + [SSLOptions setObject:[NSNumber numberWithBool:NO] + forKey:(NSString*)kCFStreamSSLValidatesCertificateChain]; + [SSLOptions setObject:(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL + forKey:(NSString*)kCFStreamSSLLevel]; + [SSLOptions setObject:(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL + forKey:(NSString*)kCFStreamPropertySocketSecurityLevel]; + [SSLOptions setObject:certificates + forKey:(NSString*)kCFStreamSSLCertificates]; + [SSLOptions setObject:[NSNumber numberWithBool:NO] + forKey:(NSString*)kCFStreamSSLIsServer]; + + [stream setProperty:SSLOptions + forKey:(__bridge id)kCFStreamPropertySSLSettings]; +} + +@end + +#pragma mark - FlipperPlatformWebSocket + +@interface FlipperPlatformWebSocket () { + NSURL* _url; + NSTimer* _keepAlive; + + FlipperClientCertificateSecurityPolicy* _policy; +} + +@property(nonatomic, strong) SRWebSocket* socket; + +@end + +@implementation FlipperPlatformWebSocket + +- (instancetype)initWithURL:(NSURL* _Nonnull)url { + self = [super init]; + if (self) { + _url = url; + _policy = [FlipperClientCertificateSecurityPolicy new]; + } + + return self; +} + +- (void)dealloc { + [self disconnect]; +} + +- (void)connect { + if (_socket) { + return; + } + + self.socket = [[SRWebSocket alloc] initWithURL:_url securityPolicy:_policy]; + [_socket setDelegate:self]; + [_socket open]; +} + +- (void)disconnect { + if ([_keepAlive isValid]) { + [_keepAlive invalidate]; + } + _keepAlive = nil; + + if (_socket) { + // Manually trigger a 'close' event as SocketRocket close method will + // not notify the delegate. SocketRocket only triggers the close event + // when the connection is closed from the server. + _eventHandler(facebook::flipper::SocketEvent::CLOSE); + + [_socket close]; + _socket = nil; + } +} + +- (void)send:(NSString*)message error:(NSError**)error { + [_socket sendString:message error:error]; + if (error != nil && *error) { + facebook::flipper::log("Unable to send message."); + } +} + +- (void)setCertificateProvider: + (facebook::flipper::SocketCertificateProvider)certificateProvider { + _certificateProvider = certificateProvider; + _policy.certificateProvider = certificateProvider; +} + +- (void)sendScheduledKeepAlive:(NSTimer*)timer { + [_socket sendPing:nil error:nil]; +} + +- (void)webSocketDidOpen:(SRWebSocket*)webSocket { + _eventHandler(facebook::flipper::SocketEvent::OPEN); + + if (!_keepAlive) { + __weak auto weakSocket = _socket; + _keepAlive = + [NSTimer scheduledTimerWithTimeInterval:connectionKeepaliveSeconds + repeats:YES + block:^(NSTimer* timer) { + auto _Nullable socket = weakSocket; + [socket sendPing:nil error:nil]; + }]; + } +} + +- (void)webSocket:(SRWebSocket*)webSocket didFailWithError:(NSError*)error { + _eventHandler(facebook::flipper::SocketEvent::ERROR); + _socket = nil; +} + +- (void)webSocket:(SRWebSocket*)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString*)reason + wasClean:(BOOL)wasClean { + _eventHandler(facebook::flipper::SocketEvent::CLOSE); + _socket = nil; +} + +- (void)webSocket:(SRWebSocket*)webSocket didReceiveMessage:(id)message { + if (message && _messageHandler) { + NSString* response = message; + _messageHandler([response UTF8String]); + } +} + +@end diff --git a/iOS/FlipperKit/FlipperWebSocket.h b/iOS/FlipperKit/FlipperWebSocket.h new file mode 100644 index 000000000..45008105f --- /dev/null +++ b/iOS/FlipperKit/FlipperWebSocket.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#import +#import +#import +#import +#import +#import +#import + +@class FlipperPlatformWebSocket; + +namespace facebook { +namespace flipper { + +class FlipperConnectionManager; +class ConnectionContextStore; +class FlipperWebSocket : public FlipperSocket { + public: + FlipperWebSocket( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase); + FlipperWebSocket( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase, + ConnectionContextStore* connectionContextStore); + + virtual ~FlipperWebSocket() {} + + virtual void setEventHandler(SocketEventHandler eventHandler) override; + virtual void setMessageHandler(SocketMessageHandler messageHandler) override; + + virtual bool connect(FlipperConnectionManager* manager) override; + virtual void disconnect() override; + + virtual void send(const folly::dynamic& message, SocketSendHandler completion) + override; + virtual void send(const std::string& message, SocketSendHandler completion) + override; + virtual void sendExpectResponse( + const std::string& message, + SocketSendExpectResponseHandler completion) override; + + private: + FlipperConnectionEndpoint endpoint_; + std::unique_ptr payload_; + folly::EventBase* eventBase_; + ConnectionContextStore* connectionContextStore_; + + FlipperPlatformWebSocket* socket_; + + SocketEventHandler eventHandler_; + SocketMessageHandler messageHandler_; +}; + +class FlipperWebSocketProvider : public FlipperSocketProvider { + public: + FlipperWebSocketProvider() {} + virtual std::unique_ptr create( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase) override { + return std::make_unique( + std::move(endpoint), std::move(payload), eventBase); + } + virtual std::unique_ptr create( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase, + ConnectionContextStore* connectionContextStore) override { + return std::make_unique( + std::move(endpoint), + std::move(payload), + eventBase, + connectionContextStore); + } +}; + +} // namespace flipper +} // namespace facebook diff --git a/iOS/FlipperKit/FlipperWebSocket.mm b/iOS/FlipperKit/FlipperWebSocket.mm new file mode 100644 index 000000000..bcedb0214 --- /dev/null +++ b/iOS/FlipperKit/FlipperWebSocket.mm @@ -0,0 +1,242 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FlipperWebSocket.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import "FlipperPlatformWebSocket.h" + +namespace facebook { +namespace flipper { + +class WebSocketSerializer : public FlipperPayloadSerializer { + public: + void put(std::string key, std::string value) override { + object_[key] = value; + } + void put(std::string key, int value) override { + object_[key] = value; + } + std::string url_encode(const std::string& value) { + std::ostringstream escaped; + escaped.fill('0'); + escaped << std::hex; + + for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; + ++i) { + std::string::value_type c = (*i); + + // Keep alphanumeric and other accepted characters intact + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + escaped << c; + continue; + } + + // Any other characters are percent-encoded + escaped << std::uppercase; + escaped << '%' << std::setw(2) << int((unsigned char)c); + escaped << std::nouppercase; + } + + return escaped.str(); + } + std::string serialize() override { + std::string query = ""; + bool append = false; + + for (auto& pair : object_.items()) { + auto key = pair.first.asString(); + auto value = pair.second.asString(); + if (append) { + query += "&"; + } + query += key; + query += "="; + if (key == "csr") { + NSString* csr = [NSString stringWithUTF8String:value.c_str()]; + NSData* data = [csr dataUsingEncoding:NSUTF8StringEncoding]; + NSString* base64 = [data base64EncodedStringWithOptions:0]; + + query += base64.UTF8String; + } else { + query += url_encode(value); + } + append = true; + } + + return query; + } + ~WebSocketSerializer() {} + + private: + folly::dynamic object_ = folly::dynamic::object(); +}; + +FlipperWebSocket::FlipperWebSocket( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase) + : endpoint_(std::move(endpoint)), + payload_(std::move(payload)), + eventBase_(eventBase) {} + +FlipperWebSocket::FlipperWebSocket( + FlipperConnectionEndpoint endpoint, + std::unique_ptr payload, + folly::EventBase* eventBase, + ConnectionContextStore* connectionContextStore) + : endpoint_(std::move(endpoint)), + payload_(std::move(payload)), + eventBase_(eventBase), + connectionContextStore_(connectionContextStore) {} + +void FlipperWebSocket::setEventHandler(SocketEventHandler eventHandler) { + eventHandler_ = std::move(eventHandler); +} + +void FlipperWebSocket::setMessageHandler(SocketMessageHandler messageHandler) { + messageHandler_ = std::move(messageHandler); +} + +bool FlipperWebSocket::connect(FlipperConnectionManager* manager) { + if (socket_ != NULL) { + return true; + } + + std::string connectionURL = endpoint_.secure ? "wss://" : "ws://"; + connectionURL += endpoint_.host; + connectionURL += ":"; + connectionURL += std::to_string(endpoint_.port); + + auto serializer = WebSocketSerializer{}; + payload_->serialize(serializer); + auto payload = serializer.serialize(); + + if (payload.size()) { + connectionURL += "?"; + connectionURL += payload; + } + + __block bool fullfilled = false; + __block std::promise promise; + auto connected = promise.get_future(); + + NSURL* urlObjc = [NSURL + URLWithString:[NSString stringWithUTF8String:connectionURL.c_str()]]; + + auto eventHandler = eventHandler_; + socket_ = [[FlipperPlatformWebSocket alloc] initWithURL:urlObjc]; + socket_.eventHandler = ^(SocketEvent event) { + /** + Only fulfill the promise the first time the event handler is used. If the + open event is received, then set the promise value to true. For any other + event, consider a failure and set to false. + */ + if (!fullfilled) { + fullfilled = true; + if (event == SocketEvent::OPEN) { + promise.set_value(true); + } else { + promise.set_value(false); + } + } + eventHandler(event); + }; + socket_.messageHandler = ^(const std::string& message) { + this->messageHandler_(message); + }; + + if (endpoint_.secure) { + socket_.certificateProvider = [this]( + char* _Nonnull password, size_t length) { + auto pkcs12 = connectionContextStore_->getCertificate(); + if (pkcs12.first.length() == 0) { + return std::string(""); + } + strncpy(password, pkcs12.second.c_str(), length); + return pkcs12.first; + }; + } + + eventBase_->runInEventBaseThread([this]() { [socket_ connect]; }); + + auto state = connected.wait_for(std::chrono::seconds(10)); + if (state == std::future_status::ready) { + return connected.get(); + } + + disconnect(); + return false; +} + +void FlipperWebSocket::disconnect() { + eventBase_->runInEventBaseThread([this]() { + [socket_ disconnect]; + socket_ = NULL; + }); +} + +void FlipperWebSocket::send( + const folly::dynamic& message, + SocketSendHandler completion) { + if (socket_ == NULL) { + return; + } + std::string json = folly::toJson(message); + send(json, std::move(completion)); +} + +void FlipperWebSocket::send( + const std::string& message, + SocketSendHandler completion) { + if (socket_ == NULL) { + return; + } + NSString* messageObjc = [NSString stringWithUTF8String:message.c_str()]; + [socket_ send:messageObjc error:NULL]; + completion(); +} + +/** + Only ever used for insecure connections to receive the device_id from a + signCertificate request. If the intended usage ever changes, then a better + approach needs to be put in place. + */ +void FlipperWebSocket::sendExpectResponse( + const std::string& message, + SocketSendExpectResponseHandler completion) { + if (socket_ == NULL) { + return; + } + NSString* messageObjc = [NSString stringWithUTF8String:message.c_str()]; + + [socket_ setMessageHandler:^(const std::string& msg) { + completion(msg, false); + [socket_ setMessageHandler:NULL]; + }]; + NSError* error = NULL; + [socket_ send:messageObjc error:&error]; + + if (error != NULL) { + completion(error.description.UTF8String, true); + } +} + +} // namespace flipper +} // namespace facebook diff --git a/iOS/Podfile b/iOS/Podfile index 3f6defadb..b565db4bc 100644 --- a/iOS/Podfile +++ b/iOS/Podfile @@ -16,5 +16,6 @@ target 'FlipperKit' do pod 'glog', '~>0.3' pod 'Flipper-Folly', '~>2.2' pod 'CocoaAsyncSocket', '~>7.6' + pod 'SocketRocket', '~> 0.6.0' end diff --git a/iOS/Podfile.lock b/iOS/Podfile.lock index b54428bab..5de162d2e 100644 --- a/iOS/Podfile.lock +++ b/iOS/Podfile.lock @@ -1,26 +1,27 @@ PODS: - - boost-for-react-native (1.63.0) - - CocoaAsyncSocket (7.6.4) - - CocoaLibEvent (1.0.0) + - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.5) - - Flipper (0.45.0): - - Flipper-Folly (~> 2.2) - - Flipper-RSocket (~> 1.1) - - Flipper-DoubleConversion (1.1.7) - - Flipper-Folly (2.2.0): - - boost-for-react-native - - CocoaLibEvent (~> 1.0) + - Flipper (0.104.0): + - Flipper-Folly (~> 2.6) + - Flipper-RSocket (~> 1.4) + - Flipper-Boost-iOSX (1.76.0.1.11) + - Flipper-DoubleConversion (3.1.7) + - Flipper-Fmt (7.1.7) + - Flipper-Folly (2.6.9): + - Flipper-Boost-iOSX - Flipper-DoubleConversion + - Flipper-Fmt (= 7.1.7) - Flipper-Glog - - OpenSSL-Universal (= 1.0.2.19) - - Flipper-Glog (0.3.6) + - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) + - Flipper-Glog (0.3.9) - Flipper-PeerTalk (0.0.4) - - Flipper-RSocket (1.1.0): - - Flipper-Folly (~> 2.2) + - Flipper-RSocket (1.4.3): + - Flipper-Folly (~> 2.6) - glog (0.3.4) - - OpenSSL-Universal (1.0.2.19): - - OpenSSL-Universal/Static (= 1.0.2.19) - - OpenSSL-Universal/Static (1.0.2.19) + - libevent (2.1.12) + - OpenSSL-Universal (1.1.1100) + - SocketRocket (0.6.0) DEPENDENCIES: - CocoaAsyncSocket (~> 7.6) @@ -30,39 +31,44 @@ DEPENDENCIES: - Flipper-PeerTalk (~> 0.0) - Flipper-RSocket (~> 1.1) - glog (~> 0.3) + - SocketRocket (~> 0.6.0) SPEC REPOS: https://github.com/CocoaPods/Specs: - - boost-for-react-native - CocoaAsyncSocket - - CocoaLibEvent - DoubleConversion + - Flipper-Boost-iOSX - Flipper-DoubleConversion + - Flipper-Fmt - Flipper-Folly - Flipper-Glog - Flipper-PeerTalk - Flipper-RSocket - glog + - libevent - OpenSSL-Universal + - SocketRocket EXTERNAL SOURCES: Flipper: :path: "../Flipper.podspec" SPEC CHECKSUMS: - boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c - CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 - CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f + CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: e22e0762848812a87afd67ffda3998d9ef29170c - Flipper: 18ad3ac4a8e41db9db2ef72239b8ff4eab5b3522 - Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 - Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 - Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6 + Flipper: 3532e5cc3145575ed516093fe5227831cd62d464 + Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c + Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c + Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b + Flipper-Folly: 4c7cf530a9038ae25b0fa37e00b00491c467aaea + Flipper-Glog: 05579840e2750ec907ee2f81544f41ad76a7cae4 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 + Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 glog: 1de0bb937dccdc981596d3b5825ebfb765017ded - OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 + libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c + SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 -PODFILE CHECKSUM: c0e22ce9737ae531ae7290d9e16882825f8ebed9 +PODFILE CHECKSUM: 5b16ac1a3addfd00d5cb34dd4b15551ff07cb929 -COCOAPODS: 1.9.0 +COCOAPODS: 1.10.2 diff --git a/iOS/Sample/Podfile b/iOS/Sample/Podfile index ff27bd08d..f2212b18f 100644 --- a/iOS/Sample/Podfile +++ b/iOS/Sample/Podfile @@ -22,4 +22,6 @@ target 'Sample' do pod 'OpenSSL-Universal', :configuration => 'Debug' pod 'CocoaAsyncSocket', :configuration => 'Debug' pod 'ComponentKit', '~> 0.31' + pod 'SocketRocket', '~> 0.6.0' + end diff --git a/iOS/Sample/Podfile.lock b/iOS/Sample/Podfile.lock index 2686266cd..838e7849c 100644 --- a/iOS/Sample/Podfile.lock +++ b/iOS/Sample/Podfile.lock @@ -28,6 +28,7 @@ PODS: - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding + - SocketRocket (~> 0.6.0) - FlipperKit/CppBridge (0.104.0): - Flipper (~> 0.104.0) - FlipperKit/FBCxxFollyDynamicConvert (0.104.0): @@ -76,6 +77,7 @@ PODS: - libevent (2.1.12) - OpenSSL-Universal (1.1.1100) - RenderCore (0.31) + - SocketRocket (0.6.0) - Yoga (1.14.0) - YogaKit (1.18.1): - Yoga (~> 1.14) @@ -97,6 +99,7 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (from `../../FlipperKit.podspec`) - libevent - OpenSSL-Universal + - SocketRocket (~> 0.6.0) SPEC REPOS: https://github.com/CocoaPods/Specs: @@ -112,6 +115,7 @@ SPEC REPOS: - libevent - OpenSSL-Universal - RenderCore + - SocketRocket - Yoga - YogaKit @@ -132,13 +136,14 @@ SPEC CHECKSUMS: Flipper-Glog: 05579840e2750ec907ee2f81544f41ad76a7cae4 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 - FlipperKit: 9d78475d353d45f915523494908381afef1cf0c3 + FlipperKit: fd70e8414049b3704be99710cbdb79fce8f39200 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RenderCore: 090beb17b5bff80b86929a7ceb49df789923d23a + SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: cff67a400f6b74dc38eb0bad4f156673d9aa980c YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 154af3b1cdd6d65b1141c1215a3789297116c992 +PODFILE CHECKSUM: 8f7b8c1a8e7cee47eaef4736990315bfc090e2af COCOAPODS: 1.10.2