Skip to content

Commit 4544037

Browse files
committed
Fix SmartCardConnection to support the new connections semantics
1 parent 14b970f commit 4544037

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

YubiKit/YubiKit/Connection.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public protocol SmartCardConnection: Sendable {
6868

6969
/// SmartCardConnection Errors.
7070
public enum ConnectionError: Error, Sendable {
71+
/// There is an active connection.
72+
case busy
7173
/// No current connection.
7274
case noConnection
7375
/// Unexpected result returned from YubiKey.

YubiKit/YubiKit/USBSmartCardConnection.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ extension USBSmartCardConnection: SmartCardConnection {
5757

5858
// @TraceScope
5959
public func close(error: Error?) async {
60-
6160
try? await didClose.fulfill(error)
6261
trace(message: "disconnect called on sessionManager")
6362
}
@@ -166,12 +165,10 @@ private final actor SmartCardConnectionsManager {
166165

167166
// @TraceScope
168167
func connect(slot: SmartCardSlot) async throws -> USBSmartCardConnection {
169-
// if there is already a connection for this slot...
170-
// we close it and create a new one reusing it's TKSmartCard
171-
if let state = connections[slot] {
172-
// finish it
173-
await state.didClose.fulfill(nil)
174-
connections[slot] = nil
168+
// if there is already a connection for this slot we throw `ConnectionError.busy`.
169+
// The caller must close the connection first.
170+
guard connections[slot] == nil else {
171+
throw ConnectionError.busy
175172
}
176173

177174
// To proceed with a new connection we need to acquire a lock
@@ -201,8 +198,20 @@ private final actor SmartCardConnectionsManager {
201198
}
202199
trace(message: "card.beginSession() succeded")
203200

204-
// create a new state and return a new connection
205-
connections[slot] = ConnectionState(card: card)
201+
// create and save a new connection state
202+
let state = ConnectionState(card: card)
203+
connections[slot] = state
204+
205+
// register for the eventual clean up when the connection is closed
206+
Task {
207+
_ = try await state.didClose.value()
208+
state.card.endSession()
209+
if connections[slot] === state {
210+
connections[slot] = nil
211+
}
212+
}
213+
214+
// return the newly established connection
206215
return USBSmartCardConnection(slot: slot)
207216
}
208217

0 commit comments

Comments
 (0)