Outage detection.

pull/1/head
Matthew Chen 6 years ago
parent 37e3f26859
commit 20b1a2606e

@ -96,7 +96,6 @@
346129721FD1D74C00532771 /* SignalKeyingStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129591FD1D74B00532771 /* SignalKeyingStorage.m */; };
346129731FD1E01700532771 /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 451DE9F11DC1585F00810E42 /* PromiseKit.framework */; };
346129741FD1E02D00532771 /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 451DE9F11DC1585F00810E42 /* PromiseKit.framework */; };
346129761FD1E0B500532771 /* WeakTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346129751FD1E0B500532771 /* WeakTimer.swift */; };
346129951FD1E30000532771 /* OWSDatabaseMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129931FD1E30000532771 /* OWSDatabaseMigration.h */; settings = {ATTRIBUTES = (Public, ); }; };
346129961FD1E30000532771 /* OWSDatabaseMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129941FD1E30000532771 /* OWSDatabaseMigration.m */; };
346129991FD1E4DA00532771 /* SignalApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129971FD1E4D900532771 /* SignalApp.m */; };
@ -697,7 +696,6 @@
346129571FD1D74B00532771 /* Release.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Release.m; sourceTree = "<group>"; };
346129581FD1D74B00532771 /* SignalKeyingStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalKeyingStorage.h; sourceTree = "<group>"; };
346129591FD1D74B00532771 /* SignalKeyingStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalKeyingStorage.m; sourceTree = "<group>"; };
346129751FD1E0B500532771 /* WeakTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeakTimer.swift; sourceTree = "<group>"; };
346129931FD1E30000532771 /* OWSDatabaseMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDatabaseMigration.h; sourceTree = "<group>"; };
346129941FD1E30000532771 /* OWSDatabaseMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseMigration.m; sourceTree = "<group>"; };
346129971FD1E4D900532771 /* SignalApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalApp.m; sourceTree = "<group>"; };
@ -1461,7 +1459,6 @@
B97940251832BD2400BD66CB /* UIUtil.h */,
B97940261832BD2400BD66CB /* UIUtil.m */,
45F170D51E315310003FC1F2 /* Weak.swift */,
346129751FD1E0B500532771 /* WeakTimer.swift */,
);
path = utils;
sourceTree = "<group>";
@ -3076,7 +3073,6 @@
344F249A200FD03300CFB4F4 /* MessageApprovalViewController.swift in Sources */,
450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */,
347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */,
346129761FD1E0B500532771 /* WeakTimer.swift in Sources */,
346129F81FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.m in Sources */,
34074F61203D0CBE004596AE /* OWSSounds.m in Sources */,
346129B51FD1F7E800532771 /* OWSProfileManager.m in Sources */,

@ -9,6 +9,7 @@
#import "TSAccountManager.h"
#import "TSVerifyCodeRequest.h"
#import <AFNetworking/AFNetworking.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NSString *const TSNetworkManagerDomain = @"org.whispersystems.signal.networkManager";
@ -93,6 +94,8 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error);
}
successBlock(task, responseObject);
[OutageDetection.sharedManager reportNetworkSuccess];
};
TSNetworkManagerFailure failure = [TSNetworkManager errorPrettifyingForFailureBlock:failureBlock request:request];
@ -151,6 +154,9 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error);
return ^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull networkError) {
NSInteger statusCode = [task statusCode];
[OutageDetection.sharedManager reportNetworkFailure];
NSError *error = [self errorWithHTTPCode:statusCode
description:nil
failureReason:nil

@ -0,0 +1,110 @@
//
// 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()
// These properties should only be accessed on the main thread.
private var hasOutage = false {
didSet {
SwiftAssertIsOnMainThread(#function)
}
}
private var mayHaveOutage = false {
didSet {
SwiftAssertIsOnMainThread(#function)
ensureCheckTimer()
}
}
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)
if addressString != "127.0.0.1" {
Logger.verbose("\(logTag) addressString: \(addressString)")
isOutageDetected = true
}
}
}
return isOutageDetected
}
private func checkForOutageAsync() {
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 mayHaveOutage {
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 reportNetworkSuccess() {
SwiftAssertIsOnMainThread(#function)
mayHaveOutage = true
hasOutage = false
}
@objc
public func reportNetworkFailure() {
SwiftAssertIsOnMainThread(#function)
mayHaveOutage = false
}
}

@ -24,6 +24,7 @@
#import "TextSecureKitEnv.h"
#import "Threading.h"
#import "WebSocketResources.pb.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -677,6 +678,8 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
// If socket opens, we know we're not de-registered.
[TSAccountManager.sharedInstance setIsDeregistered:NO];
[OutageDetection.sharedManager reportNetworkSuccess];
}
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
@ -822,6 +825,8 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
// Otherwise clean up and align state.
[self applyDesiredSocketState];
}
[OutageDetection.sharedManager reportNetworkFailure];
}
- (void)webSocket:(SRWebSocket *)webSocket

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
/**
Loading…
Cancel
Save