QNDnsPrefetch.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. //
  2. // QNDnsPrefetch.m
  3. // QnDNS
  4. //
  5. // Created by yangsen on 2020/3/26.
  6. // Copyright © 2020 com.qiniu. All rights reserved.
  7. //
  8. #import "QNDnsPrefetch.h"
  9. #import "QNInetAddress.h"
  10. #import "QNDnsCacheInfo.h"
  11. #import "QNZoneInfo.h"
  12. #import "QNDefine.h"
  13. #import "QNConfig.h"
  14. #import "QNDnsCacheFile.h"
  15. #import "QNUtils.h"
  16. #import "QNAsyncRun.h"
  17. #import "QNFixedZone.h"
  18. #import "QNAutoZone.h"
  19. #import <HappyDNS/HappyDNS.h>
  20. //MARK: -- 缓存模型
  21. @interface QNDnsNetworkAddress : NSObject<QNIDnsNetworkAddress>
  22. @property(nonatomic, copy)NSString *hostValue;
  23. @property(nonatomic, copy)NSString *ipValue;
  24. @property(nonatomic, strong)NSNumber *ttlValue;
  25. @property(nonatomic, copy)NSString *sourceValue;
  26. @property(nonatomic, strong)NSNumber *timestampValue;
  27. /// 构造方法 addressData为json String / Dictionary / Data / 遵循 QNIDnsNetworkAddress的实例
  28. + (instancetype)inetAddress:(id)addressInfo;
  29. /// 是否有效,根据时间戳判断
  30. - (BOOL)isValid;
  31. /// 对象转json
  32. - (NSString *)toJsonInfo;
  33. /// 对象转字典
  34. - (NSDictionary *)toDictionary;
  35. @end
  36. @implementation QNDnsNetworkAddress
  37. + (instancetype)inetAddress:(id)addressInfo{
  38. NSDictionary *addressDic = nil;
  39. if ([addressInfo isKindOfClass:[NSDictionary class]]) {
  40. addressDic = (NSDictionary *)addressInfo;
  41. } else if ([addressInfo isKindOfClass:[NSString class]]){
  42. NSData *data = [(NSString *)addressInfo dataUsingEncoding:NSUTF8StringEncoding];
  43. addressDic = [NSJSONSerialization JSONObjectWithData:data
  44. options:NSJSONReadingMutableLeaves
  45. error:nil];
  46. } else if ([addressInfo isKindOfClass:[NSData class]]) {
  47. addressDic = [NSJSONSerialization JSONObjectWithData:(NSData *)addressInfo
  48. options:NSJSONReadingMutableLeaves
  49. error:nil];
  50. } else if ([addressInfo conformsToProtocol:@protocol(QNIDnsNetworkAddress)]){
  51. id <QNIDnsNetworkAddress> address = (id <QNIDnsNetworkAddress> )addressInfo;
  52. NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  53. if ([address respondsToSelector:@selector(hostValue)] && [address hostValue]) {
  54. dic[@"hostValue"] = [address hostValue];
  55. }
  56. if ([address respondsToSelector:@selector(ipValue)] && [address ipValue]) {
  57. dic[@"ipValue"] = [address ipValue];
  58. }
  59. if ([address respondsToSelector:@selector(ttlValue)] && [address ttlValue]) {
  60. dic[@"ttlValue"] = [address ttlValue];
  61. }
  62. if ([address respondsToSelector:@selector(sourceValue)] && [address sourceValue]) {
  63. dic[@"sourceValue"] = [address sourceValue];
  64. } else {
  65. dic[@"sourceValue"] = kQNDnsSourceCustom;
  66. }
  67. if ([address respondsToSelector:@selector(timestampValue)] && [address timestampValue]) {
  68. dic[@"timestampValue"] = [address timestampValue];
  69. }
  70. addressDic = [dic copy];
  71. }
  72. if (addressDic) {
  73. QNDnsNetworkAddress *address = [[QNDnsNetworkAddress alloc] init];
  74. [address setValuesForKeysWithDictionary:addressDic];
  75. return address;
  76. } else {
  77. return nil;
  78. }
  79. }
  80. /// 过了 ttl 时间则需要刷新
  81. - (BOOL)needRefresh{
  82. if (!self.timestampValue || !self.ipValue || self.ipValue.length == 0) {
  83. return NO;
  84. }
  85. NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
  86. return currentTimestamp > (self.timestampValue.doubleValue + self.ttlValue.doubleValue);
  87. }
  88. /// 只要在最大 ttl 时间内,即为有效
  89. - (BOOL)isValid{
  90. if (!self.timestampValue || !self.ipValue || self.ipValue.length == 0) {
  91. return NO;
  92. }
  93. NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
  94. return currentTimestamp < (self.timestampValue.doubleValue + kQNGlobalConfiguration.dnsCacheMaxTTL);
  95. }
  96. - (NSString *)toJsonInfo{
  97. NSString *defaultString = @"{}";
  98. NSDictionary *infoDic = [self toDictionary];
  99. if (!infoDic) {
  100. return defaultString;
  101. }
  102. NSData *infoData = [NSJSONSerialization dataWithJSONObject:infoDic
  103. options:NSJSONWritingPrettyPrinted
  104. error:nil];
  105. if (!infoData) {
  106. return defaultString;
  107. }
  108. NSString *infoStr = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
  109. if (!infoStr) {
  110. return defaultString;
  111. } else {
  112. return infoStr;
  113. }
  114. }
  115. - (NSDictionary *)toDictionary{
  116. return [self dictionaryWithValuesForKeys:@[@"ipValue", @"hostValue", @"ttlValue", @"sourceValue", @"timestampValue"]];
  117. }
  118. - (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
  119. @end
  120. //MARK: -- HappyDNS 适配
  121. @interface QNRecord(DNS)<QNIDnsNetworkAddress>
  122. @end
  123. @implementation QNRecord(DNS)
  124. - (NSString *)hostValue{
  125. return nil;
  126. }
  127. - (NSString *)ipValue{
  128. return self.value;
  129. }
  130. - (NSNumber *)ttlValue{
  131. return @(self.ttl);
  132. }
  133. - (NSNumber *)timestampValue{
  134. return @(self.timeStamp);
  135. }
  136. - (NSString *)sourceValue{
  137. if (self.source == QNRecordSourceSystem) {
  138. return kQNDnsSourceSystem;
  139. } else if (self.source == QNRecordSourceDoh) {
  140. return [NSString stringWithFormat:@"%@<%@>", kQNDnsSourceDoh, self.server];
  141. } else if (self.source == QNRecordSourceUdp) {
  142. return [NSString stringWithFormat:@"%@<%@>", kQNDnsSourceUdp, self.server];
  143. } else if (self.source == QNRecordSourceDnspodEnterprise) {
  144. return kQNDnsSourceDnspod;
  145. } else if (self.ipValue == nil || self.ipValue.length == 0) {
  146. return kQNDnsSourceNone;
  147. } else {
  148. return kQNDnsSourceCustom;
  149. }
  150. }
  151. @end
  152. @interface QNInternalDns : NSObject
  153. @property(nonatomic, strong)id<QNDnsDelegate> dns;
  154. @property(nonatomic, strong)id<QNResolverDelegate> resolver;
  155. @end
  156. @implementation QNInternalDns
  157. + (instancetype)dnsWithDns:(id<QNDnsDelegate>)dns {
  158. QNInternalDns *interDns = [[QNInternalDns alloc] init];
  159. interDns.dns = dns;
  160. return interDns;
  161. }
  162. + (instancetype)dnsWithResolver:(id<QNResolverDelegate>)resolver {
  163. QNInternalDns *interDns = [[QNInternalDns alloc] init];
  164. interDns.resolver = resolver;
  165. return interDns;
  166. }
  167. - (NSArray < id <QNIDnsNetworkAddress> > *)query:(NSString *)host error:(NSError **)error {
  168. if (self.dns && [self.dns respondsToSelector:@selector(query:)]) {
  169. return [self.dns query:host];
  170. } else if (self.resolver) {
  171. NSArray <QNRecord *>* records = [self.resolver query:[[QNDomain alloc] init:host] networkInfo:nil error:error];
  172. return [self filterRecords:records];
  173. }
  174. return nil;
  175. }
  176. - (NSArray <QNRecord *>*)filterRecords:(NSArray <QNRecord *>*)records {
  177. NSMutableArray <QNRecord *> *newRecords = [NSMutableArray array];
  178. for (QNRecord *record in records) {
  179. if (record.type == kQNTypeA || record.type == kQNTypeAAAA) {
  180. [newRecords addObject:record];
  181. }
  182. }
  183. return [newRecords copy];
  184. }
  185. @end
  186. //MARK: -- DNS Prefetcher
  187. @interface QNDnsPrefetch()
  188. // dns 预解析超时,默认3s
  189. @property(nonatomic, assign)int dnsPrefetchTimeout;
  190. // 最近一次预取错误信息
  191. @property(nonatomic, copy)NSString *lastPrefetchedErrorMessage;
  192. /// 是否正在预取,正在预取会直接取消新的预取操作请求
  193. @property(atomic, assign)BOOL isPrefetching;
  194. /// 获取AutoZone时的同步锁
  195. @property(nonatomic, strong)dispatch_semaphore_t getAutoZoneSemaphore;
  196. /// DNS信息本地缓存key
  197. @property(nonatomic, strong)QNDnsCacheInfo *dnsCacheInfo;
  198. // 用户定制 dns
  199. @property(nonatomic, strong)QNInternalDns *customDns;
  200. // 系统 dns
  201. @property(nonatomic, strong)QNInternalDns *systemDns;
  202. /// prefetch hosts
  203. @property(nonatomic, strong)NSMutableSet *prefetchHosts;
  204. /// 缓存DNS解析结果
  205. /// 线程安全:内部方法均是在同一线程执行,读写不必加锁,对外开放接口读操作 需要和内部写操作枷锁
  206. @property(nonatomic, strong)NSMutableDictionary <NSString *, NSArray<QNDnsNetworkAddress *>*> *addressDictionary;
  207. @property(nonatomic, strong)QNDnsCacheFile *diskCache;
  208. @end
  209. @implementation QNDnsPrefetch
  210. + (instancetype)shared{
  211. static QNDnsPrefetch *prefetcher = nil;
  212. static dispatch_once_t onceToken;
  213. dispatch_once(&onceToken, ^{
  214. prefetcher = [[QNDnsPrefetch alloc] init];
  215. });
  216. return prefetcher;
  217. }
  218. - (instancetype)init{
  219. if (self = [super init]) {
  220. _isPrefetching = NO;
  221. _dnsPrefetchTimeout = 3;
  222. }
  223. return self;
  224. }
  225. //MARK: -- uploadManager初始化时,加载本地缓存到内存
  226. /// 同步本地预取缓存 如果存在且满足使用返回false,反之为true
  227. - (BOOL)recoverCache{
  228. id <QNRecorderDelegate> recorder = nil;
  229. NSError *error;
  230. recorder = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir
  231. error:&error];
  232. if (error) {
  233. return YES;
  234. }
  235. NSData *data = [recorder get:[QNIP local]];
  236. if (!data) {
  237. return YES;
  238. }
  239. QNDnsCacheInfo *cacheInfo = [QNDnsCacheInfo dnsCacheInfo:data];
  240. if (!cacheInfo) {
  241. return YES;
  242. }
  243. NSString *localIp = [QNIP local];
  244. if (!localIp || localIp.length == 0 || ![cacheInfo.localIp isEqualToString:localIp]) {
  245. return YES;
  246. }
  247. [self setDnsCacheInfo:cacheInfo];
  248. return [self recoverDnsCache:cacheInfo.info];
  249. }
  250. /// 本地缓存读取失败后,加载本地域名,预取DNS解析信息
  251. - (void)localFetch{
  252. if ([self prepareToPreFetch] == NO) {
  253. return;
  254. }
  255. NSArray *hosts = [self getLocalPreHost];
  256. @synchronized (self) {
  257. [self.prefetchHosts addObjectsFromArray:hosts];
  258. }
  259. [self preFetchHosts:hosts];
  260. [self recorderDnsCache];
  261. [self endPreFetch];
  262. }
  263. //MARK: -- 检测并预取
  264. /// 根据token检测Dns缓存信息时效,无效则预取。 完成预取操作返回YES,反之返回NO
  265. - (void)checkAndPrefetchDnsIfNeed:(QNZone *)currentZone token:(QNUpToken *)token{
  266. if ([self prepareToPreFetch] == NO) {
  267. return;
  268. }
  269. NSArray *hosts = [self getCurrentZoneHosts:currentZone token:token];
  270. if (hosts == nil) {
  271. return;
  272. }
  273. @synchronized (self) {
  274. [self.prefetchHosts addObjectsFromArray:hosts];
  275. }
  276. [self preFetchHosts:hosts];
  277. [self recorderDnsCache];
  278. [self endPreFetch];
  279. }
  280. /// 检测已预取dns是否还有效,无效则重新预取
  281. - (void)checkWhetherCachedDnsValid{
  282. if ([self prepareToPreFetch] == NO) {
  283. return;
  284. }
  285. NSArray *hosts = nil;
  286. @synchronized (self) {
  287. hosts = [self.prefetchHosts allObjects];
  288. }
  289. [self preFetchHosts:hosts];
  290. [self recorderDnsCache];
  291. [self endPreFetch];
  292. }
  293. //MARK: -- 读取缓存的DNS信息
  294. /// 根据host从缓存中读取DNS信息
  295. - (NSArray <id <QNIDnsNetworkAddress> > *)getInetAddressByHost:(NSString *)host{
  296. if ([self isDnsOpen] == NO) {
  297. return nil;
  298. }
  299. [self clearDnsCacheIfNeeded];
  300. NSArray <QNDnsNetworkAddress *> *addressList = nil;
  301. @synchronized (self) {
  302. addressList = self.addressDictionary[host];
  303. }
  304. if (addressList && addressList.count > 0 && [addressList.firstObject isValid]) {
  305. return addressList;
  306. } else {
  307. return nil;
  308. }
  309. }
  310. - (void)invalidNetworkAddressOfHost:(NSString *)host {
  311. if (host == nil || host.length == 0) {
  312. return;
  313. }
  314. @synchronized (self) {
  315. [self.addressDictionary removeObjectForKey:host];
  316. }
  317. }
  318. - (void)clearDnsCache:(NSError *__autoreleasing _Nullable *)error {
  319. [self clearDnsMemoryCache];
  320. [self clearDnsDiskCache:error];
  321. }
  322. //MARK: --
  323. //MARK: -- 根据dns预取
  324. - (NSString *)prefetchHostBySafeDns:(NSString *)host error:(NSError * __autoreleasing *)error {
  325. if (host == nil) {
  326. return nil;
  327. }
  328. [self invalidNetworkAddressOfHost:host];
  329. NSError *err = nil;
  330. NSArray *nextFetchHosts = @[host];
  331. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.customDns error:&err];
  332. if (nextFetchHosts.count == 0) {
  333. return [self getInetAddressByHost:host].firstObject.sourceValue;
  334. }
  335. if (!kQNGlobalConfiguration.dohEnable) {
  336. if (error != nil && err) {
  337. *error = err;
  338. }
  339. return nil;
  340. }
  341. if (kQNGlobalConfiguration.dohIpv4Servers && [kQNGlobalConfiguration.dohIpv4Servers count] > 0) {
  342. QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  343. QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
  344. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:&err];
  345. if (nextFetchHosts.count == 0) {
  346. return [self getInetAddressByHost:host].firstObject.sourceValue;
  347. }
  348. if (error != nil && err) {
  349. *error = err;
  350. }
  351. }
  352. if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.dohIpv6Servers && [kQNGlobalConfiguration.dohIpv6Servers count] > 0) {
  353. QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  354. QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
  355. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:&err];
  356. if (error != nil && err) {
  357. *error = err;
  358. }
  359. }
  360. if (nextFetchHosts.count == 0) {
  361. return [self getInetAddressByHost:host].firstObject.sourceValue;
  362. } else {
  363. return nil;
  364. }
  365. }
  366. - (BOOL)prepareToPreFetch {
  367. if ([self isDnsOpen] == NO) {
  368. return NO;
  369. }
  370. self.lastPrefetchedErrorMessage = nil;
  371. if (self.isPrefetching == YES) {
  372. return NO;
  373. }
  374. [self clearDnsCacheIfNeeded];
  375. self.isPrefetching = YES;
  376. return YES;
  377. }
  378. - (void)endPreFetch{
  379. self.isPrefetching = NO;
  380. }
  381. - (void)preFetchHosts:(NSArray <NSString *> *)fetchHosts {
  382. NSError *err = nil;
  383. [self preFetchHosts:fetchHosts error:&err];
  384. self.lastPrefetchedErrorMessage = err.description;
  385. }
  386. - (void)preFetchHosts:(NSArray <NSString *> *)fetchHosts error:(NSError **)error {
  387. NSArray *nextFetchHosts = fetchHosts;
  388. // 定制
  389. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.customDns error:error];
  390. if (nextFetchHosts.count == 0) {
  391. return;
  392. }
  393. // 系统
  394. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.systemDns error:error];
  395. if (nextFetchHosts.count == 0) {
  396. return;
  397. }
  398. // doh
  399. if (kQNGlobalConfiguration.dohEnable) {
  400. if (kQNGlobalConfiguration.dohIpv4Servers && [kQNGlobalConfiguration.dohIpv4Servers count] > 0) {
  401. QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  402. QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
  403. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:error];
  404. if (nextFetchHosts.count == 0) {
  405. return;
  406. }
  407. }
  408. if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.dohIpv6Servers && [kQNGlobalConfiguration.dohIpv6Servers count] > 0) {
  409. QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  410. QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
  411. nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:error];
  412. if (nextFetchHosts.count == 0) {
  413. return;
  414. }
  415. }
  416. }
  417. // udp
  418. if (kQNGlobalConfiguration.udpDnsEnable) {
  419. if (kQNGlobalConfiguration.udpDnsIpv4Servers && [kQNGlobalConfiguration.udpDnsIpv4Servers count] > 0) {
  420. QNDnsUdpResolver *udpDnsResolver = [QNDnsUdpResolver resolverWithServerIPs:kQNGlobalConfiguration.udpDnsIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  421. QNInternalDns *udpDns = [QNInternalDns dnsWithResolver:udpDnsResolver];
  422. [self preFetchHosts:nextFetchHosts dns:udpDns error:error];
  423. }
  424. if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.udpDnsIpv6Servers && [kQNGlobalConfiguration.udpDnsIpv6Servers count] > 0) {
  425. QNDnsUdpResolver *udpDnsResolver = [QNDnsUdpResolver resolverWithServerIPs:kQNGlobalConfiguration.udpDnsIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
  426. QNInternalDns *udpDns = [QNInternalDns dnsWithResolver:udpDnsResolver];
  427. [self preFetchHosts:nextFetchHosts dns:udpDns error:error];
  428. }
  429. }
  430. }
  431. - (NSArray *)preFetchHosts:(NSArray <NSString *> *)preHosts dns:(QNInternalDns *)dns error:(NSError **)error {
  432. if (!preHosts || preHosts.count == 0) {
  433. return nil;
  434. }
  435. if (!dns) {
  436. return [preHosts copy];
  437. }
  438. int dnsRepreHostNum = kQNGlobalConfiguration.dnsRepreHostNum;
  439. NSMutableArray *failHosts = [NSMutableArray array];
  440. for (NSString *host in preHosts) {
  441. int rePreNum = 0;
  442. BOOL isSuccess = NO;
  443. while (rePreNum < dnsRepreHostNum) {
  444. if ([self preFetchHost:host dns:dns error:error]) {
  445. isSuccess = YES;
  446. break;
  447. }
  448. rePreNum += 1;
  449. }
  450. if (!isSuccess) {
  451. [failHosts addObject:host];
  452. }
  453. }
  454. return [failHosts copy];
  455. }
  456. - (BOOL)preFetchHost:(NSString *)preHost dns:(QNInternalDns *)dns error:(NSError **)error {
  457. if (!preHost || preHost.length == 0) {
  458. return NO;
  459. }
  460. NSDictionary *addressDictionary = nil;
  461. @synchronized (self) {
  462. addressDictionary = [self.addressDictionary copy];
  463. }
  464. NSArray<QNDnsNetworkAddress *>* preAddressList = addressDictionary[preHost];
  465. if (preAddressList && ![preAddressList.firstObject needRefresh]) {
  466. return YES;
  467. }
  468. NSArray <id <QNIDnsNetworkAddress> > * addressList = [dns query:preHost error:error];
  469. if (addressList && addressList.count > 0) {
  470. NSMutableArray *addressListP = [NSMutableArray array];
  471. for (id <QNIDnsNetworkAddress>inetAddress in addressList) {
  472. QNDnsNetworkAddress *address = [QNDnsNetworkAddress inetAddress:inetAddress];
  473. if (address) {
  474. address.hostValue = preHost;
  475. if (!address.ttlValue) {
  476. address.ttlValue = @(kQNDefaultDnsCacheTime);
  477. }
  478. if (!address.timestampValue) {
  479. address.timestampValue = @([[NSDate date] timeIntervalSince1970]);
  480. }
  481. [addressListP addObject:address];
  482. }
  483. }
  484. addressListP = [addressListP copy];
  485. @synchronized (self) {
  486. self.addressDictionary[preHost] = addressListP;
  487. }
  488. return YES;
  489. } else {
  490. return NO;
  491. }
  492. }
  493. //MARK: -- 加载和存储缓存信息
  494. - (BOOL)recoverDnsCache:(NSDictionary *)dataDic{
  495. if (dataDic == nil) {
  496. return NO;
  497. }
  498. NSMutableDictionary *records = [NSMutableDictionary dictionary];
  499. for (NSString *key in dataDic.allKeys) {
  500. NSArray *ips = dataDic[key];
  501. if ([ips isKindOfClass:[NSArray class]]) {
  502. NSMutableArray <QNDnsNetworkAddress *> * addressList = [NSMutableArray array];
  503. for (NSDictionary *ipInfo in ips) {
  504. if ([ipInfo isKindOfClass:[NSDictionary class]]) {
  505. QNDnsNetworkAddress *address = [QNDnsNetworkAddress inetAddress:ipInfo];
  506. if (address) {
  507. [addressList addObject:address];
  508. }
  509. }
  510. }
  511. if (addressList.count > 0) {
  512. records[key] = [addressList copy];
  513. }
  514. }
  515. }
  516. @synchronized (self) {
  517. [self.addressDictionary setValuesForKeysWithDictionary:records];
  518. }
  519. return NO;
  520. }
  521. - (BOOL)recorderDnsCache{
  522. NSTimeInterval currentTime = [QNUtils currentTimestamp];
  523. NSString *localIp = [QNIP local];
  524. if (localIp == nil || localIp.length == 0) {
  525. return NO;
  526. }
  527. NSError *error;
  528. id <QNRecorderDelegate> recorder = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir
  529. error:&error];
  530. if (error) {
  531. return NO;
  532. }
  533. NSDictionary *addressDictionary = nil;
  534. @synchronized (self) {
  535. addressDictionary = [self.addressDictionary copy];
  536. }
  537. NSMutableDictionary *addressInfo = [NSMutableDictionary dictionary];
  538. for (NSString *key in addressDictionary.allKeys) {
  539. NSArray *addressModelList = addressDictionary[key];
  540. NSMutableArray * addressDicList = [NSMutableArray array];
  541. for (QNDnsNetworkAddress *ipInfo in addressModelList) {
  542. NSDictionary *addressDic = [ipInfo toDictionary];
  543. if (addressDic) {
  544. [addressDicList addObject:addressDic];
  545. }
  546. }
  547. if (addressDicList.count > 0) {
  548. addressInfo[key] = addressDicList;
  549. }
  550. }
  551. QNDnsCacheInfo *cacheInfo = [QNDnsCacheInfo dnsCacheInfo:[NSString stringWithFormat:@"%.0lf",currentTime]
  552. localIp:localIp
  553. info:addressInfo];
  554. NSData *cacheData = [cacheInfo jsonData];
  555. if (!cacheData) {
  556. return NO;
  557. }
  558. [self setDnsCacheInfo:cacheInfo];
  559. [recorder set:localIp data:cacheData];
  560. return true;
  561. }
  562. - (void)clearDnsCacheIfNeeded{
  563. NSString *localIp = [QNIP local];
  564. if (localIp == nil || (self.dnsCacheInfo && ![localIp isEqualToString:self.dnsCacheInfo.localIp])) {
  565. [self clearDnsMemoryCache];
  566. }
  567. }
  568. - (void)clearDnsMemoryCache {
  569. @synchronized (self) {
  570. [self.addressDictionary removeAllObjects];
  571. }
  572. }
  573. - (void)clearDnsDiskCache:(NSError **)error {
  574. [self.diskCache clearCache:error];
  575. }
  576. //MARK: -- 获取预取hosts
  577. - (NSArray <NSString *> *)getLocalPreHost{
  578. NSMutableArray *localHosts = [NSMutableArray array];
  579. [localHosts addObject:kQNUpLogHost];
  580. return [localHosts copy];
  581. }
  582. - (NSArray <NSString *> *)getCurrentZoneHosts:(QNZone *)currentZone
  583. token:(QNUpToken *)token{
  584. if (!currentZone || !token || !token.token) {
  585. return nil;
  586. }
  587. [currentZone preQuery:token on:^(int code, QNResponseInfo *responseInfo, QNUploadRegionRequestMetrics *metrics) {
  588. dispatch_semaphore_signal(self.semaphore);
  589. }];
  590. dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
  591. QNZonesInfo *autoZonesInfo = [currentZone getZonesInfoWithToken:token];
  592. NSMutableArray *autoHosts = [NSMutableArray array];
  593. NSArray *zoneInfoList = autoZonesInfo.zonesInfo;
  594. for (QNZoneInfo *info in zoneInfoList) {
  595. if (info.allHosts) {
  596. [autoHosts addObjectsFromArray:info.allHosts];
  597. }
  598. }
  599. return [autoHosts copy];
  600. }
  601. //MARK: --
  602. - (BOOL)isDnsOpen{
  603. return [kQNGlobalConfiguration isDnsOpen];
  604. }
  605. - (QNDnsCacheInfo *)dnsCacheInfo{
  606. if (_dnsCacheInfo == nil) {
  607. _dnsCacheInfo = [[QNDnsCacheInfo alloc] init];
  608. }
  609. return _dnsCacheInfo;
  610. }
  611. - (NSMutableDictionary<NSString *,NSArray<QNDnsNetworkAddress *> *> *)addressDictionary{
  612. if (_addressDictionary == nil) {
  613. _addressDictionary = [NSMutableDictionary dictionary];
  614. }
  615. return _addressDictionary;
  616. }
  617. - (dispatch_semaphore_t)semaphore{
  618. if (_getAutoZoneSemaphore == NULL) {
  619. _getAutoZoneSemaphore = dispatch_semaphore_create(0);
  620. }
  621. return _getAutoZoneSemaphore;
  622. }
  623. - (QNDnsCacheFile *)diskCache {
  624. if (!_diskCache) {
  625. NSError *error;
  626. QNDnsCacheFile *cache = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir error:&error];
  627. if (!error) {
  628. _diskCache = cache;
  629. }
  630. }
  631. return _diskCache;
  632. }
  633. - (QNInternalDns *)customDns {
  634. if (_customDns == nil && kQNGlobalConfiguration.dns) {
  635. _customDns = [QNInternalDns dnsWithDns:kQNGlobalConfiguration.dns];
  636. }
  637. return _customDns;
  638. }
  639. - (QNInternalDns *)systemDns {
  640. if (_systemDns == nil) {
  641. _systemDns = [QNInternalDns dnsWithResolver:[[QNResolver alloc] initWithAddress:nil timeout:self.dnsPrefetchTimeout]];
  642. }
  643. return _systemDns;
  644. }
  645. - (NSMutableSet *)prefetchHosts {
  646. if (!_prefetchHosts) {
  647. _prefetchHosts = [NSMutableSet set];
  648. }
  649. return _prefetchHosts;
  650. }
  651. @end
  652. //MARK: -- DNS 事务
  653. @implementation QNTransactionManager(Dns)
  654. #define kQNLoadLocalDnsTransactionName @"QNLoadLocalDnsTransaction"
  655. #define kQNDnsCheckAndPrefetchTransactionName @"QNDnsCheckAndPrefetchTransactionName"
  656. - (void)addDnsLocalLoadTransaction{
  657. if ([kQNDnsPrefetch isDnsOpen] == NO) {
  658. return;
  659. }
  660. static dispatch_once_t onceToken;
  661. dispatch_once(&onceToken, ^{
  662. QNTransaction *transaction = [QNTransaction transaction:kQNLoadLocalDnsTransactionName after:0 action:^{
  663. [kQNDnsPrefetch recoverCache];
  664. [kQNDnsPrefetch localFetch];
  665. }];
  666. [[QNTransactionManager shared] addTransaction:transaction];
  667. [self setDnsCheckWhetherCachedValidTransactionAction];
  668. });
  669. }
  670. - (BOOL)addDnsCheckAndPrefetchTransaction:(QNZone *)currentZone token:(QNUpToken *)token{
  671. if (!token) {
  672. return NO;
  673. }
  674. if ([kQNDnsPrefetch isDnsOpen] == NO) {
  675. return NO;
  676. }
  677. BOOL ret = NO;
  678. @synchronized (kQNDnsPrefetch) {
  679. QNTransactionManager *transactionManager = [QNTransactionManager shared];
  680. if (![transactionManager existTransactionsForName:token.token]) {
  681. QNTransaction *transaction = [QNTransaction transaction:token.token after:0 action:^{
  682. [kQNDnsPrefetch checkAndPrefetchDnsIfNeed:currentZone token:token];
  683. }];
  684. [transactionManager addTransaction:transaction];
  685. ret = YES;
  686. }
  687. }
  688. return ret;
  689. }
  690. - (void)setDnsCheckWhetherCachedValidTransactionAction{
  691. if ([kQNDnsPrefetch isDnsOpen] == NO) {
  692. return;
  693. }
  694. @synchronized (kQNDnsPrefetch) {
  695. QNTransactionManager *transactionManager = [QNTransactionManager shared];
  696. QNTransaction *transaction = [transactionManager transactionsForName:kQNDnsCheckAndPrefetchTransactionName].firstObject;
  697. if (!transaction) {
  698. QNTransaction *transaction = [QNTransaction timeTransaction:kQNDnsCheckAndPrefetchTransactionName
  699. after:10
  700. interval:120
  701. action:^{
  702. [kQNDnsPrefetch checkWhetherCachedDnsValid];
  703. }];
  704. [transactionManager addTransaction:transaction];
  705. } else {
  706. [transactionManager performTransaction:transaction];
  707. }
  708. }
  709. }
  710. @end
  711. BOOL kQNIsDnsSourceDoh(NSString * _Nullable source) {
  712. return [source containsString:kQNDnsSourceDoh];
  713. }
  714. BOOL kQNIsDnsSourceUdp(NSString * _Nullable source) {
  715. return [source containsString:kQNDnsSourceUdp];
  716. }
  717. BOOL kQNIsDnsSourceDnsPod(NSString * _Nullable source) {
  718. return [source containsString:kQNDnsSourceDnspod];
  719. }
  720. BOOL kQNIsDnsSourceSystem(NSString * _Nullable source) {
  721. return [source containsString:kQNDnsSourceSystem];
  722. }
  723. BOOL kQNIsDnsSourceCustom(NSString * _Nullable source) {
  724. return [source containsString:kQNDnsSourceCustom];
  725. }