Files
waf-platform/HttpDNSSDK/sdk/ios/NewHttpDNS/Model/HttpdnsHostObject.m

307 lines
11 KiB
Objective-C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#import "HttpdnsHostObject.h"
#import "HttpdnsInternalConstant.h"
#import "HttpdnsUtil.h"
#import "HttpdnsLog_Internal.h"
#import "HttpdnsHostRecord.h"
#import "HttpdnsIPQualityDetector.h"
@implementation HttpdnsIpObject
- (instancetype)init {
if (self = [super init]) {
// åˆ<C3A5>å§åŒconnectedRT为最大整数å€?
self.connectedRT = NSIntegerMax;
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.ip = [aDecoder decodeObjectForKey:@"ip"];
self.connectedRT = [aDecoder decodeIntegerForKey:@"connectedRT"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.ip forKey:@"ip"];
[aCoder encodeInteger:self.connectedRT forKey:@"connectedRT"];
}
- (id)copyWithZone:(NSZone *)zone {
HttpdnsIpObject *copy = [[[self class] allocWithZone:zone] init];
if (copy) {
copy.ip = [self.ip copyWithZone:zone];
copy.connectedRT = self.connectedRT;
}
return copy;
}
+ (NSArray<HttpdnsIpObject *> *)IPObjectsFromIPs:(NSArray<NSString *> *)IPs {
NSMutableArray *IPObjects = [NSMutableArray arrayWithCapacity:IPs.count];
for (NSString *IP in IPs) {
HttpdnsIpObject *IPObject = [HttpdnsIpObject new];
IPObject.ip = IP;
IPObject.connectedRT = NSIntegerMax;
[IPObjects addObject:IPObject];
}
return [IPObjects copy];
}
- (NSString *)description {
if (self.connectedRT == NSIntegerMax) {
return [NSString stringWithFormat:@"ip: %@", self.ip];
} else {
return [NSString stringWithFormat:@"ip: %@, connectedRT: %ld", self.ip, self.connectedRT];
}
}
@end
@implementation HttpdnsHostObject
- (instancetype)init {
_hostName = nil;
_cacheKey = nil;
_clientIp = nil;
_v4ttl = -1;
_lastIPv4LookupTime = 0;
_v6ttl = -1;
_lastIPv6LookupTime = 0;
_isLoadFromDB = NO;
_v4Ips = nil;
_v6Ips = nil;
_extra = nil;
_hasNoIpv4Record = NO;
_hasNoIpv6Record = NO;
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
_cacheKey = [aDecoder decodeObjectForKey:@"cacheKey"];
_hostName = [aDecoder decodeObjectForKey:@"hostName"];
_clientIp = [aDecoder decodeObjectForKey:@"clientIp"];
_v4Ips = [aDecoder decodeObjectForKey:@"v4ips"];
_v4ttl = [aDecoder decodeInt64ForKey:@"v4ttl"];
_lastIPv4LookupTime = [aDecoder decodeInt64ForKey:@"lastIPv4LookupTime"];
_v6Ips = [aDecoder decodeObjectForKey:@"v6ips"];
_v6ttl = [aDecoder decodeInt64ForKey:@"v6ttl"];
_lastIPv6LookupTime = [aDecoder decodeInt64ForKey:@"lastIPv6LookupTime"];
_extra = [aDecoder decodeObjectForKey:@"extra"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_cacheKey forKey:@"cacheKey"];
[aCoder encodeObject:_hostName forKey:@"hostName"];
[aCoder encodeObject:_clientIp forKey:@"clientIp"];
[aCoder encodeObject:_v4Ips forKey:@"v4ips"];
[aCoder encodeInt64:_v4ttl forKey:@"v4ttl"];
[aCoder encodeInt64:_lastIPv4LookupTime forKey:@"lastIPv4LookupTime"];
[aCoder encodeObject:_v6Ips forKey:@"v6ips"];
[aCoder encodeInt64:_v6ttl forKey:@"v6ttl"];
[aCoder encodeInt64:_lastIPv6LookupTime forKey:@"lastIPv6LookupTime"];
[aCoder encodeObject:_extra forKey:@"extra"];
}
- (BOOL)isIpEmptyUnderQueryIpType:(HttpdnsQueryIPType)queryType {
if (queryType & HttpdnsQueryIPTypeIpv4) {
// 注æ„<C3A6>,_hasNoIpv4Record为true时,说明域å<C5B8><C3A5>没有é…<C3A9>ç½®ipv4ip,ä¸<C3A4>是需è¦<C3A8>去请æ±çš„æƒ…å†?
if ([HttpdnsUtil isEmptyArray:[self getV4Ips]] && !_hasNoIpv4Record) {
return YES;
}
} else if (queryType & HttpdnsQueryIPTypeIpv6 && !_hasNoIpv6Record) {
// 注æ„<C3A6>,_hasNoIpv6Record为true时,说明域å<C5B8><C3A5>没有é…<C3A9>ç½®ipv6ip,ä¸<C3A4>是需è¦<C3A8>去请æ±çš„æƒ…å†?
if ([HttpdnsUtil isEmptyArray:[self getV6Ips]] && !_hasNoIpv6Record) {
return YES;
}
}
return NO;
}
- (id)copyWithZone:(NSZone *)zone {
HttpdnsHostObject *copy = [[[self class] allocWithZone:zone] init];
if (copy) {
copy.cacheKey = [self.cacheKey copyWithZone:zone];
copy.hostName = [self.hostName copyWithZone:zone];
copy.clientIp = [self.clientIp copyWithZone:zone];
copy.v4Ips = [[NSArray allocWithZone:zone] initWithArray:self.v4Ips copyItems:YES];
copy.v6Ips = [[NSArray allocWithZone:zone] initWithArray:self.v6Ips copyItems:YES];
copy.v4ttl = self.v4ttl;
copy.lastIPv4LookupTime = self.lastIPv4LookupTime;
copy.v6ttl = self.v6ttl;
copy.lastIPv6LookupTime = self.lastIPv6LookupTime;
copy.hasNoIpv4Record = self.hasNoIpv4Record;
copy.hasNoIpv6Record = self.hasNoIpv6Record;
copy.extra = [self.extra copyWithZone:zone];
copy.isLoadFromDB = self.isLoadFromDB;
}
return copy;
}
- (BOOL)isExpiredUnderQueryIpType:(HttpdnsQueryIPType)queryIPType {
int64_t currentEpoch = (int64_t)[[[NSDate alloc] init] timeIntervalSince1970];
if ((queryIPType & HttpdnsQueryIPTypeIpv4)
&& !_hasNoIpv4Record
&& _lastIPv4LookupTime + _v4ttl <= currentEpoch) {
return YES;
}
if ((queryIPType & HttpdnsQueryIPTypeIpv6)
&& !_hasNoIpv6Record
&& _lastIPv6LookupTime + _v6ttl <= currentEpoch) {
return YES;
}
return NO;
}
+ (instancetype)fromDBRecord:(HttpdnsHostRecord *)hostRecord {
HttpdnsHostObject *hostObject = [HttpdnsHostObject new];
[hostObject setCacheKey:hostRecord.cacheKey];
[hostObject setHostName:hostRecord.hostName];
[hostObject setClientIp:hostRecord.clientIp];
NSArray *v4ips = hostRecord.v4ips;
NSArray *v6ips = hostRecord.v6ips;
if ([HttpdnsUtil isNotEmptyArray:v4ips]) {
[hostObject setV4Ips:[HttpdnsIpObject IPObjectsFromIPs:v4ips]];
[hostObject setV4TTL:hostRecord.v4ttl];
[hostObject setLastIPv4LookupTime:hostRecord.v4LookupTime];
}
if ([HttpdnsUtil isNotEmptyArray:v6ips]) {
[hostObject setV6Ips:[HttpdnsIpObject IPObjectsFromIPs:v6ips]];
[hostObject setV6TTL:hostRecord.v6ttl];
[hostObject setLastIPv6LookupTime:hostRecord.v6LookupTime];
}
[hostObject setExtra:hostRecord.extra];
[hostObject setIsLoadFromDB:YES];
return hostObject;
}
- (HttpdnsHostRecord *)toDBRecord {
// å°†IP对象数组转æ<C2AC>¢ä¸ºIP字符串数ç»?
NSArray<NSString *> *v4IpStrings = [self getV4IpStrings];
NSArray<NSString *> *v6IpStrings = [self getV6IpStrings];
// åˆå»ºå½“å‰<C3A5>时间作为modifyAt
NSDate *currentDate = [NSDate date];
// 使用hostName作为cacheKey,ä¿<C3A4>æŒ<C3A6>与fromDBRecordæ¹æ³•的一致æ€?
return [[HttpdnsHostRecord alloc] initWithId:0 // æ•°æ<C2B0>®åº“会自动分é…<C3A9>ID
cacheKey:self.cacheKey
hostName:self.hostName
createAt:currentDate
modifyAt:currentDate
clientIp:self.clientIp
v4ips:v4IpStrings
v4ttl:self.v4ttl
v4LookupTime:self.lastIPv4LookupTime
v6ips:v6IpStrings
v6ttl:self.v6ttl
v6LookupTime:self.lastIPv6LookupTime
extra:self.extra];
}
- (NSArray<NSString *> *)getV4IpStrings {
NSArray<HttpdnsIpObject *> *ipv4Records = [self getV4Ips];
NSMutableArray<NSString *> *ipv4Strings = [NSMutableArray arrayWithCapacity:ipv4Records.count];
for (HttpdnsIpObject *IPObject in ipv4Records) {
[ipv4Strings addObject:[IPObject getIpString]];
}
return [ipv4Strings copy];
}
- (NSArray<NSString *> *)getV6IpStrings {
NSArray<HttpdnsIpObject *> *ipv6Records = [self getV6Ips];
NSMutableArray<NSString *> *ipv6sString = [NSMutableArray arrayWithCapacity:ipv6Records.count];
for (HttpdnsIpObject *ipObject in ipv6Records) {
[ipv6sString addObject:[ipObject getIpString]];
}
return [ipv6sString copy];
}
- (void)updateConnectedRT:(NSInteger)connectedRT forIP:(NSString *)ip {
if ([HttpdnsUtil isEmptyString:ip]) {
return;
}
BOOL isIPv6 = [HttpdnsUtil isIPv6Address:ip];
NSArray<HttpdnsIpObject *> *ipObjects = isIPv6 ? [self getV6Ips] : [self getV4Ips];
if ([HttpdnsUtil isEmptyArray:ipObjects]) {
return;
}
// 查找匹é…<C3A9>çš„IPå¯¹è±¡å¹¶æ´æ°connectedRT
BOOL found = NO;
NSMutableArray<HttpdnsIpObject *> *mutableIpObjects = [ipObjects mutableCopy];
for (HttpdnsIpObject *ipObject in ipObjects) {
if ([ipObject.ip isEqualToString:ip]) {
ipObject.connectedRT = connectedRT;
found = YES;
break;
}
}
if (!found) {
return;
}
// æ ¹æ<C2B9>®connectedRT值对IP列表è¿è¡ŒæŽåº<C3A5>ï¼?1值放在最å<E282AC>?
[mutableIpObjects sortUsingComparator:^NSComparisonResult(HttpdnsIpObject *obj1, HttpdnsIpObject *obj2) {
// 妿žœobj1çš„connectedRTä¸?1,将其æŽåœ¨å<C2A8>Žé<C5BD>?
if (obj1.connectedRT == -1) {
return NSOrderedDescending;
}
// 妿žœobj2çš„connectedRTä¸?1,将其æŽåœ¨å<C2A8>Žé<C5BD>?
if (obj2.connectedRT == -1) {
return NSOrderedAscending;
}
// å<>¦åˆ™æŒ‰ç…§connectedRT值从å°<C3A5>到大æŽåº?
return obj1.connectedRT > obj2.connectedRT ? NSOrderedDescending : (obj1.connectedRT < obj2.connectedRT ? NSOrderedAscending : NSOrderedSame);
}];
// æ´æ°æŽåº<C3A5>å<EFBFBD>Žçš„IP列表
if (isIPv6) {
[self setV6Ips:[mutableIpObjects copy]];
} else {
[self setV4Ips:[mutableIpObjects copy]];
}
}
- (NSString *)description {
if (![HttpdnsUtil isNotEmptyArray:_v6Ips]) {
return [NSString stringWithFormat:@"Host = %@ v4ips = %@ v4ttl = %lld v4LastLookup = %lld extra = %@",
_hostName, _v4Ips, _v4ttl, _lastIPv4LookupTime, _extra];
} else {
return [NSString stringWithFormat:@"Host = %@ v4ips = %@ v4ttl = %lld v4LastLookup = %lld v6ips = %@ v6ttl = %lld v6LastLookup = %lld extra = %@",
_hostName, _v4Ips, _v4ttl, _lastIPv4LookupTime, _v6Ips, _v6ttl, _lastIPv6LookupTime, _extra];
}
}
@end