mirror of https://github.com/oxen-io/session-ios
Merge branch 'charlesmchen/outageDetection'
commit
e2de8f6ffa
@ -1 +1 @@
|
||||
Subproject commit 5caa906cfd9c24f464247747004cc8335b96040c
|
||||
Subproject commit d82a13db8aa161a7db21a442ad38b98bd458b951
|
@ -0,0 +1,128 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
@objc
|
||||
public class OutageDetection: NSObject {
|
||||
@objc(sharedManager)
|
||||
public static let shared = OutageDetection()
|
||||
|
||||
@objc public static let outageStateDidChange = Notification.Name("OutageStateDidChange")
|
||||
|
||||
// These properties should only be accessed on the main thread.
|
||||
@objc
|
||||
public var hasOutage = false {
|
||||
didSet {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
if hasOutage != oldValue {
|
||||
Logger.info("\(self.logTag) hasOutage: \(hasOutage).")
|
||||
|
||||
NotificationCenter.default.postNotificationNameAsync(OutageDetection.outageStateDidChange, object: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
private var shouldCheckForOutage = false {
|
||||
didSet {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
ensureCheckTimer()
|
||||
}
|
||||
}
|
||||
|
||||
// We only show the outage warning when we're certain there's an outage.
|
||||
// DNS lookup failures, etc. are not considered an outage.
|
||||
private func checkForOutageSync() -> Bool {
|
||||
let host = CFHostCreateWithName(nil, "uptime.signal.org" as CFString).takeRetainedValue()
|
||||
CFHostStartInfoResolution(host, .addresses, nil)
|
||||
var success: DarwinBoolean = false
|
||||
guard let addresses = CFHostGetAddressing(host, &success)?.takeUnretainedValue() as NSArray? else {
|
||||
Logger.error("\(logTag) CFHostGetAddressing failed: no addresses.")
|
||||
return false
|
||||
}
|
||||
guard success.boolValue else {
|
||||
Logger.error("\(logTag) CFHostGetAddressing failed.")
|
||||
return false
|
||||
}
|
||||
var isOutageDetected = false
|
||||
for case let address as NSData in addresses {
|
||||
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
||||
if getnameinfo(address.bytes.assumingMemoryBound(to: sockaddr.self), socklen_t(address.length),
|
||||
&hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 {
|
||||
let addressString = String(cString: hostname)
|
||||
let kHealthyAddress = "127.0.0.1"
|
||||
let kOutageAddress = "127.0.0.2"
|
||||
if addressString == kHealthyAddress {
|
||||
// Do nothing.
|
||||
} else if addressString == kOutageAddress {
|
||||
isOutageDetected = true
|
||||
} else {
|
||||
owsFail("\(logTag) unexpected address: \(addressString)")
|
||||
}
|
||||
}
|
||||
}
|
||||
return isOutageDetected
|
||||
}
|
||||
|
||||
private func checkForOutageAsync() {
|
||||
Logger.info("\(self.logTag) \(#function).")
|
||||
|
||||
DispatchQueue.global().async {
|
||||
let isOutageDetected = self.checkForOutageSync()
|
||||
DispatchQueue.main.async {
|
||||
self.hasOutage = isOutageDetected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var checkTimer: Timer?
|
||||
private func ensureCheckTimer() {
|
||||
// Only monitor for outages in the main app.
|
||||
guard CurrentAppContext().isMainApp else {
|
||||
return
|
||||
}
|
||||
|
||||
if shouldCheckForOutage {
|
||||
if checkTimer != nil {
|
||||
// Already has timer.
|
||||
return
|
||||
}
|
||||
|
||||
// The TTL of the DNS record is 60 seconds.
|
||||
checkTimer = WeakTimer.scheduledTimer(timeInterval: 60, target: self, userInfo: nil, repeats: true) { [weak self] _ in
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
guard CurrentAppContext().isMainAppAndActive else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.checkForOutageAsync()
|
||||
}
|
||||
} else {
|
||||
checkTimer?.invalidate()
|
||||
checkTimer = nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func reportConnectionSuccess() {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
shouldCheckForOutage = false
|
||||
hasOutage = false
|
||||
}
|
||||
|
||||
@objc
|
||||
public func reportConnectionFailure() {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
shouldCheckForOutage = true
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
/**
|
Loading…
Reference in New Issue