Issue #12: Use proper DNS library instead of handcrafted DNS query to fetch statistics.
This commit is contained in:
parent
ddcf2070f7
commit
23952582e6
3 changed files with 62 additions and 32 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
A051B5122FC9E0D700EACDC0 /* AsyncDNSResolver in Frameworks */ = {isa = PBXBuildFile; productRef = A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */; };
|
||||||
A08264132FC718790077B227 /* Stickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A082640C2FC718790077B227 /* Stickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
A08264132FC718790077B227 /* Stickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A082640C2FC718790077B227 /* Stickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -74,6 +75,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
A051B5122FC9E0D700EACDC0 /* AsyncDNSResolver in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -125,6 +127,7 @@
|
||||||
);
|
);
|
||||||
name = dns;
|
name = dns;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */,
|
||||||
);
|
);
|
||||||
productName = dns;
|
productName = dns;
|
||||||
productReference = 069DCCFA2F8C0DCE00F1EB16 /* dns.app */;
|
productReference = 069DCCFA2F8C0DCE00F1EB16 /* dns.app */;
|
||||||
|
|
@ -178,6 +181,9 @@
|
||||||
);
|
);
|
||||||
mainGroup = 069DCCF12F8C0DCD00F1EB16;
|
mainGroup = 069DCCF12F8C0DCD00F1EB16;
|
||||||
minimizedProjectReferenceProxies = 1;
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
packageReferences = (
|
||||||
|
A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */,
|
||||||
|
);
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = 069DCCFB2F8C0DCE00F1EB16 /* Products */;
|
productRefGroup = 069DCCFB2F8C0DCE00F1EB16 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
|
@ -529,6 +535,25 @@
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/apple/swift-async-dns-resolver/";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 0.7.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */;
|
||||||
|
productName = AsyncDNSResolver;
|
||||||
|
};
|
||||||
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 069DCCF22F8C0DCD00F1EB16 /* Project object */;
|
rootObject = 069DCCF22F8C0DCD00F1EB16 /* Project object */;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"originHash" : "8d197ac71cfa33d9e3396085f37fbee66795a894a6d74e24ff28bd887e01b9f2",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "swift-async-dns-resolver",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-async-dns-resolver/",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "9900d9b4113427a170d5f26075c2128be94984df",
|
||||||
|
"version" : "0.7.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import AsyncDNSResolver
|
||||||
|
|
||||||
struct BlockedCount: View {
|
struct BlockedCount: View {
|
||||||
|
|
||||||
|
@Environment(\.scenePhase)
|
||||||
|
private var scenePhase
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
private var viewModel: ViewModel
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
|
|
@ -21,46 +25,32 @@ struct BlockedCount: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(txtRecord)
|
Text(txtRecord)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
fetchTXTRecord()
|
fetchTxtRecord()
|
||||||
}
|
}
|
||||||
.onChange(of: viewModel.blocklist) { _ in
|
.onChange(of: viewModel.blocklist) { _ in
|
||||||
fetchTXTRecord()
|
fetchTxtRecord()
|
||||||
|
}
|
||||||
|
.onChange(of: scenePhase) { newPhase in
|
||||||
|
if newPhase == .active {
|
||||||
|
fetchTxtRecord()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseResponse(data: Data) -> String? {
|
private func fetchTxtRecord() {
|
||||||
// This is a DNS wire format response and we make a lot of assumptions
|
|
||||||
// It is not critical functionality so just let it fail if it fails
|
|
||||||
|
|
||||||
guard data.count > Self.startIndex else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first space character (ASCII 32).
|
|
||||||
guard let endIndex = data.suffix(from: Self.startIndex).firstIndex(of: 32) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let numberString = String(data: data[Self.startIndex ..< endIndex], encoding: .utf8)
|
|
||||||
else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return Self.formatter.string(for: Int(numberString))
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchTXTRecord() {
|
|
||||||
let dohURL = URL(string: "https://\(viewModel.blocklist.server)/dns-query?dns=DoQBAAABAAAAAAAABXN0YXRzB2ludmFsaWQAABAAAQ")!
|
|
||||||
let request = URLRequest(url: dohURL)
|
|
||||||
|
|
||||||
txtRecord = "…"
|
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let (data, _) = try await URLSession.shared.data(for: request)
|
let resolver = try AsyncDNSResolver()
|
||||||
|
|
||||||
if let count = parseResponse(data: data) {
|
let records = try await resolver.queryTXT(name: "stats.invalid")
|
||||||
txtRecord = count
|
|
||||||
|
let text = records.map { $0.txt }.joined()
|
||||||
|
|
||||||
|
if let number = text.split(separator: " ").first,
|
||||||
|
let intValue = Int(number),
|
||||||
|
let formatted = Self.formatter.string(for: intValue)
|
||||||
|
{
|
||||||
|
txtRecord = formatted
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
txtRecord = NSLocalizedString("Error", comment: "")
|
txtRecord = NSLocalizedString("Error", comment: "")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue