解决了语音上传到问题,接下来要解决下载播放问题
This commit is contained in:
41
Pods/Qiniu/QiniuSDK/Http/Dns/QNDns.h
generated
Normal file
41
Pods/Qiniu/QiniuSDK/Http/Dns/QNDns.h
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// QNDns.h
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol QNIDnsNetworkAddress <NSObject>
|
||||
|
||||
/// 域名
|
||||
@property(nonatomic, copy, readonly)NSString *hostValue;
|
||||
|
||||
/// 地址IP信息
|
||||
@property(nonatomic, copy, readonly)NSString *ipValue;
|
||||
|
||||
/// ip有效时间 单位:秒
|
||||
@property(nonatomic, strong, readonly)NSNumber *ttlValue;
|
||||
|
||||
/// ip预取来源, 自定义dns返回 @"customized"
|
||||
@property(nonatomic, copy, readonly)NSString *sourceValue;
|
||||
|
||||
/// 解析到host时的时间戳 单位:秒
|
||||
@property(nonatomic, strong, readonly)NSNumber *timestampValue;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol QNDnsDelegate <NSObject>
|
||||
|
||||
/// 根据host获取解析结果
|
||||
/// @param host 域名
|
||||
- (NSArray < id <QNIDnsNetworkAddress> > *)query:(NSString *)host;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
29
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheFile.h
generated
Normal file
29
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheFile.h
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// QNDnsCacheFile.h
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "QNRecorderDelegate.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface QNDnsCacheFile : NSObject<QNRecorderDelegate>
|
||||
|
||||
/// DNS解析信息本地缓存路径
|
||||
@property(nonatomic, copy, readonly)NSString *directory;
|
||||
|
||||
/// 构造方法 路径不存在,或进行创建,创建失败返回为nil
|
||||
/// @param directory 路径
|
||||
/// @param error 构造错误时,会有值
|
||||
+ (instancetype _Nullable)dnsCacheFile:(NSString *)directory
|
||||
error:(NSError **)error;
|
||||
|
||||
- (void)clearCache:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
91
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheFile.m
generated
Normal file
91
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheFile.m
generated
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// QNDnsCacheFile.m
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QNDnsCacheFile.h"
|
||||
|
||||
@interface QNDnsCacheFile()
|
||||
|
||||
@property(nonatomic, copy)NSString *directory;
|
||||
|
||||
@end
|
||||
@implementation QNDnsCacheFile
|
||||
|
||||
+ (instancetype)dnsCacheFile:(NSString *)directory
|
||||
error:(NSError **)error{
|
||||
NSError *err = nil;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&err];
|
||||
if (err != nil) {
|
||||
if (error != nil) *error = err;
|
||||
return nil;
|
||||
}
|
||||
|
||||
QNDnsCacheFile *f = [[QNDnsCacheFile alloc] init];
|
||||
f.directory = directory;
|
||||
return f;
|
||||
}
|
||||
|
||||
- (NSError *)set:(NSString *)key data:(NSData *)value {
|
||||
@synchronized (self) {
|
||||
NSError *error;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *filePath = [self pathOfKey:key];
|
||||
if ([fileManager fileExistsAtPath:filePath]) {
|
||||
[fileManager removeItemAtPath:filePath error:&error];
|
||||
}
|
||||
[fileManager createFileAtPath:filePath contents:value attributes:nil];
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)get:(NSString *)key {
|
||||
return [NSData dataWithContentsOfFile:[self pathOfKey:key]];
|
||||
}
|
||||
|
||||
- (NSError *)del:(NSString *)key {
|
||||
@synchronized (self) {
|
||||
NSError *error = nil;
|
||||
NSString *path = [self pathOfKey:key];
|
||||
if (path) {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
[fileManager removeItemAtPath:path error:&error];
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)clearCache:(NSError *__autoreleasing _Nullable *)error {
|
||||
@synchronized (self) {
|
||||
NSError *err;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
[fileManager removeItemAtPath:self.directory error:&err];
|
||||
if (err != nil) {
|
||||
if (error != nil) *error = err;
|
||||
return;
|
||||
}
|
||||
|
||||
[fileManager createDirectoryAtPath:self.directory withIntermediateDirectories:YES attributes:nil error:&err];
|
||||
if (error != nil) {
|
||||
*error = err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)getFileName{
|
||||
return @"dnsCache";
|
||||
}
|
||||
|
||||
- (NSString *)pathOfKey:(NSString *)key {
|
||||
return [QNDnsCacheFile pathJoin:key path:_directory];
|
||||
}
|
||||
|
||||
+ (NSString *)pathJoin:(NSString *)key
|
||||
path:(NSString *)path {
|
||||
return [[NSString alloc] initWithFormat:@"%@/%@", path, key];
|
||||
}
|
||||
|
||||
@end
|
||||
41
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheInfo.h
generated
Normal file
41
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheInfo.h
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// QNDnsCacheKey.h
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface QNDnsCacheInfo : NSObject
|
||||
|
||||
/// 缓存时间戳
|
||||
@property(nonatomic, copy, readonly)NSString *currentTime;
|
||||
/// 缓存时本地IP
|
||||
@property(nonatomic, copy, readonly)NSString *localIp;
|
||||
/// 缓存信息
|
||||
@property(nonatomic, copy, readonly)NSDictionary *info;
|
||||
|
||||
//MARK: -- 构造方法
|
||||
/// 根据json构造对象
|
||||
/// @param jsonData json数据
|
||||
+ (instancetype)dnsCacheInfo:(NSData *)jsonData;
|
||||
|
||||
/// 根据属性构造对象
|
||||
/// @param currentTime 缓存时间戳
|
||||
/// @param localIp 缓存时本地IP
|
||||
/// @param info 缓存信息
|
||||
+ (instancetype)dnsCacheInfo:(NSString *)currentTime
|
||||
localIp:(NSString *)localIp
|
||||
info:(NSDictionary *)info;
|
||||
|
||||
|
||||
/// 转化Json数据
|
||||
- (NSData *)jsonData;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
58
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheInfo.m
generated
Normal file
58
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsCacheInfo.m
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// QNDnsCacheKey.m
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QNDnsCacheInfo.h"
|
||||
|
||||
@interface QNDnsCacheInfo()
|
||||
/// 缓存时间戳
|
||||
@property(nonatomic, copy)NSString *currentTime;
|
||||
/// 缓存时本地IP
|
||||
@property(nonatomic, copy)NSString *localIp;
|
||||
/// 缓存信息
|
||||
@property(nonatomic, copy)NSDictionary *info;
|
||||
@end
|
||||
@implementation QNDnsCacheInfo
|
||||
|
||||
+ (instancetype)dnsCacheInfo:(NSData *)jsonData{
|
||||
NSDictionary *info = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
|
||||
if (!info || info.count == 0 ||
|
||||
(!info[@"currentTime"] && !info[@"localIp"] && !info[@"info"])) {
|
||||
return nil;
|
||||
}
|
||||
return [QNDnsCacheInfo dnsCacheInfo:info[@"currentTime"]
|
||||
localIp:info[@"localIp"]
|
||||
info:info[@"info"]];;
|
||||
}
|
||||
|
||||
+ (instancetype)dnsCacheInfo:(NSString *)currentTime
|
||||
localIp:(NSString *)localIp
|
||||
info:(NSDictionary *)info{
|
||||
|
||||
QNDnsCacheInfo *cacheInfo = [[QNDnsCacheInfo alloc] init];
|
||||
cacheInfo.currentTime = currentTime;
|
||||
cacheInfo.localIp = localIp;
|
||||
cacheInfo.info = info;
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
- (NSData *)jsonData{
|
||||
NSMutableDictionary *cacheInfo = [NSMutableDictionary dictionary];
|
||||
if (self.currentTime) {
|
||||
cacheInfo[@"currentTime"] = self.currentTime;
|
||||
}
|
||||
if (self.localIp) {
|
||||
cacheInfo[@"localIp"] = self.localIp;
|
||||
}
|
||||
if (self.info) {
|
||||
cacheInfo[@"info"] = self.info;
|
||||
}
|
||||
return [NSJSONSerialization dataWithJSONObject:cacheInfo options:NSJSONWritingPrettyPrinted error:nil];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
66
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsPrefetch.h
generated
Normal file
66
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsPrefetch.h
generated
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// QNDnsPrefetch.h
|
||||
// QnDNS
|
||||
//
|
||||
// Created by yangsen on 2020/3/26.
|
||||
// Copyright © 2020 com.qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QNDns.h"
|
||||
#import "QNUpToken.h"
|
||||
#import "QNConfiguration.h"
|
||||
#import "QNTransactionManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#define kQNDnsPrefetch [QNDnsPrefetch shared]
|
||||
@interface QNDnsPrefetch : NSObject
|
||||
|
||||
/// 最近一次预取错误信息
|
||||
@property(nonatomic, copy, readonly)NSString *lastPrefetchedErrorMessage;
|
||||
|
||||
+ (instancetype)shared;
|
||||
|
||||
/// 根据host从缓存中读取DNS信息
|
||||
/// @param host 域名
|
||||
- (NSArray <id <QNIDnsNetworkAddress> > *)getInetAddressByHost:(NSString *)host;
|
||||
|
||||
/// 通过安全的方式预取 dns
|
||||
- (NSString *)prefetchHostBySafeDns:(NSString *)host error:(NSError **)error;
|
||||
|
||||
- (void)clearDnsCache:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@interface QNTransactionManager(Dns)
|
||||
|
||||
/// 添加加载本地dns事务
|
||||
- (void)addDnsLocalLoadTransaction;
|
||||
|
||||
/// 添加检测并预取dns事务 如果未开启DNS 或 事务队列中存在token对应的事务未处理,则返回NO
|
||||
/// @param currentZone 当前区域
|
||||
/// @param token token信息
|
||||
- (BOOL)addDnsCheckAndPrefetchTransaction:(QNZone *)currentZone token:(QNUpToken *)token;
|
||||
- (BOOL)addDnsCheckAndPrefetchTransaction:(QNConfiguration *)config zone:(QNZone *)currentZone token:(QNUpToken *)token;
|
||||
|
||||
/// 设置定时事务:检测已缓存DNS有效情况事务 无效会重新预取
|
||||
- (void)setDnsCheckWhetherCachedValidTransactionAction;
|
||||
|
||||
@end
|
||||
|
||||
#define kQNDnsSourceDoh @"doh"
|
||||
#define kQNDnsSourceUdp @"dns"
|
||||
#define kQNDnsSourceDnspod @"dnspod"
|
||||
#define kQNDnsSourceSystem @"system"
|
||||
#define kQNDnsSourceCustom @"customized"
|
||||
#define kQNDnsSourceNone @"none"
|
||||
|
||||
BOOL kQNIsDnsSourceDoh(NSString * _Nullable source);
|
||||
BOOL kQNIsDnsSourceUdp(NSString * _Nullable source);
|
||||
BOOL kQNIsDnsSourceDnsPod(NSString * _Nullable source);
|
||||
BOOL kQNIsDnsSourceSystem(NSString * _Nullable source);
|
||||
BOOL kQNIsDnsSourceCustom(NSString * _Nullable source);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
874
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsPrefetch.m
generated
Normal file
874
Pods/Qiniu/QiniuSDK/Http/Dns/QNDnsPrefetch.m
generated
Normal 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;
|
||||
|
||||
/// 构造方法 addressData为json 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;
|
||||
/// DNS信息本地缓存key
|
||||
@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初始化时,加载本地缓存到内存
|
||||
/// 同步本地预取缓存 如果存在且满足使用返回false,反之为true
|
||||
- (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: -- 检测并预取
|
||||
/// 根据token检测Dns缓存信息时效,无效则预取。 完成预取操作返回YES,反之返回NO
|
||||
- (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信息
|
||||
/// 根据host从缓存中读取DNS信息
|
||||
- (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];
|
||||
}
|
||||
37
Pods/Qiniu/QiniuSDK/Http/Dns/QNInetAddress.h
generated
Normal file
37
Pods/Qiniu/QiniuSDK/Http/Dns/QNInetAddress.h
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// QNInetAddress.h
|
||||
// QiniuSDK
|
||||
//
|
||||
// Created by 杨森 on 2020/7/27.
|
||||
// Copyright © 2020 Qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QNDns.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface QNInetAddress : NSObject <QNIDnsNetworkAddress>
|
||||
|
||||
@property(nonatomic, copy)NSString *hostValue;
|
||||
@property(nonatomic, copy)NSString *ipValue;
|
||||
@property(nonatomic, strong)NSNumber *ttlValue;
|
||||
@property(nonatomic, strong)NSNumber *timestampValue;
|
||||
@property(nonatomic, copy)NSString *sourceValue;
|
||||
|
||||
|
||||
/// 构造方法 addressData为json
|
||||
/// @param addressInfo 地址信息,类型可能为String / Dictionary / Data / 遵循 QNInetAddressDelegate的实例
|
||||
+ (instancetype)inetAddress:(id)addressInfo;
|
||||
|
||||
/// 是否有效,根据时间戳判断
|
||||
- (BOOL)isValid;
|
||||
|
||||
/// 对象转json
|
||||
- (NSString *)toJsonInfo;
|
||||
|
||||
/// 对象转字典
|
||||
- (NSDictionary *)toDictionary;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
95
Pods/Qiniu/QiniuSDK/Http/Dns/QNInetAddress.m
generated
Normal file
95
Pods/Qiniu/QiniuSDK/Http/Dns/QNInetAddress.m
generated
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// QNInetAddress.m
|
||||
// QiniuSDK
|
||||
//
|
||||
// Created by 杨森 on 2020/7/27.
|
||||
// Copyright © 2020 Qiniu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QNInetAddress.h"
|
||||
|
||||
@interface QNInetAddress()
|
||||
@end
|
||||
@implementation QNInetAddress
|
||||
+ (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(timestampValue)] && [address timestampValue]) {
|
||||
dic[@"timestampValue"] = [address timestampValue];
|
||||
}
|
||||
addressDic = [dic copy];
|
||||
}
|
||||
|
||||
if (addressDic) {
|
||||
QNInetAddress *address = [[QNInetAddress alloc] init];
|
||||
[address setValuesForKeysWithDictionary:addressDic];
|
||||
return address;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isValid{
|
||||
if (!self.timestampValue || !self.ipValue || self.ipValue.length == 0) {
|
||||
return NO;
|
||||
}
|
||||
NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
|
||||
if (currentTimestamp > self.timestampValue.doubleValue + self.ttlValue.doubleValue) {
|
||||
return NO;
|
||||
} else {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (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", @"timestampValue"]];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user