RLMSyncManager.mm 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "RLMSyncManager_Private.hpp"
  19. #import "RLMApp_Private.hpp"
  20. #import "RLMSyncSession_Private.hpp"
  21. #import "RLMUser_Private.hpp"
  22. #import "RLMSyncUtil_Private.hpp"
  23. #import "RLMUtil.hpp"
  24. #import <realm/sync/config.hpp>
  25. #import <realm/object-store/sync/sync_manager.hpp>
  26. #import <realm/object-store/sync/sync_session.hpp>
  27. #if !defined(REALM_COCOA_VERSION)
  28. #import "RLMVersion.h"
  29. #endif
  30. #include <os/lock.h>
  31. using namespace realm;
  32. // NEXT-MAJOR: All the code associated to the logger from sync manager should be removed.
  33. using Level = realm::util::Logger::Level;
  34. namespace {
  35. #pragma clang diagnostic push
  36. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  37. Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) {
  38. switch (logLevel) {
  39. case RLMSyncLogLevelOff: return Level::off;
  40. case RLMSyncLogLevelFatal: return Level::fatal;
  41. case RLMSyncLogLevelError: return Level::error;
  42. case RLMSyncLogLevelWarn: return Level::warn;
  43. case RLMSyncLogLevelInfo: return Level::info;
  44. case RLMSyncLogLevelDetail: return Level::detail;
  45. case RLMSyncLogLevelDebug: return Level::debug;
  46. case RLMSyncLogLevelTrace: return Level::trace;
  47. case RLMSyncLogLevelAll: return Level::all;
  48. }
  49. REALM_UNREACHABLE(); // Unrecognized log level.
  50. }
  51. RLMSyncLogLevel logLevelForLevel(Level logLevel) {
  52. switch (logLevel) {
  53. case Level::off: return RLMSyncLogLevelOff;
  54. case Level::fatal: return RLMSyncLogLevelFatal;
  55. case Level::error: return RLMSyncLogLevelError;
  56. case Level::warn: return RLMSyncLogLevelWarn;
  57. case Level::info: return RLMSyncLogLevelInfo;
  58. case Level::detail: return RLMSyncLogLevelDetail;
  59. case Level::debug: return RLMSyncLogLevelDebug;
  60. case Level::trace: return RLMSyncLogLevelTrace;
  61. case Level::all: return RLMSyncLogLevelAll;
  62. }
  63. REALM_UNREACHABLE(); // Unrecognized log level.
  64. }
  65. #pragma clang diagnostic pop
  66. #pragma mark - Loggers
  67. struct CocoaSyncLogger : public realm::util::Logger {
  68. void do_log(Level, const std::string& message) override {
  69. NSLog(@"Sync: %@", RLMStringDataToNSString(message));
  70. }
  71. };
  72. static std::unique_ptr<realm::util::Logger> defaultSyncLogger(realm::util::Logger::Level level) {
  73. auto logger = std::make_unique<CocoaSyncLogger>();
  74. logger->set_level_threshold(level);
  75. return std::move(logger);
  76. }
  77. struct CallbackLogger : public realm::util::Logger {
  78. RLMSyncLogFunction logFn;
  79. void do_log(Level level, const std::string& message) override {
  80. @autoreleasepool {
  81. logFn(logLevelForLevel(level), RLMStringDataToNSString(message));
  82. }
  83. }
  84. };
  85. } // anonymous namespace
  86. std::shared_ptr<realm::util::Logger> RLMWrapLogFunction(RLMSyncLogFunction fn) {
  87. auto logger = std::make_shared<CallbackLogger>();
  88. logger->logFn = fn;
  89. logger->set_level_threshold(Level::all);
  90. return logger;
  91. }
  92. #pragma mark - RLMSyncManager
  93. @interface RLMSyncTimeoutOptions () {
  94. @public
  95. realm::SyncClientTimeouts _options;
  96. }
  97. - (instancetype)initWithOptions:(realm::SyncClientTimeouts)options;
  98. @end
  99. @implementation RLMSyncManager {
  100. RLMUnfairMutex _mutex;
  101. std::shared_ptr<SyncManager> _syncManager;
  102. NSDictionary<NSString *,NSString *> *_customRequestHeaders;
  103. RLMSyncLogFunction _logger;
  104. }
  105. - (instancetype)initWithSyncManager:(std::shared_ptr<realm::SyncManager>)syncManager {
  106. if (self = [super init]) {
  107. [RLMUser _setUpBindingContextFactory];
  108. _syncManager = syncManager;
  109. return self;
  110. }
  111. return nil;
  112. }
  113. + (SyncClientConfig)configurationWithRootDirectory:(NSURL *)rootDirectory appId:(NSString *)appId {
  114. SyncClientConfig config;
  115. bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground();
  116. config.logger_factory = defaultSyncLogger;
  117. config.metadata_mode = should_encrypt ? SyncManager::MetadataMode::Encryption
  118. : SyncManager::MetadataMode::NoEncryption;
  119. @autoreleasepool {
  120. rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)];
  121. config.base_file_path = rootDirectory.path.UTF8String;
  122. bool isSwift = !!NSClassFromString(@"RealmSwiftObjectUtil");
  123. config.user_agent_binding_info =
  124. util::format("Realm%1/%2", isSwift ? "Swift" : "ObjectiveC",
  125. RLMStringDataWithNSString(REALM_COCOA_VERSION));
  126. config.user_agent_application_info = RLMStringDataWithNSString(appId);
  127. }
  128. return config;
  129. }
  130. - (std::weak_ptr<realm::app::App>)app {
  131. return _syncManager->app();
  132. }
  133. - (NSDictionary<NSString *,NSString *> *)customRequestHeaders {
  134. std::lock_guard lock(_mutex);
  135. return _customRequestHeaders;
  136. }
  137. - (void)setCustomRequestHeaders:(NSDictionary<NSString *,NSString *> *)customRequestHeaders {
  138. {
  139. std::lock_guard lock(_mutex);
  140. _customRequestHeaders = customRequestHeaders.copy;
  141. }
  142. for (auto&& user : _syncManager->all_users()) {
  143. for (auto&& session : user->all_sessions()) {
  144. auto config = session->config();
  145. config.custom_http_headers.clear();
  146. for (NSString *key in customRequestHeaders) {
  147. config.custom_http_headers.emplace(key.UTF8String, customRequestHeaders[key].UTF8String);
  148. }
  149. session->update_configuration(std::move(config));
  150. }
  151. }
  152. }
  153. - (RLMSyncLogFunction)logger {
  154. std::lock_guard lock(_mutex);
  155. return _logger;
  156. }
  157. - (void)setLogger:(RLMSyncLogFunction)logFn {
  158. {
  159. std::lock_guard lock(_mutex);
  160. _logger = logFn;
  161. }
  162. if (logFn) {
  163. _syncManager->set_logger_factory([logFn](realm::util::Logger::Level level) {
  164. auto logger = std::make_unique<CallbackLogger>();
  165. logger->logFn = logFn;
  166. logger->set_level_threshold(level);
  167. return logger;
  168. });
  169. }
  170. else {
  171. _syncManager->set_logger_factory(defaultSyncLogger);
  172. }
  173. }
  174. #pragma mark - Passthrough properties
  175. - (NSString *)userAgent {
  176. return @(_syncManager->config().user_agent_application_info.c_str());
  177. }
  178. - (void)setUserAgent:(NSString *)userAgent {
  179. _syncManager->set_user_agent(RLMStringDataWithNSString(userAgent));
  180. }
  181. - (RLMSyncTimeoutOptions *)timeoutOptions {
  182. return [[RLMSyncTimeoutOptions alloc] initWithOptions:_syncManager->config().timeouts];
  183. }
  184. - (void)setTimeoutOptions:(RLMSyncTimeoutOptions *)timeoutOptions {
  185. _syncManager->set_timeouts(timeoutOptions->_options);
  186. }
  187. - (RLMSyncLogLevel)logLevel {
  188. return logLevelForLevel(_syncManager->log_level());
  189. }
  190. - (void)setLogLevel:(RLMSyncLogLevel)logLevel {
  191. _syncManager->set_log_level(levelForSyncLogLevel(logLevel));
  192. }
  193. #pragma mark - Private API
  194. - (void)resetForTesting {
  195. _errorHandler = nil;
  196. _logger = nil;
  197. _authorizationHeaderName = nil;
  198. _customRequestHeaders = nil;
  199. _syncManager->reset_for_testing();
  200. }
  201. - (std::shared_ptr<realm::SyncManager>)syncManager {
  202. return _syncManager;
  203. }
  204. - (void)waitForSessionTermination {
  205. _syncManager->wait_for_sessions_to_terminate();
  206. }
  207. - (void)populateConfig:(realm::SyncConfig&)config {
  208. @synchronized (self) {
  209. if (_authorizationHeaderName) {
  210. config.authorization_header_name.emplace(_authorizationHeaderName.UTF8String);
  211. }
  212. [_customRequestHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *header, BOOL *) {
  213. config.custom_http_headers.emplace(key.UTF8String, header.UTF8String);
  214. }];
  215. }
  216. }
  217. @end
  218. #pragma mark - RLMSyncTimeoutOptions
  219. @implementation RLMSyncTimeoutOptions
  220. - (instancetype)initWithOptions:(realm::SyncClientTimeouts)options {
  221. if (self = [super init]) {
  222. _options = options;
  223. }
  224. return self;
  225. }
  226. - (NSUInteger)connectTimeout {
  227. return static_cast<NSUInteger>(_options.connect_timeout);
  228. }
  229. - (void)setConnectTimeout:(NSUInteger)connectTimeout {
  230. _options.connect_timeout = connectTimeout;
  231. }
  232. - (NSUInteger)connectLingerTime {
  233. return static_cast<NSUInteger>(_options.connection_linger_time);
  234. }
  235. - (void)setConnectionLingerTime:(NSUInteger)connectionLingerTime {
  236. _options.connection_linger_time = connectionLingerTime;
  237. }
  238. - (NSUInteger)pingKeepalivePeriod {
  239. return static_cast<NSUInteger>(_options.ping_keepalive_period);
  240. }
  241. - (void)setPingKeepalivePeriod:(NSUInteger)pingKeepalivePeriod {
  242. _options.ping_keepalive_period = pingKeepalivePeriod;
  243. }
  244. - (NSUInteger)pongKeepaliveTimeout {
  245. return static_cast<NSUInteger>(_options.pong_keepalive_timeout);
  246. }
  247. - (void)setPongKeepaliveTimeout:(NSUInteger)pongKeepaliveTimeout {
  248. _options.pong_keepalive_timeout = pongKeepaliveTimeout;
  249. }
  250. - (NSUInteger)fastReconnectLimit {
  251. return static_cast<NSUInteger>(_options.fast_reconnect_limit);
  252. }
  253. - (void)setFastReconnectLimit:(NSUInteger)fastReconnectLimit {
  254. _options.fast_reconnect_limit = fastReconnectLimit;
  255. }
  256. @end