chatsecureios / ChatSecure / Classes / Controllers / ServerCheck.swift @ 8d76e2e3
History | View | Annotate | Download (6.18 KB)
| 1 |
// |
|---|---|
| 2 |
// ServerCheck.swift |
| 3 |
// ChatSecure |
| 4 |
// |
| 5 |
// Created by Chris Ballinger on 2/15/17. |
| 6 |
// Copyright © 2017 Chris Ballinger. All rights reserved. |
| 7 |
// |
| 8 |
|
| 9 |
import Foundation |
| 10 |
import OTRAssets |
| 11 |
|
| 12 |
/** |
| 13 |
* The purpose of this class is to collect and process server |
| 14 |
* and push info in one place. |
| 15 |
* |
| 16 |
* All public members must be accessed from the main queue. |
| 17 |
*/ |
| 18 |
public class ServerCheck: NSObject, OTRServerCapabilitiesDelegate, XMPPPushDelegate {
|
| 19 |
|
| 20 |
@objc public weak var xmpp: XMPPManager? |
| 21 |
@objc public let push: PushController |
| 22 |
|
| 23 |
@objc public var result = ServerCheckResult() |
| 24 |
|
| 25 |
@objc public static let UpdateNotificationName = Notification.Name(rawValue: "ServerCheckUpdateNotification") |
| 26 |
|
| 27 |
deinit {
|
| 28 |
xmpp?.serverCapabilities.removeDelegate(self) |
| 29 |
xmpp?.xmppPushModule.removeDelegate(self) |
| 30 |
NotificationCenter.default.removeObserver(self) |
| 31 |
} |
| 32 |
|
| 33 |
|
| 34 |
@objc public init(xmpp: XMPPManager, push: PushController) {
|
| 35 |
self.push = push |
| 36 |
self.xmpp = xmpp |
| 37 |
super.init() |
| 38 |
xmpp.serverCapabilities.addDelegate(self, delegateQueue: DispatchQueue.main) |
| 39 |
xmpp.xmppPushModule.addDelegate(self, delegateQueue: DispatchQueue.main) |
| 40 |
NotificationCenter.default.addObserver(self, selector: #selector(pushAccountChanged(_:)), name: Notification.Name(rawValue: OTRPushAccountDeviceChanged), object: push) |
| 41 |
NotificationCenter.default.addObserver(self, selector: #selector(pushAccountChanged(_:)), name: Notification.Name(rawValue: OTRPushAccountTokensChanged), object: push) |
| 42 |
fetch() |
| 43 |
} |
| 44 |
|
| 45 |
@objc public func getCombinedPushStatus() -> ServerCheckPushStatus {
|
| 46 |
if let xmpp = xmpp, xmpp.connectionStatus != .connected {
|
| 47 |
return .unknown |
| 48 |
} |
| 49 |
return result.getCombinedPushStatus() |
| 50 |
} |
| 51 |
|
| 52 |
|
| 53 |
|
| 54 |
/// set pushInfoReady, capabilitiesReady, pushStatusUpdate to get result |
| 55 |
@objc public func fetch() {
|
| 56 |
refreshPush() |
| 57 |
refreshCapabilities() |
| 58 |
checkReady() |
| 59 |
} |
| 60 |
|
| 61 |
/// Must be called from main queue |
| 62 |
@objc public func refresh() {
|
| 63 |
result.pushInfo = nil |
| 64 |
xmpp?.serverCapabilities.fetchAllCapabilities() |
| 65 |
fetch() |
| 66 |
} |
| 67 |
|
| 68 |
// This will refresh the pushStatusUpdate block |
| 69 |
private func updatePushStatus() {
|
| 70 |
guard let push = result.pushInfo, let pubsubEndpoint = push.pubsubEndpoint else { return }
|
| 71 |
if let jid = XMPPJID(user: nil, domain: pubsubEndpoint, resource: nil), |
| 72 |
let status = xmpp?.xmppPushModule.registrationStatus(forServerJID: jid) {
|
| 73 |
result.pushStatus = status |
| 74 |
postUpdateNotification() |
| 75 |
} |
| 76 |
} |
| 77 |
|
| 78 |
@objc private func pushAccountChanged(_ notification: Notification) {
|
| 79 |
DispatchQueue.main.async {
|
| 80 |
self.refresh() |
| 81 |
} |
| 82 |
} |
| 83 |
|
| 84 |
private func checkReady() {
|
| 85 |
if let _ = result.pushInfo {
|
| 86 |
postUpdateNotification() |
| 87 |
} |
| 88 |
if let _ = result.capabilities {
|
| 89 |
postUpdateNotification() |
| 90 |
} |
| 91 |
updatePushStatus() |
| 92 |
} |
| 93 |
|
| 94 |
private func postUpdateNotification() {
|
| 95 |
NotificationCenter.default.post(name: type(of: self).UpdateNotificationName, object: self) |
| 96 |
} |
| 97 |
|
| 98 |
private func refreshPush() {
|
| 99 |
push.gatherPushInfo(completion: { (info) in
|
| 100 |
self.result.pushInfo = info |
| 101 |
self.checkReady() |
| 102 |
}, callbackQueue: DispatchQueue.main) |
| 103 |
} |
| 104 |
|
| 105 |
private func refreshCapabilities() {
|
| 106 |
let caps = ServerCapabilityInfo.allCapabilities() |
| 107 |
result.capabilities = xmpp?.serverCapabilities.markAvailable(capabilities: caps) |
| 108 |
checkReady() |
| 109 |
} |
| 110 |
|
| 111 |
// MARK: - OTRServerCapabilitiesDelegate |
| 112 |
|
| 113 |
@objc public func serverCapabilities(_ sender: OTRServerCapabilities, didDiscoverCapabilities capabilities: [XMPPJID : XMLElement]) {
|
| 114 |
checkReady() |
| 115 |
} |
| 116 |
|
| 117 |
// MARK: - XMPPPushDelegate |
| 118 |
|
| 119 |
public func pushModule(_ module: XMPPPushModule, didRegisterWithResponseIq responseIq: XMPPIQ, outgoingIq: XMPPIQ) {
|
| 120 |
checkReady() |
| 121 |
} |
| 122 |
|
| 123 |
public func pushModule(_ module: XMPPPushModule, failedToRegisterWithErrorIq errorIq: XMPPIQ?, outgoingIq: XMPPIQ) {
|
| 124 |
checkReady() |
| 125 |
} |
| 126 |
|
| 127 |
public func pushModule(_ module: XMPPPushModule, disabledPushForServerJID serverJID: XMPPJID, node: String?, responseIq: XMPPIQ, outgoingIq: XMPPIQ) {
|
| 128 |
checkReady() |
| 129 |
} |
| 130 |
|
| 131 |
public func pushModule(_ module: XMPPPushModule, failedToDisablePushWithErrorIq errorIq: XMPPIQ?, serverJID: XMPPJID, node: String?, outgoingIq: XMPPIQ) {
|
| 132 |
checkReady() |
| 133 |
} |
| 134 |
|
| 135 |
public func pushModule(_ module: XMPPPushModule, readyWithCapabilities caps: XMLElement, jid: XMPPJID) {
|
| 136 |
// This _should_ be handled elsewhere in OTRServerCapabilities |
| 137 |
// Not sure why it's not working properly |
| 138 |
if var caps = result.capabilities {
|
| 139 |
caps[.XEP0357]?.status = .Available |
| 140 |
} |
| 141 |
checkReady() |
| 142 |
} |
| 143 |
} |
| 144 |
|
| 145 |
@objc |
| 146 |
public enum ServerCheckPushStatus: UInt {
|
| 147 |
case unknown |
| 148 |
case broken |
| 149 |
case working |
| 150 |
} |
| 151 |
|
| 152 |
@objc(OTRServerCheckResult) |
| 153 |
public class ServerCheckResult: NSObject {
|
| 154 |
public var capabilities: [CapabilityCode : ServerCapabilityInfo]? |
| 155 |
public var pushInfo: PushInfo? |
| 156 |
public var pushStatus: XMPPPushStatus? |
| 157 |
|
| 158 |
/** This lets you collect all push info in one place */ |
| 159 |
fileprivate func getCombinedPushStatus() -> ServerCheckPushStatus {
|
| 160 |
var checkStatus: ServerCheckPushStatus = .unknown |
| 161 |
if let pushInfo = pushInfo, !pushInfo.pushMaybeWorks() {
|
| 162 |
return .broken |
| 163 |
} |
| 164 |
if let pushStatus = pushStatus, pushStatus != .registered {
|
| 165 |
return .broken |
| 166 |
} |
| 167 |
if let pushCap = capabilities?[.XEP0357], pushCap.status != .Available {
|
| 168 |
return .broken |
| 169 |
} |
| 170 |
guard let caps = capabilities, let push = pushInfo, let status = pushStatus else {
|
| 171 |
return .unknown |
| 172 |
} |
| 173 |
var xepExists = false |
| 174 |
if let pushCap = caps[.XEP0357], pushCap.status == .Available {
|
| 175 |
xepExists = true |
| 176 |
} |
| 177 |
let pushAcctWorks = push.pushMaybeWorks() |
| 178 |
let xmppWorks = status == .registered |
| 179 |
if xepExists && pushAcctWorks && xmppWorks {
|
| 180 |
checkStatus = .working |
| 181 |
} else {
|
| 182 |
checkStatus = .broken |
| 183 |
} |
| 184 |
return checkStatus |
| 185 |
} |
| 186 |
} |
| 187 |
|