解决了语音上传到问题,接下来要解决下载播放问题

This commit is contained in:
joywayer
2025-06-15 12:36:47 +08:00
parent bba3ed1cb4
commit c11fc62bf1
513 changed files with 31197 additions and 2969 deletions

View File

@@ -0,0 +1,874 @@
//
// QNDnsPrefetch.m
// QnDNS
//
// Created by yangsen on 2020/3/26.
// Copyright © 2020 com.qiniu. All rights reserved.
//
#import "QNDnsPrefetch.h"
#import "QNInetAddress.h"
#import "QNDnsCacheInfo.h"
#import "QNZoneInfo.h"
#import "QNDefine.h"
#import "QNConfig.h"
#import "QNDnsCacheFile.h"
#import "QNUtils.h"
#import "QNAsyncRun.h"
#import "QNFixedZone.h"
#import "QNAutoZone.h"
#import <HappyDNS/HappyDNS.h>
//MARK: --
@interface QNDnsNetworkAddress : NSObject<QNIDnsNetworkAddress>
@property(nonatomic, copy)NSString *hostValue;
@property(nonatomic, copy)NSString *ipValue;
@property(nonatomic, strong)NSNumber *ttlValue;
@property(nonatomic, copy)NSString *sourceValue;
@property(nonatomic, strong)NSNumber *timestampValue;
/// addressDatajson String / Dictionary / Data / QNIDnsNetworkAddress
+ (instancetype)inetAddress:(id)addressInfo;
///
- (BOOL)isValid;
/// json
- (NSString *)toJsonInfo;
///
- (NSDictionary *)toDictionary;
@end
@implementation QNDnsNetworkAddress
+ (instancetype)inetAddress:(id)addressInfo{
NSDictionary *addressDic = nil;
if ([addressInfo isKindOfClass:[NSDictionary class]]) {
addressDic = (NSDictionary *)addressInfo;
} else if ([addressInfo isKindOfClass:[NSString class]]){
NSData *data = [(NSString *)addressInfo dataUsingEncoding:NSUTF8StringEncoding];
addressDic = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableLeaves
error:nil];
} else if ([addressInfo isKindOfClass:[NSData class]]) {
addressDic = [NSJSONSerialization JSONObjectWithData:(NSData *)addressInfo
options:NSJSONReadingMutableLeaves
error:nil];
} else if ([addressInfo conformsToProtocol:@protocol(QNIDnsNetworkAddress)]){
id <QNIDnsNetworkAddress> address = (id <QNIDnsNetworkAddress> )addressInfo;
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
if ([address respondsToSelector:@selector(hostValue)] && [address hostValue]) {
dic[@"hostValue"] = [address hostValue];
}
if ([address respondsToSelector:@selector(ipValue)] && [address ipValue]) {
dic[@"ipValue"] = [address ipValue];
}
if ([address respondsToSelector:@selector(ttlValue)] && [address ttlValue]) {
dic[@"ttlValue"] = [address ttlValue];
}
if ([address respondsToSelector:@selector(sourceValue)] && [address sourceValue]) {
dic[@"sourceValue"] = [address sourceValue];
} else {
dic[@"sourceValue"] = kQNDnsSourceCustom;
}
if ([address respondsToSelector:@selector(timestampValue)] && [address timestampValue]) {
dic[@"timestampValue"] = [address timestampValue];
}
addressDic = [dic copy];
}
if (addressDic) {
QNDnsNetworkAddress *address = [[QNDnsNetworkAddress alloc] init];
[address setValuesForKeysWithDictionary:addressDic];
return address;
} else {
return nil;
}
}
/// ttl
- (BOOL)needRefresh{
if (!self.timestampValue || !self.ipValue || self.ipValue.length == 0) {
return NO;
}
NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
return currentTimestamp > (self.timestampValue.doubleValue + self.ttlValue.doubleValue);
}
/// ttl
- (BOOL)isValid{
if (!self.timestampValue || !self.ipValue || self.ipValue.length == 0) {
return NO;
}
NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
return currentTimestamp < (self.timestampValue.doubleValue + kQNGlobalConfiguration.dnsCacheMaxTTL);
}
- (NSString *)toJsonInfo{
NSString *defaultString = @"{}";
NSDictionary *infoDic = [self toDictionary];
if (!infoDic) {
return defaultString;
}
NSData *infoData = [NSJSONSerialization dataWithJSONObject:infoDic
options:NSJSONWritingPrettyPrinted
error:nil];
if (!infoData) {
return defaultString;
}
NSString *infoStr = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
if (!infoStr) {
return defaultString;
} else {
return infoStr;
}
}
- (NSDictionary *)toDictionary{
return [self dictionaryWithValuesForKeys:@[@"ipValue", @"hostValue", @"ttlValue", @"sourceValue", @"timestampValue"]];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
@end
//MARK: -- HappyDNS
@interface QNRecord(DNS)<QNIDnsNetworkAddress>
@end
@implementation QNRecord(DNS)
- (NSString *)hostValue{
return nil;
}
- (NSString *)ipValue{
return self.value;
}
- (NSNumber *)ttlValue{
return @(self.ttl);
}
- (NSNumber *)timestampValue{
return @(self.timeStamp);
}
- (NSString *)sourceValue{
if (self.source == QNRecordSourceSystem) {
return kQNDnsSourceSystem;
} else if (self.source == QNRecordSourceDoh) {
return [NSString stringWithFormat:@"%@<%@>", kQNDnsSourceDoh, self.server];
} else if (self.source == QNRecordSourceUdp) {
return [NSString stringWithFormat:@"%@<%@>", kQNDnsSourceUdp, self.server];
} else if (self.source == QNRecordSourceDnspodEnterprise) {
return kQNDnsSourceDnspod;
} else if (self.ipValue == nil || self.ipValue.length == 0) {
return kQNDnsSourceNone;
} else {
return kQNDnsSourceCustom;
}
}
@end
@interface QNInternalDns : NSObject
@property(nonatomic, strong)id<QNDnsDelegate> dns;
@property(nonatomic, strong)id<QNResolverDelegate> resolver;
@end
@implementation QNInternalDns
+ (instancetype)dnsWithDns:(id<QNDnsDelegate>)dns {
QNInternalDns *interDns = [[QNInternalDns alloc] init];
interDns.dns = dns;
return interDns;
}
+ (instancetype)dnsWithResolver:(id<QNResolverDelegate>)resolver {
QNInternalDns *interDns = [[QNInternalDns alloc] init];
interDns.resolver = resolver;
return interDns;
}
- (NSArray < id <QNIDnsNetworkAddress> > *)query:(NSString *)host error:(NSError **)error {
if (self.dns && [self.dns respondsToSelector:@selector(query:)]) {
return [self.dns query:host];
} else if (self.resolver) {
NSArray <QNRecord *>* records = [self.resolver query:[[QNDomain alloc] init:host] networkInfo:nil error:error];
return [self filterRecords:records];
}
return nil;
}
- (NSArray <QNRecord *>*)filterRecords:(NSArray <QNRecord *>*)records {
NSMutableArray <QNRecord *> *newRecords = [NSMutableArray array];
for (QNRecord *record in records) {
if (record.type == kQNTypeA || record.type == kQNTypeAAAA) {
[newRecords addObject:record];
}
}
return [newRecords copy];
}
@end
//MARK: -- DNS Prefetcher
@interface QNDnsPrefetch()
// dns 3s
@property(nonatomic, assign)int dnsPrefetchTimeout;
//
@property(nonatomic, copy)NSString *lastPrefetchedErrorMessage;
///
@property(atomic, assign)BOOL isPrefetching;
/// AutoZone
@property(nonatomic, strong)dispatch_semaphore_t getAutoZoneSemaphore;
/// DNSkey
@property(nonatomic, strong)QNDnsCacheInfo *dnsCacheInfo;
// dns
@property(nonatomic, strong)QNInternalDns *customDns;
// dns
@property(nonatomic, strong)QNInternalDns *systemDns;
/// prefetch hosts
@property(nonatomic, strong)NSMutableSet *prefetchHosts;
/// DNS
/// 线线
@property(nonatomic, strong)NSMutableDictionary <NSString *, NSArray<QNDnsNetworkAddress *>*> *addressDictionary;
@property(nonatomic, strong)QNDnsCacheFile *diskCache;
@end
@implementation QNDnsPrefetch
+ (instancetype)shared{
static QNDnsPrefetch *prefetcher = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
prefetcher = [[QNDnsPrefetch alloc] init];
});
return prefetcher;
}
- (instancetype)init{
if (self = [super init]) {
_isPrefetching = NO;
_dnsPrefetchTimeout = 3;
}
return self;
}
//MARK: -- uploadManager
/// 使falsetrue
- (BOOL)recoverCache{
id <QNRecorderDelegate> recorder = nil;
NSError *error;
recorder = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir
error:&error];
if (error) {
return YES;
}
NSData *data = [recorder get:[QNIP local]];
if (!data) {
return YES;
}
QNDnsCacheInfo *cacheInfo = [QNDnsCacheInfo dnsCacheInfo:data];
if (!cacheInfo) {
return YES;
}
NSString *localIp = [QNIP local];
if (!localIp || localIp.length == 0 || ![cacheInfo.localIp isEqualToString:localIp]) {
return YES;
}
[self setDnsCacheInfo:cacheInfo];
return [self recoverDnsCache:cacheInfo.info];
}
/// DNS
- (void)localFetch{
if ([self prepareToPreFetch] == NO) {
return;
}
NSArray *hosts = [self getLocalPreHost];
@synchronized (self) {
[self.prefetchHosts addObjectsFromArray:hosts];
}
[self preFetchHosts:hosts];
[self recorderDnsCache];
[self endPreFetch];
}
//MARK: --
/// tokenDns YESNO
- (void)checkAndPrefetchDnsIfNeed:(QNConfiguration *)config zone:(QNZone *)currentZone token:(QNUpToken *)token{
if ([self prepareToPreFetch] == NO) {
return;
}
NSArray *hosts = [self getCurrentZoneHosts:config zone:currentZone token:token];
if (hosts == nil) {
return;
}
@synchronized (self) {
[self.prefetchHosts addObjectsFromArray:hosts];
}
[self preFetchHosts:hosts];
[self recorderDnsCache];
[self endPreFetch];
}
/// dns
- (void)checkWhetherCachedDnsValid{
if ([self prepareToPreFetch] == NO) {
return;
}
NSArray *hosts = nil;
@synchronized (self) {
hosts = [self.prefetchHosts allObjects];
}
[self preFetchHosts:hosts];
[self recorderDnsCache];
[self endPreFetch];
}
//MARK: -- DNS
/// hostDNS
- (NSArray <id <QNIDnsNetworkAddress> > *)getInetAddressByHost:(NSString *)host{
if ([self isDnsOpen] == NO) {
return nil;
}
[self clearDnsCacheIfNeeded];
NSArray <QNDnsNetworkAddress *> *addressList = nil;
@synchronized (self) {
addressList = self.addressDictionary[host];
}
if (addressList && addressList.count > 0 && [addressList.firstObject isValid]) {
return addressList;
} else {
return nil;
}
}
- (void)invalidNetworkAddressOfHost:(NSString *)host {
if (host == nil || host.length == 0) {
return;
}
@synchronized (self) {
[self.addressDictionary removeObjectForKey:host];
}
}
- (void)clearDnsCache:(NSError *__autoreleasing _Nullable *)error {
[self clearDnsMemoryCache];
[self clearDnsDiskCache:error];
}
//MARK: --
//MARK: -- dns
- (NSString *)prefetchHostBySafeDns:(NSString *)host error:(NSError * __autoreleasing *)error {
if (host == nil) {
return nil;
}
[self invalidNetworkAddressOfHost:host];
NSError *err = nil;
NSArray *nextFetchHosts = @[host];
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.customDns error:&err];
if (nextFetchHosts.count == 0) {
return [self getInetAddressByHost:host].firstObject.sourceValue;
}
if (!kQNGlobalConfiguration.dohEnable) {
if (error != nil && err) {
*error = err;
}
return nil;
}
if (kQNGlobalConfiguration.dohIpv4Servers && [kQNGlobalConfiguration.dohIpv4Servers count] > 0) {
QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:&err];
if (nextFetchHosts.count == 0) {
return [self getInetAddressByHost:host].firstObject.sourceValue;
}
if (error != nil && err) {
*error = err;
}
}
if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.dohIpv6Servers && [kQNGlobalConfiguration.dohIpv6Servers count] > 0) {
QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:&err];
if (error != nil && err) {
*error = err;
}
}
if (nextFetchHosts.count == 0) {
return [self getInetAddressByHost:host].firstObject.sourceValue;
} else {
return nil;
}
}
- (BOOL)prepareToPreFetch {
if ([self isDnsOpen] == NO) {
return NO;
}
self.lastPrefetchedErrorMessage = nil;
if (self.isPrefetching == YES) {
return NO;
}
[self clearDnsCacheIfNeeded];
self.isPrefetching = YES;
return YES;
}
- (void)endPreFetch{
self.isPrefetching = NO;
}
- (void)preFetchHosts:(NSArray <NSString *> *)fetchHosts {
NSError *err = nil;
[self preFetchHosts:fetchHosts error:&err];
self.lastPrefetchedErrorMessage = err.description;
}
- (void)preFetchHosts:(NSArray <NSString *> *)fetchHosts error:(NSError **)error {
NSArray *nextFetchHosts = fetchHosts;
//
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.customDns error:error];
if (nextFetchHosts.count == 0) {
return;
}
//
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:self.systemDns error:error];
if (nextFetchHosts.count == 0) {
return;
}
// doh
if (kQNGlobalConfiguration.dohEnable) {
if (kQNGlobalConfiguration.dohIpv4Servers && [kQNGlobalConfiguration.dohIpv4Servers count] > 0) {
QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:error];
if (nextFetchHosts.count == 0) {
return;
}
}
if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.dohIpv6Servers && [kQNGlobalConfiguration.dohIpv6Servers count] > 0) {
QNDohResolver *dohResolver = [QNDohResolver resolverWithServers:kQNGlobalConfiguration.dohIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *doh = [QNInternalDns dnsWithResolver:dohResolver];
nextFetchHosts = [self preFetchHosts:nextFetchHosts dns:doh error:error];
if (nextFetchHosts.count == 0) {
return;
}
}
}
// udp
if (kQNGlobalConfiguration.udpDnsEnable) {
if (kQNGlobalConfiguration.udpDnsIpv4Servers && [kQNGlobalConfiguration.udpDnsIpv4Servers count] > 0) {
QNDnsUdpResolver *udpDnsResolver = [QNDnsUdpResolver resolverWithServerIPs:kQNGlobalConfiguration.udpDnsIpv4Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *udpDns = [QNInternalDns dnsWithResolver:udpDnsResolver];
[self preFetchHosts:nextFetchHosts dns:udpDns error:error];
}
if ([QNIP isIpV6FullySupported] && kQNGlobalConfiguration.udpDnsIpv6Servers && [kQNGlobalConfiguration.udpDnsIpv6Servers count] > 0) {
QNDnsUdpResolver *udpDnsResolver = [QNDnsUdpResolver resolverWithServerIPs:kQNGlobalConfiguration.udpDnsIpv6Servers recordType:kQNTypeA timeout:kQNGlobalConfiguration.dnsResolveTimeout];
QNInternalDns *udpDns = [QNInternalDns dnsWithResolver:udpDnsResolver];
[self preFetchHosts:nextFetchHosts dns:udpDns error:error];
}
}
}
- (NSArray *)preFetchHosts:(NSArray <NSString *> *)preHosts dns:(QNInternalDns *)dns error:(NSError **)error {
if (!preHosts || preHosts.count == 0) {
return nil;
}
if (!dns) {
return [preHosts copy];
}
int dnsRepreHostNum = kQNGlobalConfiguration.dnsRepreHostNum;
NSMutableArray *failHosts = [NSMutableArray array];
for (NSString *host in preHosts) {
int rePreNum = 0;
BOOL isSuccess = NO;
while (rePreNum < dnsRepreHostNum) {
if ([self preFetchHost:host dns:dns error:error]) {
isSuccess = YES;
break;
}
rePreNum += 1;
}
if (!isSuccess) {
[failHosts addObject:host];
}
}
return [failHosts copy];
}
- (BOOL)preFetchHost:(NSString *)preHost dns:(QNInternalDns *)dns error:(NSError **)error {
if (!preHost || preHost.length == 0) {
return NO;
}
NSDictionary *addressDictionary = nil;
@synchronized (self) {
addressDictionary = [self.addressDictionary copy];
}
NSArray<QNDnsNetworkAddress *>* preAddressList = addressDictionary[preHost];
if (preAddressList && ![preAddressList.firstObject needRefresh]) {
return YES;
}
NSArray <id <QNIDnsNetworkAddress> > * addressList = [dns query:preHost error:error];
if (addressList && addressList.count > 0) {
NSMutableArray *addressListP = [NSMutableArray array];
for (id <QNIDnsNetworkAddress>inetAddress in addressList) {
QNDnsNetworkAddress *address = [QNDnsNetworkAddress inetAddress:inetAddress];
if (address) {
address.hostValue = preHost;
if (!address.ttlValue) {
address.ttlValue = @(kQNDefaultDnsCacheTime);
}
if (!address.timestampValue) {
address.timestampValue = @([[NSDate date] timeIntervalSince1970]);
}
[addressListP addObject:address];
}
}
addressListP = [addressListP copy];
@synchronized (self) {
self.addressDictionary[preHost] = addressListP;
}
return YES;
} else {
return NO;
}
}
//MARK: --
- (BOOL)recoverDnsCache:(NSDictionary *)dataDic{
if (dataDic == nil) {
return NO;
}
NSMutableDictionary *records = [NSMutableDictionary dictionary];
for (NSString *key in dataDic.allKeys) {
NSArray *ips = dataDic[key];
if ([ips isKindOfClass:[NSArray class]]) {
NSMutableArray <QNDnsNetworkAddress *> * addressList = [NSMutableArray array];
for (NSDictionary *ipInfo in ips) {
if ([ipInfo isKindOfClass:[NSDictionary class]]) {
QNDnsNetworkAddress *address = [QNDnsNetworkAddress inetAddress:ipInfo];
if (address) {
[addressList addObject:address];
}
}
}
if (addressList.count > 0) {
records[key] = [addressList copy];
}
}
}
@synchronized (self) {
[self.addressDictionary setValuesForKeysWithDictionary:records];
}
return NO;
}
- (BOOL)recorderDnsCache{
NSTimeInterval currentTime = [QNUtils currentTimestamp];
NSString *localIp = [QNIP local];
if (localIp == nil || localIp.length == 0) {
return NO;
}
NSError *error;
id <QNRecorderDelegate> recorder = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir
error:&error];
if (error) {
return NO;
}
NSDictionary *addressDictionary = nil;
@synchronized (self) {
addressDictionary = [self.addressDictionary copy];
}
NSMutableDictionary *addressInfo = [NSMutableDictionary dictionary];
for (NSString *key in addressDictionary.allKeys) {
NSArray *addressModelList = addressDictionary[key];
NSMutableArray * addressDicList = [NSMutableArray array];
for (QNDnsNetworkAddress *ipInfo in addressModelList) {
NSDictionary *addressDic = [ipInfo toDictionary];
if (addressDic) {
[addressDicList addObject:addressDic];
}
}
if (addressDicList.count > 0) {
addressInfo[key] = addressDicList;
}
}
QNDnsCacheInfo *cacheInfo = [QNDnsCacheInfo dnsCacheInfo:[NSString stringWithFormat:@"%.0lf",currentTime]
localIp:localIp
info:addressInfo];
NSData *cacheData = [cacheInfo jsonData];
if (!cacheData) {
return NO;
}
[self setDnsCacheInfo:cacheInfo];
[recorder set:localIp data:cacheData];
return true;
}
- (void)clearDnsCacheIfNeeded{
NSString *localIp = [QNIP local];
if (localIp == nil || (self.dnsCacheInfo && ![localIp isEqualToString:self.dnsCacheInfo.localIp])) {
[self clearDnsMemoryCache];
}
}
- (void)clearDnsMemoryCache {
@synchronized (self) {
[self.addressDictionary removeAllObjects];
}
}
- (void)clearDnsDiskCache:(NSError **)error {
[self.diskCache clearCache:error];
}
//MARK: -- hosts
- (NSArray <NSString *> *)getLocalPreHost{
NSMutableArray *localHosts = [NSMutableArray array];
[localHosts addObject:kQNUpLogHost];
return [localHosts copy];
}
- (NSArray <NSString *> *)getCurrentZoneHosts:(QNConfiguration *)config
zone:(QNZone *)currentZone
token:(QNUpToken *)token{
if (!currentZone || !token || !token.token) {
return nil;
}
__block QNZonesInfo *zonesInfo = nil;
[currentZone query:config token:token on:^(QNResponseInfo * _Nullable httpResponseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, QNZonesInfo * _Nullable info) {
zonesInfo = info;
dispatch_semaphore_signal(self.semaphore);
}];
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
if (zonesInfo == nil) {
return nil;
}
QNZonesInfo *autoZonesInfo = [currentZone getZonesInfoWithToken:token];
NSMutableArray *autoHosts = [NSMutableArray array];
NSArray *zoneInfoList = autoZonesInfo.zonesInfo;
for (QNZoneInfo *info in zoneInfoList) {
if (info.allHosts) {
[autoHosts addObjectsFromArray:info.allHosts];
}
}
return [autoHosts copy];
}
//MARK: --
- (BOOL)isDnsOpen{
return [kQNGlobalConfiguration isDnsOpen];
}
- (QNDnsCacheInfo *)dnsCacheInfo{
if (_dnsCacheInfo == nil) {
_dnsCacheInfo = [[QNDnsCacheInfo alloc] init];
}
return _dnsCacheInfo;
}
- (NSMutableDictionary<NSString *,NSArray<QNDnsNetworkAddress *> *> *)addressDictionary{
if (_addressDictionary == nil) {
_addressDictionary = [NSMutableDictionary dictionary];
}
return _addressDictionary;
}
- (dispatch_semaphore_t)semaphore{
if (_getAutoZoneSemaphore == NULL) {
_getAutoZoneSemaphore = dispatch_semaphore_create(0);
}
return _getAutoZoneSemaphore;
}
- (QNDnsCacheFile *)diskCache {
if (!_diskCache) {
NSError *error;
QNDnsCacheFile *cache = [QNDnsCacheFile dnsCacheFile:kQNGlobalConfiguration.dnsCacheDir error:&error];
if (!error) {
_diskCache = cache;
}
}
return _diskCache;
}
- (QNInternalDns *)customDns {
if (_customDns == nil && kQNGlobalConfiguration.dns) {
_customDns = [QNInternalDns dnsWithDns:kQNGlobalConfiguration.dns];
}
return _customDns;
}
- (QNInternalDns *)systemDns {
if (_systemDns == nil) {
_systemDns = [QNInternalDns dnsWithResolver:[[QNResolver alloc] initWithAddress:nil timeout:self.dnsPrefetchTimeout]];
}
return _systemDns;
}
- (NSMutableSet *)prefetchHosts {
if (!_prefetchHosts) {
_prefetchHosts = [NSMutableSet set];
}
return _prefetchHosts;
}
@end
//MARK: -- DNS
@implementation QNTransactionManager(Dns)
#define kQNLoadLocalDnsTransactionName @"QNLoadLocalDnsTransaction"
#define kQNDnsCheckAndPrefetchTransactionName @"QNDnsCheckAndPrefetchTransactionName"
- (void)addDnsLocalLoadTransaction{
if ([kQNDnsPrefetch isDnsOpen] == NO) {
return;
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
QNTransaction *transaction = [QNTransaction transaction:kQNLoadLocalDnsTransactionName after:0 action:^{
[kQNDnsPrefetch recoverCache];
[kQNDnsPrefetch localFetch];
}];
[[QNTransactionManager shared] addTransaction:transaction];
[self setDnsCheckWhetherCachedValidTransactionAction];
});
}
- (BOOL)addDnsCheckAndPrefetchTransaction:(QNZone *)currentZone token:(QNUpToken *)token {
return [self addDnsCheckAndPrefetchTransaction:[QNConfiguration defaultConfiguration] zone:currentZone token:token];
}
- (BOOL)addDnsCheckAndPrefetchTransaction:(QNConfiguration *)config zone:(QNZone *)currentZone token:(QNUpToken *)token {
if (!token) {
return NO;
}
if ([kQNDnsPrefetch isDnsOpen] == NO) {
return NO;
}
BOOL ret = NO;
@synchronized (kQNDnsPrefetch) {
QNTransactionManager *transactionManager = [QNTransactionManager shared];
if (![transactionManager existTransactionsForName:token.token]) {
QNTransaction *transaction = [QNTransaction transaction:token.token after:0 action:^{
[kQNDnsPrefetch checkAndPrefetchDnsIfNeed:config zone:currentZone token:token];
}];
[transactionManager addTransaction:transaction];
ret = YES;
}
}
return ret;
}
- (void)setDnsCheckWhetherCachedValidTransactionAction{
if ([kQNDnsPrefetch isDnsOpen] == NO) {
return;
}
@synchronized (kQNDnsPrefetch) {
QNTransactionManager *transactionManager = [QNTransactionManager shared];
QNTransaction *transaction = [transactionManager transactionsForName:kQNDnsCheckAndPrefetchTransactionName].firstObject;
if (!transaction) {
QNTransaction *transaction = [QNTransaction timeTransaction:kQNDnsCheckAndPrefetchTransactionName
after:10
interval:120
action:^{
[kQNDnsPrefetch checkWhetherCachedDnsValid];
}];
[transactionManager addTransaction:transaction];
} else {
[transactionManager performTransaction:transaction];
}
}
}
@end
BOOL kQNIsDnsSourceDoh(NSString * _Nullable source) {
return [source containsString:kQNDnsSourceDoh];
}
BOOL kQNIsDnsSourceUdp(NSString * _Nullable source) {
return [source containsString:kQNDnsSourceUdp];
}
BOOL kQNIsDnsSourceDnsPod(NSString * _Nullable source) {
return [source containsString:kQNDnsSourceDnspod];
}
BOOL kQNIsDnsSourceSystem(NSString * _Nullable source) {
return [source containsString:kQNDnsSourceSystem];
}
BOOL kQNIsDnsSourceCustom(NSString * _Nullable source) {
return [source containsString:kQNDnsSourceCustom];
}