mirror of
https://github.com/signalapp/libsignal.git
synced 2025-12-05 01:10:27 +00:00
Switch to swift-format for formatting instead of swiftformat
swift-format is owned by the Swift project and is generally less opinionated than swiftformat (but better at formatting to a limited line length).
This commit is contained in:
9
.github/workflows/build_and_test.yml
vendored
9
.github/workflows/build_and_test.yml
vendored
@@ -415,8 +415,15 @@ jobs:
|
||||
- run: brew install protobuf swiftlint
|
||||
|
||||
- name: Check formatting
|
||||
run: swiftformat --swiftversion 5 --reporter github-actions-log --lint .
|
||||
run: swift format --in-place --parallel --recursive . && git diff --exit-code .
|
||||
working-directory: swift
|
||||
env:
|
||||
# This is only here because we're on a macOS 15 runner, which defaults to Xcode 16.0,
|
||||
# which contains a swift-format that fails on some of our Swift 6.0 code.
|
||||
# Once we're on a later runner, this should be removed.
|
||||
# We should know that immediately if this stays at 16.2,
|
||||
# because the new runners usually only keep one previous Xcode major version.
|
||||
DEVELOPER_DIR: /Applications/Xcode_16.2.app
|
||||
|
||||
- name: Run lint
|
||||
run: swiftlint lint --strict --reporter github-actions-logging
|
||||
|
||||
9
.swift-format
Normal file
9
.swift-format
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"version": 1,
|
||||
"lineLength": 120,
|
||||
"indentation": { "spaces": 4 },
|
||||
"indentConditionalCompilationBlocks": false,
|
||||
"lineBreakBeforeEachArgument": true,
|
||||
"lineBreakBetweenDeclarationAttributes": true,
|
||||
"prioritizeKeepingFunctionOutputTogether": true
|
||||
}
|
||||
25
.swiftformat
25
.swiftformat
@@ -1,25 +0,0 @@
|
||||
#--header "\nCopyright {created.year} Signal Messenger, LLC.\nSPDX-License-Identifier: AGPL-3.0-only\n"
|
||||
--disable hoistPatternLet
|
||||
# Explicit self is better than implicit self.
|
||||
--self insert
|
||||
# Some arguments that it considers unused are used in doc comments, and replacing them with '_' is an error.
|
||||
--stripunusedargs unnamed-only
|
||||
--wraparguments before-first
|
||||
--wrapcollections before-first
|
||||
# Libsignal is a collection of many languages, remembering specific of each one is hard. Make it explicit.
|
||||
--disable redundantinternal
|
||||
# Ranges look better without spaces
|
||||
--ranges no-space
|
||||
# Pragmas should start at the begining of line.
|
||||
--ifdef outdent
|
||||
--indent 4
|
||||
# Patters are not redundant, they show the shape of thing, they show the shape of things.
|
||||
--disable redundantPattern
|
||||
# Leave try in the innermost position.
|
||||
--disable hoistTry
|
||||
# Explicit ACL even in extensions.
|
||||
--extensionacl "on-declarations"
|
||||
# Explicit is better than implicit.
|
||||
--disable redundantNilInit
|
||||
# Indentation for multi-line string literals.
|
||||
--indentstrings true
|
||||
@@ -18,7 +18,6 @@ brew "rocksdb"
|
||||
brew "ruby"
|
||||
brew "rustup"
|
||||
brew "shellcheck"
|
||||
brew "swiftformat"
|
||||
brew "swiftlint"
|
||||
brew "taplo"
|
||||
brew "terraform"
|
||||
|
||||
4
justfile
4
justfile
@@ -29,7 +29,7 @@ format-jni:
|
||||
(cd java && ./gradlew spotlessApply)
|
||||
|
||||
format-ffi:
|
||||
(cd swift && swiftformat --swiftversion 5 .)
|
||||
(cd swift && swift format --in-place --parallel --recursive .)
|
||||
|
||||
format-node:
|
||||
(cd node && npm run format)
|
||||
@@ -47,7 +47,7 @@ format-all: format-jni format-ffi format-node
|
||||
check-format-all:
|
||||
cargo fmt --all -- --check
|
||||
taplo fmt --check
|
||||
(cd swift && swiftformat --swiftversion 5 . --lint)
|
||||
@echo 'warning: `swift format` does not have a check mode'
|
||||
(cd node && npm run format-check)
|
||||
(cd java && ./gradlew spotlessCheck)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
disabled_rules:
|
||||
- closure_parameter_position # swift-format takes precedence here
|
||||
- cyclomatic_complexity
|
||||
- empty_enum_arguments
|
||||
- force_try
|
||||
@@ -6,6 +7,7 @@ disabled_rules:
|
||||
- function_parameter_count
|
||||
- identifier_name
|
||||
- line_length
|
||||
- opening_brace # swift-format takes precedence here
|
||||
- redundant_optional_initialization
|
||||
- trailing_comma
|
||||
- type_body_length
|
||||
@@ -28,3 +30,4 @@ nesting:
|
||||
type_level: 2
|
||||
excluded:
|
||||
- .build/**
|
||||
- Benchmarks/.build/**
|
||||
|
||||
@@ -16,7 +16,7 @@ let package = Package(
|
||||
.macOS(.v10_15), .iOS(.v13),
|
||||
],
|
||||
products: [
|
||||
.executable(name: "Benchmarks", targets: ["Benchmarks"]),
|
||||
.executable(name: "Benchmarks", targets: ["Benchmarks"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
|
||||
@@ -27,12 +27,12 @@ let package = Package(
|
||||
name: "Benchmarks",
|
||||
dependencies: [
|
||||
.product(name: "Benchmark", package: "swift-benchmark"),
|
||||
.product(name: "LibSignalClient", package: "swift" /* the folder name, sigh */ ),
|
||||
.product(name: "LibSignalClient", package: "swift" /* the folder name, sigh */),
|
||||
],
|
||||
linkerSettings: [
|
||||
.unsafeFlags(["-L\(rustReleaseBuildDir)"], .when(configuration: .release)),
|
||||
.unsafeFlags(["-L\(rustDebugBuildDir)"], .when(configuration: .debug)),
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -15,7 +15,9 @@ let groupSendEndorsementsSuite = BenchmarkSuite(name: "GroupSendEndorsements") {
|
||||
let groupParams = try! GroupSecretParams.generate()
|
||||
let now = UInt64(Date().timeIntervalSince1970)
|
||||
let startOfDay = now - now % SECONDS_PER_DAY
|
||||
let expiration = Date(timeIntervalSince1970: TimeInterval(startOfDay)).addingTimeInterval(TimeInterval(2 * SECONDS_PER_DAY))
|
||||
let expiration = Date(timeIntervalSince1970: TimeInterval(startOfDay)).addingTimeInterval(
|
||||
TimeInterval(2 * SECONDS_PER_DAY)
|
||||
)
|
||||
|
||||
for groupSize in [10, 100, 1000] {
|
||||
let members = (0..<groupSize).map { _ in Aci(fromUUID: UUID()) }
|
||||
@@ -26,13 +28,31 @@ let groupSendEndorsementsSuite = BenchmarkSuite(name: "GroupSendEndorsements") {
|
||||
let response = GroupSendEndorsementsResponse.issue(groupMembers: encryptedMembers, keyPair: keyPair)
|
||||
|
||||
suite.benchmark("receiveWithServiceIds/\(groupSize)") {
|
||||
blackHole(try! response.receive(groupMembers: members, localUser: members[0], groupParams: groupParams, serverParams: serverPublicParams))
|
||||
blackHole(
|
||||
try! response.receive(
|
||||
groupMembers: members,
|
||||
localUser: members[0],
|
||||
groupParams: groupParams,
|
||||
serverParams: serverPublicParams
|
||||
)
|
||||
)
|
||||
}
|
||||
suite.benchmark("receiveWithCiphertexts/\(groupSize)") {
|
||||
blackHole(try! response.receive(groupMembers: encryptedMembers, localUser: encryptedMembers[0], serverParams: serverPublicParams))
|
||||
blackHole(
|
||||
try! response.receive(
|
||||
groupMembers: encryptedMembers,
|
||||
localUser: encryptedMembers[0],
|
||||
serverParams: serverPublicParams
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let endorsements = try! response.receive(groupMembers: members, localUser: members[0], groupParams: groupParams, serverParams: serverPublicParams)
|
||||
let endorsements = try! response.receive(
|
||||
groupMembers: members,
|
||||
localUser: members[0],
|
||||
groupParams: groupParams,
|
||||
serverParams: serverPublicParams
|
||||
)
|
||||
|
||||
suite.benchmark("toToken/\(groupSize)") {
|
||||
blackHole(endorsements.endorsements.map { $0.toToken(groupParams: groupParams) })
|
||||
|
||||
@@ -18,10 +18,10 @@ let package = Package(
|
||||
.library(
|
||||
name: "LibSignalClient",
|
||||
targets: ["LibSignalClient"]
|
||||
),
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.4.3"),
|
||||
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.4.3")
|
||||
],
|
||||
targets: [
|
||||
.systemLibrary(name: "SignalFfi"),
|
||||
|
||||
@@ -36,7 +36,8 @@ public func hashLocalPin<Bytes: ContiguousBytes>(_ pin: Bytes) throws -> String
|
||||
/// - parameter encodedHash: An encoded string of the hash, as returned by `localHash`
|
||||
/// - returns: true if the pin matches the hash, false otherwise
|
||||
///
|
||||
public func verifyLocalPin<Bytes: ContiguousBytes>(_ pin: Bytes, againstEncodedHash encodedHash: String) throws -> Bool {
|
||||
public func verifyLocalPin<Bytes: ContiguousBytes>(_ pin: Bytes, againstEncodedHash encodedHash: String) throws -> Bool
|
||||
{
|
||||
try encodedHash.withCString { hashPtr in
|
||||
try pin.withUnsafeBorrowedBuffer { buffer in
|
||||
try invokeFnReturningBool {
|
||||
@@ -104,11 +105,15 @@ public class PinHash: NativeHandleOwner<SignalMutPointerPinHash>, @unchecked Sen
|
||||
/// - parameter normalizedPin: A normalized, UTF-8 encoded byte representation of the pin to verify
|
||||
/// - parameter salt: A 32 byte salt
|
||||
/// - returns: A `PinHash`
|
||||
public convenience init<PinBytes: ContiguousBytes, SaltBytes: ContiguousBytes>(normalizedPin: PinBytes, salt: SaltBytes) throws {
|
||||
public convenience init<PinBytes: ContiguousBytes, SaltBytes: ContiguousBytes>(
|
||||
normalizedPin: PinBytes,
|
||||
salt: SaltBytes
|
||||
) throws {
|
||||
var result = SignalMutPointerPinHash()
|
||||
try normalizedPin.withUnsafeBorrowedBuffer { pinBytes in
|
||||
try salt.withUnsafeBytes { saltBytes in
|
||||
try ByteArray(newContents: Data(saltBytes), expectedLength: 32).withUnsafePointerToSerialized { saltTuple in
|
||||
try ByteArray(newContents: Data(saltBytes), expectedLength: 32).withUnsafePointerToSerialized {
|
||||
saltTuple in
|
||||
try checkError(signal_pin_hash_from_salt(&result, pinBytes, saltTuple))
|
||||
}
|
||||
}
|
||||
@@ -124,12 +129,18 @@ public class PinHash: NativeHandleOwner<SignalMutPointerPinHash>, @unchecked Sen
|
||||
/// - parameter username: The Basic Auth username used to authenticate with SVR2
|
||||
/// - parameter mrenclave: The mrenclave where the hashed pin will be stored
|
||||
/// - returns: A `PinHash`
|
||||
public convenience init<PinBytes: ContiguousBytes, MrenclaveBytes: ContiguousBytes>(normalizedPin: PinBytes, username: String, mrenclave: MrenclaveBytes) throws {
|
||||
public convenience init<PinBytes: ContiguousBytes, MrenclaveBytes: ContiguousBytes>(
|
||||
normalizedPin: PinBytes,
|
||||
username: String,
|
||||
mrenclave: MrenclaveBytes
|
||||
) throws {
|
||||
var result = SignalMutPointerPinHash()
|
||||
try normalizedPin.withUnsafeBorrowedBuffer { pinBytes in
|
||||
try mrenclave.withUnsafeBorrowedBuffer { mrenclaveBytes in
|
||||
try username.withCString { userBytes in
|
||||
try checkError(signal_pin_hash_from_username_mrenclave(&result, pinBytes, userBytes, mrenclaveBytes))
|
||||
try checkError(
|
||||
signal_pin_hash_from_username_mrenclave(&result, pinBytes, userBytes, mrenclaveBytes)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ public class ProtocolAddress: ClonableHandleOwner<SignalMutPointerProtocolAddres
|
||||
/// - Throws: ``SignalError#invalidProtocolAddress(name:deviceId:message:)`` if the address is not valid.
|
||||
public convenience init(name: String, deviceId: UInt32) throws {
|
||||
var handle = SignalMutPointerProtocolAddress()
|
||||
try checkError(signal_address_new(
|
||||
&handle,
|
||||
name,
|
||||
deviceId
|
||||
))
|
||||
try checkError(
|
||||
signal_address_new(
|
||||
&handle,
|
||||
name,
|
||||
deviceId
|
||||
)
|
||||
)
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
@@ -38,11 +40,16 @@ public class ProtocolAddress: ClonableHandleOwner<SignalMutPointerProtocolAddres
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerProtocolAddress, currentHandle: SignalConstPointerProtocolAddress) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerProtocolAddress,
|
||||
currentHandle: SignalConstPointerProtocolAddress
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_address_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerProtocolAddress>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerProtocolAddress>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_address_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,12 @@ public class Aes256Ctr32: NativeHandleOwner<SignalMutPointerAes256Ctr32> {
|
||||
let handle = try key.withUnsafeBorrowedBuffer { keyBuffer in
|
||||
try nonce.withUnsafeBytes { nonceBytes in
|
||||
guard nonceBytes.count == Self.nonceLength else {
|
||||
throw SignalError.invalidArgument("nonce must be \(Self.nonceLength) bytes (got \(nonceBytes.count))")
|
||||
throw SignalError.invalidArgument(
|
||||
"nonce must be \(Self.nonceLength) bytes (got \(nonceBytes.count))"
|
||||
)
|
||||
}
|
||||
// swift-format-ignore
|
||||
// (vertical alignment is clearer)
|
||||
let initialCounter =
|
||||
(UInt32(nonceBytes[12]) << 24) |
|
||||
(UInt32(nonceBytes[13]) << 16) |
|
||||
@@ -27,31 +31,37 @@ public class Aes256Ctr32: NativeHandleOwner<SignalMutPointerAes256Ctr32> {
|
||||
var nonceBufferWithoutCounter = SignalBorrowedBuffer(nonceBytes)
|
||||
nonceBufferWithoutCounter.length -= 4
|
||||
var result = SignalMutPointerAes256Ctr32()
|
||||
try checkError(signal_aes256_ctr32_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBufferWithoutCounter,
|
||||
initialCounter
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_ctr32_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBufferWithoutCounter,
|
||||
initialCounter
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerAes256Ctr32>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerAes256Ctr32>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_aes256_ctr32_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
public func process(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
try checkError(signal_aes256_ctr32_process(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_ctr32_process(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +92,14 @@ public class Aes256GcmEncryption: NativeHandleOwner<SignalMutPointerAes256GcmEnc
|
||||
try nonce.withUnsafeBorrowedBuffer { nonceBuffer in
|
||||
try associatedData.withUnsafeBorrowedBuffer { adBuffer in
|
||||
var result = SignalMutPointerAes256GcmEncryption()
|
||||
try checkError(signal_aes256_gcm_encryption_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBuffer,
|
||||
adBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_gcm_encryption_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBuffer,
|
||||
adBuffer
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -105,19 +107,23 @@ public class Aes256GcmEncryption: NativeHandleOwner<SignalMutPointerAes256GcmEnc
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerAes256GcmEncryption>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerAes256GcmEncryption>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_aes256_gcm_encryption_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
public func encrypt(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
try checkError(signal_aes256_gcm_encryption_update(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_gcm_encryption_update(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,12 +164,14 @@ public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDec
|
||||
try nonce.withUnsafeBorrowedBuffer { nonceBuffer in
|
||||
try associatedData.withUnsafeBorrowedBuffer { adBuffer in
|
||||
var result = SignalMutPointerAes256GcmDecryption()
|
||||
try checkError(signal_aes256_gcm_decryption_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBuffer,
|
||||
adBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_gcm_decryption_new(
|
||||
&result,
|
||||
keyBuffer,
|
||||
nonceBuffer,
|
||||
adBuffer
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -171,19 +179,23 @@ public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDec
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerAes256GcmDecryption>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerAes256GcmDecryption>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_aes256_gcm_decryption_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
public func decrypt(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
try checkError(signal_aes256_gcm_decryption_update(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_gcm_decryption_update(
|
||||
nativeHandle,
|
||||
SignalBorrowedMutableBuffer(messageBytes),
|
||||
0,
|
||||
UInt32(messageBytes.count)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,11 +204,13 @@ public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDec
|
||||
return try withNativeHandle { nativeHandle in
|
||||
try tag.withUnsafeBorrowedBuffer { tagBuffer in
|
||||
var result = false
|
||||
try checkError(signal_aes256_gcm_decryption_verify_tag(
|
||||
&result,
|
||||
nativeHandle,
|
||||
tagBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_aes256_gcm_decryption_verify_tag(
|
||||
&result,
|
||||
nativeHandle,
|
||||
tagBuffer
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ public class Aes256GcmSiv: NativeHandleOwner<SignalMutPointerAes256GcmSiv> {
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerAes256GcmSiv>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerAes256GcmSiv>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_aes256_gcm_siv_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,9 @@ private class Completer<Promise: PromiseStruct>: CompleterBase {
|
||||
/// You must ensure that either the callback is called, or the result is passed to
|
||||
/// ``cleanUpUncompletedPromiseStruct(_:)``.
|
||||
func makePromiseStruct() -> Promise {
|
||||
typealias RawPromiseCallback = @convention(c) (_ error: SignalFfiErrorRef?, _ value: sending UnsafeRawPointer?, _ context: UnsafeRawPointer?) -> Void
|
||||
typealias RawPromiseCallback = @convention(c) (
|
||||
_ error: SignalFfiErrorRef?, _ value: sending UnsafeRawPointer?, _ context: UnsafeRawPointer?
|
||||
) -> Void
|
||||
let completeOpaque: RawPromiseCallback = { error, value, context in
|
||||
let completer: CompleterBase = Unmanaged.fromOpaque(context!).takeRetainedValue()
|
||||
completer.completeUnsafe(error, value)
|
||||
@@ -134,8 +136,14 @@ private class Completer<Promise: PromiseStruct>: CompleterBase {
|
||||
// we know that Rust is already enforcing that the `bridge_fn` result is allowed to hop threads (Send),
|
||||
// and that it won't use or escape the C representation of that result besides passing it to the callback.
|
||||
// So first we build a promise struct---it doesn't matter which one---by reinterpreting the callback...
|
||||
typealias RawPointerPromiseCallback = @convention(c) (_ error: SignalFfiErrorRef?, _ value: UnsafePointer<UnsafeRawPointer?>?, _ context: UnsafeRawPointer?) -> Void
|
||||
let rawPromiseStruct = SignalCPromiseRawPointer(complete: unsafeBitCast(completeOpaque, to: RawPointerPromiseCallback.self), context: Unmanaged.passRetained(self).toOpaque(), cancellation_id: 0)
|
||||
typealias RawPointerPromiseCallback = @convention(c) (
|
||||
_ error: SignalFfiErrorRef?, _ value: UnsafePointer<UnsafeRawPointer?>?, _ context: UnsafeRawPointer?
|
||||
) -> Void
|
||||
let rawPromiseStruct = SignalCPromiseRawPointer(
|
||||
complete: unsafeBitCast(completeOpaque, to: RawPointerPromiseCallback.self),
|
||||
context: Unmanaged.passRetained(self).toOpaque(),
|
||||
cancellation_id: 0
|
||||
)
|
||||
|
||||
// ...And then we reinterpret the entire struct, because all promise structs *also* have the same layout.
|
||||
// (Which we at least check a little bit here.)
|
||||
|
||||
@@ -193,7 +193,8 @@ internal struct FixedLengthWrapper<FixedLengthRepr>: BorrowForFfi {
|
||||
}
|
||||
|
||||
extension BorrowForFfi {
|
||||
static func fixed<FixedLengthRepr>(_ serialized: ByteArray) -> Self where Self == FixedLengthWrapper<FixedLengthRepr> {
|
||||
static func fixed<FixedLengthRepr>(_ serialized: ByteArray) -> Self
|
||||
where Self == FixedLengthWrapper<FixedLengthRepr> {
|
||||
.init(inner: serialized)
|
||||
}
|
||||
}
|
||||
@@ -229,7 +230,8 @@ internal struct ElementsWrapper<FfiType: FfiBorrowedSlice>: BorrowForFfi {
|
||||
}
|
||||
|
||||
extension BorrowForFfi {
|
||||
static func slice<FfiType: FfiBorrowedSlice>(_ input: [FfiType.Element]) -> Self where Self == ElementsWrapper<FfiType> {
|
||||
static func slice<FfiType: FfiBorrowedSlice>(_ input: [FfiType.Element]) -> Self
|
||||
where Self == ElementsWrapper<FfiType> {
|
||||
.init(inner: input)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,14 @@ public class Cds2Client: SgxClient {
|
||||
let handle = try attestationMessage.withUnsafeBorrowedBuffer { attestationMessageBuffer in
|
||||
try mrenclave.withUnsafeBorrowedBuffer { mrenclaveBuffer in
|
||||
var result = SignalMutPointerSgxClientState()
|
||||
try checkError(signal_cds2_client_state_new(
|
||||
&result,
|
||||
mrenclaveBuffer,
|
||||
attestationMessageBuffer,
|
||||
UInt64(currentDate.timeIntervalSince1970 * 1000)
|
||||
))
|
||||
try checkError(
|
||||
signal_cds2_client_state_new(
|
||||
&result,
|
||||
mrenclaveBuffer,
|
||||
attestationMessageBuffer,
|
||||
UInt64(currentDate.timeIntervalSince1970 * 1000)
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ public class CdsiLookupRequest: NativeHandleOwner<SignalMutPointerLookupRequest>
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerLookupRequest>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerLookupRequest>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_lookup_request_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
@@ -100,7 +102,9 @@ extension SignalConstPointerLookupRequest: SignalConstPointer {
|
||||
/// Returned by ``Net/cdsiLookup(auth:request:)`` when a request is successfully initiated.
|
||||
public class CdsiLookup {
|
||||
class NativeCdsiLookup: NativeHandleOwner<SignalMutPointerCdsiLookup> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerCdsiLookup>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerCdsiLookup>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_cdsi_lookup_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
@@ -139,13 +143,18 @@ public class CdsiLookup {
|
||||
/// `SignalError.networkError` for a network-level connectivity issue,
|
||||
/// `SignalError.networkProtocolError` for a CDSI or attested connection protocol issue.
|
||||
public func complete() async throws -> CdsiLookupResponse {
|
||||
let response: SignalFfiCdsiLookupResponse = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
let response: SignalFfiCdsiLookupResponse = try await self.asyncContext.invokeAsyncFunction {
|
||||
promise,
|
||||
asyncContext in
|
||||
self.native.withNativeHandle { handle in
|
||||
signal_cdsi_lookup_complete(promise, asyncContext.const(), handle.const())
|
||||
}
|
||||
}
|
||||
|
||||
return CdsiLookupResponse(entries: LookupResponseEntryList(owned: response.entries), debugPermitsUsed: response.debug_permits_used)
|
||||
return CdsiLookupResponse(
|
||||
entries: LookupResponseEntryList(owned: response.entries),
|
||||
debugPermitsUsed: response.debug_permits_used
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +203,9 @@ public class LookupResponseEntryList: Collection {
|
||||
}
|
||||
|
||||
deinit {
|
||||
signal_free_lookup_response_entry_list(SignalOwnedBufferOfFfiCdsiLookupResponseEntry(base: self.owned.baseAddress, length: self.owned.count))
|
||||
signal_free_lookup_response_entry_list(
|
||||
SignalOwnedBufferOfFfiCdsiLookupResponseEntry(base: self.owned.baseAddress, length: self.owned.count)
|
||||
)
|
||||
}
|
||||
|
||||
public typealias Index = UnsafeMutableBufferPointer<CdsiLookupResponseEntry>.Index
|
||||
|
||||
@@ -11,12 +11,15 @@ import SignalFfi
|
||||
|
||||
extension AuthenticatedChatConnection {
|
||||
internal static func fakeConnect(
|
||||
tokioAsyncContext: TokioAsyncContext, listener: any ChatConnectionListener,
|
||||
tokioAsyncContext: TokioAsyncContext,
|
||||
listener: any ChatConnectionListener,
|
||||
alerts: [String] = []
|
||||
) -> (AuthenticatedChatConnection, FakeChatRemote) {
|
||||
let (fakeChatConnection, listenerBridge) = failOnError {
|
||||
try FakeChatConnection.create(
|
||||
tokioAsyncContext: tokioAsyncContext, listener: listener, alerts: alerts
|
||||
tokioAsyncContext: tokioAsyncContext,
|
||||
listener: listener,
|
||||
alerts: alerts
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,11 +28,14 @@ extension AuthenticatedChatConnection {
|
||||
try fakeChatConnection.withNativeHandle {
|
||||
try checkError(
|
||||
signal_testing_fake_chat_connection_take_authenticated_chat(
|
||||
&chatHandle, $0.const()
|
||||
))
|
||||
&chatHandle,
|
||||
$0.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
let chat = AuthenticatedChatConnection(
|
||||
fakeHandle: NonNull(chatHandle)!, tokioAsyncContext: tokioAsyncContext
|
||||
fakeHandle: NonNull(chatHandle)!,
|
||||
tokioAsyncContext: tokioAsyncContext
|
||||
)
|
||||
|
||||
listenerBridge.setConnection(chatConnection: chat)
|
||||
@@ -37,12 +43,15 @@ extension AuthenticatedChatConnection {
|
||||
try fakeChatConnection.withNativeHandle {
|
||||
try checkError(
|
||||
signal_testing_fake_chat_connection_take_remote(
|
||||
&fakeRemoteHandle, $0.const()
|
||||
))
|
||||
&fakeRemoteHandle,
|
||||
$0.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let fakeRemote = FakeChatRemote(
|
||||
handle: NonNull(fakeRemoteHandle)!, tokioAsyncContext: tokioAsyncContext
|
||||
handle: NonNull(fakeRemoteHandle)!,
|
||||
tokioAsyncContext: tokioAsyncContext
|
||||
)
|
||||
return (chat, fakeRemote)
|
||||
}
|
||||
@@ -56,7 +65,9 @@ extension UnauthenticatedChatConnection {
|
||||
) -> (UnauthenticatedChatConnection, FakeChatRemote) {
|
||||
let (fakeChatConnection, listenerBridge) = failOnError {
|
||||
try FakeChatConnection.create(
|
||||
tokioAsyncContext: tokioAsyncContext, listener: listener, alerts: []
|
||||
tokioAsyncContext: tokioAsyncContext,
|
||||
listener: listener,
|
||||
alerts: []
|
||||
)
|
||||
}
|
||||
|
||||
@@ -65,11 +76,15 @@ extension UnauthenticatedChatConnection {
|
||||
try fakeChatConnection.withNativeHandle {
|
||||
try checkError(
|
||||
signal_testing_fake_chat_connection_take_authenticated_chat(
|
||||
&chatHandle, $0.const()
|
||||
))
|
||||
&chatHandle,
|
||||
$0.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
let chat = UnauthenticatedChatConnection(
|
||||
fakeHandle: NonNull(chatHandle)!, tokioAsyncContext: tokioAsyncContext, environment: .staging
|
||||
fakeHandle: NonNull(chatHandle)!,
|
||||
tokioAsyncContext: tokioAsyncContext,
|
||||
environment: .staging
|
||||
)
|
||||
|
||||
listenerBridge.setConnection(chatConnection: chat)
|
||||
@@ -77,12 +92,15 @@ extension UnauthenticatedChatConnection {
|
||||
try fakeChatConnection.withNativeHandle {
|
||||
try checkError(
|
||||
signal_testing_fake_chat_connection_take_remote(
|
||||
&fakeRemoteHandle, $0.const()
|
||||
))
|
||||
&fakeRemoteHandle,
|
||||
$0.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let fakeRemote = FakeChatRemote(
|
||||
handle: NonNull(fakeRemoteHandle)!, tokioAsyncContext: tokioAsyncContext
|
||||
handle: NonNull(fakeRemoteHandle)!,
|
||||
tokioAsyncContext: tokioAsyncContext
|
||||
)
|
||||
return (chat, fakeRemote)
|
||||
}
|
||||
@@ -118,7 +136,9 @@ private class SetChatLaterListenerBridge: ChatListenerBridge {
|
||||
}
|
||||
|
||||
private class SetChatLaterUnauthListenerBridge: UnauthConnectionEventsListenerBridge {
|
||||
override init(chatConnectionEventsListenerForTesting chatListener: any ConnectionEventsListener<UnauthenticatedChatConnection>) {
|
||||
override init(
|
||||
chatConnectionEventsListenerForTesting chatListener: any ConnectionEventsListener<UnauthenticatedChatConnection>
|
||||
) {
|
||||
super.init(chatConnectionEventsListenerForTesting: chatListener)
|
||||
}
|
||||
|
||||
@@ -135,7 +155,8 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
}
|
||||
|
||||
init(
|
||||
handle: NonNull<SignalMutPointerFakeChatRemoteEnd>, tokioAsyncContext: TokioAsyncContext
|
||||
handle: NonNull<SignalMutPointerFakeChatRemoteEnd>,
|
||||
tokioAsyncContext: TokioAsyncContext
|
||||
) {
|
||||
self.tokioAsyncContext = tokioAsyncContext
|
||||
super.init(owned: handle)
|
||||
@@ -150,8 +171,10 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
requestBytes.withUnsafeBorrowedBuffer { requestBytes in
|
||||
failOnError(
|
||||
signal_testing_fake_chat_remote_end_send_raw_server_request(
|
||||
handle.const(), requestBytes
|
||||
))
|
||||
handle.const(),
|
||||
requestBytes
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +183,9 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
let request = try await self.tokioAsyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
withNativeHandle { handle in
|
||||
signal_testing_fake_chat_remote_end_receive_incoming_request(
|
||||
promise, asyncContext.const(), handle.const()
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
handle.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -181,7 +206,9 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
let fakeResponse = FakeChatResponse(requestId: requestId, response)
|
||||
try self.withNativeHandle { nativeHandle in
|
||||
try fakeResponse.withNativeHandle { response in
|
||||
try checkError(signal_testing_fake_chat_remote_end_send_server_response(nativeHandle.const(), response.const()))
|
||||
try checkError(
|
||||
signal_testing_fake_chat_remote_end_send_server_response(nativeHandle.const(), response.const())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,8 +222,10 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
responseBytes.withUnsafeBorrowedBuffer { responseBytes in
|
||||
failOnError(
|
||||
signal_testing_fake_chat_remote_end_send_raw_server_response(
|
||||
handle.const(), responseBytes
|
||||
))
|
||||
handle.const(),
|
||||
responseBytes
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +234,9 @@ internal class FakeChatRemote: NativeHandleOwner<SignalMutPointerFakeChatRemoteE
|
||||
withNativeHandle { handle in
|
||||
failOnError(
|
||||
signal_testing_fake_chat_remote_end_inject_connection_interrupted(
|
||||
handle.const()))
|
||||
handle.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +261,9 @@ internal class FakeChatServer: NativeHandleOwner<SignalMutPointerFakeChatServer>
|
||||
fatalError("cannot be invoked directly")
|
||||
}
|
||||
|
||||
override class func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerFakeChatServer>) -> SignalFfiErrorRef? {
|
||||
override class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerFakeChatServer>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_fake_chat_server_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
@@ -253,7 +286,16 @@ internal class FakeChatResponse: NativeHandleOwner<SignalMutPointerFakeChatRespo
|
||||
}.withUnsafeBorrowedBytestringArray { headers in
|
||||
try response.body.withUnsafeBorrowedBuffer { body in
|
||||
var nativeHandle = SignalMutPointerFakeChatResponse()
|
||||
try checkError(signal_testing_fake_chat_response_create(&nativeHandle, requestId, response.status, message, headers, SignalOptionalBorrowedSliceOfc_uchar(present: true, value: body)))
|
||||
try checkError(
|
||||
signal_testing_fake_chat_response_create(
|
||||
&nativeHandle,
|
||||
requestId,
|
||||
response.status,
|
||||
message,
|
||||
headers,
|
||||
SignalOptionalBorrowedSliceOfc_uchar(present: true, value: body)
|
||||
)
|
||||
)
|
||||
return nativeHandle
|
||||
}
|
||||
}
|
||||
@@ -266,35 +308,45 @@ internal class FakeChatResponse: NativeHandleOwner<SignalMutPointerFakeChatRespo
|
||||
fatalError("cannot be invoked directly")
|
||||
}
|
||||
|
||||
override class func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerFakeChatResponse>) -> SignalFfiErrorRef? {
|
||||
override class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerFakeChatResponse>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_fake_chat_response_destroy(nativeHandle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeChatConnection: NativeHandleOwner<SignalMutPointerFakeChatConnection> {
|
||||
static func create(
|
||||
tokioAsyncContext: TokioAsyncContext, listener: any ChatConnectionListener,
|
||||
tokioAsyncContext: TokioAsyncContext,
|
||||
listener: any ChatConnectionListener,
|
||||
alerts: [String]
|
||||
) throws -> (FakeChatConnection, SetChatLaterListenerBridge) {
|
||||
let listenerBridge = SetChatLaterListenerBridge(
|
||||
chatConnectionListenerForTesting: listener)
|
||||
chatConnectionListenerForTesting: listener
|
||||
)
|
||||
var listenerStruct = listenerBridge.makeListenerStruct()
|
||||
let chat = try FakeChatConnection.internalCreate(tokioAsyncContext, &listenerStruct, alerts)
|
||||
return (chat, listenerBridge)
|
||||
}
|
||||
|
||||
static func create(
|
||||
tokioAsyncContext: TokioAsyncContext, listener: any ConnectionEventsListener<UnauthenticatedChatConnection>,
|
||||
tokioAsyncContext: TokioAsyncContext,
|
||||
listener: any ConnectionEventsListener<UnauthenticatedChatConnection>,
|
||||
alerts: [String]
|
||||
) throws -> (FakeChatConnection, SetChatLaterUnauthListenerBridge) {
|
||||
let listenerBridge = SetChatLaterUnauthListenerBridge(
|
||||
chatConnectionEventsListenerForTesting: listener)
|
||||
chatConnectionEventsListenerForTesting: listener
|
||||
)
|
||||
var listenerStruct = listenerBridge.makeListenerStruct()
|
||||
let chat = try FakeChatConnection.internalCreate(tokioAsyncContext, &listenerStruct, alerts)
|
||||
return (chat, listenerBridge)
|
||||
}
|
||||
|
||||
private static func internalCreate(_ tokioAsyncContext: TokioAsyncContext, _ listenerStruct: inout SignalFfiChatListenerStruct, _ alerts: [String]) throws -> FakeChatConnection {
|
||||
private static func internalCreate(
|
||||
_ tokioAsyncContext: TokioAsyncContext,
|
||||
_ listenerStruct: inout SignalFfiChatListenerStruct,
|
||||
_ alerts: [String]
|
||||
) throws -> FakeChatConnection {
|
||||
let connection: FakeChatConnection = try withUnsafePointer(to: &listenerStruct) { listener in
|
||||
try tokioAsyncContext.withNativeHandle { asyncContext in
|
||||
try invokeFnReturningNativeHandle {
|
||||
|
||||
@@ -22,7 +22,8 @@ public protocol ChatConnection: AnyObject {
|
||||
}
|
||||
|
||||
public class ConnectionInfo: NativeHandleOwner<SignalMutPointerChatConnectionInfo>, CustomStringConvertible {
|
||||
override class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerChatConnectionInfo>) -> SignalFfiErrorRef? {
|
||||
override class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerChatConnectionInfo>) -> SignalFfiErrorRef?
|
||||
{
|
||||
// ChatConnectionInfo is an alias for ConnectionInfo, but Swift doesn't know that.
|
||||
return signal_connection_info_destroy(SignalMutPointerConnectionInfo(raw: handle.opaque))
|
||||
}
|
||||
@@ -95,21 +96,29 @@ extension ChatConnection {
|
||||
/// Before an obtained instance can be used, it must be started by calling ``AuthenticatedChatConnection/start(listener:)``.
|
||||
public class AuthenticatedChatConnection: NativeHandleOwner<
|
||||
SignalMutPointerAuthenticatedChatConnection
|
||||
>, ChatConnection, @unchecked Sendable {
|
||||
>, ChatConnection, @unchecked Sendable
|
||||
{
|
||||
internal let tokioAsyncContext: TokioAsyncContext
|
||||
|
||||
/// Initiates establishing of the underlying unauthenticated connection to the Chat Service. Once
|
||||
/// the connection is established, the returned object can be used to send and receive messages
|
||||
/// after ``AuthenticatedChatConnection/start(listener:)`` is called.
|
||||
internal init(
|
||||
tokioAsyncContext: TokioAsyncContext, connectionManager: ConnectionManager,
|
||||
username: String, password: String, receiveStories: Bool
|
||||
tokioAsyncContext: TokioAsyncContext,
|
||||
connectionManager: ConnectionManager,
|
||||
username: String,
|
||||
password: String,
|
||||
receiveStories: Bool
|
||||
) async throws {
|
||||
let nativeHandle = try await tokioAsyncContext.invokeAsyncFunction { promise, tokioAsyncContext in
|
||||
connectionManager.withNativeHandle { connectionManager in
|
||||
signal_authenticated_chat_connection_connect(
|
||||
promise, tokioAsyncContext.const(), connectionManager.const(), username,
|
||||
password, receiveStories
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
connectionManager.const(),
|
||||
username,
|
||||
password,
|
||||
receiveStories
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -127,7 +136,10 @@ public class AuthenticatedChatConnection: NativeHandleOwner<
|
||||
fatalError("should not be called directly for a ChatConnection")
|
||||
}
|
||||
|
||||
internal init(fakeHandle handle: NonNull<SignalMutPointerAuthenticatedChatConnection>, tokioAsyncContext: TokioAsyncContext) {
|
||||
internal init(
|
||||
fakeHandle handle: NonNull<SignalMutPointerAuthenticatedChatConnection>,
|
||||
tokioAsyncContext: TokioAsyncContext
|
||||
) {
|
||||
self.tokioAsyncContext = tokioAsyncContext
|
||||
super.init(owned: handle)
|
||||
}
|
||||
@@ -144,8 +156,10 @@ public class AuthenticatedChatConnection: NativeHandleOwner<
|
||||
withUnsafePointer(to: &listenerStruct) {
|
||||
failOnError(
|
||||
signal_authenticated_chat_connection_init_listener(
|
||||
chatConnection.const(), SignalConstPointerFfiChatListenerStruct(raw: $0)
|
||||
))
|
||||
chatConnection.const(),
|
||||
SignalConstPointerFfiChatListenerStruct(raw: $0)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,7 +171,9 @@ public class AuthenticatedChatConnection: NativeHandleOwner<
|
||||
_ = try await self.tokioAsyncContext.invokeAsyncFunction { promise, tokioAsyncContext in
|
||||
withNativeHandle { chatConnection in
|
||||
signal_authenticated_chat_connection_disconnect(
|
||||
promise, tokioAsyncContext.const(), chatConnection.const()
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
chatConnection.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -175,8 +191,11 @@ public class AuthenticatedChatConnection: NativeHandleOwner<
|
||||
withNativeHandle { chatService in
|
||||
internalRequest.withNativeHandle { request in
|
||||
signal_authenticated_chat_connection_send(
|
||||
promise, tokioAsyncContext.const(), chatService.const(),
|
||||
request.const(), timeoutMillis
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
chatService.const(),
|
||||
request.const(),
|
||||
timeoutMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -224,7 +243,8 @@ extension SignalConstPointerAuthenticatedChatConnection: SignalConstPointer {
|
||||
/// Before an obtained instance can be used, it must be started by calling ``UnauthenticatedChatConnection/start(listener:)``.
|
||||
public class UnauthenticatedChatConnection: NativeHandleOwner<
|
||||
SignalMutPointerUnauthenticatedChatConnection
|
||||
>, ChatConnection, @unchecked Sendable {
|
||||
>, ChatConnection, @unchecked Sendable
|
||||
{
|
||||
internal let tokioAsyncContext: TokioAsyncContext
|
||||
internal let environment: Net.Environment
|
||||
|
||||
@@ -240,7 +260,9 @@ public class UnauthenticatedChatConnection: NativeHandleOwner<
|
||||
let nativeHandle = try await tokioAsyncContext.invokeAsyncFunction { promise, tokioAsyncContext in
|
||||
connectionManager.withNativeHandle { connectionManager in
|
||||
signal_unauthenticated_chat_connection_connect(
|
||||
promise, tokioAsyncContext.const(), connectionManager.const()
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
connectionManager.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -277,13 +299,16 @@ public class UnauthenticatedChatConnection: NativeHandleOwner<
|
||||
public func start(listener: any ConnectionEventsListener<UnauthenticatedChatConnection>) {
|
||||
withNativeHandle { chatConnection in
|
||||
var listenerStruct = UnauthConnectionEventsListenerBridge(
|
||||
chatConnection: self, listener: listener
|
||||
chatConnection: self,
|
||||
listener: listener
|
||||
).makeListenerStruct()
|
||||
withUnsafePointer(to: &listenerStruct) {
|
||||
failOnError(
|
||||
signal_unauthenticated_chat_connection_init_listener(
|
||||
chatConnection.const(), SignalConstPointerFfiChatListenerStruct(raw: $0)
|
||||
))
|
||||
chatConnection.const(),
|
||||
SignalConstPointerFfiChatListenerStruct(raw: $0)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,7 +320,9 @@ public class UnauthenticatedChatConnection: NativeHandleOwner<
|
||||
_ = try await self.tokioAsyncContext.invokeAsyncFunction { promise, tokioAsyncContext in
|
||||
withNativeHandle { chatConnection in
|
||||
signal_unauthenticated_chat_connection_disconnect(
|
||||
promise, tokioAsyncContext.const(), chatConnection.const()
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
chatConnection.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -313,8 +340,11 @@ public class UnauthenticatedChatConnection: NativeHandleOwner<
|
||||
withNativeHandle { chatService in
|
||||
internalRequest.withNativeHandle { request in
|
||||
signal_unauthenticated_chat_connection_send(
|
||||
promise, tokioAsyncContext.const(), chatService.const(),
|
||||
request.const(), timeoutMillis
|
||||
promise,
|
||||
tokioAsyncContext.const(),
|
||||
chatService.const(),
|
||||
request.const(),
|
||||
timeoutMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,12 @@ public protocol ChatConnectionListener: ConnectionEventsListener<AuthenticatedCh
|
||||
///
|
||||
/// If `sendAck` is not called, the server will leave this message in the message queue and
|
||||
/// attempt to deliver it again in the future.
|
||||
func chatConnection(_ chat: AuthenticatedChatConnection, didReceiveIncomingMessage envelope: Data, serverDeliveryTimestamp: UInt64, sendAck: @escaping () throws -> Void)
|
||||
func chatConnection(
|
||||
_ chat: AuthenticatedChatConnection,
|
||||
didReceiveIncomingMessage envelope: Data,
|
||||
serverDeliveryTimestamp: UInt64,
|
||||
sendAck: @escaping () throws -> Void
|
||||
)
|
||||
|
||||
/// Called when the server indicates that there are no further messages in the message queue.
|
||||
///
|
||||
@@ -53,7 +58,9 @@ extension AuthenticatedChatConnection: ChatListenerConnection {}
|
||||
|
||||
internal class ChatListenerBridge {
|
||||
private class AckHandleOwner: NativeHandleOwner<SignalMutPointerServerMessageAck> {
|
||||
override class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerServerMessageAck>) -> SignalFfiErrorRef? {
|
||||
override class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerServerMessageAck>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_server_message_ack_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
@@ -100,7 +107,8 @@ internal class ChatListenerBridge {
|
||||
|
||||
let envelopeData = Data(bytes: envelope.base, count: envelope.length)
|
||||
bridge.chatListener.chatConnection(
|
||||
chatConnection, didReceiveIncomingMessage: envelopeData,
|
||||
chatConnection,
|
||||
didReceiveIncomingMessage: envelopeData,
|
||||
serverDeliveryTimestamp: timestamp
|
||||
) { _ = ackHandleOwner.withNativeHandle { ackHandle in signal_server_message_ack_send(ackHandle.const()) } }
|
||||
}
|
||||
@@ -195,16 +203,31 @@ internal class UnauthConnectionEventsListenerBridge {
|
||||
func makeListenerStruct() -> SignalFfiChatListenerStruct {
|
||||
let receivedIncomingMessage: SignalReceivedIncomingMessage = { _, _, _, _ in
|
||||
// Not used in the unauth chat listener
|
||||
LoggerBridge.shared?.logger.log(level: .error, file: #fileID, line: #line, message: "unauth socket received an incoming request")
|
||||
LoggerBridge.shared?.logger.log(
|
||||
level: .error,
|
||||
file: #fileID,
|
||||
line: #line,
|
||||
message: "unauth socket received an incoming request"
|
||||
)
|
||||
}
|
||||
let receivedQueueEmpty: SignalReceivedQueueEmpty = { _ in
|
||||
// Not used in the unauth chat listener
|
||||
LoggerBridge.shared?.logger.log(level: .error, file: #fileID, line: #line, message: "unauth socket received a \"queue empty\" notification")
|
||||
LoggerBridge.shared?.logger.log(
|
||||
level: .error,
|
||||
file: #fileID,
|
||||
line: #line,
|
||||
message: "unauth socket received a \"queue empty\" notification"
|
||||
)
|
||||
}
|
||||
let receivedAlerts: SignalReceivedAlerts = { _, alerts in
|
||||
// Not used in the unauth chat listener
|
||||
if alerts.lengths.length != 0 {
|
||||
LoggerBridge.shared?.logger.log(level: .error, file: #fileID, line: #line, message: "unauth socket received \(alerts.lengths.length) alerts")
|
||||
LoggerBridge.shared?.logger.log(
|
||||
level: .error,
|
||||
file: #fileID,
|
||||
line: #line,
|
||||
message: "unauth socket received \(alerts.lengths.length) alerts"
|
||||
)
|
||||
}
|
||||
}
|
||||
let connectionInterrupted: SignalConnectionInterrupted = { rawCtx, maybeError in
|
||||
|
||||
@@ -18,7 +18,13 @@ public struct ChatRequest: Equatable, Sendable {
|
||||
public var body: Data?
|
||||
public var timeout: TimeInterval
|
||||
|
||||
public init(method: String, pathAndQuery: String, headers: [String: String] = [:], body: Data? = nil, timeout: TimeInterval) {
|
||||
public init(
|
||||
method: String,
|
||||
pathAndQuery: String,
|
||||
headers: [String: String] = [:],
|
||||
body: Data? = nil,
|
||||
timeout: TimeInterval
|
||||
) {
|
||||
self.method = method
|
||||
self.pathAndQuery = pathAndQuery
|
||||
self.headers = headers
|
||||
@@ -44,7 +50,9 @@ public struct ChatRequest: Equatable, Sendable {
|
||||
var handle = SignalMutPointerHttpRequest(untyped: nil)
|
||||
if let body = request.body {
|
||||
try body.withUnsafeBorrowedBuffer { body in
|
||||
try checkError(signal_http_request_new_with_body(&handle, request.method, request.pathAndQuery, body))
|
||||
try checkError(
|
||||
signal_http_request_new_with_body(&handle, request.method, request.pathAndQuery, body)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
try checkError(signal_http_request_new_without_body(&handle, request.method, request.pathAndQuery))
|
||||
@@ -61,8 +69,8 @@ public struct ChatRequest: Equatable, Sendable {
|
||||
return signal_http_request_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
internal var method: String {
|
||||
failOnError {
|
||||
try withNativeHandle { request in
|
||||
@@ -109,7 +117,7 @@ public struct ChatRequest: Equatable, Sendable {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,28 +162,40 @@ public struct ChatResponse: Equatable, Sendable {
|
||||
|
||||
self.status = rawResponse.status
|
||||
self.message = String(cString: rawResponse.message)
|
||||
self.headers = Dictionary(uniqueKeysWithValues: rawResponse.rawHeadersAsBuffer.lazy.map { (rawHeader: UnsafePointer<CChar>?) -> (String, String) in
|
||||
guard let rawHeader else {
|
||||
fatalError("null in headers list")
|
||||
self.headers = Dictionary(
|
||||
uniqueKeysWithValues: rawResponse.rawHeadersAsBuffer.lazy.map {
|
||||
(rawHeader: UnsafePointer<CChar>?) -> (String, String) in
|
||||
guard let rawHeader else {
|
||||
fatalError("null in headers list")
|
||||
}
|
||||
let asciiColon = Int32(Character(":").asciiValue!)
|
||||
guard let colonPtr = strchr(rawHeader, asciiColon) else {
|
||||
fatalError("header returned without colon")
|
||||
}
|
||||
let nameCount = UnsafePointer(colonPtr) - rawHeader
|
||||
guard
|
||||
let name = UnsafeBufferPointer(start: rawHeader, count: nameCount).withMemoryRebound(
|
||||
to: UInt8.self,
|
||||
{
|
||||
String(bytes: $0, encoding: .utf8)
|
||||
}
|
||||
)
|
||||
else {
|
||||
fatalError("non-UTF-8 header name not rejected by Rust")
|
||||
}
|
||||
let value = String(cString: colonPtr + 1)
|
||||
return (name, value)
|
||||
}
|
||||
let asciiColon = Int32(Character(":").asciiValue!)
|
||||
guard let colonPtr = strchr(rawHeader, asciiColon) else {
|
||||
fatalError("header returned without colon")
|
||||
}
|
||||
let nameCount = UnsafePointer(colonPtr) - rawHeader
|
||||
guard let name = UnsafeBufferPointer(start: rawHeader, count: nameCount).withMemoryRebound(to: UInt8.self, {
|
||||
String(bytes: $0, encoding: .utf8)
|
||||
}) else {
|
||||
fatalError("non-UTF-8 header name not rejected by Rust")
|
||||
}
|
||||
let value = String(cString: colonPtr + 1)
|
||||
return (name, value)
|
||||
})
|
||||
)
|
||||
|
||||
// Avoid copying the body when possible!
|
||||
self.body = Data(bytesNoCopy: rawResponse.body.base, count: rawResponse.body.length, deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
})
|
||||
self.body = Data(
|
||||
bytesNoCopy: rawResponse.body.base,
|
||||
count: rawResponse.body.length,
|
||||
deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
}
|
||||
)
|
||||
// Clear it out so it doesn't get freed eagerly.
|
||||
rawResponse.body = .init()
|
||||
|
||||
|
||||
@@ -73,7 +73,9 @@ public class ComparableBackup: NativeHandleOwner<SignalMutPointerComparableBacku
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerComparableBackup>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerComparableBackup>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_comparable_backup_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ private struct SenderKeyName: Hashable {
|
||||
var distributionId: UUID
|
||||
}
|
||||
|
||||
open class InMemorySignalProtocolStore: IdentityKeyStore, PreKeyStore, SignedPreKeyStore, KyberPreKeyStore, SessionStore, SenderKeyStore {
|
||||
open class InMemorySignalProtocolStore: IdentityKeyStore, PreKeyStore, SignedPreKeyStore, KyberPreKeyStore,
|
||||
SessionStore, SenderKeyStore
|
||||
{
|
||||
private var publicKeys: [ProtocolAddress: IdentityKey] = [:]
|
||||
private var privateKey: IdentityKeyPair
|
||||
private var registrationId: UInt32
|
||||
@@ -44,7 +46,11 @@ open class InMemorySignalProtocolStore: IdentityKeyStore, PreKeyStore, SignedPre
|
||||
return self.registrationId
|
||||
}
|
||||
|
||||
open func saveIdentity(_ identity: IdentityKey, for address: ProtocolAddress, context: StoreContext) throws -> IdentityChange {
|
||||
open func saveIdentity(
|
||||
_ identity: IdentityKey,
|
||||
for address: ProtocolAddress,
|
||||
context: StoreContext
|
||||
) throws -> IdentityChange {
|
||||
let oldIdentity = self.publicKeys.updateValue(identity, forKey: address)
|
||||
if oldIdentity == nil || oldIdentity == identity {
|
||||
return .newOrUnchanged
|
||||
@@ -53,11 +59,16 @@ open class InMemorySignalProtocolStore: IdentityKeyStore, PreKeyStore, SignedPre
|
||||
}
|
||||
}
|
||||
|
||||
open func isTrustedIdentity(_ identity: IdentityKey, for address: ProtocolAddress, direction: Direction, context: StoreContext) throws -> Bool {
|
||||
open func isTrustedIdentity(
|
||||
_ identity: IdentityKey,
|
||||
for address: ProtocolAddress,
|
||||
direction: Direction,
|
||||
context: StoreContext
|
||||
) throws -> Bool {
|
||||
if let pk = publicKeys[address] {
|
||||
return pk == identity
|
||||
} else {
|
||||
return true // tofu
|
||||
return true // tofu
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +137,20 @@ open class InMemorySignalProtocolStore: IdentityKeyStore, PreKeyStore, SignedPre
|
||||
self.sessionMap[address] = record
|
||||
}
|
||||
|
||||
open func storeSenderKey(from sender: ProtocolAddress, distributionId: UUID, record: SenderKeyRecord, context: StoreContext) throws {
|
||||
open func storeSenderKey(
|
||||
from sender: ProtocolAddress,
|
||||
distributionId: UUID,
|
||||
record: SenderKeyRecord,
|
||||
context: StoreContext
|
||||
) throws {
|
||||
self.senderKeyMap[SenderKeyName(sender: sender, distributionId: distributionId)] = record
|
||||
}
|
||||
|
||||
open func loadSenderKey(from sender: ProtocolAddress, distributionId: UUID, context: StoreContext) throws -> SenderKeyRecord? {
|
||||
open func loadSenderKey(
|
||||
from sender: ProtocolAddress,
|
||||
distributionId: UUID,
|
||||
context: StoreContext
|
||||
) throws -> SenderKeyRecord? {
|
||||
return self.senderKeyMap[SenderKeyName(sender: sender, distributionId: distributionId)]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,17 @@ public protocol StoreContext {}
|
||||
public protocol IdentityKeyStore: AnyObject {
|
||||
func identityKeyPair(context: StoreContext) throws -> IdentityKeyPair
|
||||
func localRegistrationId(context: StoreContext) throws -> UInt32
|
||||
func saveIdentity(_ identity: IdentityKey, for address: ProtocolAddress, context: StoreContext) throws -> IdentityChange
|
||||
func isTrustedIdentity(_ identity: IdentityKey, for address: ProtocolAddress, direction: Direction, context: StoreContext) throws -> Bool
|
||||
func saveIdentity(
|
||||
_ identity: IdentityKey,
|
||||
for address: ProtocolAddress,
|
||||
context: StoreContext
|
||||
) throws -> IdentityChange
|
||||
func isTrustedIdentity(
|
||||
_ identity: IdentityKey,
|
||||
for address: ProtocolAddress,
|
||||
direction: Direction,
|
||||
context: StoreContext
|
||||
) throws -> Bool
|
||||
func identity(for address: ProtocolAddress, context: StoreContext) throws -> IdentityKey?
|
||||
}
|
||||
|
||||
@@ -53,6 +62,15 @@ public protocol SessionStore: AnyObject {
|
||||
}
|
||||
|
||||
public protocol SenderKeyStore: AnyObject {
|
||||
func storeSenderKey(from sender: ProtocolAddress, distributionId: UUID, record: SenderKeyRecord, context: StoreContext) throws
|
||||
func loadSenderKey(from sender: ProtocolAddress, distributionId: UUID, context: StoreContext) throws -> SenderKeyRecord?
|
||||
func storeSenderKey(
|
||||
from sender: ProtocolAddress,
|
||||
distributionId: UUID,
|
||||
record: SenderKeyRecord,
|
||||
context: StoreContext
|
||||
) throws
|
||||
func loadSenderKey(
|
||||
from sender: ProtocolAddress,
|
||||
distributionId: UUID,
|
||||
context: StoreContext
|
||||
) throws -> SenderKeyRecord?
|
||||
}
|
||||
|
||||
@@ -6,12 +6,18 @@
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context: StoreContext, _ body: (SignalConstPointerFfiIdentityKeyStoreStruct) throws -> Result) throws -> Result {
|
||||
internal func withIdentityKeyStore<Result>(
|
||||
_ store: IdentityKeyStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiIdentityKeyStoreStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimGetIdentityKeyPair(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
keyp: UnsafeMutablePointer<SignalMutPointerPrivateKey>?
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var privateKey = try store.identityKeyPair(context: context).privateKey
|
||||
keyp!.pointee = try cloneOrTakeHandle(from: &privateKey)
|
||||
@@ -23,7 +29,9 @@ internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context:
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
idp: UnsafeMutablePointer<UInt32>?
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
let id = try store.localRegistrationId(context: context)
|
||||
idp!.pointee = id
|
||||
@@ -36,7 +44,9 @@ internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context:
|
||||
address: SignalConstPointerProtocolAddress,
|
||||
public_key: SignalConstPointerPublicKey
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var address = ProtocolAddress(borrowing: address)
|
||||
defer { cloneOrForgetAsNeeded(&address) }
|
||||
@@ -55,7 +65,9 @@ internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context:
|
||||
public_key: UnsafeMutablePointer<SignalMutPointerPublicKey>?,
|
||||
address: SignalConstPointerProtocolAddress
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var address = ProtocolAddress(borrowing: address)
|
||||
defer { cloneOrForgetAsNeeded(&address) }
|
||||
@@ -75,7 +87,9 @@ internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context:
|
||||
public_key: SignalConstPointerPublicKey,
|
||||
raw_direction: UInt32
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(IdentityKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var address = ProtocolAddress(borrowing: address)
|
||||
defer { cloneOrForgetAsNeeded(&address) }
|
||||
@@ -112,7 +126,11 @@ internal func withIdentityKeyStore<Result>(_ store: IdentityKeyStore, _ context:
|
||||
}
|
||||
}
|
||||
|
||||
internal func withPreKeyStore<Result>(_ store: PreKeyStore, _ context: StoreContext, _ body: (SignalConstPointerFfiPreKeyStoreStruct) throws -> Result) throws -> Result {
|
||||
internal func withPreKeyStore<Result>(
|
||||
_ store: PreKeyStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiPreKeyStoreStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimStorePreKey(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
id: UInt32,
|
||||
@@ -164,13 +182,19 @@ internal func withPreKeyStore<Result>(_ store: PreKeyStore, _ context: StoreCont
|
||||
}
|
||||
}
|
||||
|
||||
internal func withSignedPreKeyStore<Result>(_ store: SignedPreKeyStore, _ context: StoreContext, _ body: (SignalConstPointerFfiSignedPreKeyStoreStruct) throws -> Result) throws -> Result {
|
||||
internal func withSignedPreKeyStore<Result>(
|
||||
_ store: SignedPreKeyStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiSignedPreKeyStoreStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimStoreSignedPreKey(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
id: UInt32,
|
||||
record: SignalConstPointerSignedPreKeyRecord
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(SignedPreKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(SignedPreKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var record = SignedPreKeyRecord(borrowing: record)
|
||||
defer { cloneOrForgetAsNeeded(&record) }
|
||||
@@ -184,7 +208,9 @@ internal func withSignedPreKeyStore<Result>(_ store: SignedPreKeyStore, _ contex
|
||||
recordp: UnsafeMutablePointer<SignalMutPointerSignedPreKeyRecord>?,
|
||||
id: UInt32
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(SignedPreKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(SignedPreKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var record = try store.loadSignedPreKey(id: id, context: context)
|
||||
recordp!.pointee = try cloneOrTakeHandle(from: &record)
|
||||
@@ -204,13 +230,19 @@ internal func withSignedPreKeyStore<Result>(_ store: SignedPreKeyStore, _ contex
|
||||
}
|
||||
}
|
||||
|
||||
internal func withKyberPreKeyStore<Result>(_ store: KyberPreKeyStore, _ context: StoreContext, _ body: (SignalConstPointerFfiKyberPreKeyStoreStruct) throws -> Result) throws -> Result {
|
||||
internal func withKyberPreKeyStore<Result>(
|
||||
_ store: KyberPreKeyStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiKyberPreKeyStoreStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimStoreKyberPreKey(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
id: UInt32,
|
||||
record: SignalConstPointerKyberPreKeyRecord
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var record = KyberPreKeyRecord(borrowing: record)
|
||||
defer { cloneOrForgetAsNeeded(&record) }
|
||||
@@ -224,7 +256,9 @@ internal func withKyberPreKeyStore<Result>(_ store: KyberPreKeyStore, _ context:
|
||||
recordp: UnsafeMutablePointer<SignalMutPointerKyberPreKeyRecord>?,
|
||||
id: UInt32
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
var record = try store.loadKyberPreKey(id: id, context: context)
|
||||
recordp!.pointee = try cloneOrTakeHandle(from: &record)
|
||||
@@ -236,7 +270,9 @@ internal func withKyberPreKeyStore<Result>(_ store: KyberPreKeyStore, _ context:
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
id: UInt32
|
||||
) -> Int32 {
|
||||
let storeContext = storeCtx!.assumingMemoryBound(to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self)
|
||||
let storeContext = storeCtx!.assumingMemoryBound(
|
||||
to: ErrorHandlingContext<(KyberPreKeyStore, StoreContext)>.self
|
||||
)
|
||||
return storeContext.pointee.catchCallbackErrors { store, context in
|
||||
try store.markKyberPreKeyUsed(id: id, context: context)
|
||||
return 0
|
||||
@@ -256,7 +292,11 @@ internal func withKyberPreKeyStore<Result>(_ store: KyberPreKeyStore, _ context:
|
||||
}
|
||||
}
|
||||
|
||||
internal func withSessionStore<Result>(_ store: SessionStore, _ context: StoreContext, _ body: (SignalConstPointerFfiSessionStoreStruct) throws -> Result) throws -> Result {
|
||||
internal func withSessionStore<Result>(
|
||||
_ store: SessionStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiSessionStoreStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimStoreSession(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
address: SignalConstPointerProtocolAddress,
|
||||
@@ -303,7 +343,11 @@ internal func withSessionStore<Result>(_ store: SessionStore, _ context: StoreCo
|
||||
}
|
||||
}
|
||||
|
||||
internal func withSenderKeyStore<Result>(_ store: SenderKeyStore, _ context: StoreContext, _ body: (SignalConstPointerFfiSenderKeyStoreStruct) throws -> Result) rethrows -> Result {
|
||||
internal func withSenderKeyStore<Result>(
|
||||
_ store: SenderKeyStore,
|
||||
_ context: StoreContext,
|
||||
_ body: (SignalConstPointerFfiSenderKeyStoreStruct) throws -> Result
|
||||
) rethrows -> Result {
|
||||
func ffiShimStoreSenderKey(
|
||||
storeCtx: UnsafeMutableRawPointer?,
|
||||
sender: SignalConstPointerProtocolAddress,
|
||||
|
||||
@@ -294,7 +294,11 @@ internal func checkError(_ error: SignalFfiErrorRef?) throws {
|
||||
return err
|
||||
}
|
||||
|
||||
throw RegistrationError.registrationLock(timeRemaining: TimeInterval(timeRemaining), svr2Username: svr2Username, svr2Password: svr2Password)
|
||||
throw RegistrationError.registrationLock(
|
||||
timeRemaining: TimeInterval(timeRemaining),
|
||||
svr2Username: svr2Username,
|
||||
svr2Password: svr2Password
|
||||
)
|
||||
case SignalErrorCodeKeyTransparencyError:
|
||||
throw SignalError.keyTransparencyError(errStr)
|
||||
case SignalErrorCodeKeyTransparencyVerificationFailed:
|
||||
@@ -308,7 +312,8 @@ internal func failOnError(_ error: SignalFfiErrorRef?) {
|
||||
failOnError { try checkError(error) }
|
||||
}
|
||||
|
||||
internal func failOnError<Result>(_ fn: () throws -> Result, file: StaticString = #file, line: UInt32 = #line) -> Result {
|
||||
internal func failOnError<Result>(_ fn: () throws -> Result, file: StaticString = #file, line: UInt32 = #line) -> Result
|
||||
{
|
||||
do {
|
||||
return try fn()
|
||||
} catch {
|
||||
|
||||
@@ -59,15 +59,17 @@ public struct NumericFingerprintGenerator: Sendable {
|
||||
.bytes(localIdentifier),
|
||||
.bytes(remoteIdentifier)
|
||||
) { localKeyHandle, remoteKeyHandle, localBuffer, remoteBuffer in
|
||||
try checkError(signal_fingerprint_new(
|
||||
&obj,
|
||||
UInt32(self.iterations),
|
||||
UInt32(version),
|
||||
localBuffer,
|
||||
localKeyHandle.const(),
|
||||
remoteBuffer,
|
||||
remoteKeyHandle.const()
|
||||
))
|
||||
try checkError(
|
||||
signal_fingerprint_new(
|
||||
&obj,
|
||||
UInt32(self.iterations),
|
||||
UInt32(version),
|
||||
localBuffer,
|
||||
localKeyHandle.const(),
|
||||
remoteBuffer,
|
||||
remoteKeyHandle.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let fprintStr = try invokeFnReturningString {
|
||||
|
||||
@@ -54,11 +54,13 @@ public class HsmEnclaveClient: NativeHandleOwner<SignalMutPointerHsmEnclaveClien
|
||||
let handle = try publicKey.withUnsafeBorrowedBuffer { publicKeyBuffer in
|
||||
try codeHashBytes.withUnsafeBorrowedBuffer { codeHashBuffer in
|
||||
var result = SignalMutPointerHsmEnclaveClient()
|
||||
try checkError(signal_hsm_enclave_client_new(
|
||||
&result,
|
||||
publicKeyBuffer,
|
||||
codeHashBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_hsm_enclave_client_new(
|
||||
&result,
|
||||
publicKeyBuffer,
|
||||
codeHashBuffer
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -66,7 +68,9 @@ public class HsmEnclaveClient: NativeHandleOwner<SignalMutPointerHsmEnclaveClien
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerHsmEnclaveClient>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerHsmEnclaveClient>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_hsm_enclave_client_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,14 @@ public struct IdentityKey: Equatable, Sendable {
|
||||
public func verifyAlternateIdentity<Bytes: ContiguousBytes>(_ other: IdentityKey, signature: Bytes) throws -> Bool {
|
||||
var result = false
|
||||
try withAllBorrowed(publicKey, other.publicKey, .bytes(signature)) { selfHandle, otherHandle, signatureBuffer in
|
||||
try checkError(signal_identitykey_verify_alternate_identity(&result, selfHandle.const(), otherHandle.const(), signatureBuffer))
|
||||
try checkError(
|
||||
signal_identitykey_verify_alternate_identity(
|
||||
&result,
|
||||
selfHandle.const(),
|
||||
otherHandle.const(),
|
||||
signatureBuffer
|
||||
)
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -74,7 +81,12 @@ public struct IdentityKeyPair: Sendable {
|
||||
return failOnError {
|
||||
try withAllBorrowed(self.publicKey, self.privateKey, other.publicKey) { publicKey, privateKey, other in
|
||||
try invokeFnReturningData {
|
||||
signal_identitykeypair_sign_alternate_identity($0, publicKey.const(), privateKey.const(), other.const())
|
||||
signal_identitykeypair_sign_alternate_identity(
|
||||
$0,
|
||||
publicKey.const(),
|
||||
privateKey.const(),
|
||||
other.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@ public class IncrementalMacContext: NativeHandleOwner<SignalMutPointerIncrementa
|
||||
self.chunkSizeInBytes = chunkSize
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerIncrementalMac>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerIncrementalMac>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_incremental_mac_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -97,7 +99,9 @@ public class ValidatingMacContext: NativeHandleOwner<SignalMutPointerValidatingM
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerValidatingMac>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerValidatingMac>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_validating_mac_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
internal func withInputStream<Result>(_ stream: SignalInputStream, _ body: (SignalConstPointerFfiInputStreamStruct) throws -> Result) throws -> Result {
|
||||
internal func withInputStream<Result>(
|
||||
_ stream: SignalInputStream,
|
||||
_ body: (SignalConstPointerFfiInputStreamStruct) throws -> Result
|
||||
) throws -> Result {
|
||||
func ffiShimRead(
|
||||
stream_ctx: UnsafeMutableRawPointer?,
|
||||
pBuf: UnsafeMutablePointer<UInt8>?,
|
||||
|
||||
@@ -18,12 +18,14 @@ public func hkdf(
|
||||
try inputKeyMaterial.withUnsafeBorrowedBuffer { inputBuffer in
|
||||
try salt.withUnsafeBorrowedBuffer { saltBuffer in
|
||||
try info.withUnsafeBorrowedBuffer { infoBuffer in
|
||||
try checkError(signal_hkdf_derive(
|
||||
.init(outputBuffer),
|
||||
inputBuffer,
|
||||
infoBuffer,
|
||||
saltBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_hkdf_derive(
|
||||
.init(outputBuffer),
|
||||
inputBuffer,
|
||||
infoBuffer,
|
||||
saltBuffer
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,16 @@ public class KEMKeyPair: ClonableHandleOwner<SignalMutPointerKyberKeyPair>, @unc
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerKyberKeyPair, currentHandle: SignalConstPointerKyberKeyPair) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerKyberKeyPair,
|
||||
currentHandle: SignalConstPointerKyberKeyPair
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_key_pair_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerKyberKeyPair>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerKyberKeyPair>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_key_pair_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -76,11 +81,16 @@ public class KEMPublicKey: ClonableHandleOwner<SignalMutPointerKyberPublicKey>,
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerKyberPublicKey, currentHandle: SignalConstPointerKyberPublicKey) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerKyberPublicKey,
|
||||
currentHandle: SignalConstPointerKyberPublicKey
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_public_key_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerKyberPublicKey>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerKyberPublicKey>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_public_key_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -139,11 +149,16 @@ public class KEMSecretKey: ClonableHandleOwner<SignalMutPointerKyberSecretKey>,
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerKyberSecretKey, currentHandle: SignalConstPointerKyberSecretKey) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerKyberSecretKey,
|
||||
currentHandle: SignalConstPointerKyberSecretKey
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_secret_key_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerKyberSecretKey>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerKyberSecretKey>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_secret_key_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -66,21 +66,24 @@ extension LibsignalLogger {
|
||||
public func setUpLibsignalLogging(level: LibsignalLogLevel) {
|
||||
let bridge = LoggerBridge(logger: self)
|
||||
let opaqueBridge = Unmanaged.passRetained(bridge)
|
||||
let success = signal_init_logger(level.asFFI, SignalFfiLogger(
|
||||
ctx: opaqueBridge.toOpaque(),
|
||||
log: { ctx, ffiLevel, file, line, message in
|
||||
let bridge: LoggerBridge = Unmanaged.fromOpaque(ctx!).takeUnretainedValue()
|
||||
// Unknown log levels might have personal info in them, so map them to something low.
|
||||
let level = LibsignalLogLevel(ffiLevel) ?? .debug
|
||||
"".withCString { emptyStringPtr in
|
||||
bridge.logger.log(level: level, file: file, line: line, message: message ?? emptyStringPtr)
|
||||
let success = signal_init_logger(
|
||||
level.asFFI,
|
||||
SignalFfiLogger(
|
||||
ctx: opaqueBridge.toOpaque(),
|
||||
log: { ctx, ffiLevel, file, line, message in
|
||||
let bridge: LoggerBridge = Unmanaged.fromOpaque(ctx!).takeUnretainedValue()
|
||||
// Unknown log levels might have personal info in them, so map them to something low.
|
||||
let level = LibsignalLogLevel(ffiLevel) ?? .debug
|
||||
"".withCString { emptyStringPtr in
|
||||
bridge.logger.log(level: level, file: file, line: line, message: message ?? emptyStringPtr)
|
||||
}
|
||||
},
|
||||
flush: { ctx in
|
||||
let bridge: LoggerBridge = Unmanaged.fromOpaque(ctx!).takeUnretainedValue()
|
||||
bridge.logger.flush()
|
||||
}
|
||||
},
|
||||
flush: { ctx in
|
||||
let bridge: LoggerBridge = Unmanaged.fromOpaque(ctx!).takeUnretainedValue()
|
||||
bridge.logger.flush()
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
if success {
|
||||
// We save this for use within the Swift code as well,
|
||||
// but only if it was registered as the Rust logger successfully.
|
||||
|
||||
@@ -69,7 +69,10 @@ public func sanitizeWebp(input: SignalInputStream) throws {
|
||||
}
|
||||
|
||||
public class SanitizedMetadata: ClonableHandleOwner<OpaquePointer?> {
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout OpaquePointer?, currentHandle: OpaquePointer?) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout OpaquePointer?,
|
||||
currentHandle: OpaquePointer?
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sanitized_metadata_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ public class MessageBackupKey: NativeHandleOwner<SignalMutPointerMessageBackupKe
|
||||
let handle = try backupKey.withUnsafePointerToSerialized { backupKey in
|
||||
try backupId.withUnsafePointerToSerialized { backupId in
|
||||
var outputHandle = SignalMutPointerMessageBackupKey()
|
||||
try checkError(signal_message_backup_key_from_backup_key_and_backup_id(&outputHandle, backupKey, backupId))
|
||||
try checkError(
|
||||
signal_message_backup_key_from_backup_key_and_backup_id(&outputHandle, backupKey, backupId)
|
||||
)
|
||||
return outputHandle
|
||||
}
|
||||
}
|
||||
@@ -45,7 +47,9 @@ public class MessageBackupKey: NativeHandleOwner<SignalMutPointerMessageBackupKe
|
||||
super.init(owned: handle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerMessageBackupKey>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerMessageBackupKey>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_message_backup_key_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -96,7 +100,8 @@ extension SignalConstPointerMessageBackupKey: SignalConstPointer {
|
||||
|
||||
public enum MessageBackupPurpose: UInt8, Sendable {
|
||||
// This needs to be kept in sync with the Rust version of the enum.
|
||||
case deviceTransfer = 0, remoteBackup = 1
|
||||
case deviceTransfer = 0
|
||||
case remoteBackup = 1
|
||||
}
|
||||
|
||||
/// Validates a message backup file.
|
||||
@@ -115,13 +120,23 @@ public enum MessageBackupPurpose: UInt8, Sendable {
|
||||
///
|
||||
/// - SeeAlso: ``OnlineBackupValidator``
|
||||
public func validateMessageBackup(
|
||||
key: MessageBackupKey, purpose: MessageBackupPurpose, length: UInt64, makeStream: () throws -> SignalInputStream
|
||||
key: MessageBackupKey,
|
||||
purpose: MessageBackupPurpose,
|
||||
length: UInt64,
|
||||
makeStream: () throws -> SignalInputStream
|
||||
) throws -> MessageBackupUnknownFields {
|
||||
let outcome: ValidationOutcome = try withInputStream(try makeStream()) { firstInput in
|
||||
try withInputStream(try makeStream()) { secondInput in
|
||||
try key.withNativeHandle { key in
|
||||
try invokeFnReturningNativeHandle {
|
||||
signal_message_backup_validator_validate($0, key.const(), firstInput, secondInput, length, purpose.rawValue)
|
||||
signal_message_backup_validator_validate(
|
||||
$0,
|
||||
key.const(),
|
||||
firstInput,
|
||||
secondInput,
|
||||
length,
|
||||
purpose.rawValue
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +185,9 @@ public class OnlineBackupValidator: NativeHandleOwner<SignalMutPointerOnlineBack
|
||||
super.init(owned: handle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerOnlineBackupValidator>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerOnlineBackupValidator>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_online_backup_validator_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -248,7 +265,9 @@ private class ValidationOutcome: NativeHandleOwner<SignalMutPointerMessageBackup
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerMessageBackupValidationOutcome>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerMessageBackupValidationOutcome>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_message_backup_validation_outcome_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,10 @@ public class ClonableHandleOwner<PointerType: SignalMutPointer>: NativeHandleOwn
|
||||
handle = nil
|
||||
}
|
||||
|
||||
internal class func cloneNativeHandle(_: inout PointerType, currentHandle: PointerType.ConstPointer) -> SignalFfiErrorRef? {
|
||||
internal class func cloneNativeHandle(
|
||||
_: inout PointerType,
|
||||
currentHandle: PointerType.ConstPointer
|
||||
) -> SignalFfiErrorRef? {
|
||||
fatalError("must be implemented by subclasses")
|
||||
}
|
||||
}
|
||||
@@ -173,7 +176,9 @@ internal func cloneOrForgetAsNeeded<Owner: ClonableHandleOwner<PointerType>, Poi
|
||||
///
|
||||
/// As an optimization, steals the handle if `handleOwner` has no other references.
|
||||
/// Checking this requires using `inout`; the reference itself won't be modified.
|
||||
internal func cloneOrTakeHandle<Owner: ClonableHandleOwner<PointerType>, PointerType>(from handleOwner: inout Owner) throws -> PointerType {
|
||||
internal func cloneOrTakeHandle<Owner: ClonableHandleOwner<PointerType>, PointerType>(
|
||||
from handleOwner: inout Owner
|
||||
) throws -> PointerType {
|
||||
if isKnownUniquelyReferenced(&handleOwner) {
|
||||
return handleOwner.takeNativeHandle()
|
||||
}
|
||||
|
||||
@@ -46,8 +46,20 @@ public class Net {
|
||||
///
|
||||
/// - Throws: if the scheme is unsupported or if the provided parameters are invalid for that scheme
|
||||
/// (e.g. Signal TLS proxies don't support authentication)
|
||||
public func setProxy(scheme: String, host: String, port: UInt16? = nil, username: String? = nil, password: String? = nil) throws {
|
||||
try self.connectionManager.setProxy(scheme: scheme, host: host, port: port, username: username, password: password)
|
||||
public func setProxy(
|
||||
scheme: String,
|
||||
host: String,
|
||||
port: UInt16? = nil,
|
||||
username: String? = nil,
|
||||
password: String? = nil
|
||||
) throws {
|
||||
try self.connectionManager.setProxy(
|
||||
scheme: scheme,
|
||||
host: host,
|
||||
port: port,
|
||||
username: username,
|
||||
password: password
|
||||
)
|
||||
}
|
||||
|
||||
/// Sets the Signal TLS proxy host to be used for all new connections (until overridden).
|
||||
@@ -64,13 +76,20 @@ public class Net {
|
||||
// Support <username>@<host> syntax to allow UNENCRYPTED_FOR_TESTING as a marker user.
|
||||
// This is not a stable feature of the API and may go away in the future;
|
||||
// the Rust layer will reject any other users anyway. But it's convenient for us.
|
||||
let (username, host): (String?, String) = if let atSign = host.firstIndex(of: "@") {
|
||||
(String(host[..<atSign]), String(host[atSign...].dropFirst()))
|
||||
} else {
|
||||
(nil, host)
|
||||
}
|
||||
let (username, host): (String?, String) =
|
||||
if let atSign = host.firstIndex(of: "@") {
|
||||
(String(host[..<atSign]), String(host[atSign...].dropFirst()))
|
||||
} else {
|
||||
(nil, host)
|
||||
}
|
||||
|
||||
try self.connectionManager.setProxy(scheme: Net.signalTlsProxyScheme, host: host, port: port, username: username, password: nil)
|
||||
try self.connectionManager.setProxy(
|
||||
scheme: Net.signalTlsProxyScheme,
|
||||
host: host,
|
||||
port: port,
|
||||
username: username,
|
||||
password: nil
|
||||
)
|
||||
}
|
||||
|
||||
/// Refuses to make any new connections until a new proxy configuration is set or
|
||||
@@ -139,7 +158,12 @@ public class Net {
|
||||
acisAndAccessKeys: [AciAndAccessKey],
|
||||
token: Data?
|
||||
) async throws -> CdsiLookup {
|
||||
let request = try CdsiLookupRequest(e164s: e164s, prevE164s: prevE164s, acisAndAccessKeys: acisAndAccessKeys, token: token)
|
||||
let request = try CdsiLookupRequest(
|
||||
e164s: e164s,
|
||||
prevE164s: prevE164s,
|
||||
acisAndAccessKeys: acisAndAccessKeys,
|
||||
token: token
|
||||
)
|
||||
return try await self.cdsiLookup(auth: auth, request: request)
|
||||
}
|
||||
|
||||
@@ -191,7 +215,14 @@ public class Net {
|
||||
let handle = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.connectionManager.withNativeHandle { connectionManager in
|
||||
request.withNativeHandle { request in
|
||||
signal_cdsi_lookup_new(promise, asyncContext.const(), connectionManager.const(), auth.username, auth.password, request.const())
|
||||
signal_cdsi_lookup_new(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
connectionManager.const(),
|
||||
auth.username,
|
||||
auth.password,
|
||||
request.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,8 +271,18 @@ public class Net {
|
||||
///
|
||||
/// - Returns:
|
||||
/// An object representing the established, but not yet active, connection.
|
||||
public func connectAuthenticatedChat(username: String, password: String, receiveStories: Bool) async throws -> AuthenticatedChatConnection {
|
||||
return try await AuthenticatedChatConnection(tokioAsyncContext: self.asyncContext, connectionManager: self.connectionManager, username: username, password: password, receiveStories: receiveStories)
|
||||
public func connectAuthenticatedChat(
|
||||
username: String,
|
||||
password: String,
|
||||
receiveStories: Bool
|
||||
) async throws -> AuthenticatedChatConnection {
|
||||
return try await AuthenticatedChatConnection(
|
||||
tokioAsyncContext: self.asyncContext,
|
||||
connectionManager: self.connectionManager,
|
||||
username: username,
|
||||
password: password,
|
||||
receiveStories: receiveStories
|
||||
)
|
||||
}
|
||||
|
||||
/// Asynchronously establishes an unauthenticated connection to the remote
|
||||
@@ -265,7 +306,7 @@ public class Net {
|
||||
return try await UnauthenticatedChatConnection(
|
||||
tokioAsyncContext: self.asyncContext,
|
||||
connectionManager:
|
||||
self.connectionManager,
|
||||
self.connectionManager,
|
||||
environment: self.environment
|
||||
)
|
||||
}
|
||||
@@ -299,7 +340,9 @@ extension Auth {
|
||||
|
||||
internal class ConnectionManager: NativeHandleOwner<SignalMutPointerConnectionManager> {
|
||||
private class ProxyConfig: NativeHandleOwner<SignalMutPointerConnectionProxyConfig> {
|
||||
override class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerConnectionProxyConfig>) -> SignalFfiErrorRef? {
|
||||
override class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerConnectionProxyConfig>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_connection_proxy_config_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
@@ -363,7 +406,9 @@ internal class ConnectionManager: NativeHandleOwner<SignalMutPointerConnectionMa
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerConnectionManager>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerConnectionManager>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_connection_manager_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,16 @@ public class PrivateKey: ClonableHandleOwner<SignalMutPointerPrivateKey>, @unche
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerPrivateKey, currentHandle: SignalConstPointerPrivateKey) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerPrivateKey,
|
||||
currentHandle: SignalConstPointerPrivateKey
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_privatekey_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPrivateKey>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerPrivateKey>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_privatekey_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,14 @@ public func signalEncrypt<Bytes: ContiguousBytes>(
|
||||
try withSessionStore(sessionStore, context) { ffiSessionStore in
|
||||
try withIdentityKeyStore(identityStore, context) { ffiIdentityStore in
|
||||
try invokeFnReturningNativeHandle {
|
||||
signal_encrypt_message($0, messageBuffer, addressHandle.const(), ffiSessionStore, ffiIdentityStore, UInt64(now.timeIntervalSince1970 * 1000))
|
||||
signal_encrypt_message(
|
||||
$0,
|
||||
messageBuffer,
|
||||
addressHandle.const(),
|
||||
ffiSessionStore,
|
||||
ffiIdentityStore,
|
||||
UInt64(now.timeIntervalSince1970 * 1000)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +43,13 @@ public func signalDecrypt(
|
||||
try withSessionStore(sessionStore, context) { ffiSessionStore in
|
||||
try withIdentityKeyStore(identityStore, context) { ffiIdentityStore in
|
||||
try invokeFnReturningData {
|
||||
signal_decrypt_message($0, messageHandle.const(), addressHandle.const(), ffiSessionStore, ffiIdentityStore)
|
||||
signal_decrypt_message(
|
||||
$0,
|
||||
messageHandle.const(),
|
||||
addressHandle.const(),
|
||||
ffiSessionStore,
|
||||
ffiIdentityStore
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +74,17 @@ public func signalDecryptPreKey(
|
||||
try withSignedPreKeyStore(signedPreKeyStore, context) { ffiSignedPreKeyStore in
|
||||
try withKyberPreKeyStore(kyberPreKeyStore, context) { ffiKyberPreKeyStore in
|
||||
try invokeFnReturningData {
|
||||
signal_decrypt_pre_key_message($0, messageHandle.const(), addressHandle.const(), ffiSessionStore, ffiIdentityStore, ffiPreKeyStore, ffiSignedPreKeyStore, ffiKyberPreKeyStore, usePqRatchet)
|
||||
signal_decrypt_pre_key_message(
|
||||
$0,
|
||||
messageHandle.const(),
|
||||
addressHandle.const(),
|
||||
ffiSessionStore,
|
||||
ffiIdentityStore,
|
||||
ffiPreKeyStore,
|
||||
ffiSignedPreKeyStore,
|
||||
ffiKyberPreKeyStore,
|
||||
usePqRatchet
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +106,16 @@ public func processPreKeyBundle(
|
||||
return try withAllBorrowed(bundle, address) { bundleHandle, addressHandle in
|
||||
try withSessionStore(sessionStore, context) { ffiSessionStore in
|
||||
try withIdentityKeyStore(identityStore, context) { ffiIdentityStore in
|
||||
try checkError(signal_process_prekey_bundle(bundleHandle.const(), addressHandle.const(), ffiSessionStore, ffiIdentityStore, UInt64(now.timeIntervalSince1970 * 1000), usePqRatchet))
|
||||
try checkError(
|
||||
signal_process_prekey_bundle(
|
||||
bundleHandle.const(),
|
||||
addressHandle.const(),
|
||||
ffiSessionStore,
|
||||
ffiIdentityStore,
|
||||
UInt64(now.timeIntervalSince1970 * 1000),
|
||||
usePqRatchet
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,11 +160,13 @@ public func processSenderKeyDistributionMessage(
|
||||
) throws {
|
||||
return try withAllBorrowed(sender, message) { senderHandle, messageHandle in
|
||||
try withSenderKeyStore(store, context) {
|
||||
try checkError(signal_process_sender_key_distribution_message(
|
||||
senderHandle.const(),
|
||||
messageHandle.const(),
|
||||
$0
|
||||
))
|
||||
try checkError(
|
||||
signal_process_sender_key_distribution_message(
|
||||
senderHandle.const(),
|
||||
messageHandle.const(),
|
||||
$0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,15 @@ public class PublicKey: ClonableHandleOwner<SignalMutPointerPublicKey>, @uncheck
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPublicKey>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPublicKey>) -> SignalFfiErrorRef?
|
||||
{
|
||||
return signal_publickey_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerPublicKey, currentHandle: SignalConstPointerPublicKey) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerPublicKey,
|
||||
currentHandle: SignalConstPointerPublicKey
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_publickey_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,9 @@ public enum RegistrationError: Error {
|
||||
public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistrationService>, @unchecked Sendable {
|
||||
private let asyncContext: TokioAsyncContext
|
||||
|
||||
override internal class func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerRegistrationService>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegistrationService>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_registration_service_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
@@ -107,7 +109,10 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
let service: SignalMutPointerRegistrationService =
|
||||
try await net.asyncContext.invokeAsyncFunction { promise, tokioContext in
|
||||
SignalFfiRegistrationCreateSessionRequest.withNativeStruct(
|
||||
e164: e164, pushToken: pushToken, mcc: mcc, mnc: mnc
|
||||
e164: e164,
|
||||
pushToken: pushToken,
|
||||
mcc: mcc,
|
||||
mnc: mnc
|
||||
) { request in
|
||||
withUnsafePointer(to: connectChatBridge) { connectChatBridge in
|
||||
signal_registration_service_create_session(
|
||||
@@ -115,7 +120,8 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
tokioContext.const(),
|
||||
request,
|
||||
SignalConstPointerFfiConnectChatBridgeStruct(
|
||||
raw: connectChatBridge)
|
||||
raw: connectChatBridge
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -150,9 +156,11 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
signal_registration_service_resume_session(
|
||||
promise,
|
||||
tokioContext.const(),
|
||||
sessionId, number,
|
||||
sessionId,
|
||||
number,
|
||||
SignalConstPointerFfiConnectChatBridgeStruct(
|
||||
raw: connectChatBridge)
|
||||
raw: connectChatBridge
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -170,7 +178,13 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
public func requestPushChallenge(apnPushToken: String) async throws {
|
||||
let _: Bool = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_request_push_challenge(promise, asyncContext.const(), $0.const(), apnPushToken, nil)
|
||||
signal_registration_service_request_push_challenge(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
apnPushToken,
|
||||
nil
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +200,12 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
public func submitPushChallenge(pushChallenge: String) async throws {
|
||||
let _: Bool = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_submit_push_challenge(promise, asyncContext.const(), $0.const(), pushChallenge)
|
||||
signal_registration_service_submit_push_challenge(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
pushChallenge
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,8 +230,12 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
languages.withUnsafeBorrowedBytestringArray { languages in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_request_verification_code(
|
||||
promise, asyncContext.const(), $0.const(), transport.description,
|
||||
client, languages
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
transport.description,
|
||||
client,
|
||||
languages
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -232,7 +255,10 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
let _: Bool = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_submit_verification_code(
|
||||
promise, asyncContext.const(), $0.const(), code
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
code
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -250,7 +276,10 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
let _: Bool = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_submit_verification_code(
|
||||
promise, asyncContext.const(), $0.const(), captchaValue
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
captchaValue
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -271,7 +300,12 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
var result = try await self.asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
svrTokens.withUnsafeBorrowedBytestringArray { svrTokens in
|
||||
self.withNativeHandle {
|
||||
signal_registration_service_check_svr2_credentials(promise, asyncContext.const(), $0.const(), svrTokens)
|
||||
signal_registration_service_check_svr2_credentials(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
svrTokens
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,7 +377,13 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
self.withNativeHandle { registrationService in
|
||||
request.withNativeHandle { request in
|
||||
accountAttributes.withNativeHandle { accountAttributes in
|
||||
signal_registration_service_register_account(promise, asyncContext.const(), registrationService.const(), request.const(), accountAttributes.const())
|
||||
signal_registration_service_register_account(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
registrationService.const(),
|
||||
request.const(),
|
||||
accountAttributes.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,233 +457,6 @@ public class RegistrationService: NativeHandleOwner<SignalMutPointerRegistration
|
||||
}
|
||||
}
|
||||
|
||||
public class RegistrationSessionState: NativeHandleOwner<SignalMutPointerRegistrationSession> {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegistrationSession>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_registration_session_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
public var allowedToRequestCode: Bool {
|
||||
return failOnError {
|
||||
try invokeFnReturningBool { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_allowed_to_request_code(out, $0.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var verified: Bool {
|
||||
return failOnError {
|
||||
try invokeFnReturningBool { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_verified(out, $0.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var nextSms: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_sms_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var nextCall: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_call_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var nextVerificationAttempt: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_verification_attempt_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var requestedInformation: Set<ChallengeOption> {
|
||||
return failOnError {
|
||||
let items = try invokeFnReturningData { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_requested_information(out, $0.const())
|
||||
}
|
||||
}
|
||||
return Set(try items.map { try ChallengeOption(fromNative: $0) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ChallengeOption {
|
||||
internal init(fromNative value: UInt8) throws {
|
||||
self = switch UInt32(value) {
|
||||
case SignalChallengeOptionCaptcha.rawValue:
|
||||
.captcha
|
||||
case SignalChallengeOptionPushChallenge.rawValue:
|
||||
.pushChallenge
|
||||
default:
|
||||
throw SignalError.internalError("unknown requested information")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RegisterAccountResponse: NativeHandleOwner<SignalMutPointerRegisterAccountResponse>, @unchecked Sendable {
|
||||
override internal class func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerRegisterAccountResponse>) -> SignalFfiErrorRef? {
|
||||
signal_register_account_response_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
public var aci: Aci {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningServiceId {
|
||||
signal_register_account_response_get_identity($0, native.const(), ServiceIdKind.aci.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var pni: Pni {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningServiceId {
|
||||
signal_register_account_response_get_identity($0, native.const(), ServiceIdKind.pni.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var number: String {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningString {
|
||||
signal_register_account_response_get_number($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var usernameHash: Data? {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningOptionalArray {
|
||||
signal_register_account_response_get_username_hash($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var usernameLinkHandle: UUID? {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningOptionalUuid {
|
||||
signal_register_account_response_get_username_link_handle($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var storageCapable: Bool {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningBool {
|
||||
signal_register_account_response_get_storage_capable($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var reregistration: Bool {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningBool {
|
||||
signal_register_account_response_get_reregistration($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var entitlements: ([BadgeEntitlement], BackupEntitlement?) {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
let badges = try invokeFnReturningBadgeEntitlementArray {
|
||||
signal_register_account_response_get_entitlement_badges($0, native.const())
|
||||
}
|
||||
|
||||
let backup = try BackupEntitlement(fromResponse: native.const())
|
||||
|
||||
return (badges, backup)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct BadgeEntitlement: Equatable {
|
||||
public let id: String
|
||||
public let visible: Bool
|
||||
public let expiration: TimeInterval
|
||||
}
|
||||
|
||||
public struct BackupEntitlement: Equatable {
|
||||
public let expiration: TimeInterval
|
||||
public let level: UInt64
|
||||
public init(expiration: TimeInterval, level: UInt64) {
|
||||
self.expiration = expiration
|
||||
self.level = level
|
||||
}
|
||||
|
||||
fileprivate init?(fromResponse native: SignalConstPointerRegisterAccountResponse) throws {
|
||||
let backupExpiration = try invokeFnReturningOptionalInteger {
|
||||
signal_register_account_response_get_entitlement_backup_expiration_seconds($0, native)
|
||||
}
|
||||
guard case .some(let expiration) = backupExpiration else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let level = try invokeFnReturningOptionalInteger {
|
||||
signal_register_account_response_get_entitlement_backup_level($0, native)
|
||||
}
|
||||
guard case .some(let level) = level else {
|
||||
return nil
|
||||
}
|
||||
self.init(expiration: TimeInterval(expiration), level: level)
|
||||
}
|
||||
}
|
||||
|
||||
public enum VerificationTransport: CustomStringConvertible {
|
||||
case voice
|
||||
case sms
|
||||
|
||||
public var description: String {
|
||||
return switch self {
|
||||
case .voice: "voice"
|
||||
case .sms: "sms"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Svr2CredentialsResult {
|
||||
case match
|
||||
case noMatch
|
||||
case invalid
|
||||
}
|
||||
|
||||
public enum ChallengeOption: Hashable, Sendable {
|
||||
case captcha
|
||||
case pushChallenge
|
||||
}
|
||||
|
||||
private class RegisterAccountRequst: NativeHandleOwner<SignalMutPointerRegisterAccountRequest> {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegisterAccountRequest>
|
||||
@@ -662,41 +475,83 @@ private class RegisterAccountRequst: NativeHandleOwner<SignalMutPointerRegisterA
|
||||
aciPqSignedPreKey: SignedPublicPreKey<KEMPublicKey>,
|
||||
pniPqSignedPreKey: SignedPublicPreKey<KEMPublicKey>
|
||||
) -> Self {
|
||||
let request: Self = failOnError { try invokeFnReturningNativeHandle {
|
||||
signal_register_account_request_create($0)
|
||||
} }
|
||||
let request: Self = failOnError {
|
||||
try invokeFnReturningNativeHandle {
|
||||
signal_register_account_request_create($0)
|
||||
}
|
||||
}
|
||||
failOnError {
|
||||
try request.withNativeHandle { native in
|
||||
try checkError(accountPassword.withCString {
|
||||
signal_register_account_request_set_account_password(native.const(), $0)
|
||||
})
|
||||
try checkError(
|
||||
accountPassword.withCString {
|
||||
signal_register_account_request_set_account_password(native.const(), $0)
|
||||
}
|
||||
)
|
||||
if let apnPushToken {
|
||||
try checkError(apnPushToken.withCString {
|
||||
signal_register_account_request_set_apn_push_token(native.const(), $0)
|
||||
})
|
||||
try checkError(
|
||||
apnPushToken.withCString {
|
||||
signal_register_account_request_set_apn_push_token(native.const(), $0)
|
||||
}
|
||||
)
|
||||
}
|
||||
if skipDeviceTransfer {
|
||||
try checkError(signal_register_account_request_set_skip_device_transfer(native.const()))
|
||||
}
|
||||
|
||||
try checkError(aciIdentityKey.withNativeHandle {
|
||||
signal_register_account_request_set_identity_public_key(native.const(), ServiceIdKind.aci.rawValue, $0.const())
|
||||
})
|
||||
try checkError(pniIdentityKey.withNativeHandle {
|
||||
signal_register_account_request_set_identity_public_key(native.const(), ServiceIdKind.pni.rawValue, $0.const())
|
||||
})
|
||||
try checkError(aciSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_signed_pre_key(native.const(), ServiceIdKind.aci.rawValue, $0)
|
||||
})
|
||||
try checkError(pniSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_signed_pre_key(native.const(), ServiceIdKind.pni.rawValue, $0)
|
||||
})
|
||||
try checkError(aciPqSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_pq_last_resort_pre_key(native.const(), ServiceIdKind.aci.rawValue, $0)
|
||||
})
|
||||
try checkError(pniPqSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_pq_last_resort_pre_key(native.const(), ServiceIdKind.pni.rawValue, $0)
|
||||
})
|
||||
try checkError(
|
||||
aciIdentityKey.withNativeHandle {
|
||||
signal_register_account_request_set_identity_public_key(
|
||||
native.const(),
|
||||
ServiceIdKind.aci.rawValue,
|
||||
$0.const()
|
||||
)
|
||||
}
|
||||
)
|
||||
try checkError(
|
||||
pniIdentityKey.withNativeHandle {
|
||||
signal_register_account_request_set_identity_public_key(
|
||||
native.const(),
|
||||
ServiceIdKind.pni.rawValue,
|
||||
$0.const()
|
||||
)
|
||||
}
|
||||
)
|
||||
try checkError(
|
||||
aciSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_signed_pre_key(
|
||||
native.const(),
|
||||
ServiceIdKind.aci.rawValue,
|
||||
$0
|
||||
)
|
||||
}
|
||||
)
|
||||
try checkError(
|
||||
pniSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_signed_pre_key(
|
||||
native.const(),
|
||||
ServiceIdKind.pni.rawValue,
|
||||
$0
|
||||
)
|
||||
}
|
||||
)
|
||||
try checkError(
|
||||
aciPqSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_pq_last_resort_pre_key(
|
||||
native.const(),
|
||||
ServiceIdKind.aci.rawValue,
|
||||
$0
|
||||
)
|
||||
}
|
||||
)
|
||||
try checkError(
|
||||
pniPqSignedPreKey.withNativeStruct {
|
||||
signal_register_account_request_set_identity_pq_last_resort_pre_key(
|
||||
native.const(),
|
||||
ServiceIdKind.pni.rawValue,
|
||||
$0
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,59 +559,6 @@ private class RegisterAccountRequst: NativeHandleOwner<SignalMutPointerRegisterA
|
||||
}
|
||||
}
|
||||
|
||||
/// Account attributes sent as part of a ``RegistrationService/registerAccount(accountPassword:skipDeviceTransfer:accountAttributes:apnPushToken:aciPublicKey:pniPublicKey:aciSignedPreKey:pniSignedPreKey:aciPqLastResortPreKey:pniPqLastResortPreKey:)`` request.
|
||||
public class RegisterAccountAttributes: NativeHandleOwner<SignalMutPointerRegistrationAccountAttributes> {
|
||||
/// Constructs the set of attributes to pass to the server.
|
||||
/// - Throws: ``SignalError/invalidArgument(_:)`` if the `unidentifiedAccessKey` is not 16 bytes.
|
||||
public convenience init(
|
||||
recoveryPassword: Data,
|
||||
aciRegistrationId: UInt16,
|
||||
pniRegistrationId: UInt16,
|
||||
registrationLock: String?,
|
||||
unidentifiedAccessKey: Data,
|
||||
unrestrictedUnidentifiedAccess: Bool,
|
||||
capabilities: [String],
|
||||
discoverableByPhoneNumber: Bool
|
||||
) throws {
|
||||
var uak = SignalUnidentifiedAccessKey(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
try withUnsafeMutableBytes(of: &uak) { uakBytes in
|
||||
if uakBytes.count != unidentifiedAccessKey.count {
|
||||
throw SignalError.invalidArgument("unidentifiedAccessKey has \(unidentifiedAccessKey.count) bytes; expected \(uakBytes.count)")
|
||||
}
|
||||
uakBytes.copyBytes(from: unidentifiedAccessKey)
|
||||
}
|
||||
let nativeHandle = failOnError {
|
||||
try recoveryPassword.withUnsafeBorrowedBuffer { recoveryPassword in
|
||||
try registrationLock.withCString { registrationLock in
|
||||
try withUnsafePointer(to: &uak) { unidentifiedAccessKey in
|
||||
try capabilities.withUnsafeBorrowedBytestringArray { capabilities in
|
||||
var nativeHandle = SignalMutPointerRegistrationAccountAttributes()
|
||||
try checkError(
|
||||
signal_registration_account_attributes_create(
|
||||
&nativeHandle,
|
||||
recoveryPassword,
|
||||
aciRegistrationId,
|
||||
pniRegistrationId,
|
||||
registrationLock,
|
||||
unidentifiedAccessKey,
|
||||
unrestrictedUnidentifiedAccess,
|
||||
capabilities,
|
||||
discoverableByPhoneNumber
|
||||
))
|
||||
return nativeHandle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.init(owned: NonNull(nativeHandle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerRegistrationAccountAttributes>) -> SignalFfiErrorRef? {
|
||||
signal_registration_account_attributes_destroy(nativeHandle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalFfiConnectChatBridgeStruct {
|
||||
/// Constructs a ``SignalFfiConnectChatBridgeStruct`` that uses the given
|
||||
/// ``ConnectionManager`` to create chat connections.
|
||||
@@ -776,77 +578,40 @@ extension SignalFfiConnectChatBridgeStruct {
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalFfiRegistrationCreateSessionRequest {
|
||||
internal static func withNativeStruct<Result>(
|
||||
e164: String,
|
||||
pushToken: String?,
|
||||
mcc: String?,
|
||||
mnc: String?,
|
||||
_ fn: (Self) throws -> Result
|
||||
) rethrows -> Result {
|
||||
try e164.withCString { e164 in
|
||||
try pushToken.withCString { pushToken in
|
||||
try mcc.withCString { mcc in
|
||||
try mnc.withCString { mnc in
|
||||
let request = SignalFfiRegistrationCreateSessionRequest(
|
||||
number: e164, push_token: pushToken,
|
||||
mcc: mcc, mnc: mnc
|
||||
)
|
||||
return try fn(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke a function returning an unsigned integral result where `nil` is bridged as the maximum value.
|
||||
///
|
||||
/// Bridging `nil` as max isn't a convention we want to rely on generally. It's
|
||||
/// true for the getters in this file, though, hence `fileprivate`.
|
||||
private func invokeFnReturningOptionalInteger<Result: FixedWidthInteger & UnsignedInteger>(fn: (UnsafeMutablePointer<Result>?) -> SignalFfiErrorRef?) throws -> Result? {
|
||||
let output = try invokeFnReturningInteger(fn: fn)
|
||||
return if output == Result.max { nil } else { output }
|
||||
}
|
||||
|
||||
private func invokeFnReturningBadgeEntitlementArray(fn: (_ out: UnsafeMutablePointer<SignalOwnedBufferOfFfiRegisterResponseBadge>) -> SignalFfiErrorRef?) throws -> [BadgeEntitlement] {
|
||||
var out = SignalOwnedBufferOfFfiRegisterResponseBadge()
|
||||
try checkError(fn(&out))
|
||||
defer { signal_free_list_of_register_response_badges(out) }
|
||||
|
||||
return UnsafeBufferPointer(start: out.base, count: out.length).map {
|
||||
BadgeEntitlement(id: String(cString: $0.id), visible: $0.visible, expiration: TimeInterval($0.expiration_secs))
|
||||
}
|
||||
}
|
||||
|
||||
// Exposed for testing.
|
||||
internal func invokeFnReturningCheckSvr2CredentialsResponse(fn: (_ out: UnsafeMutablePointer<SignalFfiCheckSvr2CredentialsResponse>?) -> SignalFfiErrorRef?) throws -> [String: Svr2CredentialsResult] {
|
||||
let entries = try invokeFnReturningSomeBytestringArray(fn: { out in
|
||||
// This is just a named wrapper around a bytestring array.
|
||||
var wrapper = SignalFfiCheckSvr2CredentialsResponse()
|
||||
let err = fn(&wrapper)
|
||||
// Copy the wrapped pointer into the provided output. The outer function
|
||||
// will also take care of deallocating.
|
||||
if err == nil {
|
||||
out!.update(from: &wrapper.entries, count: 1)
|
||||
internal func invokeFnReturningCheckSvr2CredentialsResponse(
|
||||
fn: (_ out: UnsafeMutablePointer<SignalFfiCheckSvr2CredentialsResponse>?) -> SignalFfiErrorRef?
|
||||
) throws -> [String: Svr2CredentialsResult] {
|
||||
let entries = try invokeFnReturningSomeBytestringArray(
|
||||
fn: { out in
|
||||
// This is just a named wrapper around a bytestring array.
|
||||
var wrapper = SignalFfiCheckSvr2CredentialsResponse()
|
||||
let err = fn(&wrapper)
|
||||
// Copy the wrapped pointer into the provided output. The outer function
|
||||
// will also take care of deallocating.
|
||||
if err == nil {
|
||||
out!.update(from: &wrapper.entries, count: 1)
|
||||
}
|
||||
return err
|
||||
},
|
||||
transform: { view in
|
||||
// The format for entries is a UTF-8 key with the value as a single byte at the end.
|
||||
let key = String(decoding: view.dropLast(), as: Unicode.UTF8.self)
|
||||
let valueByte = UInt32(view.last!)
|
||||
let value =
|
||||
switch SignalSvr2CredentialsResult(valueByte) {
|
||||
case SignalSvr2CredentialsResultInvalid:
|
||||
Svr2CredentialsResult.invalid
|
||||
case SignalSvr2CredentialsResultMatch:
|
||||
Svr2CredentialsResult.match
|
||||
case SignalSvr2CredentialsResultNoMatch:
|
||||
Svr2CredentialsResult.noMatch
|
||||
default:
|
||||
fatalError("unknown SVR2 credentials result value \(valueByte)")
|
||||
}
|
||||
return (key, value)
|
||||
}
|
||||
return err
|
||||
}, transform: { view in
|
||||
// The format for entries is a UTF-8 key with the value as a single byte at the end.
|
||||
let key = String(decoding: view.dropLast(), as: Unicode.UTF8.self)
|
||||
let valueByte = UInt32(view.last!)
|
||||
let value = switch SignalSvr2CredentialsResult(valueByte) {
|
||||
case SignalSvr2CredentialsResultInvalid:
|
||||
Svr2CredentialsResult.invalid
|
||||
case SignalSvr2CredentialsResultMatch:
|
||||
Svr2CredentialsResult.match
|
||||
case SignalSvr2CredentialsResultNoMatch:
|
||||
Svr2CredentialsResult.noMatch
|
||||
default:
|
||||
fatalError("unknown SVR2 credentials result value \(valueByte)")
|
||||
}
|
||||
return (key, value)
|
||||
})
|
||||
)
|
||||
|
||||
return Dictionary(uniqueKeysWithValues: entries)
|
||||
}
|
||||
@@ -872,91 +637,3 @@ extension SignalConstPointerRegistrationService: SignalConstPointer {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegistrationSession: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegistrationSession
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegistrationSession(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegistrationSession: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegisterAccountResponse: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegisterAccountResponse
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegisterAccountResponse(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegisterAccountResponse: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegisterAccountRequest: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegisterAccountRequest
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegisterAccountRequest(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegisterAccountRequest: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegistrationAccountAttributes: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegistrationAccountAttributes
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegistrationAccountAttributes(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegistrationAccountAttributes: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
432
swift/Sources/LibSignalClient/RegistrationServiceTypes.swift
Normal file
432
swift/Sources/LibSignalClient/RegistrationServiceTypes.swift
Normal file
@@ -0,0 +1,432 @@
|
||||
//
|
||||
// Copyright 2025 Signal Messenger, LLC.
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class RegistrationSessionState: NativeHandleOwner<SignalMutPointerRegistrationSession> {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegistrationSession>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_registration_session_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
public var allowedToRequestCode: Bool {
|
||||
return failOnError {
|
||||
try invokeFnReturningBool { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_allowed_to_request_code(out, $0.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var verified: Bool {
|
||||
return failOnError {
|
||||
try invokeFnReturningBool { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_verified(out, $0.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var nextSms: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_sms_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var nextCall: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_call_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var nextVerificationAttempt: TimeInterval? {
|
||||
return failOnError {
|
||||
try invokeFnReturningOptionalInteger { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_next_verification_attempt_seconds(out, $0.const())
|
||||
}
|
||||
}.map { TimeInterval($0) }
|
||||
}
|
||||
}
|
||||
|
||||
public var requestedInformation: Set<ChallengeOption> {
|
||||
return failOnError {
|
||||
let items = try invokeFnReturningData { out in
|
||||
self.withNativeHandle {
|
||||
signal_registration_session_get_requested_information(out, $0.const())
|
||||
}
|
||||
}
|
||||
return Set(try items.map { try ChallengeOption(fromNative: $0) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ChallengeOption {
|
||||
internal init(fromNative value: UInt8) throws {
|
||||
self =
|
||||
switch UInt32(value) {
|
||||
case SignalChallengeOptionCaptcha.rawValue:
|
||||
.captcha
|
||||
case SignalChallengeOptionPushChallenge.rawValue:
|
||||
.pushChallenge
|
||||
default:
|
||||
throw SignalError.internalError("unknown requested information")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RegisterAccountResponse: NativeHandleOwner<SignalMutPointerRegisterAccountResponse>, @unchecked Sendable {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegisterAccountResponse>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_register_account_response_destroy(nativeHandle.pointer)
|
||||
}
|
||||
|
||||
public var aci: Aci {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningServiceId {
|
||||
signal_register_account_response_get_identity($0, native.const(), ServiceIdKind.aci.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var pni: Pni {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningServiceId {
|
||||
signal_register_account_response_get_identity($0, native.const(), ServiceIdKind.pni.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var number: String {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningString {
|
||||
signal_register_account_response_get_number($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var usernameHash: Data? {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningOptionalArray {
|
||||
signal_register_account_response_get_username_hash($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var usernameLinkHandle: UUID? {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningOptionalUuid {
|
||||
signal_register_account_response_get_username_link_handle($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var storageCapable: Bool {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningBool {
|
||||
signal_register_account_response_get_storage_capable($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var reregistration: Bool {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
try invokeFnReturningBool {
|
||||
signal_register_account_response_get_reregistration($0, native.const())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var entitlements: ([BadgeEntitlement], BackupEntitlement?) {
|
||||
return failOnError {
|
||||
try self.withNativeHandle { native in
|
||||
let badges = try invokeFnReturningBadgeEntitlementArray {
|
||||
signal_register_account_response_get_entitlement_badges($0, native.const())
|
||||
}
|
||||
|
||||
let backup = try BackupEntitlement(fromResponse: native.const())
|
||||
|
||||
return (badges, backup)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct BadgeEntitlement: Equatable {
|
||||
public let id: String
|
||||
public let visible: Bool
|
||||
public let expiration: TimeInterval
|
||||
}
|
||||
|
||||
public struct BackupEntitlement: Equatable {
|
||||
public let expiration: TimeInterval
|
||||
public let level: UInt64
|
||||
public init(expiration: TimeInterval, level: UInt64) {
|
||||
self.expiration = expiration
|
||||
self.level = level
|
||||
}
|
||||
|
||||
fileprivate init?(fromResponse native: SignalConstPointerRegisterAccountResponse) throws {
|
||||
let backupExpiration = try invokeFnReturningOptionalInteger {
|
||||
signal_register_account_response_get_entitlement_backup_expiration_seconds($0, native)
|
||||
}
|
||||
guard case .some(let expiration) = backupExpiration else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let level = try invokeFnReturningOptionalInteger {
|
||||
signal_register_account_response_get_entitlement_backup_level($0, native)
|
||||
}
|
||||
guard case .some(let level) = level else {
|
||||
return nil
|
||||
}
|
||||
self.init(expiration: TimeInterval(expiration), level: level)
|
||||
}
|
||||
}
|
||||
|
||||
public enum VerificationTransport: CustomStringConvertible {
|
||||
case voice
|
||||
case sms
|
||||
|
||||
public var description: String {
|
||||
return switch self {
|
||||
case .voice: "voice"
|
||||
case .sms: "sms"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Svr2CredentialsResult {
|
||||
case match
|
||||
case noMatch
|
||||
case invalid
|
||||
}
|
||||
|
||||
public enum ChallengeOption: Hashable, Sendable {
|
||||
case captcha
|
||||
case pushChallenge
|
||||
}
|
||||
|
||||
/// Account attributes sent as part of a ``RegistrationService/registerAccount(accountPassword:skipDeviceTransfer:accountAttributes:apnPushToken:aciPublicKey:pniPublicKey:aciSignedPreKey:pniSignedPreKey:aciPqLastResortPreKey:pniPqLastResortPreKey:)`` request.
|
||||
public class RegisterAccountAttributes: NativeHandleOwner<SignalMutPointerRegistrationAccountAttributes> {
|
||||
/// Constructs the set of attributes to pass to the server.
|
||||
/// - Throws: ``SignalError/invalidArgument(_:)`` if the `unidentifiedAccessKey` is not 16 bytes.
|
||||
public convenience init(
|
||||
recoveryPassword: Data,
|
||||
aciRegistrationId: UInt16,
|
||||
pniRegistrationId: UInt16,
|
||||
registrationLock: String?,
|
||||
unidentifiedAccessKey: Data,
|
||||
unrestrictedUnidentifiedAccess: Bool,
|
||||
capabilities: [String],
|
||||
discoverableByPhoneNumber: Bool
|
||||
) throws {
|
||||
var uak = SignalUnidentifiedAccessKey(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
try withUnsafeMutableBytes(of: &uak) { uakBytes in
|
||||
if uakBytes.count != unidentifiedAccessKey.count {
|
||||
throw SignalError.invalidArgument(
|
||||
"unidentifiedAccessKey has \(unidentifiedAccessKey.count) bytes; expected \(uakBytes.count)"
|
||||
)
|
||||
}
|
||||
uakBytes.copyBytes(from: unidentifiedAccessKey)
|
||||
}
|
||||
let nativeHandle = failOnError {
|
||||
try recoveryPassword.withUnsafeBorrowedBuffer { recoveryPassword in
|
||||
try registrationLock.withCString { registrationLock in
|
||||
try withUnsafePointer(to: &uak) { unidentifiedAccessKey in
|
||||
try capabilities.withUnsafeBorrowedBytestringArray { capabilities in
|
||||
var nativeHandle = SignalMutPointerRegistrationAccountAttributes()
|
||||
try checkError(
|
||||
signal_registration_account_attributes_create(
|
||||
&nativeHandle,
|
||||
recoveryPassword,
|
||||
aciRegistrationId,
|
||||
pniRegistrationId,
|
||||
registrationLock,
|
||||
unidentifiedAccessKey,
|
||||
unrestrictedUnidentifiedAccess,
|
||||
capabilities,
|
||||
discoverableByPhoneNumber
|
||||
)
|
||||
)
|
||||
return nativeHandle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.init(owned: NonNull(nativeHandle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerRegistrationAccountAttributes>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_registration_account_attributes_destroy(nativeHandle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalFfiRegistrationCreateSessionRequest {
|
||||
internal static func withNativeStruct<Result>(
|
||||
e164: String,
|
||||
pushToken: String?,
|
||||
mcc: String?,
|
||||
mnc: String?,
|
||||
_ fn: (Self) throws -> Result
|
||||
) rethrows -> Result {
|
||||
try e164.withCString { e164 in
|
||||
try pushToken.withCString { pushToken in
|
||||
try mcc.withCString { mcc in
|
||||
try mnc.withCString { mnc in
|
||||
let request = SignalFfiRegistrationCreateSessionRequest(
|
||||
number: e164,
|
||||
push_token: pushToken,
|
||||
mcc: mcc,
|
||||
mnc: mnc
|
||||
)
|
||||
return try fn(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke a function returning an unsigned integral result where `nil` is bridged as the maximum value.
|
||||
///
|
||||
/// Bridging `nil` as max isn't a convention we want to rely on generally. It's
|
||||
/// true for the getters in this file, though, hence `fileprivate`.
|
||||
private func invokeFnReturningOptionalInteger<Result: FixedWidthInteger & UnsignedInteger>(
|
||||
fn: (UnsafeMutablePointer<Result>?) -> SignalFfiErrorRef?
|
||||
) throws -> Result? {
|
||||
let output = try invokeFnReturningInteger(fn: fn)
|
||||
return if output == Result.max { nil } else { output }
|
||||
}
|
||||
|
||||
private func invokeFnReturningBadgeEntitlementArray(
|
||||
fn: (_ out: UnsafeMutablePointer<SignalOwnedBufferOfFfiRegisterResponseBadge>) -> SignalFfiErrorRef?
|
||||
) throws -> [BadgeEntitlement] {
|
||||
var out = SignalOwnedBufferOfFfiRegisterResponseBadge()
|
||||
try checkError(fn(&out))
|
||||
defer { signal_free_list_of_register_response_badges(out) }
|
||||
|
||||
return UnsafeBufferPointer(start: out.base, count: out.length).map {
|
||||
BadgeEntitlement(id: String(cString: $0.id), visible: $0.visible, expiration: TimeInterval($0.expiration_secs))
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegistrationSession: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegistrationSession
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegistrationSession(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegistrationSession: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegisterAccountResponse: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegisterAccountResponse
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegisterAccountResponse(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegisterAccountResponse: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegisterAccountRequest: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegisterAccountRequest
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegisterAccountRequest(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegisterAccountRequest: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalMutPointerRegistrationAccountAttributes: SignalMutPointer {
|
||||
public typealias ConstPointer = SignalConstPointerRegistrationAccountAttributes
|
||||
|
||||
public init(untyped: OpaquePointer?) {
|
||||
self.init(raw: untyped)
|
||||
}
|
||||
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
|
||||
public func const() -> Self.ConstPointer {
|
||||
SignalConstPointerRegistrationAccountAttributes(raw: self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
extension SignalConstPointerRegistrationAccountAttributes: SignalConstPointer {
|
||||
public func toOpaque() -> OpaquePointer? {
|
||||
self.raw
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,8 @@ public class UnidentifiedSenderMessageContent: NativeHandleOwner<SignalMutPointe
|
||||
&result,
|
||||
messageBuffer,
|
||||
ffiIdentityStore
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
@@ -74,7 +75,8 @@ public class UnidentifiedSenderMessageContent: NativeHandleOwner<SignalMutPointe
|
||||
senderHandle.const(),
|
||||
contentHint.rawValue,
|
||||
groupIdBuffer
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
@@ -96,12 +98,15 @@ public class UnidentifiedSenderMessageContent: NativeHandleOwner<SignalMutPointe
|
||||
senderHandle.const(),
|
||||
contentHint.rawValue,
|
||||
groupIdBuffer
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerUnidentifiedSenderMessageContent>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerUnidentifiedSenderMessageContent>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_unidentified_sender_message_content_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,16 @@ public class ServerCertificate: NativeHandleOwner<SignalMutPointerServerCertific
|
||||
public convenience init(keyId: UInt32, publicKey: PublicKey, trustRoot: PrivateKey) throws {
|
||||
var result = SignalMutPointerServerCertificate()
|
||||
try withAllBorrowed(publicKey, trustRoot) { publicKeyHandle, trustRootHandle in
|
||||
try checkError(signal_server_certificate_new(&result, keyId, publicKeyHandle.const(), trustRootHandle.const()))
|
||||
try checkError(
|
||||
signal_server_certificate_new(&result, keyId, publicKeyHandle.const(), trustRootHandle.const())
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerServerCertificate>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerServerCertificate>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_server_certificate_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -113,24 +117,37 @@ public class SenderCertificate: NativeHandleOwner<SignalMutPointerSenderCertific
|
||||
}
|
||||
|
||||
// For testing
|
||||
public convenience init(sender: SealedSenderAddress, publicKey: PublicKey, expiration: UInt64, signerCertificate: ServerCertificate, signerKey: PrivateKey) throws {
|
||||
public convenience init(
|
||||
sender: SealedSenderAddress,
|
||||
publicKey: PublicKey,
|
||||
expiration: UInt64,
|
||||
signerCertificate: ServerCertificate,
|
||||
signerKey: PrivateKey
|
||||
) throws {
|
||||
var result = SignalMutPointerSenderCertificate()
|
||||
try withAllBorrowed(publicKey, signerCertificate, signerKey) { publicKeyHandle, signerCertificateHandle, signerKeyHandle in
|
||||
try checkError(signal_sender_certificate_new(
|
||||
&result,
|
||||
sender.uuidString,
|
||||
sender.e164,
|
||||
sender.deviceId,
|
||||
publicKeyHandle.const(),
|
||||
expiration,
|
||||
signerCertificateHandle.const(),
|
||||
signerKeyHandle.const()
|
||||
))
|
||||
try withAllBorrowed(publicKey, signerCertificate, signerKey) {
|
||||
publicKeyHandle,
|
||||
signerCertificateHandle,
|
||||
signerKeyHandle in
|
||||
try checkError(
|
||||
signal_sender_certificate_new(
|
||||
&result,
|
||||
sender.uuidString,
|
||||
sender.e164,
|
||||
sender.deviceId,
|
||||
publicKeyHandle.const(),
|
||||
expiration,
|
||||
signerCertificateHandle.const(),
|
||||
signerKeyHandle.const()
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSenderCertificate>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSenderCertificate>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sender_certificate_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -240,7 +257,9 @@ public class SenderCertificate: NativeHandleOwner<SignalMutPointerSenderCertific
|
||||
public func validate(trustRoot: PublicKey, time: UInt64) throws -> Bool {
|
||||
var result = false
|
||||
try withAllBorrowed(self, trustRoot) { certificateHandle, trustRootHandle in
|
||||
try checkError(signal_sender_certificate_validate(&result, certificateHandle.const(), trustRootHandle.const(), time))
|
||||
try checkError(
|
||||
signal_sender_certificate_validate(&result, certificateHandle.const(), trustRootHandle.const(), time)
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import SignalFfi
|
||||
internal typealias ServiceIdStorage = SignalServiceIdFixedWidthBinaryBytes
|
||||
|
||||
internal func == (_ lhs: ServiceIdStorage, _ rhs: ServiceIdStorage) -> Bool {
|
||||
// swift-format-ignore
|
||||
// (vertical alignment is clearer)
|
||||
return lhs.0 == rhs.0 &&
|
||||
lhs.1 == rhs.1 &&
|
||||
lhs.2 == rhs.2 &&
|
||||
@@ -152,7 +154,9 @@ public class ServiceId: @unchecked Sendable {
|
||||
return try result.downcast(to: Self.self)
|
||||
}
|
||||
|
||||
internal func withPointerToFixedWidthBinary<R>(_ callback: (UnsafePointer<ServiceIdStorage>) throws -> R) rethrows -> R {
|
||||
internal func withPointerToFixedWidthBinary<R>(
|
||||
_ callback: (UnsafePointer<ServiceIdStorage>) throws -> R
|
||||
) rethrows -> R {
|
||||
return try callback(&self.storage)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ import SignalFfi
|
||||
/// which decrypts and verifies it, passing the plaintext back to the client for processing.
|
||||
///
|
||||
public class SgxClient: NativeHandleOwner<SignalMutPointerSgxClientState> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSgxClientState>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSgxClientState>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sgx_client_state_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,14 @@ public class Svr2Client: SgxClient {
|
||||
let handle = try attestationMessage.withUnsafeBorrowedBuffer { attestationMessageBuffer in
|
||||
try mrenclave.withUnsafeBorrowedBuffer { mrenclaveBuffer in
|
||||
var result = SignalMutPointerSgxClientState()
|
||||
try checkError(signal_svr2_client_new(
|
||||
&result,
|
||||
mrenclaveBuffer,
|
||||
attestationMessageBuffer,
|
||||
UInt64(currentDate.timeIntervalSince1970 * 1000)
|
||||
))
|
||||
try checkError(
|
||||
signal_svr2_client_new(
|
||||
&result,
|
||||
mrenclaveBuffer,
|
||||
attestationMessageBuffer,
|
||||
UInt64(currentDate.timeIntervalSince1970 * 1000)
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ internal class TokioAsyncContext: NativeHandleOwner<SignalMutPointerTokioAsyncCo
|
||||
self.init(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerTokioAsyncContext>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerTokioAsyncContext>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_tokio_async_context_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -88,7 +90,12 @@ internal class TokioAsyncContext: NativeHandleOwner<SignalMutPointerTokioAsyncCo
|
||||
try checkError(signal_tokio_async_context_cancel($0.const(), id))
|
||||
}
|
||||
} catch {
|
||||
LoggerBridge.shared?.logger.log(level: .warn, file: #fileID, line: #line, message: "failed to cancel libsignal task \(id): \(error)")
|
||||
LoggerBridge.shared?.logger.log(
|
||||
level: .warn,
|
||||
file: #fileID,
|
||||
line: #line,
|
||||
message: "failed to cancel libsignal task \(id): \(error)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,17 +113,23 @@ internal class TokioAsyncContext: NativeHandleOwner<SignalMutPointerTokioAsyncCo
|
||||
_ body: (UnsafeMutablePointer<Promise>, SignalMutPointerTokioAsyncContext) -> SignalFfiErrorRef?
|
||||
) async throws -> Promise.Result {
|
||||
let cancellationHelper = CancellationHandoffHelper(context: self)
|
||||
return try await withTaskCancellationHandler(operation: {
|
||||
try await LibSignalClient.invokeAsyncFunction({ promise in
|
||||
withNativeHandle { handle in
|
||||
body(promise, handle)
|
||||
}
|
||||
}, saveCancellationId: {
|
||||
cancellationHelper.setCancellationId($0)
|
||||
})
|
||||
}, onCancel: {
|
||||
cancellationHelper.cancel()
|
||||
})
|
||||
return try await withTaskCancellationHandler(
|
||||
operation: {
|
||||
try await LibSignalClient.invokeAsyncFunction(
|
||||
{ promise in
|
||||
withNativeHandle { handle in
|
||||
body(promise, handle)
|
||||
}
|
||||
},
|
||||
saveCancellationId: {
|
||||
cancellationHelper.setCancellationId($0)
|
||||
}
|
||||
)
|
||||
},
|
||||
onCancel: {
|
||||
cancellationHelper.cancel()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,18 @@ public struct Username: Sendable {
|
||||
try self.init(username)
|
||||
}
|
||||
|
||||
public init(nickname: String, discriminator: String, withValidLengthWithin lengthRange: ClosedRange<UInt32>) throws {
|
||||
public init(nickname: String, discriminator: String, withValidLengthWithin lengthRange: ClosedRange<UInt32>) throws
|
||||
{
|
||||
self.hash = try nickname.withCString { nickname in
|
||||
try discriminator.withCString { discriminator in
|
||||
try invokeFnReturningFixedLengthArray {
|
||||
signal_username_hash_from_parts($0, nickname, discriminator, lengthRange.lowerBound, lengthRange.upperBound)
|
||||
signal_username_hash_from_parts(
|
||||
$0,
|
||||
nickname,
|
||||
discriminator,
|
||||
lengthRange.lowerBound,
|
||||
lengthRange.upperBound
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,19 @@ import SignalFfi
|
||||
import Security
|
||||
#endif
|
||||
|
||||
internal func invokeFnReturningString(fn: (UnsafeMutablePointer<UnsafePointer<CChar>?>?) -> SignalFfiErrorRef?) throws -> String {
|
||||
internal func invokeFnReturningString(
|
||||
fn: (UnsafeMutablePointer<UnsafePointer<CChar>?>?) -> SignalFfiErrorRef?
|
||||
) throws
|
||||
-> String
|
||||
{
|
||||
try invokeFnReturningOptionalString(fn: fn)!
|
||||
}
|
||||
|
||||
internal func invokeFnReturningOptionalString(fn: (UnsafeMutablePointer<UnsafePointer<CChar>?>?) -> SignalFfiErrorRef?) throws -> String? {
|
||||
internal func invokeFnReturningOptionalString(
|
||||
fn: (UnsafeMutablePointer<UnsafePointer<CChar>?>?) -> SignalFfiErrorRef?
|
||||
)
|
||||
throws -> String?
|
||||
{
|
||||
var output: UnsafePointer<Int8>?
|
||||
try checkError(fn(&output))
|
||||
if output == nil {
|
||||
@@ -25,7 +33,10 @@ internal func invokeFnReturningOptionalString(fn: (UnsafeMutablePointer<UnsafePo
|
||||
return result
|
||||
}
|
||||
|
||||
internal func invokeFnReturningSomeBytestringArray<Element>(fn: (UnsafeMutablePointer<SignalBytestringArray>?) -> SignalFfiErrorRef?, transform: (UnsafeBufferPointer<UInt8>) -> Element) throws -> [Element] {
|
||||
internal func invokeFnReturningSomeBytestringArray<Element>(
|
||||
fn: (UnsafeMutablePointer<SignalBytestringArray>?) -> SignalFfiErrorRef?,
|
||||
transform: (UnsafeBufferPointer<UInt8>) -> Element
|
||||
) throws -> [Element] {
|
||||
var array = SignalFfi.SignalBytestringArray()
|
||||
try checkError(fn(&array))
|
||||
|
||||
@@ -42,41 +53,64 @@ internal func invokeFnReturningSomeBytestringArray<Element>(fn: (UnsafeMutablePo
|
||||
return result
|
||||
}
|
||||
|
||||
internal func invokeFnReturningStringArray(fn: (UnsafeMutablePointer<SignalStringArray>?) -> SignalFfiErrorRef?) throws -> [String] {
|
||||
internal func invokeFnReturningStringArray(
|
||||
fn: (UnsafeMutablePointer<SignalStringArray>?) -> SignalFfiErrorRef?
|
||||
) throws
|
||||
-> [String]
|
||||
{
|
||||
return try invokeFnReturningSomeBytestringArray(fn: fn) {
|
||||
String(decoding: $0, as: Unicode.UTF8.self)
|
||||
}
|
||||
}
|
||||
|
||||
internal func invokeFnReturningBytestringArray(fn: (UnsafeMutablePointer<SignalBytestringArray>?) -> SignalFfiErrorRef?) throws -> [Data] {
|
||||
internal func invokeFnReturningBytestringArray(
|
||||
fn: (UnsafeMutablePointer<SignalBytestringArray>?) -> SignalFfiErrorRef?
|
||||
)
|
||||
throws -> [Data]
|
||||
{
|
||||
return try invokeFnReturningSomeBytestringArray(fn: fn) {
|
||||
Data($0)
|
||||
}
|
||||
}
|
||||
|
||||
internal func invokeFnReturningOptionalArray(fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?) throws -> Data? {
|
||||
internal func invokeFnReturningOptionalArray(
|
||||
fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?
|
||||
)
|
||||
throws -> Data?
|
||||
{
|
||||
var output = SignalOwnedBuffer()
|
||||
try checkError(fn(&output))
|
||||
|
||||
return if output.base == nil {
|
||||
nil
|
||||
} else {
|
||||
Data(bytesNoCopy: output.base, count: output.length, deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
})
|
||||
Data(
|
||||
bytesNoCopy: output.base,
|
||||
count: output.length,
|
||||
deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal func invokeFnReturningData(fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?) throws -> Data {
|
||||
internal func invokeFnReturningData(fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?) throws -> Data
|
||||
{
|
||||
var output = SignalOwnedBuffer()
|
||||
try checkError(fn(&output))
|
||||
guard let base = output.base else { return Data() }
|
||||
return Data(bytesNoCopy: base, count: output.length, deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
})
|
||||
return Data(
|
||||
bytesNoCopy: base,
|
||||
count: output.length,
|
||||
deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningFixedLengthArray<ResultAsTuple>(fn: (UnsafeMutablePointer<ResultAsTuple>) -> SignalFfiErrorRef?) throws -> Data {
|
||||
internal func invokeFnReturningFixedLengthArray<ResultAsTuple>(
|
||||
fn: (UnsafeMutablePointer<ResultAsTuple>) -> SignalFfiErrorRef?
|
||||
) throws -> Data {
|
||||
precondition(MemoryLayout<ResultAsTuple>.alignment == 1, "not a fixed-sized array (tuple) of UInt8")
|
||||
var output = Data(count: MemoryLayout<ResultAsTuple>.size)
|
||||
try output.withUnsafeMutableBytes { buffer in
|
||||
@@ -86,17 +120,23 @@ internal func invokeFnReturningFixedLengthArray<ResultAsTuple>(fn: (UnsafeMutabl
|
||||
return output
|
||||
}
|
||||
|
||||
internal func invokeFnReturningSerialized<Result: ByteArray, SerializedResult>(fn: (UnsafeMutablePointer<SerializedResult>) -> SignalFfiErrorRef?) throws -> Result {
|
||||
internal func invokeFnReturningSerialized<Result: ByteArray, SerializedResult>(
|
||||
fn: (UnsafeMutablePointer<SerializedResult>) -> SignalFfiErrorRef?
|
||||
) throws -> Result {
|
||||
let output = try invokeFnReturningFixedLengthArray(fn: fn)
|
||||
return try Result(contents: output)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningVariableLengthSerialized<Result: ByteArray>(fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?) throws -> Result {
|
||||
internal func invokeFnReturningVariableLengthSerialized<Result: ByteArray>(
|
||||
fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?
|
||||
) throws -> Result {
|
||||
let output = try invokeFnReturningData(fn: fn)
|
||||
return try Result(contents: output)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningOptionalVariableLengthSerialized<Result: ByteArray>(fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?) throws -> Result? {
|
||||
internal func invokeFnReturningOptionalVariableLengthSerialized<Result: ByteArray>(
|
||||
fn: (UnsafeMutablePointer<SignalOwnedBuffer>?) -> SignalFfiErrorRef?
|
||||
) throws -> Result? {
|
||||
let output = try invokeFnReturningData(fn: fn)
|
||||
if output.isEmpty {
|
||||
return nil
|
||||
@@ -110,7 +150,9 @@ internal func invokeFnReturningUuid(fn: (UnsafeMutablePointer<uuid_t>?) -> Signa
|
||||
return UUID(uuid: output)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningOptionalUuid(fn: (UnsafeMutablePointer<SignalOptionalUuid>?) -> SignalFfiErrorRef?) throws -> UUID? {
|
||||
internal func invokeFnReturningOptionalUuid(
|
||||
fn: (UnsafeMutablePointer<SignalOptionalUuid>?) -> SignalFfiErrorRef?
|
||||
) throws -> UUID? {
|
||||
var output: SignalOptionalUuid = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
try checkError(fn(&output))
|
||||
let (isPresent, u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11, u12, u13, u14, u15) = output
|
||||
@@ -120,13 +162,17 @@ internal func invokeFnReturningOptionalUuid(fn: (UnsafeMutablePointer<SignalOpti
|
||||
return UUID(uuid: (u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11, u12, u13, u14, u15))
|
||||
}
|
||||
|
||||
internal func invokeFnReturningServiceId<Id: ServiceId>(fn: (UnsafeMutablePointer<ServiceIdStorage>?) -> SignalFfiErrorRef?) throws -> Id {
|
||||
internal func invokeFnReturningServiceId<Id: ServiceId>(
|
||||
fn: (UnsafeMutablePointer<ServiceIdStorage>?) -> SignalFfiErrorRef?
|
||||
) throws -> Id {
|
||||
var output: ServiceIdStorage = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
try checkError(fn(&output))
|
||||
return try Id.parseFrom(fixedWidthBinary: output)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningInteger<Result: FixedWidthInteger>(fn: (UnsafeMutablePointer<Result>?) -> SignalFfiErrorRef?) throws -> Result {
|
||||
internal func invokeFnReturningInteger<Result: FixedWidthInteger>(
|
||||
fn: (UnsafeMutablePointer<Result>?) -> SignalFfiErrorRef?
|
||||
) throws -> Result {
|
||||
var output: Result = 0
|
||||
try checkError(fn(&output))
|
||||
return output
|
||||
@@ -138,13 +184,17 @@ internal func invokeFnReturningBool(fn: (UnsafeMutablePointer<Bool>?) -> SignalF
|
||||
return output
|
||||
}
|
||||
|
||||
internal func invokeFnReturningNativeHandle<Owner: NativeHandleOwner<PointerType>, PointerType>(fn: (UnsafeMutablePointer<PointerType>?) -> SignalFfiErrorRef?) throws -> Owner {
|
||||
internal func invokeFnReturningNativeHandle<Owner: NativeHandleOwner<PointerType>, PointerType>(
|
||||
fn: (UnsafeMutablePointer<PointerType>?) -> SignalFfiErrorRef?
|
||||
) throws -> Owner {
|
||||
var handle = PointerType(untyped: nil)
|
||||
try checkError(fn(&handle))
|
||||
return Owner(owned: NonNull(handle)!)
|
||||
}
|
||||
|
||||
internal func invokeFnReturningOptionalNativeHandle<Owner: NativeHandleOwner<PointerType>, PointerType>(fn: (UnsafeMutablePointer<PointerType>?) -> SignalFfiErrorRef?) throws -> Owner? {
|
||||
internal func invokeFnReturningOptionalNativeHandle<Owner: NativeHandleOwner<PointerType>, PointerType>(
|
||||
fn: (UnsafeMutablePointer<PointerType>?) -> SignalFfiErrorRef?
|
||||
) throws -> Owner? {
|
||||
var handle = PointerType(untyped: nil)
|
||||
try checkError(fn(&handle))
|
||||
return NonNull<PointerType>(handle).map { Owner(owned: $0) }
|
||||
@@ -178,7 +228,9 @@ internal func withUnsafeOptionalBorrowedSlice<
|
||||
}
|
||||
|
||||
extension Sequence where Self.Element == String {
|
||||
func withUnsafeBorrowedBytestringArray<Result>(_ body: (SignalBorrowedBytestringArray) throws -> Result) rethrows -> Result {
|
||||
func withUnsafeBorrowedBytestringArray<Result>(
|
||||
_ body: (SignalBorrowedBytestringArray) throws -> Result
|
||||
) rethrows -> Result {
|
||||
let lengths = self.map { $0.utf8.count }
|
||||
var concatenated = Data(capacity: lengths.reduce(0) { $0 + $1 })
|
||||
for s in self {
|
||||
@@ -187,10 +239,12 @@ extension Sequence where Self.Element == String {
|
||||
|
||||
return try concatenated.withUnsafeBorrowedBuffer { bytes in
|
||||
try lengths.withUnsafeBufferPointer { lengths in
|
||||
try body(SignalBorrowedBytestringArray(
|
||||
bytes: bytes,
|
||||
lengths: SignalBorrowedSliceOfusize(base: lengths.baseAddress, length: lengths.count)
|
||||
))
|
||||
try body(
|
||||
SignalBorrowedBytestringArray(
|
||||
bytes: bytes,
|
||||
lengths: SignalBorrowedSliceOfusize(base: lengths.baseAddress, length: lengths.count)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,9 +265,13 @@ extension SignalBorrowedMutableBuffer {
|
||||
extension Data {
|
||||
internal init(consuming buffer: SignalOwnedBuffer) {
|
||||
if let base = buffer.base {
|
||||
self.init(bytesNoCopy: base, count: buffer.length, deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
})
|
||||
self.init(
|
||||
bytesNoCopy: base,
|
||||
count: buffer.length,
|
||||
deallocator: .custom { base, length in
|
||||
signal_free_buffer(base, length)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
self.init()
|
||||
}
|
||||
@@ -227,16 +285,16 @@ internal func fillRandom(_ buffer: UnsafeMutableRawBufferPointer) throws {
|
||||
return
|
||||
}
|
||||
|
||||
#if canImport(Security)
|
||||
#if canImport(Security)
|
||||
let result = SecRandomCopyBytes(kSecRandomDefault, buffer.count, baseAddress)
|
||||
guard result == errSecSuccess else {
|
||||
throw SignalError.internalError("SecRandomCopyBytes failed (error code \(result))")
|
||||
}
|
||||
#else
|
||||
#else
|
||||
for i in buffer.indices {
|
||||
buffer[i] = UInt8.random(in: .min ... .max)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Wraps a store while providing a place to hang on to any user-thrown errors.
|
||||
@@ -258,7 +316,10 @@ internal struct ErrorHandlingContext<Store> {
|
||||
}
|
||||
}
|
||||
|
||||
internal func rethrowCallbackErrors<Store, Result>(_ store: Store, _ body: (UnsafeMutablePointer<ErrorHandlingContext<Store>>) throws -> Result) rethrows -> Result {
|
||||
internal func rethrowCallbackErrors<Store, Result>(
|
||||
_ store: Store,
|
||||
_ body: (UnsafeMutablePointer<ErrorHandlingContext<Store>>) throws -> Result
|
||||
) rethrows -> Result {
|
||||
var context = ErrorHandlingContext(store)
|
||||
do {
|
||||
return try withUnsafeMutablePointer(to: &context) {
|
||||
@@ -323,7 +384,9 @@ extension Data {
|
||||
}
|
||||
|
||||
extension [String: String] {
|
||||
internal func withBridgedStringMap<Result>(_ callback: (SignalMutPointerBridgedStringMap) throws -> Result) rethrows -> Result {
|
||||
internal func withBridgedStringMap<Result>(
|
||||
_ callback: (SignalMutPointerBridgedStringMap) throws -> Result
|
||||
) rethrows -> Result {
|
||||
var map = SignalMutPointerBridgedStringMap()
|
||||
failOnError(signal_bridged_string_map_new(&map, UInt32(clamping: self.count)))
|
||||
defer { signal_bridged_string_map_destroy(map) }
|
||||
|
||||
@@ -34,7 +34,9 @@ public class CiphertextMessage: NativeHandleOwner<SignalMutPointerCiphertextMess
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerCiphertextMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerCiphertextMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_ciphertext_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class PlaintextContent: NativeHandleOwner<SignalMutPointerPlaintextContent> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPlaintextContent>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerPlaintextContent>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_plaintext_content_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -71,7 +73,9 @@ extension SignalConstPointerPlaintextContent: SignalConstPointer {
|
||||
}
|
||||
|
||||
public class DecryptionErrorMessage: NativeHandleOwner<SignalMutPointerDecryptionErrorMessage> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerDecryptionErrorMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerDecryptionErrorMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_decryption_error_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -83,16 +87,31 @@ public class DecryptionErrorMessage: NativeHandleOwner<SignalMutPointerDecryptio
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
public convenience init<Bytes: ContiguousBytes>(originalMessageBytes bytes: Bytes, type: CiphertextMessage.MessageType, timestamp: UInt64, originalSenderDeviceId: UInt32) throws {
|
||||
public convenience init<Bytes: ContiguousBytes>(
|
||||
originalMessageBytes bytes: Bytes,
|
||||
type: CiphertextMessage.MessageType,
|
||||
timestamp: UInt64,
|
||||
originalSenderDeviceId: UInt32
|
||||
) throws {
|
||||
var result = SignalMutPointerDecryptionErrorMessage()
|
||||
try bytes.withUnsafeBorrowedBuffer {
|
||||
try checkError(signal_decryption_error_message_for_original_message(&result, $0, type.rawValue, timestamp, originalSenderDeviceId))
|
||||
try checkError(
|
||||
signal_decryption_error_message_for_original_message(
|
||||
&result,
|
||||
$0,
|
||||
type.rawValue,
|
||||
timestamp,
|
||||
originalSenderDeviceId
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
// For testing
|
||||
public static func extractFromSerializedContent<Bytes: ContiguousBytes>(_ bytes: Bytes) throws -> DecryptionErrorMessage {
|
||||
public static func extractFromSerializedContent<Bytes: ContiguousBytes>(
|
||||
_ bytes: Bytes
|
||||
) throws -> DecryptionErrorMessage {
|
||||
return try bytes.withUnsafeBorrowedBuffer { buffer in
|
||||
try invokeFnReturningNativeHandle {
|
||||
signal_decryption_error_message_extract_from_serialized_content($0, buffer)
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class PreKeySignalMessage: NativeHandleOwner<SignalMutPointerPreKeySignalMessage> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPreKeySignalMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerPreKeySignalMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_pre_key_signal_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SenderKeyDistributionMessage: NativeHandleOwner<SignalMutPointerSenderKeyDistributionMessage> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSenderKeyDistributionMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSenderKeyDistributionMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sender_key_distribution_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -21,12 +23,14 @@ public class SenderKeyDistributionMessage: NativeHandleOwner<SignalMutPointerSen
|
||||
try sender.withNativeHandle { senderHandle in
|
||||
try withUnsafePointer(to: distributionId.uuid) { distributionId in
|
||||
try withSenderKeyStore(store, context) {
|
||||
try checkError(signal_sender_key_distribution_message_create(
|
||||
&result,
|
||||
senderHandle.const(),
|
||||
distributionId,
|
||||
$0
|
||||
))
|
||||
try checkError(
|
||||
signal_sender_key_distribution_message_create(
|
||||
&result,
|
||||
senderHandle.const(),
|
||||
distributionId,
|
||||
$0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SenderKeyMessage: NativeHandleOwner<SignalMutPointerSenderKeyMessage> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSenderKeyMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSenderKeyMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sender_key_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -72,7 +74,9 @@ public class SenderKeyMessage: NativeHandleOwner<SignalMutPointerSenderKeyMessag
|
||||
public func verifySignature(against key: PublicKey) throws -> Bool {
|
||||
var result = false
|
||||
try withAllBorrowed(self, key) { messageHandle, keyHandle in
|
||||
try checkError(signal_sender_key_message_verify_signature(&result, messageHandle.const(), keyHandle.const()))
|
||||
try checkError(
|
||||
signal_sender_key_message_verify_signature(&result, messageHandle.const(), keyHandle.const())
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SignalMessage: NativeHandleOwner<SignalMutPointerSignalMessage> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSignalMessage>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSignalMessage>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_message_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -81,13 +83,15 @@ public class SignalMessage: NativeHandleOwner<SignalMutPointerSignalMessage> {
|
||||
.bytes(macKey)
|
||||
) { messageHandle, senderHandle, receiverHandle, macKey in
|
||||
var result = false
|
||||
try checkError(signal_message_verify_mac(
|
||||
&result,
|
||||
messageHandle.const(),
|
||||
senderHandle.const(),
|
||||
receiverHandle.const(),
|
||||
macKey
|
||||
))
|
||||
try checkError(
|
||||
signal_message_verify_mac(
|
||||
&result,
|
||||
messageHandle.const(),
|
||||
senderHandle.const(),
|
||||
receiverHandle.const(),
|
||||
macKey
|
||||
)
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class KyberPreKeyRecord: ClonableHandleOwner<SignalMutPointerKyberPreKeyRecord> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerKyberPreKeyRecord>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerKyberPreKeyRecord>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_pre_key_record_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerKyberPreKeyRecord, currentHandle: SignalConstPointerKyberPreKeyRecord) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerKyberPreKeyRecord,
|
||||
currentHandle: SignalConstPointerKyberPreKeyRecord
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_kyber_pre_key_record_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class PreKeyBundle: NativeHandleOwner<SignalMutPointerPreKeyBundle> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPreKeyBundle>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerPreKeyBundle>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_pre_key_bundle_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
@@ -36,21 +38,29 @@ public class PreKeyBundle: NativeHandleOwner<SignalMutPointerPreKeyBundle> {
|
||||
kyberPrekey,
|
||||
.bytes(signedPrekeySignature),
|
||||
.bytes(kyberPrekeySignature)
|
||||
) { prekeyHandle, signedPrekeyHandle, identityKeyHandle, kyberKeyHandle, ecSignatureBuffer, kyberSignatureBuffer in
|
||||
try checkError(signal_pre_key_bundle_new(
|
||||
&result,
|
||||
registrationId,
|
||||
deviceId,
|
||||
prekeyId,
|
||||
prekeyHandle.const(),
|
||||
signedPrekeyId,
|
||||
signedPrekeyHandle.const(),
|
||||
ecSignatureBuffer,
|
||||
identityKeyHandle.const(),
|
||||
kyberPrekeyId,
|
||||
kyberKeyHandle.const(),
|
||||
kyberSignatureBuffer
|
||||
))
|
||||
) {
|
||||
prekeyHandle,
|
||||
signedPrekeyHandle,
|
||||
identityKeyHandle,
|
||||
kyberKeyHandle,
|
||||
ecSignatureBuffer,
|
||||
kyberSignatureBuffer in
|
||||
try checkError(
|
||||
signal_pre_key_bundle_new(
|
||||
&result,
|
||||
registrationId,
|
||||
deviceId,
|
||||
prekeyId,
|
||||
prekeyHandle.const(),
|
||||
signedPrekeyId,
|
||||
signedPrekeyHandle.const(),
|
||||
ecSignatureBuffer,
|
||||
identityKeyHandle.const(),
|
||||
kyberPrekeyId,
|
||||
kyberKeyHandle.const(),
|
||||
kyberSignatureBuffer
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
@@ -78,20 +88,22 @@ public class PreKeyBundle: NativeHandleOwner<SignalMutPointerPreKeyBundle> {
|
||||
.bytes(signedPrekeySignature),
|
||||
.bytes(kyberPrekeySignature)
|
||||
) { signedPrekeyHandle, identityKeyHandle, kyberKeyHandle, ecSignatureBuffer, kyberSignatureBuffer in
|
||||
try checkError(signal_pre_key_bundle_new(
|
||||
&result,
|
||||
registrationId,
|
||||
deviceId,
|
||||
~0,
|
||||
SignalConstPointerPublicKey(),
|
||||
signedPrekeyId,
|
||||
signedPrekeyHandle.const(),
|
||||
ecSignatureBuffer,
|
||||
identityKeyHandle.const(),
|
||||
kyberPrekeyId,
|
||||
kyberKeyHandle.const(),
|
||||
kyberSignatureBuffer
|
||||
))
|
||||
try checkError(
|
||||
signal_pre_key_bundle_new(
|
||||
&result,
|
||||
registrationId,
|
||||
deviceId,
|
||||
~0,
|
||||
SignalConstPointerPublicKey(),
|
||||
signedPrekeyId,
|
||||
signedPrekeyHandle.const(),
|
||||
ecSignatureBuffer,
|
||||
identityKeyHandle.const(),
|
||||
kyberPrekeyId,
|
||||
kyberKeyHandle.const(),
|
||||
kyberSignatureBuffer
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class PreKeyRecord: ClonableHandleOwner<SignalMutPointerPreKeyRecord> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerPreKeyRecord>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerPreKeyRecord>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_pre_key_record_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerPreKeyRecord, currentHandle: SignalConstPointerPreKeyRecord) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerPreKeyRecord,
|
||||
currentHandle: SignalConstPointerPreKeyRecord
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_pre_key_record_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,16 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SenderKeyRecord: ClonableHandleOwner<SignalMutPointerSenderKeyRecord> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSenderKeyRecord>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSenderKeyRecord>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sender_key_record_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerSenderKeyRecord, currentHandle: SignalConstPointerSenderKeyRecord) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerSenderKeyRecord,
|
||||
currentHandle: SignalConstPointerSenderKeyRecord
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_sender_key_record_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,16 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SessionRecord: ClonableHandleOwner<SignalMutPointerSessionRecord> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSessionRecord>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSessionRecord>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_session_record_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerSessionRecord, currentHandle: SignalConstPointerSessionRecord) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerSessionRecord,
|
||||
currentHandle: SignalConstPointerSessionRecord
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_session_record_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
@@ -41,7 +46,13 @@ public class SessionRecord: ClonableHandleOwner<SignalMutPointerSessionRecord> {
|
||||
public func hasCurrentState(now: Date) -> Bool {
|
||||
var result = false
|
||||
self.withNativeHandle { nativeHandle in
|
||||
failOnError(signal_session_record_has_usable_sender_chain(&result, nativeHandle.const(), UInt64(now.timeIntervalSince1970 * 1000)))
|
||||
failOnError(
|
||||
signal_session_record_has_usable_sender_chain(
|
||||
&result,
|
||||
nativeHandle.const(),
|
||||
UInt64(now.timeIntervalSince1970 * 1000)
|
||||
)
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -63,7 +74,9 @@ public class SessionRecord: ClonableHandleOwner<SignalMutPointerSessionRecord> {
|
||||
public func currentRatchetKeyMatches(_ key: PublicKey) throws -> Bool {
|
||||
var result = false
|
||||
try withAllBorrowed(self, key) { sessionHandle, keyHandle in
|
||||
try checkError(signal_session_record_current_ratchet_key_matches(&result, sessionHandle.const(), keyHandle.const()))
|
||||
try checkError(
|
||||
signal_session_record_current_ratchet_key_matches(&result, sessionHandle.const(), keyHandle.const())
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ import Foundation
|
||||
import SignalFfi
|
||||
|
||||
public class SignedPreKeyRecord: ClonableHandleOwner<SignalMutPointerSignedPreKeyRecord> {
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerSignedPreKeyRecord>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerSignedPreKeyRecord>
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_signed_pre_key_record_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
override internal class func cloneNativeHandle(_ newHandle: inout SignalMutPointerSignedPreKeyRecord, currentHandle: SignalConstPointerSignedPreKeyRecord) -> SignalFfiErrorRef? {
|
||||
override internal class func cloneNativeHandle(
|
||||
_ newHandle: inout SignalMutPointerSignedPreKeyRecord,
|
||||
currentHandle: SignalConstPointerSignedPreKeyRecord
|
||||
) -> SignalFfiErrorRef? {
|
||||
return signal_signed_pre_key_record_clone(&newHandle, currentHandle)
|
||||
}
|
||||
|
||||
@@ -33,14 +38,16 @@ public class SignedPreKeyRecord: ClonableHandleOwner<SignalMutPointerSignedPreKe
|
||||
let publicKey = privateKey.publicKey
|
||||
var result = SignalMutPointerSignedPreKeyRecord()
|
||||
try withAllBorrowed(publicKey, privateKey, .bytes(signature)) { publicKeyHandle, privateKeyHandle, signature in
|
||||
try checkError(signal_signed_pre_key_record_new(
|
||||
&result,
|
||||
id,
|
||||
timestamp,
|
||||
publicKeyHandle.const(),
|
||||
privateKeyHandle.const(),
|
||||
signature
|
||||
))
|
||||
try checkError(
|
||||
signal_signed_pre_key_record_new(
|
||||
&result,
|
||||
id,
|
||||
timestamp,
|
||||
publicKeyHandle.const(),
|
||||
privateKeyHandle.const(),
|
||||
signature
|
||||
)
|
||||
)
|
||||
}
|
||||
self.init(owned: NonNull(result)!)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ public class BackupAuthCredential: ByteArray, @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public func present(serverParams: GenericServerPublicParams, randomness: Randomness) -> BackupAuthCredentialPresentation {
|
||||
public func present(
|
||||
serverParams: GenericServerPublicParams,
|
||||
randomness: Randomness
|
||||
) -> BackupAuthCredentialPresentation {
|
||||
return failOnError {
|
||||
try withAllBorrowed(self, serverParams, randomness) { contents, serverParams, randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
|
||||
@@ -13,7 +13,13 @@ public class BackupAuthCredentialPresentation: ByteArray, @unchecked Sendable {
|
||||
|
||||
public func verify(now: Date = Date(), serverParams: GenericServerSecretParams) throws {
|
||||
try withAllBorrowed(self, serverParams) { contents, serverParams in
|
||||
try checkError(signal_backup_auth_credential_presentation_verify(contents, UInt64(now.timeIntervalSince1970), serverParams))
|
||||
try checkError(
|
||||
signal_backup_auth_credential_presentation_verify(
|
||||
contents,
|
||||
UInt64(now.timeIntervalSince1970),
|
||||
serverParams
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,42 @@ public class BackupAuthCredentialRequest: ByteArray, @unchecked Sendable {
|
||||
try super.init(contents, checkValid: signal_backup_auth_credential_request_check_valid_contents)
|
||||
}
|
||||
|
||||
public func issueCredential(timestamp: Date, backupLevel: BackupLevel, type: BackupCredentialType, params: GenericServerSecretParams) -> BackupAuthCredentialResponse {
|
||||
public func issueCredential(
|
||||
timestamp: Date,
|
||||
backupLevel: BackupLevel,
|
||||
type: BackupCredentialType,
|
||||
params: GenericServerSecretParams
|
||||
) -> BackupAuthCredentialResponse {
|
||||
return failOnError {
|
||||
self.issueCredential(timestamp: timestamp, backupLevel: backupLevel, type: type, params: params, randomness: try .generate())
|
||||
self.issueCredential(
|
||||
timestamp: timestamp,
|
||||
backupLevel: backupLevel,
|
||||
type: type,
|
||||
params: params,
|
||||
randomness: try .generate()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func issueCredential(timestamp: Date, backupLevel: BackupLevel, type: BackupCredentialType, params: GenericServerSecretParams, randomness: Randomness) -> BackupAuthCredentialResponse {
|
||||
public func issueCredential(
|
||||
timestamp: Date,
|
||||
backupLevel: BackupLevel,
|
||||
type: BackupCredentialType,
|
||||
params: GenericServerSecretParams,
|
||||
randomness: Randomness
|
||||
) -> BackupAuthCredentialResponse {
|
||||
return failOnError {
|
||||
try withAllBorrowed(self, params, randomness) { contents, params, randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_backup_auth_credential_request_issue_deterministic($0, contents, UInt64(timestamp.timeIntervalSince1970), backupLevel.rawValue, type.rawValue, params, randomness)
|
||||
signal_backup_auth_credential_request_issue_deterministic(
|
||||
$0,
|
||||
contents,
|
||||
UInt64(timestamp.timeIntervalSince1970),
|
||||
backupLevel.rawValue,
|
||||
type.rawValue,
|
||||
params,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,20 @@ public class BackupAuthCredentialRequestContext: ByteArray, @unchecked Sendable
|
||||
}
|
||||
}
|
||||
|
||||
public func receive(_ response: BackupAuthCredentialResponse, timestamp: Date, params: GenericServerPublicParams) throws -> BackupAuthCredential {
|
||||
public func receive(
|
||||
_ response: BackupAuthCredentialResponse,
|
||||
timestamp: Date,
|
||||
params: GenericServerPublicParams
|
||||
) throws -> BackupAuthCredential {
|
||||
return try withAllBorrowed(self, response, params) { contents, response, params in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_backup_auth_credential_request_context_receive_response($0, contents, response, UInt64(timestamp.timeIntervalSince1970), params)
|
||||
signal_backup_auth_credential_request_context_receive_response(
|
||||
$0,
|
||||
contents,
|
||||
response,
|
||||
UInt64(timestamp.timeIntervalSince1970),
|
||||
params
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ import SignalFfi
|
||||
|
||||
public enum BackupLevel: UInt8, Sendable {
|
||||
// This must match the Rust version of the enum.
|
||||
case free = 200, paid = 201
|
||||
case free = 200
|
||||
case paid = 201
|
||||
}
|
||||
|
||||
public enum BackupCredentialType: UInt8 {
|
||||
// This must match the Rust version of the enum.
|
||||
case messages = 1, media = 2
|
||||
case messages = 1
|
||||
case media = 2
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ public class ByteArray {
|
||||
|
||||
init(newContents: Data, expectedLength: Int, unrecoverable: Bool = false) throws {
|
||||
if newContents.count != expectedLength {
|
||||
throw SignalError.invalidType("\(type(of: self)) uses \(expectedLength) bytes, but tried to deserialize from an array of \(newContents.count) bytes")
|
||||
throw SignalError.invalidType(
|
||||
"\(type(of: self)) uses \(expectedLength) bytes, but tried to deserialize from an array of \(newContents.count) bytes"
|
||||
)
|
||||
}
|
||||
self.contents = newContents
|
||||
}
|
||||
@@ -42,13 +44,17 @@ public class ByteArray {
|
||||
/// tuples representing a fixed-size array; using another type, or using the wrong size of
|
||||
/// array, is considered a programmer error and can result in arbitrary behavior (including
|
||||
/// violating type safety). So, uh, don't do that.
|
||||
func withUnsafePointerToSerialized<Serialized, Result>(_ callback: (UnsafePointer<Serialized>) throws -> Result) throws -> Result {
|
||||
func withUnsafePointerToSerialized<Serialized, Result>(
|
||||
_ callback: (UnsafePointer<Serialized>) throws -> Result
|
||||
) throws -> Result {
|
||||
precondition(MemoryLayout<Serialized>.alignment == 1, "not a fixed-sized array (tuple) of UInt8")
|
||||
|
||||
return try self.contents.withUnsafeBytes { buffer in
|
||||
let expectedSize = MemoryLayout<Serialized>.size
|
||||
guard expectedSize == buffer.count else {
|
||||
throw SignalError.invalidType("\(type(of: self)) uses \(buffer.count) bytes, but was passed to a callback that uses \(expectedSize) bytes")
|
||||
throw SignalError.invalidType(
|
||||
"\(type(of: self)) uses \(buffer.count) bytes, but was passed to a callback that uses \(expectedSize) bytes"
|
||||
)
|
||||
}
|
||||
|
||||
// Use assumingMemoryBound(to:) here rather than bindMemory(to:)
|
||||
|
||||
@@ -11,13 +11,30 @@ public class CallLinkAuthCredential: ByteArray, @unchecked Sendable {
|
||||
try super.init(contents, checkValid: signal_call_link_auth_credential_check_valid_contents)
|
||||
}
|
||||
|
||||
public func present(userId: Aci, redemptionTime: Date, serverParams: GenericServerPublicParams, callLinkParams: CallLinkSecretParams) -> CallLinkAuthCredentialPresentation {
|
||||
public func present(
|
||||
userId: Aci,
|
||||
redemptionTime: Date,
|
||||
serverParams: GenericServerPublicParams,
|
||||
callLinkParams: CallLinkSecretParams
|
||||
) -> CallLinkAuthCredentialPresentation {
|
||||
return failOnError {
|
||||
self.present(userId: userId, redemptionTime: redemptionTime, serverParams: serverParams, callLinkParams: callLinkParams, randomness: try .generate())
|
||||
self.present(
|
||||
userId: userId,
|
||||
redemptionTime: redemptionTime,
|
||||
serverParams: serverParams,
|
||||
callLinkParams: callLinkParams,
|
||||
randomness: try .generate()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func present(userId: Aci, redemptionTime: Date, serverParams: GenericServerPublicParams, callLinkParams: CallLinkSecretParams, randomness: Randomness) -> CallLinkAuthCredentialPresentation {
|
||||
public func present(
|
||||
userId: Aci,
|
||||
redemptionTime: Date,
|
||||
serverParams: GenericServerPublicParams,
|
||||
callLinkParams: CallLinkSecretParams,
|
||||
randomness: Randomness
|
||||
) -> CallLinkAuthCredentialPresentation {
|
||||
return failOnError {
|
||||
try withAllBorrowed(
|
||||
self,
|
||||
@@ -27,7 +44,15 @@ public class CallLinkAuthCredential: ByteArray, @unchecked Sendable {
|
||||
randomness
|
||||
) { contents, userId, serverParams, callLinkParams, randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_call_link_auth_credential_present_deterministic($0, contents, userId, UInt64(redemptionTime.timeIntervalSince1970), serverParams, callLinkParams, randomness)
|
||||
signal_call_link_auth_credential_present_deterministic(
|
||||
$0,
|
||||
contents,
|
||||
userId,
|
||||
UInt64(redemptionTime.timeIntervalSince1970),
|
||||
serverParams,
|
||||
callLinkParams,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,20 @@ public class CallLinkAuthCredentialPresentation: ByteArray, @unchecked Sendable
|
||||
try super.init(contents, checkValid: signal_call_link_auth_credential_presentation_check_valid_contents)
|
||||
}
|
||||
|
||||
public func verify(now: Date = Date(), serverParams: GenericServerSecretParams, callLinkParams: CallLinkPublicParams) throws {
|
||||
public func verify(
|
||||
now: Date = Date(),
|
||||
serverParams: GenericServerSecretParams,
|
||||
callLinkParams: CallLinkPublicParams
|
||||
) throws {
|
||||
try withAllBorrowed(self, serverParams, callLinkParams) { contents, serverParams, callLinkParams in
|
||||
try checkError(signal_call_link_auth_credential_presentation_verify(contents, UInt64(now.timeIntervalSince1970), serverParams, callLinkParams))
|
||||
try checkError(
|
||||
signal_call_link_auth_credential_presentation_verify(
|
||||
contents,
|
||||
UInt64(now.timeIntervalSince1970),
|
||||
serverParams,
|
||||
callLinkParams
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,26 +11,56 @@ public class CallLinkAuthCredentialResponse: ByteArray, @unchecked Sendable {
|
||||
try super.init(contents, checkValid: signal_call_link_auth_credential_response_check_valid_contents)
|
||||
}
|
||||
|
||||
public static func issueCredential(userId: Aci, redemptionTime: Date, params: GenericServerSecretParams) -> CallLinkAuthCredentialResponse {
|
||||
public static func issueCredential(
|
||||
userId: Aci,
|
||||
redemptionTime: Date,
|
||||
params: GenericServerSecretParams
|
||||
) -> CallLinkAuthCredentialResponse {
|
||||
return failOnError {
|
||||
self.issueCredential(userId: userId, redemptionTime: redemptionTime, params: params, randomness: try .generate())
|
||||
self.issueCredential(
|
||||
userId: userId,
|
||||
redemptionTime: redemptionTime,
|
||||
params: params,
|
||||
randomness: try .generate()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public static func issueCredential(userId: Aci, redemptionTime: Date, params: GenericServerSecretParams, randomness: Randomness) -> CallLinkAuthCredentialResponse {
|
||||
public static func issueCredential(
|
||||
userId: Aci,
|
||||
redemptionTime: Date,
|
||||
params: GenericServerSecretParams,
|
||||
randomness: Randomness
|
||||
) -> CallLinkAuthCredentialResponse {
|
||||
return failOnError {
|
||||
try withAllBorrowed(userId, params, randomness) { userId, params, randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_call_link_auth_credential_response_issue_deterministic($0, userId, UInt64(redemptionTime.timeIntervalSince1970), params, randomness)
|
||||
signal_call_link_auth_credential_response_issue_deterministic(
|
||||
$0,
|
||||
userId,
|
||||
UInt64(redemptionTime.timeIntervalSince1970),
|
||||
params,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func receive(userId: Aci, redemptionTime: Date, params: GenericServerPublicParams) throws -> CallLinkAuthCredential {
|
||||
public func receive(
|
||||
userId: Aci,
|
||||
redemptionTime: Date,
|
||||
params: GenericServerPublicParams
|
||||
) throws -> CallLinkAuthCredential {
|
||||
return try withAllBorrowed(self, userId, params) { contents, userId, params in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_call_link_auth_credential_response_receive($0, contents, userId, UInt64(redemptionTime.timeIntervalSince1970), params)
|
||||
signal_call_link_auth_credential_response_receive(
|
||||
$0,
|
||||
contents,
|
||||
userId,
|
||||
UInt64(redemptionTime.timeIntervalSince1970),
|
||||
params
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,25 @@ public class ClientZkAuthOperations {
|
||||
/// Produces the `AuthCredentialWithPni` from a server-generated `AuthCredentialWithPniResponse`.
|
||||
///
|
||||
/// - parameter redemptionTime: This is provided by the server as an integer, and should be passed through directly.
|
||||
public func receiveAuthCredentialWithPniAsServiceId(aci: Aci, pni: Pni, redemptionTime: UInt64, authCredentialResponse: AuthCredentialWithPniResponse) throws -> AuthCredentialWithPni {
|
||||
public func receiveAuthCredentialWithPniAsServiceId(
|
||||
aci: Aci,
|
||||
pni: Pni,
|
||||
redemptionTime: UInt64,
|
||||
authCredentialResponse: AuthCredentialWithPniResponse
|
||||
) throws -> AuthCredentialWithPni {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try aci.withPointerToFixedWidthBinary { aci in
|
||||
try pni.withPointerToFixedWidthBinary { pni in
|
||||
try authCredentialResponse.withUnsafeBorrowedBuffer { authCredentialResponse in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_server_public_params_receive_auth_credential_with_pni_as_service_id($0, serverPublicParams.const(), aci, pni, redemptionTime, authCredentialResponse)
|
||||
signal_server_public_params_receive_auth_credential_with_pni_as_service_id(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
aci,
|
||||
pni,
|
||||
redemptionTime,
|
||||
authCredentialResponse
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,17 +42,34 @@ public class ClientZkAuthOperations {
|
||||
}
|
||||
}
|
||||
|
||||
public func createAuthCredentialPresentation(groupSecretParams: GroupSecretParams, authCredential: AuthCredentialWithPni) throws -> AuthCredentialPresentation {
|
||||
return try self.createAuthCredentialPresentation(randomness: Randomness.generate(), groupSecretParams: groupSecretParams, authCredential: authCredential)
|
||||
public func createAuthCredentialPresentation(
|
||||
groupSecretParams: GroupSecretParams,
|
||||
authCredential: AuthCredentialWithPni
|
||||
) throws -> AuthCredentialPresentation {
|
||||
return try self.createAuthCredentialPresentation(
|
||||
randomness: Randomness.generate(),
|
||||
groupSecretParams: groupSecretParams,
|
||||
authCredential: authCredential
|
||||
)
|
||||
}
|
||||
|
||||
public func createAuthCredentialPresentation(randomness: Randomness, groupSecretParams: GroupSecretParams, authCredential: AuthCredentialWithPni) throws -> AuthCredentialPresentation {
|
||||
public func createAuthCredentialPresentation(
|
||||
randomness: Randomness,
|
||||
groupSecretParams: GroupSecretParams,
|
||||
authCredential: AuthCredentialWithPni
|
||||
) throws -> AuthCredentialPresentation {
|
||||
return try self.serverPublicParams.withNativeHandle { contents in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try groupSecretParams.withUnsafePointerToSerialized { groupSecretParams in
|
||||
try authCredential.withUnsafeBorrowedBuffer { authCredential in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_server_public_params_create_auth_credential_with_pni_presentation_deterministic($0, contents.const(), randomness, groupSecretParams, authCredential)
|
||||
signal_server_public_params_create_auth_credential_with_pni_presentation_deterministic(
|
||||
$0,
|
||||
contents.const(),
|
||||
randomness,
|
||||
groupSecretParams,
|
||||
authCredential
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,12 @@ public class ClientZkGroupCipher {
|
||||
try profileKeyCiphertext.withUnsafePointerToSerialized { profileKeyCiphertext in
|
||||
try userId.withPointerToFixedWidthBinary { userId in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_group_secret_params_decrypt_profile_key($0, groupSecretParams, profileKeyCiphertext, userId)
|
||||
signal_group_secret_params_decrypt_profile_key(
|
||||
$0,
|
||||
groupSecretParams,
|
||||
profileKeyCiphertext,
|
||||
userId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +71,13 @@ public class ClientZkGroupCipher {
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try plaintext.withUnsafeBorrowedBuffer { plaintext in
|
||||
try invokeFnReturningData {
|
||||
signal_group_secret_params_encrypt_blob_with_padding_deterministic($0, groupSecretParams, randomness, plaintext, 0)
|
||||
signal_group_secret_params_encrypt_blob_with_padding_deterministic(
|
||||
$0,
|
||||
groupSecretParams,
|
||||
randomness,
|
||||
plaintext,
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,34 @@ public class ClientZkProfileOperations {
|
||||
self.serverPublicParams = serverPublicParams
|
||||
}
|
||||
|
||||
public func createProfileKeyCredentialRequestContext(userId: Aci, profileKey: ProfileKey) throws -> ProfileKeyCredentialRequestContext {
|
||||
return try self.createProfileKeyCredentialRequestContext(randomness: Randomness.generate(), userId: userId, profileKey: profileKey)
|
||||
public func createProfileKeyCredentialRequestContext(
|
||||
userId: Aci,
|
||||
profileKey: ProfileKey
|
||||
) throws -> ProfileKeyCredentialRequestContext {
|
||||
return try self.createProfileKeyCredentialRequestContext(
|
||||
randomness: Randomness.generate(),
|
||||
userId: userId,
|
||||
profileKey: profileKey
|
||||
)
|
||||
}
|
||||
|
||||
public func createProfileKeyCredentialRequestContext(randomness: Randomness, userId: Aci, profileKey: ProfileKey) throws -> ProfileKeyCredentialRequestContext {
|
||||
public func createProfileKeyCredentialRequestContext(
|
||||
randomness: Randomness,
|
||||
userId: Aci,
|
||||
profileKey: ProfileKey
|
||||
) throws -> ProfileKeyCredentialRequestContext {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try userId.withPointerToFixedWidthBinary { userId in
|
||||
try profileKey.withUnsafePointerToSerialized { profileKey in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_public_params_create_profile_key_credential_request_context_deterministic($0, serverPublicParams.const(), randomness, userId, profileKey)
|
||||
signal_server_public_params_create_profile_key_credential_request_context_deterministic(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
randomness,
|
||||
userId,
|
||||
profileKey
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,24 +57,47 @@ public class ClientZkProfileOperations {
|
||||
try profileKeyCredentialRequestContext.withUnsafePointerToSerialized { requestContext in
|
||||
try profileKeyCredentialResponse.withUnsafePointerToSerialized { response in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_public_params_receive_expiring_profile_key_credential($0, serverPublicParams.const(), requestContext, response, UInt64(now.timeIntervalSince1970))
|
||||
signal_server_public_params_receive_expiring_profile_key_credential(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
requestContext,
|
||||
response,
|
||||
UInt64(now.timeIntervalSince1970)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func createProfileKeyCredentialPresentation(groupSecretParams: GroupSecretParams, profileKeyCredential: ExpiringProfileKeyCredential) throws -> ProfileKeyCredentialPresentation {
|
||||
return try self.createProfileKeyCredentialPresentation(randomness: Randomness.generate(), groupSecretParams: groupSecretParams, profileKeyCredential: profileKeyCredential)
|
||||
public func createProfileKeyCredentialPresentation(
|
||||
groupSecretParams: GroupSecretParams,
|
||||
profileKeyCredential: ExpiringProfileKeyCredential
|
||||
) throws -> ProfileKeyCredentialPresentation {
|
||||
return try self.createProfileKeyCredentialPresentation(
|
||||
randomness: Randomness.generate(),
|
||||
groupSecretParams: groupSecretParams,
|
||||
profileKeyCredential: profileKeyCredential
|
||||
)
|
||||
}
|
||||
|
||||
public func createProfileKeyCredentialPresentation(randomness: Randomness, groupSecretParams: GroupSecretParams, profileKeyCredential: ExpiringProfileKeyCredential) throws -> ProfileKeyCredentialPresentation {
|
||||
public func createProfileKeyCredentialPresentation(
|
||||
randomness: Randomness,
|
||||
groupSecretParams: GroupSecretParams,
|
||||
profileKeyCredential: ExpiringProfileKeyCredential
|
||||
) throws -> ProfileKeyCredentialPresentation {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try groupSecretParams.withUnsafePointerToSerialized { groupSecretParams in
|
||||
try profileKeyCredential.withUnsafePointerToSerialized { profileKeyCredential in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_server_public_params_create_expiring_profile_key_credential_presentation_deterministic($0, serverPublicParams.const(), randomness, groupSecretParams, profileKeyCredential)
|
||||
signal_server_public_params_create_expiring_profile_key_credential_presentation_deterministic(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
randomness,
|
||||
groupSecretParams,
|
||||
profileKeyCredential
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,44 +13,78 @@ public class ClientZkReceiptOperations {
|
||||
self.serverPublicParams = serverPublicParams
|
||||
}
|
||||
|
||||
public func createReceiptCredentialRequestContext(receiptSerial: ReceiptSerial) throws -> ReceiptCredentialRequestContext {
|
||||
return try self.createReceiptCredentialRequestContext(randomness: Randomness.generate(), receiptSerial: receiptSerial)
|
||||
public func createReceiptCredentialRequestContext(
|
||||
receiptSerial: ReceiptSerial
|
||||
) throws -> ReceiptCredentialRequestContext {
|
||||
return try self.createReceiptCredentialRequestContext(
|
||||
randomness: Randomness.generate(),
|
||||
receiptSerial: receiptSerial
|
||||
)
|
||||
}
|
||||
|
||||
public func createReceiptCredentialRequestContext(randomness: Randomness, receiptSerial: ReceiptSerial) throws -> ReceiptCredentialRequestContext {
|
||||
public func createReceiptCredentialRequestContext(
|
||||
randomness: Randomness,
|
||||
receiptSerial: ReceiptSerial
|
||||
) throws -> ReceiptCredentialRequestContext {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try receiptSerial.withUnsafePointerToSerialized { receiptSerial in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_public_params_create_receipt_credential_request_context_deterministic($0, serverPublicParams.const(), randomness, receiptSerial)
|
||||
signal_server_public_params_create_receipt_credential_request_context_deterministic(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
randomness,
|
||||
receiptSerial
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func receiveReceiptCredential(receiptCredentialRequestContext: ReceiptCredentialRequestContext, receiptCredentialResponse: ReceiptCredentialResponse) throws -> ReceiptCredential {
|
||||
public func receiveReceiptCredential(
|
||||
receiptCredentialRequestContext: ReceiptCredentialRequestContext,
|
||||
receiptCredentialResponse: ReceiptCredentialResponse
|
||||
) throws -> ReceiptCredential {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try receiptCredentialRequestContext.withUnsafePointerToSerialized { requestContext in
|
||||
try receiptCredentialResponse.withUnsafePointerToSerialized { response in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_public_params_receive_receipt_credential($0, serverPublicParams.const(), requestContext, response)
|
||||
signal_server_public_params_receive_receipt_credential(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
requestContext,
|
||||
response
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func createReceiptCredentialPresentation(receiptCredential: ReceiptCredential) throws -> ReceiptCredentialPresentation {
|
||||
return try self.createReceiptCredentialPresentation(randomness: Randomness.generate(), receiptCredential: receiptCredential)
|
||||
public func createReceiptCredentialPresentation(
|
||||
receiptCredential: ReceiptCredential
|
||||
) throws -> ReceiptCredentialPresentation {
|
||||
return try self.createReceiptCredentialPresentation(
|
||||
randomness: Randomness.generate(),
|
||||
receiptCredential: receiptCredential
|
||||
)
|
||||
}
|
||||
|
||||
public func createReceiptCredentialPresentation(randomness: Randomness, receiptCredential: ReceiptCredential) throws -> ReceiptCredentialPresentation {
|
||||
public func createReceiptCredentialPresentation(
|
||||
randomness: Randomness,
|
||||
receiptCredential: ReceiptCredential
|
||||
) throws -> ReceiptCredentialPresentation {
|
||||
return try self.serverPublicParams.withNativeHandle { serverPublicParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try receiptCredential.withUnsafePointerToSerialized { receiptCredential in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_public_params_create_receipt_credential_presentation_deterministic($0, serverPublicParams.const(), randomness, receiptCredential)
|
||||
signal_server_public_params_create_receipt_credential_presentation_deterministic(
|
||||
$0,
|
||||
serverPublicParams.const(),
|
||||
randomness,
|
||||
receiptCredential
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,30 @@ public class CreateCallLinkCredential: ByteArray, @unchecked Sendable {
|
||||
try super.init(contents, checkValid: signal_create_call_link_credential_check_valid_contents)
|
||||
}
|
||||
|
||||
public func present<RoomId: ContiguousBytes>(roomId: RoomId, userId: Aci, serverParams: GenericServerPublicParams, callLinkParams: CallLinkSecretParams) -> CreateCallLinkCredentialPresentation {
|
||||
public func present<RoomId: ContiguousBytes>(
|
||||
roomId: RoomId,
|
||||
userId: Aci,
|
||||
serverParams: GenericServerPublicParams,
|
||||
callLinkParams: CallLinkSecretParams
|
||||
) -> CreateCallLinkCredentialPresentation {
|
||||
return failOnError {
|
||||
self.present(roomId: roomId, userId: userId, serverParams: serverParams, callLinkParams: callLinkParams, randomness: try .generate())
|
||||
self.present(
|
||||
roomId: roomId,
|
||||
userId: userId,
|
||||
serverParams: serverParams,
|
||||
callLinkParams: callLinkParams,
|
||||
randomness: try .generate()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func present<RoomId: ContiguousBytes>(roomId: RoomId, userId: Aci, serverParams: GenericServerPublicParams, callLinkParams: CallLinkSecretParams, randomness: Randomness) -> CreateCallLinkCredentialPresentation {
|
||||
public func present<RoomId: ContiguousBytes>(
|
||||
roomId: RoomId,
|
||||
userId: Aci,
|
||||
serverParams: GenericServerPublicParams,
|
||||
callLinkParams: CallLinkSecretParams,
|
||||
randomness: Randomness
|
||||
) -> CreateCallLinkCredentialPresentation {
|
||||
return failOnError {
|
||||
try withUnsafeBorrowedBuffer { contents in
|
||||
try roomId.withUnsafeBorrowedBuffer { roomId in
|
||||
@@ -26,7 +43,15 @@ public class CreateCallLinkCredential: ByteArray, @unchecked Sendable {
|
||||
try callLinkParams.withUnsafeBorrowedBuffer { callLinkParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_create_call_link_credential_present_deterministic($0, contents, roomId, userId, serverParams, callLinkParams, randomness)
|
||||
signal_create_call_link_credential_present_deterministic(
|
||||
$0,
|
||||
contents,
|
||||
roomId,
|
||||
userId,
|
||||
serverParams,
|
||||
callLinkParams,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,25 @@ public class CreateCallLinkCredentialPresentation: ByteArray, @unchecked Sendabl
|
||||
try super.init(contents, checkValid: signal_create_call_link_credential_presentation_check_valid_contents)
|
||||
}
|
||||
|
||||
public func verify<RoomId: ContiguousBytes>(roomId: RoomId, now: Date = Date(), serverParams: GenericServerSecretParams, callLinkParams: CallLinkPublicParams) throws {
|
||||
public func verify<RoomId: ContiguousBytes>(
|
||||
roomId: RoomId,
|
||||
now: Date = Date(),
|
||||
serverParams: GenericServerSecretParams,
|
||||
callLinkParams: CallLinkPublicParams
|
||||
) throws {
|
||||
try withUnsafeBorrowedBuffer { contents in
|
||||
try roomId.withUnsafeBorrowedBuffer { roomId in
|
||||
try serverParams.withUnsafeBorrowedBuffer { serverParams in
|
||||
try callLinkParams.withUnsafeBorrowedBuffer { callLinkParams in
|
||||
try checkError(signal_create_call_link_credential_presentation_verify(contents, roomId, UInt64(now.timeIntervalSince1970), serverParams, callLinkParams))
|
||||
try checkError(
|
||||
signal_create_call_link_credential_presentation_verify(
|
||||
contents,
|
||||
roomId,
|
||||
UInt64(now.timeIntervalSince1970),
|
||||
serverParams,
|
||||
callLinkParams
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,36 @@ public class CreateCallLinkCredentialRequest: ByteArray, @unchecked Sendable {
|
||||
try super.init(contents, checkValid: signal_create_call_link_credential_request_check_valid_contents)
|
||||
}
|
||||
|
||||
public func issueCredential(userId: Aci, timestamp: Date, params: GenericServerSecretParams) -> CreateCallLinkCredentialResponse {
|
||||
public func issueCredential(
|
||||
userId: Aci,
|
||||
timestamp: Date,
|
||||
params: GenericServerSecretParams
|
||||
) -> CreateCallLinkCredentialResponse {
|
||||
return failOnError {
|
||||
self.issueCredential(userId: userId, timestamp: timestamp, params: params, randomness: try .generate())
|
||||
}
|
||||
}
|
||||
|
||||
public func issueCredential(userId: Aci, timestamp: Date, params: GenericServerSecretParams, randomness: Randomness) -> CreateCallLinkCredentialResponse {
|
||||
public func issueCredential(
|
||||
userId: Aci,
|
||||
timestamp: Date,
|
||||
params: GenericServerSecretParams,
|
||||
randomness: Randomness
|
||||
) -> CreateCallLinkCredentialResponse {
|
||||
return failOnError {
|
||||
try withUnsafeBorrowedBuffer { contents in
|
||||
try userId.withPointerToFixedWidthBinary { userId in
|
||||
try params.withUnsafeBorrowedBuffer { params in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_create_call_link_credential_request_issue_deterministic($0, contents, userId, UInt64(timestamp.timeIntervalSince1970), params, randomness)
|
||||
signal_create_call_link_credential_request_issue_deterministic(
|
||||
$0,
|
||||
contents,
|
||||
userId,
|
||||
UInt64(timestamp.timeIntervalSince1970),
|
||||
params,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,13 +39,23 @@ public class CreateCallLinkCredentialRequestContext: ByteArray, @unchecked Senda
|
||||
}
|
||||
}
|
||||
|
||||
public func receive(_ response: CreateCallLinkCredentialResponse, userId: Aci, params: GenericServerPublicParams) throws -> CreateCallLinkCredential {
|
||||
public func receive(
|
||||
_ response: CreateCallLinkCredentialResponse,
|
||||
userId: Aci,
|
||||
params: GenericServerPublicParams
|
||||
) throws -> CreateCallLinkCredential {
|
||||
return try withUnsafeBorrowedBuffer { contents in
|
||||
try response.withUnsafeBorrowedBuffer { response in
|
||||
try userId.withPointerToFixedWidthBinary { userId in
|
||||
try params.withUnsafeBorrowedBuffer { params in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_create_call_link_credential_request_context_receive_response($0, contents, response, userId, params)
|
||||
signal_create_call_link_credential_request_context_receive_response(
|
||||
$0,
|
||||
contents,
|
||||
response,
|
||||
userId,
|
||||
params
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,11 @@ public class GroupSendDerivedKeyPair: ByteArray, @unchecked Sendable {
|
||||
return failOnError {
|
||||
try params.withNativeHandle { params in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_group_send_derived_key_pair_for_expiration($0, UInt64(expiration.timeIntervalSince1970), params.const())
|
||||
signal_group_send_derived_key_pair_for_expiration(
|
||||
$0,
|
||||
UInt64(expiration.timeIntervalSince1970),
|
||||
params.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,10 @@ public class GroupSendEndorsement: ByteArray, @unchecked Sendable {
|
||||
return slices.withUnsafeBufferPointer { slices in
|
||||
failOnError {
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_group_send_endorsement_combine($0, SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count))
|
||||
signal_group_send_endorsement_combine(
|
||||
$0,
|
||||
SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,12 @@ public class GroupSendEndorsementsResponse: ByteArray, @unchecked Sendable {
|
||||
try keyPair.withUnsafeBorrowedBuffer { keyPair in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_group_send_endorsements_response_issue_deterministic($0, concatenated, keyPair, randomness)
|
||||
signal_group_send_endorsements_response_issue_deterministic(
|
||||
$0,
|
||||
concatenated,
|
||||
keyPair,
|
||||
randomness
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +104,15 @@ public class GroupSendEndorsementsResponse: ByteArray, @unchecked Sendable {
|
||||
try groupParams.withUnsafePointerToSerialized { groupParams in
|
||||
try serverParams.withNativeHandle { serverParams in
|
||||
try invokeFnReturningBytestringArray {
|
||||
signal_group_send_endorsements_response_receive_and_combine_with_service_ids($0, response, groupMembers, localUser, UInt64(now.timeIntervalSince1970), groupParams, serverParams.const())
|
||||
signal_group_send_endorsements_response_receive_and_combine_with_service_ids(
|
||||
$0,
|
||||
response,
|
||||
groupMembers,
|
||||
localUser,
|
||||
UInt64(now.timeIntervalSince1970),
|
||||
groupParams,
|
||||
serverParams.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,7 +150,14 @@ public class GroupSendEndorsementsResponse: ByteArray, @unchecked Sendable {
|
||||
try localUser.withUnsafeBorrowedBuffer { localUser in
|
||||
try serverParams.withNativeHandle { serverParams in
|
||||
try invokeFnReturningBytestringArray {
|
||||
signal_group_send_endorsements_response_receive_and_combine_with_ciphertexts($0, response, groupMembers, localUser, UInt64(now.timeIntervalSince1970), serverParams.const())
|
||||
signal_group_send_endorsements_response_receive_and_combine_with_ciphertexts(
|
||||
$0,
|
||||
response,
|
||||
groupMembers,
|
||||
localUser,
|
||||
UInt64(now.timeIntervalSince1970),
|
||||
serverParams.const()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,18 @@ public struct Randomness: Sendable {
|
||||
}
|
||||
|
||||
static func generate() throws -> Randomness {
|
||||
var bytes: SignalRandomnessBytes = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
var bytes: SignalRandomnessBytes = (
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
)
|
||||
try withUnsafeMutableBytes(of: &bytes) {
|
||||
try fillRandom($0)
|
||||
}
|
||||
return Randomness(bytes)
|
||||
}
|
||||
|
||||
func withUnsafePointerToBytes<Result>(_ callback: (UnsafePointer<SignalRandomnessBytes>) throws -> Result) rethrows -> Result {
|
||||
func withUnsafePointerToBytes<Result>(
|
||||
_ callback: (UnsafePointer<SignalRandomnessBytes>) throws -> Result
|
||||
) rethrows -> Result {
|
||||
try withUnsafePointer(to: self.bytes, callback)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@ public class ServerPublicParams: NativeHandleOwner<SignalMutPointerServerPublicP
|
||||
try withNativeHandle { contents in
|
||||
try message.withUnsafeBorrowedBuffer { message in
|
||||
try notarySignature.withUnsafePointerToSerialized { notarySignature in
|
||||
try checkError(signal_server_public_params_verify_signature(contents.const(), message, notarySignature))
|
||||
try checkError(
|
||||
signal_server_public_params_verify_signature(contents.const(), message, notarySignature)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +56,9 @@ public class ServerPublicParams: NativeHandleOwner<SignalMutPointerServerPublicP
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerServerPublicParams>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerServerPublicParams>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_server_public_params_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,9 @@ public class ServerSecretParams: NativeHandleOwner<SignalMutPointerServerSecretP
|
||||
}
|
||||
}
|
||||
|
||||
override internal class func destroyNativeHandle(_ handle: NonNull<SignalMutPointerServerSecretParams>) -> SignalFfiErrorRef? {
|
||||
override internal class func destroyNativeHandle(
|
||||
_ handle: NonNull<SignalMutPointerServerSecretParams>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_server_secret_params_destroy(handle.pointer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,38 @@ public class ServerZkAuthOperations {
|
||||
self.serverSecretParams = serverSecretParams
|
||||
}
|
||||
|
||||
public func issueAuthCredentialWithPniZkc(aci: Aci, pni: Pni, redemptionTime: UInt64) throws -> AuthCredentialWithPniResponse {
|
||||
return try self.issueAuthCredentialWithPniZkc(randomness: Randomness.generate(), aci: aci, pni: pni, redemptionTime: redemptionTime)
|
||||
public func issueAuthCredentialWithPniZkc(
|
||||
aci: Aci,
|
||||
pni: Pni,
|
||||
redemptionTime: UInt64
|
||||
) throws -> AuthCredentialWithPniResponse {
|
||||
return try self.issueAuthCredentialWithPniZkc(
|
||||
randomness: Randomness.generate(),
|
||||
aci: aci,
|
||||
pni: pni,
|
||||
redemptionTime: redemptionTime
|
||||
)
|
||||
}
|
||||
|
||||
public func issueAuthCredentialWithPniZkc(randomness: Randomness, aci: Aci, pni: Pni, redemptionTime: UInt64) throws -> AuthCredentialWithPniResponse {
|
||||
public func issueAuthCredentialWithPniZkc(
|
||||
randomness: Randomness,
|
||||
aci: Aci,
|
||||
pni: Pni,
|
||||
redemptionTime: UInt64
|
||||
) throws -> AuthCredentialWithPniResponse {
|
||||
return try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try aci.withPointerToFixedWidthBinary { aci in
|
||||
try pni.withPointerToFixedWidthBinary { pni in
|
||||
try invokeFnReturningVariableLengthSerialized {
|
||||
signal_server_secret_params_issue_auth_credential_with_pni_zkc_deterministic($0, serverSecretParams.const(), randomness, aci, pni, redemptionTime)
|
||||
signal_server_secret_params_issue_auth_credential_with_pni_zkc_deterministic(
|
||||
$0,
|
||||
serverSecretParams.const(),
|
||||
randomness,
|
||||
aci,
|
||||
pni,
|
||||
redemptionTime
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,11 +52,22 @@ public class ServerZkAuthOperations {
|
||||
}
|
||||
}
|
||||
|
||||
public func verifyAuthCredentialPresentation(groupPublicParams: GroupPublicParams, authCredentialPresentation: AuthCredentialPresentation, now: Date = Date()) throws {
|
||||
public func verifyAuthCredentialPresentation(
|
||||
groupPublicParams: GroupPublicParams,
|
||||
authCredentialPresentation: AuthCredentialPresentation,
|
||||
now: Date = Date()
|
||||
) throws {
|
||||
try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try groupPublicParams.withUnsafePointerToSerialized { groupPublicParams in
|
||||
try authCredentialPresentation.withUnsafeBorrowedBuffer { authCredentialPresentation in
|
||||
try checkError(signal_server_secret_params_verify_auth_credential_presentation(serverSecretParams.const(), groupPublicParams, authCredentialPresentation, UInt64(now.timeIntervalSince1970)))
|
||||
try checkError(
|
||||
signal_server_secret_params_verify_auth_credential_presentation(
|
||||
serverSecretParams.const(),
|
||||
groupPublicParams,
|
||||
authCredentialPresentation,
|
||||
UInt64(now.timeIntervalSince1970)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,43 @@ public class ServerZkProfileOperations {
|
||||
self.serverSecretParams = serverSecretParams
|
||||
}
|
||||
|
||||
public func issueExpiringProfileKeyCredential(profileKeyCredentialRequest: ProfileKeyCredentialRequest, userId: Aci, profileKeyCommitment: ProfileKeyCommitment, expiration: UInt64) throws -> ExpiringProfileKeyCredentialResponse {
|
||||
return try self.issueExpiringProfileKeyCredential(randomness: Randomness.generate(), profileKeyCredentialRequest: profileKeyCredentialRequest, userId: userId, profileKeyCommitment: profileKeyCommitment, expiration: expiration)
|
||||
public func issueExpiringProfileKeyCredential(
|
||||
profileKeyCredentialRequest: ProfileKeyCredentialRequest,
|
||||
userId: Aci,
|
||||
profileKeyCommitment: ProfileKeyCommitment,
|
||||
expiration: UInt64
|
||||
) throws -> ExpiringProfileKeyCredentialResponse {
|
||||
return try self.issueExpiringProfileKeyCredential(
|
||||
randomness: Randomness.generate(),
|
||||
profileKeyCredentialRequest: profileKeyCredentialRequest,
|
||||
userId: userId,
|
||||
profileKeyCommitment: profileKeyCommitment,
|
||||
expiration: expiration
|
||||
)
|
||||
}
|
||||
|
||||
public func issueExpiringProfileKeyCredential(randomness: Randomness, profileKeyCredentialRequest: ProfileKeyCredentialRequest, userId: Aci, profileKeyCommitment: ProfileKeyCommitment, expiration: UInt64) throws -> ExpiringProfileKeyCredentialResponse {
|
||||
public func issueExpiringProfileKeyCredential(
|
||||
randomness: Randomness,
|
||||
profileKeyCredentialRequest: ProfileKeyCredentialRequest,
|
||||
userId: Aci,
|
||||
profileKeyCommitment: ProfileKeyCommitment,
|
||||
expiration: UInt64
|
||||
) throws -> ExpiringProfileKeyCredentialResponse {
|
||||
return try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try profileKeyCredentialRequest.withUnsafePointerToSerialized { request in
|
||||
try userId.withPointerToFixedWidthBinary { userId in
|
||||
try profileKeyCommitment.withUnsafePointerToSerialized { commitment in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_secret_params_issue_expiring_profile_key_credential_deterministic($0, serverSecretParams.const(), randomness, request, userId, commitment, expiration)
|
||||
signal_server_secret_params_issue_expiring_profile_key_credential_deterministic(
|
||||
$0,
|
||||
serverSecretParams.const(),
|
||||
randomness,
|
||||
request,
|
||||
userId,
|
||||
commitment,
|
||||
expiration
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +66,14 @@ public class ServerZkProfileOperations {
|
||||
try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try groupPublicParams.withUnsafePointerToSerialized { groupPublicParams in
|
||||
try profileKeyCredentialPresentation.withUnsafeBorrowedBuffer { presentation in
|
||||
try checkError(signal_server_secret_params_verify_profile_key_credential_presentation(serverSecretParams.const(), groupPublicParams, presentation, UInt64(now.timeIntervalSince1970)))
|
||||
try checkError(
|
||||
signal_server_secret_params_verify_profile_key_credential_presentation(
|
||||
serverSecretParams.const(),
|
||||
groupPublicParams,
|
||||
presentation,
|
||||
UInt64(now.timeIntervalSince1970)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,26 +13,53 @@ public class ServerZkReceiptOperations {
|
||||
self.serverSecretParams = serverSecretParams
|
||||
}
|
||||
|
||||
public func issueReceiptCredential(receiptCredentialRequest: ReceiptCredentialRequest, receiptExpirationTime: UInt64, receiptLevel: UInt64) throws -> ReceiptCredentialResponse {
|
||||
return try self.issueReceiptCredential(randomness: Randomness.generate(), receiptCredentialRequest: receiptCredentialRequest, receiptExpirationTime: receiptExpirationTime, receiptLevel: receiptLevel)
|
||||
public func issueReceiptCredential(
|
||||
receiptCredentialRequest: ReceiptCredentialRequest,
|
||||
receiptExpirationTime: UInt64,
|
||||
receiptLevel: UInt64
|
||||
) throws -> ReceiptCredentialResponse {
|
||||
return try self.issueReceiptCredential(
|
||||
randomness: Randomness.generate(),
|
||||
receiptCredentialRequest: receiptCredentialRequest,
|
||||
receiptExpirationTime: receiptExpirationTime,
|
||||
receiptLevel: receiptLevel
|
||||
)
|
||||
}
|
||||
|
||||
public func issueReceiptCredential(randomness: Randomness, receiptCredentialRequest: ReceiptCredentialRequest, receiptExpirationTime: UInt64, receiptLevel: UInt64) throws -> ReceiptCredentialResponse {
|
||||
public func issueReceiptCredential(
|
||||
randomness: Randomness,
|
||||
receiptCredentialRequest: ReceiptCredentialRequest,
|
||||
receiptExpirationTime: UInt64,
|
||||
receiptLevel: UInt64
|
||||
) throws -> ReceiptCredentialResponse {
|
||||
return try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try randomness.withUnsafePointerToBytes { randomness in
|
||||
try receiptCredentialRequest.withUnsafePointerToSerialized { receiptCredentialRequest in
|
||||
try invokeFnReturningSerialized {
|
||||
signal_server_secret_params_issue_receipt_credential_deterministic($0, serverSecretParams.const(), randomness, receiptCredentialRequest, receiptExpirationTime, receiptLevel)
|
||||
signal_server_secret_params_issue_receipt_credential_deterministic(
|
||||
$0,
|
||||
serverSecretParams.const(),
|
||||
randomness,
|
||||
receiptCredentialRequest,
|
||||
receiptExpirationTime,
|
||||
receiptLevel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func verifyReceiptCredentialPresentation(receiptCredentialPresentation: ReceiptCredentialPresentation) throws {
|
||||
public func verifyReceiptCredentialPresentation(receiptCredentialPresentation: ReceiptCredentialPresentation) throws
|
||||
{
|
||||
try self.serverSecretParams.withNativeHandle { serverSecretParams in
|
||||
try receiptCredentialPresentation.withUnsafePointerToSerialized { receiptCredentialPresentation in
|
||||
try checkError(signal_server_secret_params_verify_receipt_credential_presentation(serverSecretParams.const(), receiptCredentialPresentation))
|
||||
try checkError(
|
||||
signal_server_secret_params_verify_receipt_credential_presentation(
|
||||
serverSecretParams.const(),
|
||||
receiptCredentialPresentation
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ class AccountEntropyTests: TestCaseBase {
|
||||
for _ in 0..<numTestIterations {
|
||||
let pool = AccountEntropyPool.generate()
|
||||
|
||||
XCTAssertTrue(generatedEntropyPools.insert(pool).inserted, "Generated pool should be unique, got repeat: \(pool)")
|
||||
XCTAssertTrue(
|
||||
generatedEntropyPools.insert(pool).inserted,
|
||||
"Generated pool should be unique, got repeat: \(pool)"
|
||||
)
|
||||
XCTAssertEqual(pool.count, 64, "Pool \(pool) is not the right length")
|
||||
for c in pool {
|
||||
XCTAssertTrue(validCharacters.contains(c), "Generated pool \(pool) contains invalid character \(c)")
|
||||
|
||||
@@ -84,7 +84,9 @@ extension SignalFfi.SignalConstPointerTestingFutureCancellationCounter: LibSigna
|
||||
}
|
||||
}
|
||||
|
||||
private final class CancelCounter: NativeHandleOwner<SignalMutPointerTestingFutureCancellationCounter>, @unchecked Sendable {
|
||||
private final class CancelCounter: NativeHandleOwner<SignalMutPointerTestingFutureCancellationCounter>, @unchecked
|
||||
Sendable
|
||||
{
|
||||
public convenience init(initialValue: UInt8 = 0) {
|
||||
var out = SignalMutPointerTestingFutureCancellationCounter()
|
||||
failOnError {
|
||||
@@ -96,12 +98,19 @@ private final class CancelCounter: NativeHandleOwner<SignalMutPointerTestingFutu
|
||||
public func waitForCount(asyncContext: TokioAsyncContext, target: UInt8) async throws {
|
||||
let _: Bool = try await asyncContext.invokeAsyncFunction { promise, asyncContext in
|
||||
self.withNativeHandle {
|
||||
signal_testing_future_cancellation_counter_wait_for_count(promise, asyncContext.const(), $0.const(), target)
|
||||
signal_testing_future_cancellation_counter_wait_for_count(
|
||||
promise,
|
||||
asyncContext.const(),
|
||||
$0.const(),
|
||||
target
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override static func destroyNativeHandle(_ nativeHandle: NonNull<SignalMutPointerTestingFutureCancellationCounter>) -> SignalFfiErrorRef? {
|
||||
override static func destroyNativeHandle(
|
||||
_ nativeHandle: NonNull<SignalMutPointerTestingFutureCancellationCounter>
|
||||
) -> SignalFfiErrorRef? {
|
||||
signal_testing_future_cancellation_counter_destroy(nativeHandle.pointer)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +118,11 @@ private final class CancelCounter: NativeHandleOwner<SignalMutPointerTestingFutu
|
||||
final class AsyncTests: TestCaseBase {
|
||||
func testSuccess() async throws {
|
||||
let result: Int32 = try await invokeAsyncFunction {
|
||||
signal_testing_future_success($0, SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)), 21)
|
||||
signal_testing_future_success(
|
||||
$0,
|
||||
SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)),
|
||||
21
|
||||
)
|
||||
}
|
||||
XCTAssertEqual(42, result)
|
||||
}
|
||||
@@ -117,7 +130,11 @@ final class AsyncTests: TestCaseBase {
|
||||
func testFailure() async throws {
|
||||
do {
|
||||
let _: Int32 = try await invokeAsyncFunction {
|
||||
signal_testing_future_failure($0, SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)), 21)
|
||||
signal_testing_future_failure(
|
||||
$0,
|
||||
SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)),
|
||||
21
|
||||
)
|
||||
}
|
||||
XCTFail("should have failed")
|
||||
} catch SignalError.invalidArgument(_) {
|
||||
@@ -129,27 +146,37 @@ final class AsyncTests: TestCaseBase {
|
||||
do {
|
||||
let value = UInt8(44)
|
||||
let handle = try await invokeAsyncFunction {
|
||||
signal_testing_future_produces_pointer_type($0, SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)), value)
|
||||
signal_testing_future_produces_pointer_type(
|
||||
$0,
|
||||
SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)),
|
||||
value
|
||||
)
|
||||
}
|
||||
defer { signal_testing_handle_type_destroy(handle) }
|
||||
XCTAssertEqual(
|
||||
try invokeFnReturningInteger { result in
|
||||
signal_testing_testing_handle_type_get_value(result, handle.const())
|
||||
}, value
|
||||
},
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
do {
|
||||
let value = "into the future"
|
||||
let otherHandle = try await invokeAsyncFunction {
|
||||
signal_testing_future_produces_other_pointer_type($0, SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)), value)
|
||||
signal_testing_future_produces_other_pointer_type(
|
||||
$0,
|
||||
SignalConstPointerNonSuspendingBackgroundThreadRuntime(raw: OpaquePointer(bitPattern: -1)),
|
||||
value
|
||||
)
|
||||
}
|
||||
defer { signal_other_testing_handle_type_destroy(otherHandle) }
|
||||
|
||||
XCTAssertEqual(
|
||||
try invokeFnReturningString { result in
|
||||
signal_testing_other_testing_handle_type_get_value(result, otherHandle.const())
|
||||
}, value
|
||||
},
|
||||
value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,10 +188,15 @@ final class BridgingTests: XCTestCase {
|
||||
let result = try first.withUnsafeBytes { first in
|
||||
try empty.withUnsafeBytes { empty in
|
||||
try second.withUnsafeBytes { second in
|
||||
let slices = [SignalBorrowedBuffer(first), SignalBorrowedBuffer(empty), SignalBorrowedBuffer(second)]
|
||||
let slices = [
|
||||
SignalBorrowedBuffer(first), SignalBorrowedBuffer(empty), SignalBorrowedBuffer(second),
|
||||
]
|
||||
return try slices.withUnsafeBufferPointer { slices in
|
||||
try invokeFnReturningBytestringArray {
|
||||
signal_testing_process_bytestring_array($0, SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count))
|
||||
signal_testing_process_bytestring_array(
|
||||
$0,
|
||||
SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,7 +209,10 @@ final class BridgingTests: XCTestCase {
|
||||
let slices: [SignalBorrowedBuffer] = []
|
||||
let result = try slices.withUnsafeBufferPointer { slices in
|
||||
try invokeFnReturningBytestringArray {
|
||||
signal_testing_process_bytestring_array($0, SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count))
|
||||
signal_testing_process_bytestring_array(
|
||||
$0,
|
||||
SignalBorrowedSliceOfBuffers(base: slices.baseAddress, length: slices.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
XCTAssertEqual(result, [])
|
||||
@@ -223,13 +231,16 @@ final class BridgingTests: XCTestCase {
|
||||
signal_testing_bridged_string_map_dump_to_json($0, map.const())
|
||||
}
|
||||
}
|
||||
XCTAssertEqual(dumped, """
|
||||
XCTAssertEqual(
|
||||
dumped,
|
||||
"""
|
||||
{
|
||||
"a": "aaa",
|
||||
"b": "bbb",
|
||||
"c": "ccc"
|
||||
}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testReturnOptionalUuid() throws {
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@testable import LibSignalClient
|
||||
import SignalFfi
|
||||
import XCTest
|
||||
|
||||
@testable import LibSignalClient
|
||||
|
||||
extension ConnectionManager {
|
||||
func assertIsUsingProxyIs(_ value: Int32) {
|
||||
// The testing native function used to implement this isn't available on device
|
||||
// builds to save on code size. If it's present use it, otherwise this is a no-op.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
// The testing native function used to implement this isn't available on device
|
||||
// builds to save on code size. If it's present use it, otherwise this is a no-op.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
let isUsingProxy =
|
||||
withNativeHandle { handle in
|
||||
failOnError {
|
||||
@@ -22,15 +23,15 @@ extension ConnectionManager {
|
||||
}
|
||||
}
|
||||
XCTAssertEqual(isUsingProxy, value)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatServiceTests: TestCaseBase {
|
||||
private static let userAgent = "test"
|
||||
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
|
||||
private static let expectedStatus: UInt16 = 200
|
||||
private static let expectedMessage = "OK"
|
||||
@@ -127,27 +128,45 @@ final class ChatServiceTests: TestCaseBase {
|
||||
let expectedMethod = "GET"
|
||||
let expectedPathAndQuery = "/test"
|
||||
|
||||
let request = ChatConnection.Request(method: expectedMethod, pathAndQuery: expectedPathAndQuery, headers: Self.expectedHeaders, body: Self.expectedContent, timeout: 5)
|
||||
let request = ChatConnection.Request(
|
||||
method: expectedMethod,
|
||||
pathAndQuery: expectedPathAndQuery,
|
||||
headers: Self.expectedHeaders,
|
||||
body: Self.expectedContent,
|
||||
timeout: 5
|
||||
)
|
||||
let internalRequest = try ChatConnection.Request.InternalRequest(request)
|
||||
try internalRequest.withNativeHandle { internalRequest in
|
||||
XCTAssertEqual(expectedMethod, try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_method($0, internalRequest.const())
|
||||
})
|
||||
XCTAssertEqual(expectedPathAndQuery, try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_path($0, internalRequest.const())
|
||||
})
|
||||
XCTAssertEqual(Self.expectedContent, try invokeFnReturningData {
|
||||
signal_testing_chat_request_get_body($0, internalRequest.const())
|
||||
})
|
||||
XCTAssertEqual(
|
||||
expectedMethod,
|
||||
try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_method($0, internalRequest.const())
|
||||
}
|
||||
)
|
||||
XCTAssertEqual(
|
||||
expectedPathAndQuery,
|
||||
try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_path($0, internalRequest.const())
|
||||
}
|
||||
)
|
||||
XCTAssertEqual(
|
||||
Self.expectedContent,
|
||||
try invokeFnReturningData {
|
||||
signal_testing_chat_request_get_body($0, internalRequest.const())
|
||||
}
|
||||
)
|
||||
for (k, v) in Self.expectedHeaders {
|
||||
XCTAssertEqual(v, try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_header_value($0, internalRequest.const(), k)
|
||||
})
|
||||
XCTAssertEqual(
|
||||
v,
|
||||
try invokeFnReturningString {
|
||||
signal_testing_chat_request_get_header_value($0, internalRequest.const(), k)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
func testInvalidProxyRejected() {
|
||||
let net = Net(env: .production, userAgent: Self.userAgent)
|
||||
@@ -182,8 +201,8 @@ final class ChatServiceTests: TestCaseBase {
|
||||
final class ChatConnectionTests: TestCaseBase {
|
||||
private static let userAgent = "test"
|
||||
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
func testListenerCallbacks() async throws {
|
||||
class Listener: ChatConnectionListener {
|
||||
let queueEmpty: XCTestExpectation
|
||||
@@ -193,7 +212,10 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
let connectionInterrupted: XCTestExpectation
|
||||
|
||||
var expectations: [XCTestExpectation] {
|
||||
[self.alertsReceived, self.firstMessageReceived, self.secondMessageReceived, self.queueEmpty, self.connectionInterrupted]
|
||||
[
|
||||
self.alertsReceived, self.firstMessageReceived, self.secondMessageReceived, self.queueEmpty,
|
||||
self.connectionInterrupted,
|
||||
]
|
||||
}
|
||||
|
||||
init(
|
||||
@@ -210,7 +232,12 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
self.connectionInterrupted = connectionInterrupted
|
||||
}
|
||||
|
||||
func chatConnection(_: AuthenticatedChatConnection, didReceiveIncomingMessage envelope: Data, serverDeliveryTimestamp: UInt64, sendAck: () throws -> Void) {
|
||||
func chatConnection(
|
||||
_: AuthenticatedChatConnection,
|
||||
didReceiveIncomingMessage envelope: Data,
|
||||
serverDeliveryTimestamp: UInt64,
|
||||
sendAck: () throws -> Void
|
||||
) {
|
||||
// This assumes a little-endian platform.
|
||||
XCTAssertEqual(envelope, withUnsafeBytes(of: serverDeliveryTimestamp) { Data($0) })
|
||||
switch serverDeliveryTimestamp {
|
||||
@@ -263,13 +290,17 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
// 3: {1000i64}
|
||||
// 5: {"x-signal-timestamp:1000"}
|
||||
// 4: 1
|
||||
fakeRemote.injectServerRequest(base64: "CgNQVVQSDy9hcGkvdjEvbWVzc2FnZRoI6AMAAAAAAAAqF3gtc2lnbmFsLXRpbWVzdGFtcDoxMDAwIAE=")
|
||||
fakeRemote.injectServerRequest(
|
||||
base64: "CgNQVVQSDy9hcGkvdjEvbWVzc2FnZRoI6AMAAAAAAAAqF3gtc2lnbmFsLXRpbWVzdGFtcDoxMDAwIAE="
|
||||
)
|
||||
// 1: {"PUT"}
|
||||
// 2: {"/api/v1/message"}
|
||||
// 3: {2000i64}
|
||||
// 5: {"x-signal-timestamp:2000"}
|
||||
// 4: 2
|
||||
fakeRemote.injectServerRequest(base64: "CgNQVVQSDy9hcGkvdjEvbWVzc2FnZRoI0AcAAAAAAAAqF3gtc2lnbmFsLXRpbWVzdGFtcDoyMDAwIAI=")
|
||||
fakeRemote.injectServerRequest(
|
||||
base64: "CgNQVVQSDy9hcGkvdjEvbWVzc2FnZRoI0AcAAAAAAAAqF3gtc2lnbmFsLXRpbWVzdGFtcDoyMDAwIAI="
|
||||
)
|
||||
|
||||
// Sending an invalid message should not affect the listener at all, nor should it stop future requests.
|
||||
// 1: {"PUT"}
|
||||
@@ -289,15 +320,29 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
|
||||
func testAuthenticatedSending() async throws {
|
||||
class NoOpListener: ChatConnectionListener {
|
||||
func chatConnection(_: AuthenticatedChatConnection, didReceiveIncomingMessage envelope: Data, serverDeliveryTimestamp: UInt64, sendAck: () throws -> Void) {}
|
||||
func chatConnection(
|
||||
_: AuthenticatedChatConnection,
|
||||
didReceiveIncomingMessage envelope: Data,
|
||||
serverDeliveryTimestamp: UInt64,
|
||||
sendAck: () throws -> Void
|
||||
) {}
|
||||
|
||||
func connectionWasInterrupted(_: AuthenticatedChatConnection, error: Error?) {}
|
||||
}
|
||||
let tokioAsyncContext = TokioAsyncContext()
|
||||
let (chat, fakeRemote) = AuthenticatedChatConnection.fakeConnect(tokioAsyncContext: tokioAsyncContext, listener: NoOpListener())
|
||||
let (chat, fakeRemote) = AuthenticatedChatConnection.fakeConnect(
|
||||
tokioAsyncContext: tokioAsyncContext,
|
||||
listener: NoOpListener()
|
||||
)
|
||||
defer { withExtendedLifetime(chat) {} }
|
||||
|
||||
let request = ChatRequest(method: "PUT", pathAndQuery: "/some/path", headers: ["purpose": "test request"], body: Data([1, 1, 2, 3]), timeout: TimeInterval(5))
|
||||
let request = ChatRequest(
|
||||
method: "PUT",
|
||||
pathAndQuery: "/some/path",
|
||||
headers: ["purpose": "test request"],
|
||||
body: Data([1, 1, 2, 3]),
|
||||
timeout: TimeInterval(5)
|
||||
)
|
||||
async let responseFuture = chat.send(request)
|
||||
|
||||
let (requestFromServer, id) = try await fakeRemote.getNextIncomingRequest()
|
||||
@@ -326,10 +371,19 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
func connectionWasInterrupted(_: UnauthenticatedChatConnection, error: Error?) {}
|
||||
}
|
||||
let tokioAsyncContext = TokioAsyncContext()
|
||||
let (chat, fakeRemote) = UnauthenticatedChatConnection.fakeConnect(tokioAsyncContext: tokioAsyncContext, listener: NoOpListener())
|
||||
let (chat, fakeRemote) = UnauthenticatedChatConnection.fakeConnect(
|
||||
tokioAsyncContext: tokioAsyncContext,
|
||||
listener: NoOpListener()
|
||||
)
|
||||
defer { withExtendedLifetime(chat) {} }
|
||||
|
||||
let request = ChatRequest(method: "PUT", pathAndQuery: "/some/path", headers: ["purpose": "test request"], body: Data([1, 1, 2, 3]), timeout: TimeInterval(5))
|
||||
let request = ChatRequest(
|
||||
method: "PUT",
|
||||
pathAndQuery: "/some/path",
|
||||
headers: ["purpose": "test request"],
|
||||
body: Data([1, 1, 2, 3]),
|
||||
timeout: TimeInterval(5)
|
||||
)
|
||||
async let responseFuture = chat.send(request)
|
||||
|
||||
let (requestFromServer, id) = try await fakeRemote.getNextIncomingRequest()
|
||||
@@ -352,7 +406,7 @@ final class ChatConnectionTests: TestCaseBase {
|
||||
XCTAssertEqual(responseFromServer.headers, ["purpose": "test response"])
|
||||
XCTAssertEqual(responseFromServer.body, Data([5]))
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
func testListenerCleanup() async throws {
|
||||
// Use the presence of the environment setting to know whether we should make network requests in our tests.
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
@testable import LibSignalClient
|
||||
import XCTest
|
||||
|
||||
@testable import LibSignalClient
|
||||
|
||||
private struct FakeHandle {
|
||||
// We're using the tuple to guarantee in-memory layout for this test.
|
||||
// It's a little sketchy but it keeps the test from getting more complicated.
|
||||
@@ -14,7 +15,10 @@ private struct FakeHandle {
|
||||
}
|
||||
|
||||
private class MockClonableHandleOwner: ClonableHandleOwner<OpaquePointer?> {
|
||||
override class func cloneNativeHandle(_ newHandle: inout OpaquePointer?, currentHandle: OpaquePointer?) -> SignalFfiErrorRef? {
|
||||
override class func cloneNativeHandle(
|
||||
_ newHandle: inout OpaquePointer?,
|
||||
currentHandle: OpaquePointer?
|
||||
) -> SignalFfiErrorRef? {
|
||||
XCTAssertFalse(UnsafePointer<Bool>(currentHandle!).pointee)
|
||||
newHandle = OpaquePointer(UnsafePointer<Bool>(currentHandle!) + 1)
|
||||
return nil
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,14 +10,18 @@ class HsmEnclaveTests: TestCaseBase {
|
||||
func testCreateClient() {
|
||||
let validKey = IdentityKeyPair.generate().publicKey
|
||||
var hashes = HsmCodeHashList()
|
||||
try! hashes.append(Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]))
|
||||
try! hashes.append(Data([
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
]))
|
||||
try! hashes.append(
|
||||
Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
])
|
||||
)
|
||||
try! hashes.append(
|
||||
Data([
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
])
|
||||
)
|
||||
let hsmEnclaveClient = try! HsmEnclaveClient(publicKey: validKey.keyBytes, codeHashes: hashes)
|
||||
let initialMessage = hsmEnclaveClient.initialRequest()
|
||||
XCTAssertEqual(112, initialMessage.count)
|
||||
@@ -32,10 +36,12 @@ class HsmEnclaveTests: TestCaseBase {
|
||||
func testCompleteHandshakeWithoutInitialRequest() {
|
||||
let validKey = IdentityKeyPair.generate().publicKey
|
||||
var hashes = HsmCodeHashList()
|
||||
try! hashes.append(Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]))
|
||||
try! hashes.append(
|
||||
Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
])
|
||||
)
|
||||
let hsmEnclaveClient = try! HsmEnclaveClient(publicKey: validKey.keyBytes, codeHashes: hashes)
|
||||
let handshakeResponse: [UInt8] = [0x01, 0x02, 0x03]
|
||||
XCTAssertThrowsError(try hsmEnclaveClient.completeHandshake(handshakeResponse))
|
||||
@@ -44,10 +50,12 @@ class HsmEnclaveTests: TestCaseBase {
|
||||
func testEstablishedSendFailsPriorToEstablishment() {
|
||||
let validKey = IdentityKeyPair.generate().publicKey
|
||||
var hashes = HsmCodeHashList()
|
||||
try! hashes.append(Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]))
|
||||
try! hashes.append(
|
||||
Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
])
|
||||
)
|
||||
let hsmEnclaveClient = try! HsmEnclaveClient(publicKey: validKey.keyBytes, codeHashes: hashes)
|
||||
let plaintextToSend: [UInt8] = [0x01, 0x02, 0x03]
|
||||
XCTAssertThrowsError(try hsmEnclaveClient.establishedSend(plaintextToSend))
|
||||
@@ -56,10 +64,12 @@ class HsmEnclaveTests: TestCaseBase {
|
||||
func testEstablishedRecvFailsPriorToEstablishment() {
|
||||
let validKey = IdentityKeyPair.generate().publicKey
|
||||
var hashes = HsmCodeHashList()
|
||||
try! hashes.append(Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]))
|
||||
try! hashes.append(
|
||||
Data([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
])
|
||||
)
|
||||
let hsmEnclaveClient = try! HsmEnclaveClient(publicKey: validKey.keyBytes, codeHashes: hashes)
|
||||
let receivedCiphertext: [UInt8] = [0x01, 0x02, 0x03]
|
||||
XCTAssertThrowsError(try hsmEnclaveClient.establishedRecv(receivedCiphertext))
|
||||
|
||||
@@ -16,14 +16,17 @@ class InMemorySignalProtocolStoreTests: TestCaseBase {
|
||||
|
||||
let firstIdentity = IdentityKeyPair.generate().identityKey
|
||||
XCTAssert(
|
||||
try store.isTrustedIdentity(firstIdentity, for: address, direction: .sending, context: context))
|
||||
try store.isTrustedIdentity(firstIdentity, for: address, direction: .sending, context: context)
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
try store.saveIdentity(firstIdentity, for: address, context: context), .newOrUnchanged
|
||||
try store.saveIdentity(firstIdentity, for: address, context: context),
|
||||
.newOrUnchanged
|
||||
)
|
||||
// Idempotent
|
||||
XCTAssertEqual(
|
||||
try store.saveIdentity(firstIdentity, for: address, context: context), .newOrUnchanged
|
||||
try store.saveIdentity(firstIdentity, for: address, context: context),
|
||||
.newOrUnchanged
|
||||
)
|
||||
XCTAssert(try store.isTrustedIdentity(firstIdentity, for: address, direction: .sending, context: context))
|
||||
XCTAssertEqual(try store.identity(for: address, context: context), firstIdentity)
|
||||
@@ -31,7 +34,8 @@ class InMemorySignalProtocolStoreTests: TestCaseBase {
|
||||
let secondIdentity = IdentityKeyPair.generate().identityKey
|
||||
|
||||
XCTAssertFalse(
|
||||
try store.isTrustedIdentity(secondIdentity, for: address, direction: .sending, context: context))
|
||||
try store.isTrustedIdentity(secondIdentity, for: address, direction: .sending, context: context)
|
||||
)
|
||||
XCTAssertEqual(
|
||||
try store.saveIdentity(secondIdentity, for: address, context: context),
|
||||
.replacedExisting
|
||||
@@ -43,7 +47,8 @@ class InMemorySignalProtocolStoreTests: TestCaseBase {
|
||||
)
|
||||
|
||||
XCTAssert(
|
||||
try store.isTrustedIdentity(secondIdentity, for: address, direction: .sending, context: context))
|
||||
try store.isTrustedIdentity(secondIdentity, for: address, direction: .sending, context: context)
|
||||
)
|
||||
XCTAssertEqual(try store.identity(for: address, context: context), secondIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import XCTest
|
||||
class IncrementalMacTests: TestCaseBase {
|
||||
private let TEST_KEY = Data(base64Encoded: "qDSBRX7+zGmtE0LiHZwCl/cd679ckwS0wbLkM8Gnj5g=")!
|
||||
private let TEST_INPUT = ["this is a test", " input to the incremental ", "mac stream"].map { Data($0.utf8) }
|
||||
private let TEST_DIGEST = Data(base64Encoded: "hIkvcGAOVJ+3KHlmep2WonPxRLaY/571p2BipWBhqQmIT22fQpGKnkdu1RjErI9xS9M/BFFSrgSYd/09Gw2yWg==")!
|
||||
private let TEST_DIGEST = Data(
|
||||
base64Encoded: "hIkvcGAOVJ+3KHlmep2WonPxRLaY/571p2BipWBhqQmIT22fQpGKnkdu1RjErI9xS9M/BFFSrgSYd/09Gw2yWg=="
|
||||
)!
|
||||
private let CHUNK_SIZE = SizeChoice.bytes(32)
|
||||
|
||||
func testIncrementalDigestCreation() throws {
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
@testable import LibSignalClient
|
||||
@testable import SignalFfi
|
||||
import XCTest
|
||||
|
||||
@testable import LibSignalClient
|
||||
@testable import SignalFfi
|
||||
|
||||
class IoTests: TestCaseBase {
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
// These testing endpoints aren't generated in device builds, to save on code size.
|
||||
#if !os(iOS) || targetEnvironment(simulator)
|
||||
func testReadIntoEmptyBuffer() throws {
|
||||
let input = Data("ABCDEFGHIJKLMNOPQRSTUVWXYZ".utf8)
|
||||
let inputStream = SignalInputStreamAdapter(input)
|
||||
@@ -20,5 +21,5 @@ class IoTests: TestCaseBase {
|
||||
}
|
||||
XCTAssertEqual(input, output)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user