216 lines
8.5 KiB
Objective-C
216 lines
8.5 KiB
Objective-C
//
|
|
// DemoViewController.m
|
|
// NewHttpDNSTestDemo
|
|
//
|
|
|
|
#import "DemoViewController.h"
|
|
#import "DemoResolveModel.h"
|
|
#import "DemoLogViewController.h"
|
|
#import "DemoHttpdnsScenario.h"
|
|
|
|
@interface DemoViewController () <DemoHttpdnsScenarioDelegate>
|
|
|
|
@property (nonatomic, strong) DemoHttpdnsScenario *scenario;
|
|
@property (nonatomic, strong) DemoHttpdnsScenarioConfig *scenarioConfig;
|
|
@property (nonatomic, strong) DemoResolveModel *model;
|
|
|
|
@property (nonatomic, strong) UIScrollView *scrollView;
|
|
@property (nonatomic, strong) UIStackView *stack;
|
|
|
|
@property (nonatomic, strong) UITextField *hostField;
|
|
@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;
|
|
|
|
@end
|
|
|
|
@implementation DemoViewController
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
self.title = @"HTTPDNS Demo";
|
|
self.view.backgroundColor = [UIColor systemBackgroundColor];
|
|
self.scenario = [[DemoHttpdnsScenario alloc] initWithDelegate:self];
|
|
self.model = self.scenario.model;
|
|
self.scenarioConfig = [[DemoHttpdnsScenarioConfig alloc] init];
|
|
[self buildUI];
|
|
[self reloadUIFromModel:self.model];
|
|
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
|
|
initWithTitle:@"日志" style:UIBarButtonItemStylePlain target:self action:@selector(onShowLog)];
|
|
}
|
|
|
|
- (void)buildUI {
|
|
self.scrollView = [[UIScrollView alloc] init];
|
|
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.view addSubview:self.scrollView];
|
|
[NSLayoutConstraint activateConstraints:@[
|
|
[self.scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
|
|
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
|
|
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
|
|
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
|
|
]];
|
|
|
|
self.stack = [[UIStackView alloc] init];
|
|
self.stack.axis = UILayoutConstraintAxisVertical;
|
|
self.stack.spacing = 12.0;
|
|
self.stack.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.scrollView addSubview:self.stack];
|
|
[NSLayoutConstraint activateConstraints:@[
|
|
[self.stack.topAnchor constraintEqualToAnchor:self.scrollView.topAnchor constant:16],
|
|
[self.stack.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
|
|
[self.stack.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
|
|
[self.stack.bottomAnchor constraintEqualToAnchor:self.scrollView.bottomAnchor constant:-16],
|
|
[self.stack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-32]
|
|
]];
|
|
|
|
// Host 输入
|
|
UIStackView *row1 = [self labeledRow:@"Host"];
|
|
self.hostField = [[UITextField alloc] init];
|
|
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:@"类型"];
|
|
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];
|
|
|
|
// 解析按钮
|
|
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: -"];
|
|
[info addArrangedSubview:self.elapsedLabel];
|
|
[info addArrangedSubview:self.ttlLabel];
|
|
[self.stack addArrangedSubview:info];
|
|
|
|
// 结果
|
|
UILabel *resultTitle = [[UILabel alloc] init];
|
|
resultTitle.text = @"结果";
|
|
resultTitle.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
|
|
[self.stack addArrangedSubview:resultTitle];
|
|
|
|
self.resultTextView = [[UITextView alloc] init];
|
|
self.resultTextView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
self.resultTextView.editable = NO;
|
|
if (@available(iOS 13.0, *)) {
|
|
self.resultTextView.font = [UIFont monospacedSystemFontOfSize:12 weight:UIFontWeightRegular];
|
|
self.resultTextView.textColor = [UIColor labelColor];
|
|
}
|
|
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;
|
|
row.alignment = UIStackViewAlignmentCenter;
|
|
row.spacing = 8.0;
|
|
UILabel *label = [[UILabel alloc] init];
|
|
label.text = title;
|
|
[label.widthAnchor constraintGreaterThanOrEqualToConstant:64].active = YES;
|
|
[row addArrangedSubview:label];
|
|
return row;
|
|
}
|
|
|
|
- (UILabel *)monoLabel:(NSString *)text {
|
|
UILabel *l = [[UILabel alloc] init];
|
|
l.text = text;
|
|
if (@available(iOS 13.0, *)) {
|
|
l.font = [UIFont monospacedSystemFontOfSize:12 weight:UIFontWeightRegular];
|
|
}
|
|
return l;
|
|
}
|
|
|
|
- (UIButton *)filledButton:(NSString *)title action:(SEL)sel {
|
|
UIButton *b = [UIButton buttonWithType:UIButtonTypeSystem];
|
|
[b setTitle:title forState:UIControlStateNormal];
|
|
b.backgroundColor = [UIColor systemBlueColor];
|
|
[b setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
|
b.layer.cornerRadius = 8;
|
|
[b.heightAnchor constraintEqualToConstant:44].active = YES;
|
|
[b addTarget:self action:sel forControlEvents:UIControlEventTouchUpInside];
|
|
return b;
|
|
}
|
|
|
|
#pragma mark - DemoHttpdnsScenarioDelegate
|
|
|
|
- (void)scenario:(DemoHttpdnsScenario *)scenario didUpdateModel:(DemoResolveModel *)model {
|
|
[self reloadUIFromModel:model];
|
|
}
|
|
|
|
- (void)scenario:(DemoHttpdnsScenario *)scenario didAppendLogLine:(NSString *)line {
|
|
if (self.presentedLogVC != nil) {
|
|
[self.presentedLogVC appendLine:line];
|
|
}
|
|
}
|
|
|
|
@end
|