// // DemoHttpdnsScenario.m // NewHttpDNSTestDemo // #import "DemoHttpdnsScenario.h" #import "DemoConfigLoader.h" #import @interface DemoHttpdnsScenarioConfig () @end @implementation DemoHttpdnsScenarioConfig - (instancetype)init { if (self = [super init]) { _host = @"demo.cloudxdr.com"; _queryType = @"A"; } return self; } - (id)copyWithZone:(NSZone *)zone { DemoHttpdnsScenarioConfig *cfg = [[[self class] allocWithZone:zone] init]; cfg.host = self.host; cfg.queryType = self.queryType; return cfg; } @end @interface DemoHttpdnsScenario () @property (nonatomic, strong) HttpdnsEdgeService *service; @property (nonatomic, strong) DemoHttpdnsScenarioConfig *config; @property (nonatomic, strong) NSMutableString *logBuffer; @property (nonatomic, strong) dispatch_queue_t logQueue; @end @implementation DemoHttpdnsScenario - (instancetype)initWithDelegate:(id)delegate { if (self = [super init]) { _delegate = delegate; _model = [[DemoResolveModel alloc] init]; _config = [[DemoHttpdnsScenarioConfig alloc] init]; _logBuffer = [NSMutableString string]; _logQueue = dispatch_queue_create("com.new.httpdns.demo.log", DISPATCH_QUEUE_SERIAL); [self buildService]; } return self; } - (void)buildService { DemoConfigLoader *cfg = [DemoConfigLoader shared]; self.service = [[HttpdnsEdgeService alloc] initWithAppId:cfg.appId primaryServiceHost:cfg.primaryServiceHost backupServiceHost:nil servicePort:cfg.servicePort signSecret:cfg.signSecret]; [self appendLog:[NSString stringWithFormat:@"[init] appId=%@ host=%@:%ld", cfg.appId, cfg.primaryServiceHost, (long)cfg.servicePort]]; } - (void)applyConfig:(DemoHttpdnsScenarioConfig *)config { self.config = [config copy]; self.model.host = self.config.host; } - (void)resolve { [self resolveSyncNonBlocking]; } - (void)resolveSyncNonBlocking { NSString *host = self.config.host.length > 0 ? self.config.host : @"demo.cloudxdr.com"; NSString *queryType = self.config.queryType.length > 0 ? self.config.queryType : @"A"; NSTimeInterval startMs = [[NSDate date] timeIntervalSince1970] * 1000.0; [self appendLog:[NSString stringWithFormat:@"[resolve] host=%@ type=%@", host, queryType]]; __weak typeof(self) weakSelf = self; [self.service resolveHost:host queryType:queryType completion:^(HttpdnsEdgeResolveResult *result, NSError *error) { [weakSelf handleResult:result host:host queryType:queryType start:startMs error:error]; }]; } - (void)resolveSync { [self resolveSyncNonBlocking]; } - (void)handleResult:(HttpdnsEdgeResolveResult *)result host:(NSString *)host queryType:(NSString *)queryType start:(NSTimeInterval)startMs error:(NSError *)error { NSTimeInterval elapsedMs = [[NSDate date] timeIntervalSince1970] * 1000.0 - startMs; if (error != nil) { [self appendLog:[NSString stringWithFormat:@"[error] %@", error.localizedDescription]]; } else { [self appendLog:[NSString stringWithFormat:@"[result] requestId=%@ ipv4=%@ ipv6=%@ ttl=%ld elapsed=%.0fms", result.requestId, result.ipv4s, result.ipv6s, (long)result.ttl, elapsedMs]]; } dispatch_async(dispatch_get_main_queue(), ^{ self.model.host = host; if (result != nil) { self.model.ipv4s = result.ipv4s; self.model.ipv6s = result.ipv6s; self.model.ttlV4 = result.ipv4s.count > 0 ? result.ttl : 0; self.model.ttlV6 = result.ipv6s.count > 0 ? result.ttl : 0; self.model.error = nil; } else { self.model.ipv4s = @[]; self.model.ipv6s = @[]; self.model.error = error; } self.model.elapsedMs = elapsedMs; id delegate = self.delegate; if (delegate != nil) { [delegate scenario:self didUpdateModel:self.model]; } }); } - (void)appendLog:(NSString *)msg { if (msg.length == 0) return; NSString *line = [NSString stringWithFormat:@"%@ %@\n", [NSDate date], msg]; dispatch_async(self.logQueue, ^{ [self.logBuffer appendString:line]; id delegate = self.delegate; if (delegate != nil) { dispatch_async(dispatch_get_main_queue(), ^{ [delegate scenario:self didAppendLogLine:line]; }); } }); } - (NSString *)logSnapshot { __block NSString *snapshot = @""; dispatch_sync(self.logQueue, ^{ snapshot = [self.logBuffer copy]; }); return snapshot; } @end