Skip to content

Commit fddf9a6

Browse files
authored
fix(predictions): remove liveness event listeners on session completion (#4092)
* fix(predictions): remove liveness event listeners on session completion * resolve swiftformat issues * cancel web socket task on deinit and add more logs
1 parent 0340886 commit fddf9a6

File tree

3 files changed

+79
-24
lines changed

3 files changed

+79
-24
lines changed

AmplifyPlugins/Predictions/AWSPredictionsPlugin/Liveness/Service/FaceLivenessSession.swift

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,27 @@ public final class FaceLivenessSession: LivenessService {
4545
self.websocket = websocket
4646

4747
websocket.onMessageReceived { [weak self] result in
48-
self?.receive(result: result) ?? .stopAndInvalidateSession
48+
guard let receiveResult = self?.receive(result: result) else {
49+
self?.removeLivenessEventListeners()
50+
return .stopAndInvalidateSession
51+
}
52+
return receiveResult
4953
}
5054

5155
websocket.onSocketClosed { [weak self] closeCode in
5256
self?.onComplete(.unexpectedClosure(closeCode))
57+
self?.removeLivenessEventListeners()
5358
}
5459

5560
websocket.onServerDateReceived { [weak self] serverDate in
5661
self?.serverDate = serverDate
5762
}
5863
}
5964

65+
deinit {
66+
Amplify.log.verbose("\(#fileID)-\(#function)")
67+
}
68+
6069
public var onServiceException: (FaceLivenessSessionError) -> Void = { _ in }
6170

6271
public func register(
@@ -77,18 +86,19 @@ public final class FaceLivenessSession: LivenessService {
7786
}
7887

7988
public func closeSocket(with code: URLSessionWebSocketTask.CloseCode) {
80-
livenessServiceDispatchQueue.async {
81-
self.websocket.close(with: code)
89+
Amplify.log.verbose("\(#fileID)-\(#function): closeSocket with code: \(code)")
90+
livenessServiceDispatchQueue.async { [weak self] in
91+
self?.websocket.close(with: code)
8292
}
8393
}
8494

8595
public func initializeLivenessStream(
8696
withSessionID sessionID: String,
87-
88-
userAgent: String = "",
97+
userAgent: String = "",
8998
challenges: [Challenge] = FaceLivenessSession.supportedChallenges,
9099
options: FaceLivenessSession.Options
91100
) throws {
101+
Amplify.log.verbose("\(#fileID)-\(#function): Initialize liveness stream")
92102
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
93103
components?.queryItems = [
94104
URLQueryItem(name: "session-id", value: sessionID),
@@ -108,17 +118,19 @@ public final class FaceLivenessSession: LivenessService {
108118

109119
savedURLForReconnect = url
110120
let signedConnectionURL = signer.sign(url: url)
111-
livenessServiceDispatchQueue.async {
112-
self.websocket.open(url: signedConnectionURL)
121+
livenessServiceDispatchQueue.async { [weak self] in
122+
self?.websocket.open(url: signedConnectionURL)
113123
}
114124
}
115125

116126
public func send(
117127
_ event: LivenessEvent<some Any>,
118128
eventDate: @escaping () -> Date = Date.init
119129
) {
120-
livenessServiceDispatchQueue.async {
121-
let encodedPayload = self.eventStreamEncoder.encode(
130+
Amplify.log.verbose("\(#fileID)-\(#function): Sending websocket event: \(event)")
131+
livenessServiceDispatchQueue.async { [weak self] in
132+
guard let self else { return }
133+
let encodedPayload = eventStreamEncoder.encode(
122134
payload: event.payload,
123135
headers: [
124136
":content-type": .string("application/json"),
@@ -128,44 +140,49 @@ public final class FaceLivenessSession: LivenessService {
128140
)
129141

130142
let dateForSigning: Date
131-
if let serverDate = self.serverDate {
143+
if let serverDate {
132144
dateForSigning = serverDate
133145
} else {
134146
dateForSigning = eventDate()
135147
}
136148

137-
let signedPayload = self.signer.signWithPreviousSignature(
149+
let signedPayload = signer.signWithPreviousSignature(
138150
payload: encodedPayload,
139151
dateHeader: (key: ":date", value: dateForSigning)
140152
)
141153

142-
let encodedEvent = self.eventStreamEncoder.encode(
154+
let encodedEvent = eventStreamEncoder.encode(
143155
payload: encodedPayload,
144156
headers: [
145157
":date": .timestamp(dateForSigning),
146158
":chunk-signature": .data(signedPayload)
147159
]
148160
)
149161

150-
self.websocket.send(
162+
websocket.send(
151163
message: .data(encodedEvent),
152-
onError: { _ in }
164+
onError: { error in
165+
Amplify.log.verbose("\(#fileID)-\(#function): Error sending web socket message: \(error)")
166+
}
153167
)
154168
}
155169
}
156170

157171
private func fallbackDecoding(_ message: EventStream.Message) -> WebSocketSession.WebSocketMessageResult {
158-
// We only care about two events above.
159172
// Just in case the header value changes (it shouldn't)
160173
// We'll try to decode each of these events
161174
if let payload = try? JSONDecoder().decode(ServerSessionInformationEvent.self, from: message.payload) {
175+
Amplify.log.verbose("\(#fileID)-\(#function): Fallback decoding server session information: \(payload)")
162176
let sessionConfiguration = sessionConfiguration(from: payload)
163177
serverEventListeners[.challenge]?(sessionConfiguration)
164178
} else if let payload = try? JSONDecoder().decode(ChallengeEvent.self, from: message.payload) {
179+
Amplify.log.verbose("\(#fileID)-\(#function): Fallback decoding challenge: \(payload)")
165180
let challenge = challenge(from: payload)
166181
challengeTypeListeners[.challenge]?(challenge)
167-
} else if (try? JSONDecoder().decode(DisconnectEvent.self, from: message.payload)) != nil {
182+
} else if let payload = try? JSONDecoder().decode(DisconnectEvent.self, from: message.payload) {
183+
Amplify.log.verbose("\(#fileID)-\(#function): Fallback decoding disconnect: \(payload)")
168184
onComplete(.disconnectionEvent)
185+
removeLivenessEventListeners()
169186
return .stopAndInvalidateSession
170187
}
171188
return .continueToReceive
@@ -179,6 +196,7 @@ public final class FaceLivenessSession: LivenessService {
179196

180197
if let eventType = message.headers.first(where: { $0.name == ":event-type" }) {
181198
let serverEvent = LivenessEventKind.Server(rawValue: eventType.value)
199+
Amplify.log.verbose("\(#fileID)-\(#function): Received server event: \(serverEvent)")
182200
switch serverEvent {
183201
case .challenge:
184202
// :event-type ChallengeEvent
@@ -199,22 +217,24 @@ public final class FaceLivenessSession: LivenessService {
199217
case .disconnect:
200218
// :event-type DisconnectionEvent
201219
onComplete(.disconnectionEvent)
220+
removeLivenessEventListeners()
202221
return .stopAndInvalidateSession
203222
default:
204223
return .continueToReceive
205224
}
206225
} else if let exceptionType = message.headers.first(where: { $0.name == ":exception-type" }) {
207226
let exceptionEvent = LivenessEventKind.Exception(rawValue: exceptionType.value)
208-
Amplify.log.verbose("\(#function): Received exception: \(exceptionEvent)")
227+
Amplify.log.verbose("\(#fileID)-\(#function): Received exception: \(exceptionEvent)")
209228
guard exceptionEvent == .invalidSignature,
210229
connectingState == .normal,
211230
let savedURLForReconnect,
212231
let serverDate else {
213232
if let runtimeError = URLSessionWebSocketTask.CloseCode(rawValue: 4_005) {
214-
Amplify.log.verbose("\(#function): Closing websocket with runtime error")
233+
Amplify.log.verbose("\(#fileID)-\(#function): Closing websocket with runtime error")
215234
closeSocket(with: runtimeError)
216235
}
217236
onServiceException(.init(event: exceptionEvent))
237+
removeLivenessEventListeners()
218238
return .stopAndInvalidateSession
219239
}
220240

@@ -228,12 +248,21 @@ public final class FaceLivenessSession: LivenessService {
228248
return fallbackDecoding(message)
229249
}
230250
} catch {
251+
Amplify.log.verbose("\(#fileID)-\(#function): Error decoding web socket message: \(error)")
252+
removeLivenessEventListeners()
231253
return .stopAndInvalidateSession
232254
}
233255
case .success:
234256
return .continueToReceive
235-
case .failure:
257+
case .failure(let error):
258+
Amplify.log.verbose("\(#fileID)-\(#function): Failure result in web socket message: \(error)")
259+
removeLivenessEventListeners()
236260
return .stopAndInvalidateSession
237261
}
238262
}
263+
264+
private func removeLivenessEventListeners() {
265+
serverEventListeners.removeAll()
266+
challengeTypeListeners.removeAll()
267+
}
239268
}

AmplifyPlugins/Predictions/AWSPredictionsPlugin/Liveness/Service/FaceLivenessSessionRepresentable.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ public protocol LivenessService {
2121

2222
func initializeLivenessStream(
2323
withSessionID sessionID: String,
24-
25-
userAgent: String,
24+
userAgent: String,
2625
challenges: [Challenge],
2726
options: FaceLivenessSession.Options
2827
) throws

AmplifyPlugins/Predictions/AWSPredictionsPlugin/Liveness/Service/WebSocketSession.swift

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ final class WebSocketSession {
3131
)
3232
}
3333

34+
deinit {
35+
Amplify.log.verbose("\(#fileID)-\(#function)")
36+
task?.cancel(with: .normalClosure, reason: nil)
37+
}
38+
3439
func onMessageReceived(_ receive: @escaping (Result<URLSessionWebSocketTask.Message, Error>) -> WebSocketMessageResult) {
3540
receiveMessage = receive
3641
}
@@ -92,17 +97,22 @@ final class WebSocketSession {
9297
)
9398
}
9499

95-
final class Delegate: NSObject, URLSessionWebSocketDelegate, URLSessionTaskDelegate {
100+
final class Delegate: NSObject, URLSessionWebSocketDelegate {
96101
var onClose: (URLSessionWebSocketTask.CloseCode) -> Void = { _ in }
97102
var onOpen: () -> Void = {}
98103
var onServerDateReceived: (Date?) -> Void = { _ in }
99104

105+
deinit {
106+
Amplify.log.verbose("\(#fileID).Delegate-\(#function)")
107+
}
108+
100109
// MARK: - URLSessionWebSocketDelegate methods
101110
func urlSession(
102111
_ session: URLSession,
103112
webSocketTask: URLSessionWebSocketTask,
104113
didOpenWithProtocol protocol: String?
105114
) {
115+
Amplify.log.verbose("\(#fileID)-\(#function): Web socket task didOpen")
106116
onOpen()
107117
}
108118

@@ -112,6 +122,7 @@ final class WebSocketSession {
112122
didCloseWith closeCode: URLSessionWebSocketTask.CloseCode,
113123
reason: Data?
114124
) {
125+
Amplify.log.verbose("\(#fileID)-\(#function): Web socket task didCloseWith: \(closeCode)")
115126
onClose(closeCode)
116127
}
117128

@@ -123,7 +134,7 @@ final class WebSocketSession {
123134
) {
124135
guard let httpResponse = metrics.transactionMetrics.first?.response as? HTTPURLResponse,
125136
let dateString = httpResponse.value(forHTTPHeaderField: "Date") else {
126-
Amplify.log.verbose("\(#function): Couldn't find Date header in URLSession metrics")
137+
Amplify.log.verbose("\(#fileID)-\(#function): Couldn't find Date header in URLSession metrics")
127138
onServerDateReceived(nil)
128139
return
129140
}
@@ -133,13 +144,29 @@ final class WebSocketSession {
133144
dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss z"
134145
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
135146
guard let serverDate = dateFormatter.date(from: dateString) else {
136-
Amplify.log.verbose("\(#function): Error parsing Date header in expected format")
147+
Amplify.log.verbose("\(#fileID)-\(#function): Error parsing Date header in expected format")
137148
onServerDateReceived(nil)
138149
return
139150
}
140151

141152
onServerDateReceived(serverDate)
142153
}
154+
155+
func urlSession(
156+
_ session: URLSession,
157+
task: URLSessionTask,
158+
didCompleteWithError error: Error?
159+
) {
160+
Amplify.log.verbose("\(#fileID)-\(#function): Session task didCompleteWithError : \(error)")
161+
}
162+
163+
// MARK: - URLSessionDelegate methods
164+
func urlSession(
165+
_ session: URLSession,
166+
didBecomeInvalidWithError error: Error?
167+
) {
168+
Amplify.log.verbose("\(#fileID)-\(#function): Session task didBecomeInvalidWithError : \(error)")
169+
}
143170
}
144171

145172
enum WebSocketMessageResult {

0 commit comments

Comments
 (0)