NetworkMonitor.m 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #import "NetworkMonitor.h"
  19. #import "Network.h"
  20. #import "ServiceCom.h"
  21. #import "NodeStatus.h"
  22. @import AppKit;
  23. NSString * const NetworkUpdateKey = @"com.zerotier.one.network-list";
  24. NSString * const StatusUpdateKey = @"com.zerotier.one.status";
  25. @interface NetworkMonitor (private)
  26. - (NSString*)dataFile;
  27. - (void)internal_updateNetworkInfo;
  28. - (NSInteger)findNetworkWithID:(UInt64)networkId;
  29. - (NSInteger)findSavedNetworkWithID:(UInt64)networkId;
  30. - (void)saveNetworks;
  31. @end
  32. @implementation NetworkMonitor
  33. - (id)init
  34. {
  35. self = [super init];
  36. if(self)
  37. {
  38. _savedNetworks = [NSMutableArray<Network*> array];
  39. _receivedNetworks = [NSArray<Network*> array];
  40. _allNetworks = [NSMutableArray<Network*> array];
  41. _timer = nil;
  42. }
  43. return self;
  44. }
  45. - (void)dealloc
  46. {
  47. [_timer invalidate];
  48. }
  49. - (void)start
  50. {
  51. NSLog(@"ZeroTier monitor started");
  52. _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
  53. target:self
  54. selector:@selector(updateNetworkInfo)
  55. userInfo:nil
  56. repeats:YES];
  57. }
  58. - (void)stop
  59. {
  60. NSLog(@"ZeroTier monitor stopped");
  61. [_timer invalidate];
  62. _timer = nil;
  63. }
  64. - (void)updateNetworkInfo
  65. {
  66. NSString *filePath = [self dataFile];
  67. if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  68. NSArray<Network*> *networks = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
  69. if(networks != nil) {
  70. _savedNetworks = [networks mutableCopy];
  71. }
  72. }
  73. NSError *error = nil;
  74. [[ServiceCom sharedInstance] getNetworklist:^(NSArray<Network *> *networkList) {
  75. _receivedNetworks = networkList;
  76. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  77. [self internal_updateNetworkInfo];
  78. } ];
  79. } error:&error];
  80. if(error) {
  81. [self stop];
  82. NSAlert *alert = [NSAlert alertWithError:error];
  83. alert.alertStyle = NSCriticalAlertStyle;
  84. [alert addButtonWithTitle:@"Quit"];
  85. [alert addButtonWithTitle:@"Retry"];
  86. NSModalResponse res = [alert runModal];
  87. if(res == NSAlertFirstButtonReturn) {
  88. [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
  89. }
  90. else if(res == NSAlertSecondButtonReturn) {
  91. [self start];
  92. return;
  93. }
  94. }
  95. [[ServiceCom sharedInstance] getNodeStatus:^(NodeStatus *status) {
  96. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:status forKey:@"status"];
  97. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  98. [[NSNotificationCenter defaultCenter] postNotificationName:StatusUpdateKey
  99. object:nil
  100. userInfo:userInfo];
  101. }];
  102. } error:&error];
  103. if (error) {
  104. [self stop];
  105. NSAlert *alert = [NSAlert alertWithError:error];
  106. alert.alertStyle = NSCriticalAlertStyle;
  107. [alert addButtonWithTitle:@"Quit"];
  108. [alert addButtonWithTitle:@"Retry"];
  109. NSModalResponse res = [alert runModal];
  110. if(res == NSAlertFirstButtonReturn) {
  111. [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
  112. }
  113. else if(res == NSAlertSecondButtonReturn) {
  114. [self start];
  115. return;
  116. }
  117. }
  118. }
  119. - (void)deleteSavedNetwork:(NSString*)networkId
  120. {
  121. UInt64 nwid = 0;
  122. NSScanner *scanner = [NSScanner scannerWithString:networkId];
  123. [scanner scanHexLongLong:&nwid];
  124. NSInteger index = [self findNetworkWithID:nwid];
  125. if(index != NSNotFound) {
  126. [_allNetworks removeObjectAtIndex:index];
  127. }
  128. index = [self findSavedNetworkWithID:nwid];
  129. if(index != NSNotFound) {
  130. [_savedNetworks removeObjectAtIndex:index];
  131. }
  132. [self saveNetworks];
  133. }
  134. @end
  135. @implementation NetworkMonitor (private)
  136. - (NSString*)dataFile
  137. {
  138. NSURL *appSupport = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
  139. inDomains:NSUserDomainMask] objectAtIndex:0];
  140. appSupport = [[[appSupport URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"] URLByAppendingPathComponent:@"networkinfo.dat"];
  141. return appSupport.path;
  142. }
  143. - (void)internal_updateNetworkInfo
  144. {
  145. NSMutableArray<Network*> *networks = [_savedNetworks mutableCopy];
  146. for(Network *nw in _receivedNetworks) {
  147. NSInteger index = [self findSavedNetworkWithID:nw.nwid];
  148. if(index != NSNotFound) {
  149. [networks setObject:nw atIndexedSubscript:index];
  150. }
  151. else {
  152. [networks addObject:nw];
  153. }
  154. }
  155. [networks sortUsingComparator:^NSComparisonResult(Network *obj1, Network *obj2) {
  156. if(obj1.nwid > obj2.nwid) {
  157. return true;
  158. }
  159. return false;
  160. }];
  161. @synchronized(_allNetworks) {
  162. _allNetworks = networks;
  163. }
  164. [self saveNetworks];
  165. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:networks forKey:@"networks"];
  166. [[NSNotificationCenter defaultCenter] postNotificationName:NetworkUpdateKey
  167. object:nil
  168. userInfo:userInfo];
  169. }
  170. - (NSInteger)findNetworkWithID:(UInt64)networkId
  171. {
  172. for(int i = 0; i < [_allNetworks count]; ++i) {
  173. Network *nw = [_allNetworks objectAtIndex:i];
  174. if(nw.nwid == networkId) {
  175. return i;
  176. }
  177. }
  178. return NSNotFound;
  179. }
  180. - (NSInteger)findSavedNetworkWithID:(UInt64)networkId
  181. {
  182. for(int i = 0; i < [_savedNetworks count]; ++i) {
  183. Network *nw = [_savedNetworks objectAtIndex:i];
  184. if(nw.nwid == networkId) {
  185. return i;
  186. }
  187. }
  188. return NSNotFound;
  189. }
  190. - (void)saveNetworks
  191. {
  192. NSString *filePath = [self dataFile];
  193. @synchronized(_allNetworks) {
  194. [NSKeyedArchiver archiveRootObject:_allNetworks toFile:filePath];
  195. }
  196. }
  197. @end