Warning, /network/kdeconnect-ios/KDE Connect/KDE Connect/ObjC Backend/BackgroundService.m is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2014 YANG Qiao <yangqiao0505@me.com> 0003 * 2020 Weixuan Xiao <veyx.shaw@gmail.com> 0004 * 2021 Lucas Wang <lucas.wang@tuta.io> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 // Original header below: 0010 //Copyright 2/5/14 YANG Qiao yangqiao0505@me.com 0011 //kdeconnect is distributed under two licenses. 0012 // 0013 //* The Mozilla Public License (MPL) v2.0 0014 // 0015 //or 0016 // 0017 //* The General Public License (GPL) v2.1 0018 // 0019 //---------------------------------------------------------------------- 0020 // 0021 //Software distributed under these licenses is distributed on an "AS 0022 //IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 0023 //implied. See the License for the specific language governing rights 0024 //and limitations under the License. 0025 //kdeconnect is distributed under both the GPL and the MPL. The MPL 0026 //notice, reproduced below, covers the use of either of the licenses. 0027 // 0028 //--------------------------------------------------------------------- 0029 0030 #import "BackgroundService.h" 0031 #import "LanLinkProvider.h" 0032 //#import "SettingsStore.h" 0033 //#import "PluginFactory.h" 0034 //#import "KeychainItemWrapper.h" 0035 //#import "Device.h" 0036 #import "KDE_Connect-Swift.h" 0037 @import os.log; 0038 0039 @interface BackgroundService () <NetworkChangeMonitorDelegate> { 0040 NSMutableDictionary<NSString *, Device *> *_devices; 0041 NSMutableDictionary<NSString *, NSData *> *_settings; 0042 os_log_t logger; 0043 } 0044 0045 @property(nonatomic) NetworkChangeMonitor *networkChangeMonitor; 0046 @property(nonatomic) NSMutableArray<BaseLinkProvider *> *_linkProviders; 0047 @property(nonatomic) NSMutableArray<Device *> *visibleDevices; 0048 @property(nonatomic) NSMutableDictionary<NSString *, Device *> *_savedDevices; 0049 @property(nonatomic, assign) ConnectedDevicesViewModel *_backgroundServiceDelegate; 0050 @property(nonatomic, assign) CertificateService *_certificateService; 0051 0052 @end 0053 0054 @implementation BackgroundService 0055 0056 @synthesize _backgroundServiceDelegate; 0057 @synthesize _certificateService; 0058 - (void)setDevices:(NSDictionary<NSString *, Device *> *)devices 0059 { 0060 _devices = [[NSMutableDictionary alloc] initWithDictionary:devices]; 0061 } 0062 @synthesize _linkProviders; 0063 - (void)setSettings:(NSDictionary<NSString *, NSData *> *)settings 0064 { 0065 _settings = [[NSMutableDictionary alloc] initWithDictionary:settings]; 0066 } 0067 @synthesize _savedDevices; 0068 0069 //+ (id) sharedInstance 0070 //{ 0071 // DEFINE_SHARED_INSTANCE_USING_BLOCK(^{ 0072 // return [[self alloc] init]; 0073 // }); 0074 //} 0075 // 0076 //+ (id) allocWithZone:(struct _NSZone *)zone 0077 //{ 0078 // DEFINE_SHARED_INSTANCE_USING_BLOCK(^{ 0079 // return [super allocWithZone:zone]; 0080 // }); 0081 //} 0082 // 0083 //- (id)copyWithZone:(NSZone *)zone;{ 0084 // return self; 0085 //} 0086 0087 - (BackgroundService*) initWithconnectedDeviceViewModel:(ConnectedDevicesViewModel*)connectedDeviceViewModel certificateService:(CertificateService*) certificateService 0088 { 0089 if ((self=[super init])) { 0090 logger = os_log_create([NSString kdeConnectOSLogSubsystem].UTF8String, 0091 NSStringFromClass([self class]).UTF8String); 0092 // MARK: comment this out for production, this is for debugging, for clearing the saved devices dictionary in UserDefaults 0093 //[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"savedDevices"]; 0094 //[_certificateService deleteAllItemsFromKeychain]; 0095 //NSLog(@"Host identity deleted from keychain with exit code %i", [KeychainOperations deleteHostCertificateFromKeychain]); 0096 0097 _linkProviders=[NSMutableArray arrayWithCapacity:1]; 0098 _devices=[NSMutableDictionary dictionaryWithCapacity:1]; 0099 _visibleDevices=[NSMutableArray arrayWithCapacity:1]; 0100 _settings=[NSMutableDictionary dictionaryWithCapacity:1]; 0101 _savedDevices = [NSMutableDictionary dictionary]; 0102 //[[SettingsStore alloc] initWithPath:KDECONNECT_REMEMBERED_DEV_FILE_PATH]; 0103 0104 _backgroundServiceDelegate = connectedDeviceViewModel; 0105 _certificateService = certificateService; 0106 0107 _networkChangeMonitor = [[NetworkChangeMonitor alloc] init]; 0108 _networkChangeMonitor.delegate = self; 0109 0110 NSDictionary* tempDic = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"savedDevices"]; 0111 if (tempDic != nil) { 0112 for (NSString* deviceId in [tempDic allKeys]) { 0113 NSData* deviceData = tempDic[deviceId]; 0114 [_settings setObject:deviceData forKey:deviceId]; // do this here since Settings holds exclusively encoded Data, NOT Device objects, otherwise will throw "non-property list" error upon trying to save to UserDefaults 0115 NSError* error; 0116 Device* device = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[Device class], [NSString class], [NSArray class], nil] fromData:deviceData error:&error]; 0117 os_log_with_type(logger, OS_LOG_TYPE_DEFAULT, "device with pair status %lu is decoded from UserDefaults as: %{public}@ with error %{public}@", [device _pairStatus], device, error); 0118 if ([device _pairStatus] == Paired) { 0119 device.deviceDelegate = self; 0120 //[device reloadPlugins]; 0121 [_savedDevices setObject:device forKey:deviceId]; 0122 } else { 0123 os_log_with_type(logger, self.debugLogLevel, "Not loading device above since it's previous status is NOT paired."); 0124 } 0125 } 0126 } 0127 0128 os_log_with_type(logger, self.debugLogLevel, "%{public}@", _savedDevices); 0129 //[[NSUserDefaults standardUserDefaults] registerDefaults:_settings]; 0130 //[[NSUserDefaults standardUserDefaults] synchronize]; 0131 [self registerLinkProviders]; 0132 [self loadRemenberedDevices]; 0133 //[PluginFactory sharedInstance]; 0134 0135 //#ifdef DEBUG 0136 // NSString* deviceId = @"test-purpose-device"; 0137 // Device* device=[[Device alloc] initTest]; 0138 // [_devices setObject:device forKey:deviceId]; 0139 //#endif 0140 // [_visibleDevices addObject:device]; 0141 } 0142 return self; 0143 } 0144 0145 - (os_log_type_t)debugLogLevel { 0146 if ([SelfDeviceData shared].isDebuggingDiscovery) { 0147 return OS_LOG_TYPE_INFO; 0148 } 0149 return OS_LOG_TYPE_DEBUG; 0150 } 0151 0152 // TODO: fix typo in this name 0153 - (void) loadRemenberedDevices 0154 { 0155 for (Device* device in [_savedDevices allValues]) { 0156 //Device* device=[[Device alloc] init:deviceId setDelegate:self]; 0157 [_devices setObject:device forKey:[device _id]]; 0158 //[_settings setObject:device forKey:[device _id]]; 0159 } 0160 if (_backgroundServiceDelegate) { 0161 [_backgroundServiceDelegate onDevicesListUpdatedWithDevicesListsMap:[self getDevicesLists]]; 0162 } 0163 } 0164 0165 - (void) registerLinkProviders 0166 { 0167 os_log_with_type(logger, self.debugLogLevel, "bg register linkproviders"); 0168 // TO-DO: read setting for linkProvider registration 0169 LanLinkProvider* linkProvider=[[LanLinkProvider alloc] initWithDelegate:self certificateService:_certificateService]; 0170 [_linkProviders addObject:linkProvider]; 0171 } 0172 0173 - (void) startDiscovery 0174 { 0175 [_networkChangeMonitor startMonitoring]; 0176 os_log_with_type(logger, self.debugLogLevel, "bg start Discovery"); 0177 for (BaseLinkProvider* lp in _linkProviders) { 0178 [lp onStart]; 0179 } 0180 } 0181 0182 - (void) refreshDiscovery 0183 { 0184 os_log_with_type(logger, self.debugLogLevel, "bg refresh Discovery"); 0185 for (BaseLinkProvider* lp in _linkProviders) { 0186 [lp onRefresh]; 0187 } 0188 } 0189 0190 - (void) stopDiscovery 0191 { 0192 [_networkChangeMonitor stopMonitoring]; 0193 os_log_with_type(logger, self.debugLogLevel, "bg stop Discovery"); 0194 for (BaseLinkProvider* lp in _linkProviders) { 0195 [lp onStop]; 0196 } 0197 } 0198 0199 - (NSDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *) getDevicesLists 0200 { 0201 os_log_with_type(logger, self.debugLogLevel, "bg get devices lists"); 0202 NSMutableDictionary* _visibleDevicesList=[NSMutableDictionary dictionaryWithCapacity:1]; 0203 NSMutableDictionary* _connectedDevicesList=[NSMutableDictionary dictionaryWithCapacity:1]; 0204 NSMutableDictionary* _rememberedDevicesList=[NSMutableDictionary dictionaryWithCapacity:1]; 0205 for (Device *device in [_devices allValues]) { 0206 if ((![device isReachable]) && [device isPaired]) { 0207 [_rememberedDevicesList setValue:[device _name] forKey:[device _id]]; 0208 0209 } else if([device isPaired] && [device isReachable]){ 0210 //[device reloadPlugins]; 0211 [_connectedDevicesList setValue:[device _name] forKey:[device _id]]; 0212 //TODO: move this to a different thread maybe, and also in Swift 0213 //[device reloadPlugins]; 0214 } else if ((![device isPaired]) && [device isReachable]) { 0215 [_visibleDevicesList setValue:[device _name] forKey:[device _id]]; 0216 } 0217 } 0218 NSDictionary* list=[NSDictionary dictionaryWithObjectsAndKeys: 0219 _connectedDevicesList, @"connected", 0220 _visibleDevicesList, @"visible", 0221 _rememberedDevicesList, @"remembered",nil]; 0222 return list; 0223 } 0224 0225 - (void) pairDevice:(NSString*)deviceId; 0226 { 0227 os_log_with_type(logger, self.debugLogLevel, "bg pair device"); 0228 Device* device=[_devices valueForKey:deviceId]; 0229 if ([device isReachable]) { 0230 [device requestPairing]; 0231 } 0232 } 0233 0234 /// @remark This should be the ONLY method used for unpairing Devices, DO NOT call the device's own unpair() method as it DOES NOT remove the device from the Arrays like this one does. For other files already using _backgroundServiceDelegate AKA ConnectedDevicesViewModel, use unpairFromBackgroundServiceInstance() in that. That's the same thing as calling this 0235 - (void)unpairDevice:(NSString *)deviceId { 0236 os_log_with_type(logger, self.debugLogLevel, "bg unpair device"); 0237 Device* device=[_devices valueForKey:deviceId]; 0238 if ([device isReachable]) { 0239 [device unpair]; 0240 } else { 0241 // we'll also be calling this to unpair remembered (unReachable) devices 0242 [device setAsUnpaired]; 0243 [_devices removeObjectForKey:deviceId]; 0244 } 0245 [self onDeviceUnpaired:device]; 0246 } 0247 0248 - (void)refreshVisibleDeviceList { 0249 NSMutableArray<Device *> *newVisibleDevices = [[NSMutableArray alloc] init]; 0250 0251 for (Device* device in [_devices allValues]) { 0252 if ([device isReachable]) { 0253 [newVisibleDevices addObject:device]; 0254 } 0255 } 0256 BOOL updated; 0257 @synchronized (_visibleDevices) { 0258 updated = ![newVisibleDevices isEqualToArray:_visibleDevices]; 0259 os_log_with_type(logger, self.debugLogLevel, 0260 "bg on device refresh visible device list, %{public}@", 0261 updated ? @"UPDATED" : @"NO UPDATE"); 0262 if (updated) { 0263 [_visibleDevices setArray:newVisibleDevices]; 0264 } 0265 } 0266 if (_backgroundServiceDelegate && updated) { 0267 [_backgroundServiceDelegate onDevicesListUpdatedWithDevicesListsMap:[self getDevicesLists]]; 0268 } 0269 } 0270 0271 #pragma mark reactions 0272 - (void) onDeviceReachableStatusChanged:(Device*)device 0273 { // TODO: Is this what gets called when paired device goes offline/becomes "remembered device" 0274 // FIXME: NOOOOOOOOOO ITS NOT, must be somewhere else, but this is called by Device when links == 0 aka unreachable???? 0275 os_log_with_type(logger, self.debugLogLevel, "bg on device reachable status changed"); 0276 if (![device isReachable]) { 0277 os_log_with_type(logger, self.debugLogLevel, "bg device not reachable"); 0278 os_log_with_type(logger, OS_LOG_TYPE_INFO, "%{mask.hash}@", [device _id]); 0279 //[_backgroundServiceDelegate currDeviceDetailsViewDisconnectedFromRemote:[device _id]]; 0280 } 0281 if (![device isPaired] && ![device isReachable]) { 0282 [_devices removeObjectForKey:[device _id]]; 0283 os_log_with_type(logger, self.debugLogLevel, "bg destroy device"); 0284 } 0285 //[self refreshDiscovery]; 0286 [self refreshVisibleDeviceList]; // might want to reverse this after figuring out why refreshDiscovery is causing Plugins to disappear 0287 } 0288 0289 - (void) onNetworkChange 0290 { 0291 os_log_with_type(logger, self.debugLogLevel, "bg on network change"); 0292 for (LanLinkProvider* lp in _linkProviders){ 0293 [lp onNetworkChange]; 0294 } 0295 } 0296 0297 - (void) onConnectionReceived:(NetworkPackage *)np link:(BaseLink *)link 0298 { 0299 os_log_with_type(logger, self.debugLogLevel, "bg on connection received"); 0300 NSString* deviceId=[np objectForKey:@"deviceId"]; 0301 os_log_with_type(logger, OS_LOG_TYPE_INFO, "Device discovered: %{mask.hash}@",deviceId); 0302 if ([_devices valueForKey:deviceId]) { 0303 os_log_with_type(logger, self.debugLogLevel, "known device"); 0304 Device* device=[_devices objectForKey:deviceId]; 0305 [device updateInfoWithNetworkPackage:np]; 0306 [device addLink:link]; 0307 [_backgroundServiceDelegate onDevicesListUpdatedWithDevicesListsMap:[self getDevicesLists]]; 0308 } 0309 else{ 0310 os_log_with_type(logger, OS_LOG_TYPE_INFO, 0311 "new device from network package: %{public}@", 0312 np._Id); 0313 Device *device=[[Device alloc] initWithNetworkPackage:np link:link delegate:self]; 0314 [_devices setObject:device forKey:deviceId]; 0315 [self refreshVisibleDeviceList]; 0316 } 0317 } 0318 0319 - (void)onDeviceIdentityUpdatePackageReceived:(NetworkPackage *)np { 0320 NSString *deviceID = [np objectForKey:@"deviceId"]; 0321 os_log_with_type(logger, self.debugLogLevel, 0322 "on identity update for %{mask.hash}@ received", 0323 deviceID); 0324 Device *device = [_devices objectForKey:deviceID]; 0325 if (device) { 0326 [device updateInfoWithNetworkPackage:np]; 0327 [_backgroundServiceDelegate onDevicesListUpdatedWithDevicesListsMap:[self getDevicesLists]]; 0328 } else { 0329 os_log_with_type(logger, OS_LOG_TYPE_FAULT, 0330 "missing device %{mask.hash}@ to update for", 0331 deviceID); 0332 } 0333 } 0334 0335 - (void) onLinkDestroyed:(BaseLink *)link 0336 { 0337 os_log_with_type(logger, self.debugLogLevel, "bg on link destroyed"); 0338 for (BaseLinkProvider* lp in _linkProviders) { 0339 [lp onLinkDestroyed:link]; 0340 } 0341 } 0342 0343 - (void) onDevicePairRequest:(Device *)device 0344 { 0345 os_log_with_type(logger, self.debugLogLevel, "bg on device pair request"); 0346 if (_backgroundServiceDelegate) { 0347 [_backgroundServiceDelegate onPairRequest:[device _id]]; 0348 } 0349 } 0350 0351 - (void) onDevicePairTimeout:(Device*)device 0352 { 0353 os_log_with_type(logger, self.debugLogLevel, "bg on device pair timeout"); 0354 if (_backgroundServiceDelegate) { 0355 [_backgroundServiceDelegate onPairTimeout:[device _id]]; 0356 } 0357 [_settings removeObjectForKey:[device _id]]; 0358 [[NSUserDefaults standardUserDefaults] setObject:_settings forKey:@"savedDevices"]; 0359 } 0360 0361 - (void) onDevicePairSuccess:(Device*)device 0362 { 0363 //NSLog(@"%lu", [device _type]); 0364 os_log_with_type(logger, self.debugLogLevel, "bg on device pair success"); 0365 if (_backgroundServiceDelegate) { 0366 [_backgroundServiceDelegate onPairSuccess:[device _id]]; 0367 } 0368 //[device setAsPaired]; is already called in the caller of this method 0369 NSError* error; 0370 NSData* deviceData = [NSKeyedArchiver archivedDataWithRootObject:device requiringSecureCoding:YES error:&error]; 0371 os_log_with_type(logger, OS_LOG_TYPE_INFO, "device object with pair status %lu encoded into UserDefaults as: %{public}@ with error: %{public}@", [device _pairStatus], deviceData, error); 0372 [_settings setValue:deviceData forKey:[device _id]]; //[device _name] 0373 [[NSUserDefaults standardUserDefaults] setObject:_settings forKey:@"savedDevices"]; 0374 } 0375 0376 - (void) onDevicePairRejected:(Device*)device 0377 { 0378 os_log_with_type(logger, self.debugLogLevel, "bg on device pair rejected"); 0379 if (_backgroundServiceDelegate) { 0380 [_backgroundServiceDelegate onPairRejected:[device _id]]; 0381 } 0382 [_settings removeObjectForKey:[device _id]]; 0383 [[NSUserDefaults standardUserDefaults] setObject:_settings forKey:@"savedDevices"]; 0384 } 0385 0386 - (void)onDeviceUnpaired:(Device *)device { 0387 NSString *deviceId = [device _id]; 0388 os_log_with_type(logger, OS_LOG_TYPE_INFO, "bg on device unpair %{mask.hash}@", deviceId); 0389 [_settings removeObjectForKey:deviceId]; 0390 [[NSUserDefaults standardUserDefaults] setObject:_settings forKey:@"savedDevices"]; 0391 device._SHA256HashFormatted = nil; 0392 BOOL status = [_certificateService deleteRemoteDeviceSavedCertWithDeviceId:deviceId]; 0393 os_log_with_type(logger, OS_LOG_TYPE_INFO, "Device remove, stored cert also removed with status %d", status); 0394 if (_backgroundServiceDelegate) { 0395 [_backgroundServiceDelegate onDevicesListUpdatedWithDevicesListsMap:[self getDevicesLists]]; 0396 } 0397 } 0398 0399 - (void) reloadAllPlugins 0400 { 0401 for (Device* device in _devices) { //_visibleDevices 0402 [device reloadPlugins]; 0403 } 0404 } 0405 0406 @end 0407