diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfig.plist b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfig.plist
index 6ac5211..ffa5dbb 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfig.plist
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfig.plist
@@ -2,11 +2,13 @@
- accountID
- 139450
- secretKey
- 807a19762f8eaefa8563489baf198535
- aesSecretKey
- 82c0af0d0cb2d69c4f87bb25c2e23929
+ appId
+ app1flndpo9
+ primaryServiceHost
+ httpdns.deepwaf.xyz
+ servicePort
+ 8445
+ signSecret
+
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.h b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.h
index 14bbe35..f9083f1 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.h
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.h
@@ -1,21 +1,17 @@
//
// DemoConfigLoader.h
-// TrustHttpDNSTestDemo
-//
-// @author Created by Claude Code on 2025-10-05
+// NewHttpDNSTestDemo
//
#import
@interface DemoConfigLoader : NSObject
-@property (nonatomic, assign, readonly) NSInteger accountID;
-@property (nonatomic, copy, readonly) NSString *secretKey;
-@property (nonatomic, copy, readonly) NSString *aesSecretKey;
-
-@property (nonatomic, assign, readonly) BOOL hasValidAccount;
+@property (nonatomic, copy, readonly) NSString *appId;
+@property (nonatomic, copy, readonly) NSString *primaryServiceHost;
+@property (nonatomic, assign, readonly) NSInteger servicePort;
+@property (nonatomic, copy, readonly, nullable) NSString *signSecret;
+ (instancetype)shared;
@end
-
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.m b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.m
index b9abafc..13c5223 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.m
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoConfigLoader.m
@@ -1,17 +1,15 @@
//
// DemoConfigLoader.m
-// TrustHttpDNSTestDemo
-//
-// @author Created by Claude Code on 2025-10-05
+// NewHttpDNSTestDemo
//
#import "DemoConfigLoader.h"
@implementation DemoConfigLoader {
- NSInteger _accountID;
- NSString *_secretKey;
- NSString *_aesSecretKey;
- BOOL _hasValidAccount;
+ NSString *_appId;
+ NSString *_primaryServiceHost;
+ NSInteger _servicePort;
+ NSString *_signSecret;
}
+ (instancetype)shared {
@@ -30,56 +28,23 @@
return self;
}
-// 复杂逻辑:配置加载顺序为 Bundle > 环境变量;并?accountID 进行有效性校?
- (void)loadConfig {
- _accountID = 0;
- _secretKey = @"";
- _aesSecretKey = @"";
- _hasValidAccount = NO;
-
- NSDictionary *bundleDict = nil;
+ NSDictionary *dict = nil;
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"DemoConfig" ofType:@"plist"];
if (plistPath.length > 0) {
- bundleDict = [NSDictionary dictionaryWithContentsOfFile:plistPath];
+ dict = [NSDictionary dictionaryWithContentsOfFile:plistPath];
}
- NSDictionary *env = [[NSProcessInfo processInfo] environment];
-
- NSNumber *acc = bundleDict[@"accountID"]; // NSNumber preferred in plist
- NSString *secret = bundleDict[@"secretKey"] ?: @"";
- NSString *aes = bundleDict[@"aesSecretKey"] ?: @"";
-
- NSString *envAcc = env[@"HTTPDNS_ACCOUNT_ID"];
- NSString *envSecret = env[@"HTTPDNS_SECRET_KEY"];
- NSString *envAes = env[@"HTTPDNS_AES_SECRET_KEY"];
-
- if (envAcc.length > 0) {
- acc = @([envAcc integerValue]);
- }
- if (envSecret.length > 0) {
- secret = envSecret;
- }
- if (envAes.length > 0) {
- aes = envAes;
- }
-
- if (acc != nil && [acc integerValue] > 0 && secret.length > 0) {
- _accountID = [acc integerValue];
- _secretKey = secret;
- _aesSecretKey = aes ?: @"";
- _hasValidAccount = YES;
- } else {
- _accountID = 0;
- _secretKey = @"";
- _aesSecretKey = @"";
- _hasValidAccount = NO;
- }
+ _appId = dict[@"appId"] ?: @"";
+ _primaryServiceHost = dict[@"primaryServiceHost"] ?: @"";
+ _servicePort = [dict[@"servicePort"] integerValue] ?: 443;
+ NSString *secret = dict[@"signSecret"] ?: @"";
+ _signSecret = secret.length > 0 ? secret : nil;
}
-- (NSInteger)accountID { return _accountID; }
-- (NSString *)secretKey { return _secretKey; }
-- (NSString *)aesSecretKey { return _aesSecretKey; }
-- (BOOL)hasValidAccount { return _hasValidAccount; }
+- (NSString *)appId { return _appId; }
+- (NSString *)primaryServiceHost { return _primaryServiceHost; }
+- (NSInteger)servicePort { return _servicePort; }
+- (NSString *)signSecret { return _signSecret; }
@end
-
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.h b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.h
index 8e0840e..f247ceb 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.h
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.h
@@ -1,13 +1,10 @@
//
// DemoHttpdnsScenario.h
-// TrustHttpDNSTestDemo
-//
-// @author Created by Claude Code on 2025-10-23
+// NewHttpDNSTestDemo
//
#import
#import "DemoResolveModel.h"
-#import "HttpdnsService.h"
NS_ASSUME_NONNULL_BEGIN
@@ -16,10 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface DemoHttpdnsScenarioConfig : NSObject
@property (nonatomic, copy) NSString *host;
-@property (nonatomic, assign) HttpdnsQueryIPType ipType;
-@property (nonatomic, assign) BOOL httpsEnabled;
-@property (nonatomic, assign) BOOL persistentCacheEnabled;
-@property (nonatomic, assign) BOOL reuseExpiredIPEnabled;
+@property (nonatomic, copy) NSString *queryType; // @"A", @"AAAA", @"both"
- (instancetype)init;
@@ -39,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithDelegate:(id)delegate;
- (void)applyConfig:(DemoHttpdnsScenarioConfig *)config;
+- (void)resolve;
- (void)resolveSyncNonBlocking;
- (void)resolveSync;
- (NSString *)logSnapshot;
@@ -46,4 +41,3 @@ NS_ASSUME_NONNULL_BEGIN
@end
NS_ASSUME_NONNULL_END
-
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.m b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.m
index 496e6ca..b708d71 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.m
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoHttpdnsScenario.m
@@ -1,12 +1,11 @@
-//
+//
// DemoHttpdnsScenario.m
// NewHttpDNSTestDemo
//
-// @author Created by Claude Code on 2025-10-23
-//
#import "DemoHttpdnsScenario.h"
#import "DemoConfigLoader.h"
+#import
@interface DemoHttpdnsScenarioConfig ()
@end
@@ -15,11 +14,8 @@
- (instancetype)init {
if (self = [super init]) {
- _host = @"www.new.com";
- _ipType = HttpdnsQueryIPTypeBoth;
- _httpsEnabled = YES;
- _persistentCacheEnabled = YES;
- _reuseExpiredIPEnabled = YES;
+ _host = @"demo.cloudxdr.com";
+ _queryType = @"A";
}
return self;
}
@@ -27,18 +23,15 @@
- (id)copyWithZone:(NSZone *)zone {
DemoHttpdnsScenarioConfig *cfg = [[[self class] allocWithZone:zone] init];
cfg.host = self.host;
- cfg.ipType = self.ipType;
- cfg.httpsEnabled = self.httpsEnabled;
- cfg.persistentCacheEnabled = self.persistentCacheEnabled;
- cfg.reuseExpiredIPEnabled = self.reuseExpiredIPEnabled;
+ cfg.queryType = self.queryType;
return cfg;
}
@end
-@interface DemoHttpdnsScenario ()
+@interface DemoHttpdnsScenario ()
-@property (nonatomic, strong) HttpDnsService *service;
+@property (nonatomic, strong) HttpdnsEdgeService *service;
@property (nonatomic, strong) DemoHttpdnsScenarioConfig *config;
@property (nonatomic, strong) NSMutableString *logBuffer;
@property (nonatomic, strong) dispatch_queue_t logQueue;
@@ -55,73 +48,76 @@
_logBuffer = [NSMutableString string];
_logQueue = dispatch_queue_create("com.new.httpdns.demo.log", DISPATCH_QUEUE_SERIAL);
[self buildService];
- [self applyConfig:_config];
}
return self;
}
- (void)buildService {
DemoConfigLoader *cfg = [DemoConfigLoader shared];
- if (cfg.hasValidAccount) {
- if (cfg.aesSecretKey.length > 0) {
- self.service = [[HttpDnsService alloc] initWithAccountID:cfg.accountID secretKey:cfg.secretKey aesSecretKey:cfg.aesSecretKey];
- } else {
- self.service = [[HttpDnsService alloc] initWithAccountID:cfg.accountID secretKey:cfg.secretKey];
- }
- } else {
- self.service = [HttpDnsService sharedInstance];
- }
- [self.service setLogEnabled:YES];
- [self.service setNetworkingTimeoutInterval:8];
- [self.service setDegradeToLocalDNSEnabled:YES];
- self.service.ttlDelegate = self;
- [self.service setLogHandler:self];
+ 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;
- self.model.ipType = self.config.ipType;
- [self.service setHTTPSRequestEnabled:self.config.httpsEnabled];
- [self.service setPersistentCacheIPEnabled:self.config.persistentCacheEnabled];
- [self.service setReuseExpiredIPEnabled:self.config.reuseExpiredIPEnabled];
+}
+
+- (void)resolve {
+ [self resolveSyncNonBlocking];
}
- (void)resolveSyncNonBlocking {
- NSString *queryHost = [self currentHost];
- HttpdnsQueryIPType ipType = self.config.ipType;
+ 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;
- HttpdnsResult *result = [self.service resolveHostSyncNonBlocking:queryHost byIpType:ipType];
- [self handleResult:result host:queryHost ipType:ipType start:startMs];
+
+ [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 {
- NSString *queryHost = [self currentHost];
- HttpdnsQueryIPType ipType = self.config.ipType;
- dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
- NSTimeInterval startMs = [[NSDate date] timeIntervalSince1970] * 1000.0;
- HttpdnsResult *result = [self.service resolveHostSync:queryHost byIpType:ipType];
- [self handleResult:result host:queryHost ipType:ipType start:startMs];
- });
+ [self resolveSyncNonBlocking];
}
-- (NSString *)logSnapshot {
- __block NSString *snapshot = @"";
- dispatch_sync(self.logQueue, ^{
- snapshot = [self.logBuffer copy];
- });
- return snapshot;
-}
+- (void)handleResult:(HttpdnsEdgeResolveResult *)result
+ host:(NSString *)host
+ queryType:(NSString *)queryType
+ start:(NSTimeInterval)startMs
+ error:(NSError *)error {
+ NSTimeInterval elapsedMs = [[NSDate date] timeIntervalSince1970] * 1000.0 - startMs;
-- (NSString *)currentHost {
- return self.config.host.length > 0 ? self.config.host : @"www.new.com";
-}
+ 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]];
+ }
-- (void)handleResult:(HttpdnsResult *)result host:(NSString *)host ipType:(HttpdnsQueryIPType)ipType start:(NSTimeInterval)startMs {
dispatch_async(dispatch_get_main_queue(), ^{
self.model.host = host;
- self.model.ipType = ipType;
- [self.model updateWithResult:result startTimeMs:startMs];
+ 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];
@@ -129,12 +125,9 @@
});
}
-- (void)log:(NSString *)logStr {
- if (logStr.length == 0) {
- return;
- }
- NSString *line = [NSString stringWithFormat:@"%@ %@\n", [NSDate date], logStr];
- // 使用串行队列保证日志追加与快照的一致性
+- (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;
@@ -146,8 +139,12 @@
});
}
-- (int64_t)httpdnsHost:(NSString *)host ipType:(NewHttpDNS_IPType)ipType ttl:(int64_t)ttl {
- return ttl;
+- (NSString *)logSnapshot {
+ __block NSString *snapshot = @"";
+ dispatch_sync(self.logQueue, ^{
+ snapshot = [self.logBuffer copy];
+ });
+ return snapshot;
}
@end
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.h b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.h
index 751f721..e20da78 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.h
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.h
@@ -1,27 +1,18 @@
//
// DemoResolveModel.h
-// TrustHttpDNSTestDemo
-//
-// @author Created by Claude Code on 2025-10-05
+// NewHttpDNSTestDemo
//
#import
-#import "HttpdnsRequest.h"
-#import "HttpdnsResult.h"
@interface DemoResolveModel : NSObject
@property (nonatomic, copy) NSString *host;
-@property (nonatomic, assign) HttpdnsQueryIPType ipType;
-
@property (nonatomic, copy) NSArray *ipv4s;
@property (nonatomic, copy) NSArray *ipv6s;
-
@property (nonatomic, assign) NSTimeInterval elapsedMs;
@property (nonatomic, assign) NSTimeInterval ttlV4;
@property (nonatomic, assign) NSTimeInterval ttlV6;
-
-- (void)updateWithResult:(HttpdnsResult *)result startTimeMs:(NSTimeInterval)startMs;
+@property (nonatomic, strong, nullable) NSError *error;
@end
-
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.m b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.m
index 403258e..7500640 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.m
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoResolveModel.m
@@ -1,9 +1,7 @@
-//
+//
// DemoResolveModel.m
// NewHttpDNSTestDemo
//
-// @author Created by Claude Code on 2025-10-05
-//
#import "DemoResolveModel.h"
@@ -11,32 +9,15 @@
- (instancetype)init {
if (self = [super init]) {
- _host = @"www.new.com";
- _ipType = HttpdnsQueryIPTypeBoth;
+ _host = @"demodemo.cloudxdr.com";
_ipv4s = @[];
_ipv6s = @[];
_elapsedMs = 0;
_ttlV4 = 0;
_ttlV6 = 0;
+ _error = nil;
}
return self;
}
-- (void)updateWithResult:(HttpdnsResult *)result startTimeMs:(NSTimeInterval)startMs {
- NSTimeInterval now = [[NSDate date] timeIntervalSince1970] * 1000.0;
- _elapsedMs = MAX(0, now - startMs);
- if (result != nil) {
- _ipv4s = result.ips ?: @[];
- _ipv6s = result.ipv6s ?: @[];
- _ttlV4 = result.ttl;
- _ttlV6 = result.v6ttl;
- } else {
- _ipv4s = @[];
- _ipv6s = @[];
- _ttlV4 = 0;
- _ttlV6 = 0;
- }
-}
-
@end
-
diff --git a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoViewController.m b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoViewController.m
index 1b43cde..2b6a9c4 100644
--- a/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoViewController.m
+++ b/HttpDNSSDK/sdk/ios/NewHttpDNSTestDemo/DemoViewController.m
@@ -1,8 +1,6 @@
-//
-// DNSDemoViewController.m
-// NewHttpDNSTestDemo
//
-// @author Created by Claude Code on 2025-10-05
+// DemoViewController.m
+// NewHttpDNSTestDemo
//
#import "DemoViewController.h"
@@ -20,15 +18,10 @@
@property (nonatomic, strong) UIStackView *stack;
@property (nonatomic, strong) UITextField *hostField;
-@property (nonatomic, strong) UISegmentedControl *ipTypeSeg;
-
-@property (nonatomic, strong) UISwitch *swHTTPS;
-@property (nonatomic, strong) UISwitch *swPersist;
-@property (nonatomic, strong) UISwitch *swReuse;
+@property (nonatomic, strong) UISegmentedControl *queryTypeSeg;
@property (nonatomic, strong) UILabel *elapsedLabel;
@property (nonatomic, strong) UILabel *ttlLabel;
-
@property (nonatomic, strong) UITextView *resultTextView;
@property (nonatomic, weak) DemoLogViewController *presentedLogVC;
@@ -46,7 +39,8 @@
self.scenarioConfig = [[DemoHttpdnsScenarioConfig alloc] init];
[self buildUI];
[self reloadUIFromModel:self.model];
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"日志" style:UIBarButtonItemStylePlain target:self action:@selector(onShowLog)];
+ self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
+ initWithTitle:@"日志" style:UIBarButtonItemStylePlain target:self action:@selector(onShowLog)];
}
- (void)buildUI {
@@ -73,57 +67,36 @@
[self.stack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-32]
]];
+ // Host 输入
UIStackView *row1 = [self labeledRow:@"Host"];
self.hostField = [[UITextField alloc] init];
- self.hostField.placeholder = @"www.new.com";
+ self.hostField.placeholder = @"demodemo.cloudxdr.com";
self.hostField.text = self.scenarioConfig.host;
self.hostField.borderStyle = UITextBorderStyleRoundedRect;
[row1 addArrangedSubview:self.hostField];
[self.stack addArrangedSubview:row1];
- UIStackView *row2 = [self labeledRow:@"IP Type"];
- self.ipTypeSeg = [[UISegmentedControl alloc] initWithItems:@[@"IPv4", @"IPv6", @"Both"]];
- self.ipTypeSeg.selectedSegmentIndex = [self segmentIndexForIpType:self.scenarioConfig.ipType];
- [self.ipTypeSeg addTarget:self action:@selector(onIPTypeChanged:) forControlEvents:UIControlEventValueChanged];
- [row2 addArrangedSubview:self.ipTypeSeg];
+ // 查询类型
+ UIStackView *row2 = [self labeledRow:@"类型"];
+ self.queryTypeSeg = [[UISegmentedControl alloc] initWithItems:@[@"A (IPv4)", @"AAAA (IPv6)", @"both"]];
+ self.queryTypeSeg.selectedSegmentIndex = 0;
+ [self.queryTypeSeg addTarget:self action:@selector(onQueryTypeChanged:) forControlEvents:UIControlEventValueChanged];
+ [row2 addArrangedSubview:self.queryTypeSeg];
[self.stack addArrangedSubview:row2];
- UIStackView *opts = [[UIStackView alloc] init];
- opts.axis = UILayoutConstraintAxisHorizontal;
- opts.alignment = UIStackViewAlignmentCenter;
- opts.distribution = UIStackViewDistributionFillEqually;
- opts.spacing = 8;
- [self.stack addArrangedSubview:opts];
-
- [opts addArrangedSubview:[self switchItem:@"HTTPS" action:@selector(onToggleHTTPS:) out:&_swHTTPS]];
- [opts addArrangedSubview:[self switchItem:@"持久化" action:@selector(onTogglePersist:) out:&_swPersist]];
- [opts addArrangedSubview:[self switchItem:@"复用过期" action:@selector(onToggleReuse:) out:&_swReuse]];
-
- self.swHTTPS.on = self.scenarioConfig.httpsEnabled;
- self.swPersist.on = self.scenarioConfig.persistentCacheEnabled;
- self.swReuse.on = self.scenarioConfig.reuseExpiredIPEnabled;
- [self applyOptionSwitches];
-
- UIStackView *actions = [[UIStackView alloc] init];
- actions.axis = UILayoutConstraintAxisHorizontal;
- actions.spacing = 12;
- actions.distribution = UIStackViewDistributionFillEqually;
- [self.stack addArrangedSubview:actions];
-
- UIButton *btnAsync = [self filledButton:@"Resolve (SyncNonBlocing)" action:@selector(onResolveAsync)];
- UIButton *btnSync = [self borderButton:@"Resolve (Sync)" action:@selector(onResolveSync)];
- [actions addArrangedSubview:btnAsync];
- [actions addArrangedSubview:btnSync];
+ // 解析按钮
+ UIButton *btnResolve = [self filledButton:@"Resolve" action:@selector(onResolve)];
+ [self.stack addArrangedSubview:btnResolve];
+ // 耗时 / TTL
UIStackView *info = [self labeledRow:@"Info"];
self.elapsedLabel = [self monoLabel:@"elapsed: - ms"];
- self.ttlLabel = [self monoLabel:@"ttl v4/v6: -/- s"];
+ self.ttlLabel = [self monoLabel:@"ttl: -"];
[info addArrangedSubview:self.elapsedLabel];
[info addArrangedSubview:self.ttlLabel];
[self.stack addArrangedSubview:info];
- if (@available(iOS 11.0, *)) { [self.stack setCustomSpacing:24 afterView:info]; }
-
+ // 结果
UILabel *resultTitle = [[UILabel alloc] init];
resultTitle.text = @"结果";
resultTitle.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
@@ -135,18 +108,66 @@
if (@available(iOS 13.0, *)) {
self.resultTextView.font = [UIFont monospacedSystemFontOfSize:12 weight:UIFontWeightRegular];
self.resultTextView.textColor = [UIColor labelColor];
- } else {
- self.resultTextView.font = [UIFont systemFontOfSize:12];
- self.resultTextView.textColor = [UIColor blackColor];
}
self.resultTextView.backgroundColor = [UIColor clearColor];
self.resultTextView.textContainerInset = UIEdgeInsetsMake(8, 12, 8, 12);
[self.stack addArrangedSubview:self.resultTextView];
[self.resultTextView.heightAnchor constraintEqualToConstant:320].active = YES;
-
-
}
+#pragma mark - Actions
+
+- (void)onQueryTypeChanged:(UISegmentedControl *)seg {
+ NSArray *types = @[@"A", @"AAAA", @"both"];
+ self.scenarioConfig.queryType = types[seg.selectedSegmentIndex];
+ [self.scenario applyConfig:self.scenarioConfig];
+}
+
+- (void)onResolve {
+ [self.view endEditing:YES];
+ NSString *host = self.hostField.text.length > 0 ? self.hostField.text : @"demodemo.cloudxdr.com";
+ self.scenarioConfig.host = host;
+ [self.scenario applyConfig:self.scenarioConfig];
+ [self.scenario resolve];
+}
+
+- (void)onShowLog {
+ DemoLogViewController *logVC = [DemoLogViewController new];
+ [logVC setInitialText:[self.scenario logSnapshot]];
+ self.presentedLogVC = logVC;
+ UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:logVC];
+ nav.modalPresentationStyle = UIModalPresentationAutomatic;
+ [self presentViewController:nav animated:YES completion:nil];
+}
+
+- (void)reloadUIFromModel:(DemoResolveModel *)model {
+ self.model = model;
+ if (![self.hostField isFirstResponder]) {
+ self.hostField.text = model.host;
+ }
+ self.elapsedLabel.text = [NSString stringWithFormat:@"elapsed: %.0f ms", model.elapsedMs];
+ self.ttlLabel.text = [NSString stringWithFormat:@"ttl v4/v6: %.0f/%.0f s", model.ttlV4, model.ttlV6];
+ self.resultTextView.text = [self buildResultText:model];
+}
+
+- (NSString *)buildResultText:(DemoResolveModel *)model {
+ if (model.error != nil) {
+ return [NSString stringWithFormat:@"Error:\n%@", model.error.localizedDescription];
+ }
+ NSDictionary *dict = @{
+ @"host": model.host ?: @"",
+ @"elapsed": [NSString stringWithFormat:@"%.0f ms", model.elapsedMs],
+ @"ttl": @{ @"v4": @(model.ttlV4), @"v6": @(model.ttlV6) },
+ @"ipv4": model.ipv4s ?: @[],
+ @"ipv6": model.ipv6s ?: @[]
+ };
+ NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
+ if (data == nil) return @"{}";
+ return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+}
+
+#pragma mark - Helpers
+
- (UIStackView *)labeledRow:(NSString *)title {
UIStackView *row = [[UIStackView alloc] init];
row.axis = UILayoutConstraintAxisHorizontal;
@@ -164,8 +185,6 @@
l.text = text;
if (@available(iOS 13.0, *)) {
l.font = [UIFont monospacedSystemFontOfSize:12 weight:UIFontWeightRegular];
- } else {
- l.font = [UIFont systemFontOfSize:12];
}
return l;
}
@@ -181,131 +200,6 @@
return b;
}
-- (UIButton *)borderButton:(NSString *)title action:(SEL)sel {
- UIButton *b = [UIButton buttonWithType:UIButtonTypeSystem];
- [b setTitle:title forState:UIControlStateNormal];
- b.layer.borderWidth = 1;
- b.layer.borderColor = [UIColor systemBlueColor].CGColor;
- b.layer.cornerRadius = 8;
- [b.heightAnchor constraintEqualToConstant:44].active = YES;
- [b addTarget:self action:sel forControlEvents:UIControlEventTouchUpInside];
- return b;
-}
-
-- (UIView *)switchItem:(NSString *)title action:(SEL)sel out:(UISwitch * __strong *)outSwitch {
- UIStackView *box = [[UIStackView alloc] init];
- box.axis = UILayoutConstraintAxisVertical;
- box.alignment = UIStackViewAlignmentCenter;
- UILabel *l = [[UILabel alloc] init];
- l.text = title;
- UISwitch *s = [[UISwitch alloc] init];
- [s addTarget:self action:sel forControlEvents:UIControlEventValueChanged];
- [box addArrangedSubview:s];
- [box addArrangedSubview:l];
- if (outSwitch != NULL) {
- *outSwitch = s;
- }
- return box;
-}
-
-- (NSInteger)segmentIndexForIpType:(HttpdnsQueryIPType)ipType {
- switch (ipType) {
- case HttpdnsQueryIPTypeIpv4: { return 0; }
- case HttpdnsQueryIPTypeIpv6: { return 1; }
- default: { return 2; }
- }
-}
-
-#pragma mark - Actions
-
-- (void)onIPTypeChanged:(UISegmentedControl *)seg {
- HttpdnsQueryIPType type = HttpdnsQueryIPTypeBoth;
- switch (seg.selectedSegmentIndex) {
- case 0: type = HttpdnsQueryIPTypeIpv4; break;
- case 1: type = HttpdnsQueryIPTypeIpv6; break;
- default: type = HttpdnsQueryIPTypeBoth; break;
- }
- self.model.ipType = type;
- self.scenarioConfig.ipType = type;
- [self.scenario applyConfig:self.scenarioConfig];
-}
-
-- (void)applyOptionSwitches {
- self.scenarioConfig.httpsEnabled = self.swHTTPS.isOn;
- self.scenarioConfig.persistentCacheEnabled = self.swPersist.isOn;
- self.scenarioConfig.reuseExpiredIPEnabled = self.swReuse.isOn;
- [self.scenario applyConfig:self.scenarioConfig];
-}
-
-- (void)onToggleHTTPS:(UISwitch *)s { [self applyOptionSwitches]; }
-- (void)onTogglePersist:(UISwitch *)s { [self applyOptionSwitches]; }
-- (void)onToggleReuse:(UISwitch *)s { [self applyOptionSwitches]; }
-
-- (void)onResolveAsync {
- [self.view endEditing:YES];
- NSString *host = self.hostField.text.length > 0 ? self.hostField.text : @"www.new.com";
- self.model.host = host;
- self.scenarioConfig.host = host;
- [self.scenario applyConfig:self.scenarioConfig];
- [self.scenario resolveSyncNonBlocking];
-}
-
-- (void)onResolveSync {
- [self.view endEditing:YES];
- NSString *host = self.hostField.text.length > 0 ? self.hostField.text : @"www.new.com";
- self.model.host = host;
- self.scenarioConfig.host = host;
- [self.scenario applyConfig:self.scenarioConfig];
- [self.scenario resolveSync];
-}
-
-- (void)onShowLog {
- DemoLogViewController *logVC = [DemoLogViewController new];
- [logVC setInitialText:[self.scenario logSnapshot]];
- self.presentedLogVC = logVC;
- UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:logVC];
- nav.modalPresentationStyle = UIModalPresentationAutomatic;
- [self presentViewController:nav animated:YES completion:nil];
-}
-
-- (void)reloadUIFromModel:(DemoResolveModel *)model {
- self.model = model;
- if (![self.hostField isFirstResponder]) {
- self.hostField.text = model.host;
- }
- NSInteger segIndex = [self segmentIndexForIpType:model.ipType];
- if (self.ipTypeSeg.selectedSegmentIndex != segIndex) {
- self.ipTypeSeg.selectedSegmentIndex = segIndex;
- }
- self.elapsedLabel.text = [NSString stringWithFormat:@"elapsed: %.0f ms", model.elapsedMs];
- self.ttlLabel.text = [NSString stringWithFormat:@"ttl v4/v6: %.0f/%.0f s", model.ttlV4, model.ttlV6];
- self.resultTextView.text = [self buildJSONText:model];
-}
-
-
-- (NSString *)buildJSONText:(DemoResolveModel *)model {
- NSString *ipTypeStr = @"both";
- switch (model.ipType) {
- case HttpdnsQueryIPTypeIpv4: { ipTypeStr = @"ipv4"; break; }
- case HttpdnsQueryIPTypeIpv6: { ipTypeStr = @"ipv6"; break; }
- default: { ipTypeStr = @"both"; break; }
- }
- NSDictionary *dict = @{
- @"host": model.host ?: @"",
- @"ipType": ipTypeStr,
- @"elapsedMs": @(model.elapsedMs),
- @"ttl": @{ @"v4": @(model.ttlV4), @"v6": @(model.ttlV6) },
- @"ipv4": model.ipv4s ?: @[],
- @"ipv6": model.ipv6s ?: @[]
- };
- NSError *err = nil;
- NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&err];
- if (data == nil || err != nil) {
- return [NSString stringWithFormat:@"{\n \"error\": \"%@\"\n}", err.localizedDescription ?: @"json serialize failed"];
- }
- return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-}
-
#pragma mark - DemoHttpdnsScenarioDelegate
- (void)scenario:(DemoHttpdnsScenario *)scenario didUpdateModel:(DemoResolveModel *)model {