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 |
|