Skip to content

Commit

Permalink
Add MDoc Reader support
Browse files Browse the repository at this point in the history
  • Loading branch information
sbihel authored and Ryanmtate committed Aug 29, 2024
1 parent 4181b29 commit b94d87f
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 3 deletions.
22 changes: 22 additions & 0 deletions Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Secure transmission of mobile DL data</string>
</dict>
</plist>
5 changes: 2 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ let package = Package(
targets: ["SpruceIDMobileSdk"])
],
dependencies: [
// .package(url: "https://github.com/spruceid/mobile-sdk-rs.git", .branch("main")),
.package(url: "https://github.com/spruceid/mobile-sdk-rs.git", from: "0.0.27"),
// .package(path: "../mobile-sdk-rs"),
// .package(url: "https://github.com/spruceid/mobile-sdk-rs.git", .branch("main")),
.package(path: "../mobile-sdk-rs"),
.package(url: "https://github.com/apple/swift-algorithms", from: "1.2.0")
],
targets: [
Expand Down
21 changes: 21 additions & 0 deletions Sources/MobileSdk/MDocBLEUtils.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CoreBluetooth
import SpruceIDMobileSdkRs

let holderStateCharacteristicId = CBUUID(string: "00000001-A123-48CE-896B-4C76973373E6")
let holderClient2ServerCharacteristicId = CBUUID(string: "00000002-A123-48CE-896B-4C76973373E6")
Expand All @@ -18,6 +19,13 @@ enum MdocHolderBleError {
case bluetooth(CBCentralManager)
}

enum MdocReaderBleError {
/// When communication with the server fails
case server(String)
/// When Bluetooth is unusable (e.g. unauthorized).
case bluetooth(CBCentralManager)
}

enum MDocBLECallback {
case done
case connected
Expand All @@ -30,3 +38,16 @@ enum MDocBLECallback {
protocol MDocBLEDelegate: AnyObject {
func callback(message: MDocBLECallback)
}

enum MDocReaderBLECallback {
case done([String: [String: [String: MDocItem]]])
case connected
case error(MdocReaderBleError)
case message(Data)
/// Chunks received so far
case downloadProgress(Int)
}

protocol MDocReaderBLEDelegate: AnyObject {
func callback(message: MDocReaderBLECallback)
}
1 change: 1 addition & 0 deletions Sources/MobileSdk/MDocHolderBLECentral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ class MDocHolderBLECentral: NSObject {
case let .some(byte):
throw DataError.unknownDataTransferPrefix(byte: byte)
}
// Looks like this should just happen after discovering characteristics
case readerIdentCharacteristicId:
self.peripheral?.setNotifyValue(true, for: self.readCharacteristic!)
self.peripheral?.setNotifyValue(true, for: self.stateCharacteristic!)
Expand Down
87 changes: 87 additions & 0 deletions Sources/MobileSdk/MDocReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import CoreBluetooth
import SpruceIDWalletSdkRs

public class MDocReader {
var sessionManager: MdlSessionManager
var bleManager: MDocReaderBLEPeripheral!
var callback: BLEReaderSessionStateDelegate

public init?(callback: BLEReaderSessionStateDelegate, uri: String, requestedItems: [String: [String: Bool]]) {
self.callback = callback
do {
let sessionData = try SpruceIDWalletSdkRs.establishSession(uri: uri, requestedItems: requestedItems, trustAnchorRegistry: nil)
self.sessionManager = sessionData.state
self.bleManager = MDocReaderBLEPeripheral(callback: self, serviceUuid: CBUUID(string: sessionData.uuid), request: sessionData.request, bleIdent: Data(sessionData.bleIdent.utf8))
} catch {
print("\(error)")
return nil
}
}

public func cancel() {
bleManager.disconnect()
}
}

extension MDocReader: MDocReaderBLEDelegate {
func callback(message: MDocReaderBLECallback) {
switch message {
case .done(let data):
self.callback.update(state: .success(data))
case .connected:
self.callback.update(state: .connected)
case .error(let error):
self.callback.update(state: .error(BleReaderSessionError(readerBleError: error)))
self.cancel()
case .message(let data):
do {
let responseData = try SpruceIDWalletSdkRs.handleResponse(state: self.sessionManager, response: data)
self.sessionManager = responseData.state
self.callback.update(state: .success(responseData.verifiedResponse))
} catch {
self.callback.update(state: .error(.generic("\(error)")))
self.cancel()
}
case .downloadProgress(let index):
self.callback.update(state: .downloadProgress(index))
}
}
}

/// To be implemented by the consumer to update the UI
public protocol BLEReaderSessionStateDelegate: AnyObject {
func update(state: BLEReaderSessionState)
}

public enum BLEReaderSessionState {
/// App should display the error message
case error(BleReaderSessionError)
/// App should indicate to the reader is waiting to connect to the holder
case advertizing
/// App should indicate to the user that BLE connection has been established
case connected
/// App should display the fact that a certain amount of data has been received
/// - Parameters:
/// - 0: The number of chunks received to far
case downloadProgress(Int)
/// App should display a success message and offer to close the page
case success([String: [String: [String: MDocItem]]])
}

public enum BleReaderSessionError {
/// When communication with the server fails
case server(String)
/// When Bluetooth is unusable (e.g. unauthorized).
case bluetooth(CBCentralManager)
/// Generic unrecoverable error
case generic(String)

init(readerBleError: MdocReaderBleError) {
switch readerBleError {
case .server(let string):
self = .server(string)
case .bluetooth(let string):
self = .bluetooth(string)
}
}
}
Loading

0 comments on commit b94d87f

Please sign in to comment.