YH_HttpDnsService.m 5.63 KB
//
//  YH_HttpDnsService.m
//  YH_Mall
//
//  Created by jhsonzhi on 16/7/18.
//  Copyright © 2016年 YOHO. All rights reserved.
//

#import "YH_HttpDnsService.h"
#import "YH_DNSCacheManager.h"
#import "YH_DNSNetworkManager.h"
#import "YH_DNSDomainModel.h"
#import "YH_DNSUtils.h"
#import <UIKit/UIKit.h>


#ifdef  SUPPORT_REQUEST_UDID
#import "OpenUDID.h"
#endif

static const NSTimeInterval  processPeriodicTaskSeconds = 60.0;

@interface YH_HttpDnsService ()
@property (strong, nonatomic) YH_DNSCacheManager *cacheManager;
@property (strong, nonatomic) YH_DNSNetworkManager *networkManager;
@property (strong, nonatomic) NSMutableDictionary *runningTask;
@property (strong, nonatomic) NSOperationQueue *taskQueue;
@property (strong, nonatomic) NSTimer *refreshTimer;
@property (copy, nonatomic)  NSString *dnsFlag;
@end
@implementation YH_HttpDnsService

+ (instancetype)shareInstance
{
    static YH_HttpDnsService *httpDnsService = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        httpDnsService = [[YH_HttpDnsService alloc] init];

    });
    return httpDnsService;
}

- (instancetype)init{
    if (self = [super init]) {
        self.cacheManager   = [YH_DNSCacheManager sharedInstance];
        self.networkManager = [[YH_DNSNetworkManager alloc] init];
        self.networkManager.appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey];
        self.networkManager.osVersion = [[UIDevice currentDevice] systemVersion];
#ifdef  SUPPORT_REQUEST_UDID
        self.networkManager.udid = [OpenUDID value];
#endif
    }
    
    return  self;
}

- (NSMutableDictionary *)runningTask{
    if (!_runningTask) {
        _runningTask = [[NSMutableDictionary alloc] init];
    }
    
    return _runningTask;
}

- (NSOperationQueue *)taskQueue{
    if (!_taskQueue) {
        _taskQueue = [[NSOperationQueue alloc] init];
    }
    
    return _taskQueue;
}

- (NSTimer *)refreshTimer{
    if (!_refreshTimer) {
        _refreshTimer = [NSTimer timerWithTimeInterval:processPeriodicTaskSeconds
                                                target:self
                                              selector:@selector(processPeriodicTask)
                                              userInfo:nil
                                               repeats:YES];
    }
    
    return _refreshTimer;
}

-(void)dealloc{
    _cacheManager   = nil;
    _networkManager = nil;
    _refreshTimer = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)checkUpdate:(NSString *)domain {

    if (YHDNS_isStrEmpty(domain)) {
        return;
    }
    
    NSBlockOperation* operation = self.runningTask[domain];
    if (operation == nil) {
        __weak __typeof(&*self)weakSelf = self;
        NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
            [weakSelf.networkManager fetchHttpDnsByDomain:domain completionHandler:^(YH_DNSHttpDnsPack *dnsPack) {
                if(dnsPack){
                    [weakSelf.cacheManager insertDnsCache:dnsPack];
                }
                
                [weakSelf.runningTask performSelectorOnMainThread:@selector(removeObjectForKey:) withObject:domain waitUntilDone:NO];
            }];
        }];
        [self.runningTask setObject:operation forKey:domain];
        [self.taskQueue addOperation:operation];
    }
}

- (void)setPreResolveHosts:(NSArray *)hosts {
    for (NSString* domain in hosts) {
        NSString* host = domain;
        if ([domain hasPrefix:@"http://"]) {
            NSURL* url = [NSURL URLWithString:domain];
            host = url.host;
        }
        
        [self checkUpdate:host];
    }
}

- (NSString *)getIpByHost:(NSString *)urlString {
    
    NSURL* url = [NSURL URLWithString:urlString];
    
    if (url.host == nil) {
        NSLog(@"ERROR:%s:%d get host from (%@) failed ",__FUNCTION__,__LINE__, urlString);
        return nil;
    }
    
    if ([YH_DNSUtils isIpV4Address:url.host]) {
        NSLog(@"ERROR:%s:%d get host from (%@) failed ",__FUNCTION__,__LINE__, urlString);
        return urlString;
    }
    
    NSDictionary *resultDic = [[self.cacheManager getDnsCacheByHost:url.host] copy];
    NSString *resultIpSting = resultDic[@"ip"];
    BOOL isNeedPrefetch = [resultDic[@"prefetch"] boolValue];
    
    if (!resultDic || YHDNS_isStrEmpty(resultIpSting) || isNeedPrefetch) {
        NSLog(@"fetch host:%@ isNeedPrefetch:%d",url.host,isNeedPrefetch);
        [self checkUpdate:url.host];
    }else{
        NSLog(@"INFO:%s:%d get host:(%@) ip:(%@) failed ",__FUNCTION__,__LINE__, urlString ,resultIpSting);
    }
    
    return resultIpSting;
}

- (void)addTimer{
    [[NSRunLoop currentRunLoop] addTimer:self.refreshTimer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"INFO:===> Start HttpDNS timer and add in runlloop!");
}

- (void)enableScheduledTask{
    
    if ([_refreshTimer isValid]) {
        [_refreshTimer invalidate];
        _refreshTimer = nil;
    }
    
    [self performSelectorInBackground:@selector(addTimer) withObject:nil];
    [self.refreshTimer fire];
}

- (void)disableScheduledTask{
    
    if ([self.refreshTimer isValid]) {
        [self.refreshTimer invalidate];
        _refreshTimer = nil;
        NSLog(@"INFO:===> Stop HttpDNS timer!");
    }
}

#pragma mark- 定时任务 -刷新域名对应IP

- (void)processPeriodicTask {
    NSLog(@"start process periodic(time:%.1f) task,is main thread:%@",processPeriodicTaskSeconds,[NSThread isMainThread]? @"YES" :@"NO");
    NSArray* expiredDomainInfos = [self.cacheManager getExpireDnsCache];
    for (YH_DNSDomainModel* model in expiredDomainInfos) {
        [self checkUpdate:model.domain];
    }
}

@end