mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-09 22:35:56 +05:45
`DNSChecker.errorWithBlockedHostFromError` already checks `isBlockedAPIError` when constructing this error, so we can simplify this to avoid calling `DNSChecker.resolvedHost` twice.
87 lines
2.5 KiB
Swift
87 lines
2.5 KiB
Swift
//
|
|
// Copyright RevenueCat Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the MIT License (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://opensource.org/licenses/MIT
|
|
//
|
|
// DNSChecker.swift
|
|
//
|
|
// Created by Joshua Liebowitz on 12/20/21.
|
|
|
|
import Foundation
|
|
|
|
protocol DNSCheckerType {
|
|
|
|
static func isBlockedAPIError(_ error: Error?) -> Bool
|
|
static func errorWithBlockedHostFromError(_ error: Error?) -> NetworkError?
|
|
static func isBlockedURL(_ url: URL) -> Bool
|
|
static func resolvedHost(fromURL url: URL) -> String?
|
|
|
|
}
|
|
|
|
enum DNSChecker: DNSCheckerType {
|
|
|
|
static let invalidHosts = Set(["0.0.0.0", "127.0.0.1"])
|
|
|
|
static func isBlockedAPIError(_ error: Error?) -> Bool {
|
|
guard let error = error else {
|
|
return false
|
|
}
|
|
|
|
let nsError = error as NSError
|
|
guard nsError.domain == NSURLErrorDomain,
|
|
nsError.code == NSURLErrorCannotConnectToHost else {
|
|
return false
|
|
}
|
|
|
|
guard let failedURL = nsError.userInfo[NSURLErrorFailingURLErrorKey] as? URL else {
|
|
return false
|
|
}
|
|
|
|
return isBlockedURL(failedURL)
|
|
}
|
|
|
|
static func errorWithBlockedHostFromError(_ error: Error?) -> NetworkError? {
|
|
guard self.isBlockedAPIError(error),
|
|
let nsError = error as NSError?,
|
|
let failedURL = nsError.userInfo[NSURLErrorFailingURLErrorKey] as? URL else {
|
|
return nil
|
|
}
|
|
|
|
let host = self.resolvedHost(fromURL: failedURL)
|
|
return .dnsError(failedURL: failedURL, resolvedHost: host)
|
|
}
|
|
|
|
static func isBlockedURL(_ url: URL) -> Bool {
|
|
guard let resolvedHostName = self.resolvedHost(fromURL: url) else {
|
|
return false
|
|
}
|
|
|
|
Logger.debug(Strings.network.failing_url_resolved_to_host(url: url,
|
|
resolvedHost: resolvedHostName))
|
|
|
|
return self.invalidHosts.contains(resolvedHostName)
|
|
}
|
|
|
|
static func resolvedHost(fromURL url: URL) -> String? {
|
|
guard let name = url.host,
|
|
let host = name.withCString({gethostbyname($0)}),
|
|
host.pointee.h_length > 0 else {
|
|
return nil
|
|
}
|
|
var addr = in_addr()
|
|
memcpy(&addr.s_addr, host.pointee.h_addr_list[0], Int(host.pointee.h_length))
|
|
|
|
guard let remoteIPAsC = inet_ntoa(addr) else {
|
|
return nil
|
|
}
|
|
|
|
let hostIP = String(cString: remoteIPAsC)
|
|
return hostIP
|
|
}
|
|
|
|
}
|