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
|
|
@ -1,9 +1,13 @@
|
|||
|
||||
import SwiftUI
|
||||
import Foundation
|
||||
import AsyncDNSResolver
|
||||
|
||||
struct BlockedCount: View {
|
||||
|
||||
@Environment(\.scenePhase)
|
||||
private var scenePhase
|
||||
|
||||
@EnvironmentObject
|
||||
private var viewModel: ViewModel
|
||||
|
||||
|
|
@ -21,46 +25,32 @@ struct BlockedCount: View {
|
|||
var body: some View {
|
||||
Text(txtRecord)
|
||||
.onAppear {
|
||||
fetchTXTRecord()
|
||||
fetchTxtRecord()
|
||||
}
|
||||
.onChange(of: viewModel.blocklist) { _ in
|
||||
fetchTXTRecord()
|
||||
fetchTxtRecord()
|
||||
}
|
||||
.onChange(of: scenePhase) { newPhase in
|
||||
if newPhase == .active {
|
||||
fetchTxtRecord()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseResponse(data: Data) -> String? {
|
||||
// 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 = "…"
|
||||
|
||||
private func fetchTxtRecord() {
|
||||
Task {
|
||||
do {
|
||||
let (data, _) = try await URLSession.shared.data(for: request)
|
||||
let resolver = try AsyncDNSResolver()
|
||||
|
||||
if let count = parseResponse(data: data) {
|
||||
txtRecord = count
|
||||
let records = try await resolver.queryTXT(name: "stats.invalid")
|
||||
|
||||
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 {
|
||||
txtRecord = NSLocalizedString("Error", comment: "")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue