提交
This commit is contained in:
147
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSHttpdns.m
generated
Normal file
147
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSHttpdns.m
generated
Normal file
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// OSSHttpdns.m
|
||||
// AliyunOSSiOS
|
||||
//
|
||||
// Created by zhouzhuo on 5/1/16.
|
||||
// Copyright © 2016 zhouzhuo. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OSSLog.h"
|
||||
#import "OSSHttpdns.h"
|
||||
#import "OSSIPv6Adapter.h"
|
||||
|
||||
NSString * const OSS_HTTPDNS_SERVER_IP = @"203.107.1.1";
|
||||
NSString * const OSS_HTTPDNS_SERVER_PORT = @"80";
|
||||
|
||||
NSString * const ACCOUNT_ID = @"181345";
|
||||
NSTimeInterval const MAX_ENDURABLE_EXPIRED_TIME_IN_SECOND = 60; // The DNS entry's expiration time in seconds. After it expires, the entry is invalid.
|
||||
NSTimeInterval const PRERESOLVE_IN_ADVANCE_IN_SECOND = 10; // Once the remaining valid time of an DNS entry is less than this number, issue a DNS request to prefetch the data.
|
||||
|
||||
@interface IpObject : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString * ip;
|
||||
@property (nonatomic, assign) NSTimeInterval expiredTime;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IpObject
|
||||
@end
|
||||
|
||||
|
||||
@implementation OSSHttpdns {
|
||||
NSMutableDictionary * gHostIpMap;
|
||||
NSMutableSet * penddingSet;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static OSSHttpdns * sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [OSSHttpdns new];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
gHostIpMap = [NSMutableDictionary new];
|
||||
penddingSet = [NSMutableSet new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* OSS SDK specific
|
||||
*
|
||||
* @param host it needs strictly follow the domain's format, such as oss-cn-hangzhou.aliyuncs.com
|
||||
*
|
||||
* @return an ip in the ip list of the resolved host.
|
||||
*/
|
||||
- (NSString *)asynGetIpByHost:(NSString *)host {
|
||||
IpObject * ipObject = [gHostIpMap objectForKey:host];
|
||||
if (!ipObject) {
|
||||
|
||||
// if the host is not resolved, asynchronously resolve it and return nil
|
||||
[self resolveHost:host];
|
||||
return nil;
|
||||
} else if ([[NSDate date] timeIntervalSince1970] - ipObject.expiredTime > MAX_ENDURABLE_EXPIRED_TIME_IN_SECOND) {
|
||||
|
||||
// If the entry is expired, asynchronously resolve it and return nil.
|
||||
[self resolveHost:host];
|
||||
return nil;
|
||||
} else if (ipObject.expiredTime -[[NSDate date] timeIntervalSince1970] < PRERESOLVE_IN_ADVANCE_IN_SECOND) {
|
||||
|
||||
// If the entry is about to expire, asynchronously resolve it and return the current value.
|
||||
[self resolveHost:host];
|
||||
return ipObject.ip;
|
||||
} else {
|
||||
|
||||
// returns the current result.
|
||||
return ipObject.ip;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve the host asynchronously
|
||||
|
||||
* If the host is being resolved, the call will be skipped.
|
||||
*
|
||||
* @param host the host to resolve
|
||||
*/
|
||||
- (void)resolveHost:(NSString *)host {
|
||||
|
||||
@synchronized (self) {
|
||||
if ([penddingSet containsObject:host]) {
|
||||
return;
|
||||
} else {
|
||||
[penddingSet addObject:host];
|
||||
}
|
||||
}
|
||||
|
||||
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@/%@/d?host=%@", [[OSSIPv6Adapter getInstance] handleIpv4Address:OSS_HTTPDNS_SERVER_IP], ACCOUNT_ID, host]];
|
||||
NSURLSession * session = [NSURLSession sharedSession];
|
||||
|
||||
NSURLSessionDataTask * dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
|
||||
IpObject * ipObject = nil;
|
||||
NSUInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
|
||||
if (statusCode != 200) {
|
||||
OSSLogError(@"Httpdns resolve host: %@ failed, responseCode: %lu", host, (unsigned long)statusCode);
|
||||
} else {
|
||||
NSError *error = nil;
|
||||
NSDictionary *json = nil;
|
||||
if (data != nil){
|
||||
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
|
||||
}
|
||||
|
||||
if (error != nil || json == nil){
|
||||
return;
|
||||
}
|
||||
|
||||
NSTimeInterval expiredTime = [[NSDate new] timeIntervalSince1970] + [[json objectForKey:@"ttl"] longLongValue];
|
||||
|
||||
NSArray *ips = [json objectForKey:@"ips"];
|
||||
if (ips == nil || [ips count] == 0) {
|
||||
OSSLogError(@"Httpdns resolve host: %@ failed, ip list empty.", host);
|
||||
} else {
|
||||
NSString * ip = ips[0];
|
||||
ipObject = [IpObject new];
|
||||
ipObject.expiredTime = expiredTime;
|
||||
ipObject.ip = ip;
|
||||
OSSLogDebug(@"Httpdns resolve host: %@ success, ip: %@, expiredTime: %lf", host, ipObject.ip, ipObject.expiredTime);
|
||||
}
|
||||
}
|
||||
|
||||
@synchronized (self) {
|
||||
if (ipObject) {
|
||||
gHostIpMap[host] = ipObject;
|
||||
}
|
||||
|
||||
[penddingSet removeObject:host];
|
||||
}
|
||||
}];
|
||||
|
||||
[dataTask resume];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user