Browse Source

Add missing dependency & fix various errors

voice-calls
Niels Andriesse 10 months ago
parent
commit
6b8b934556
  1. 1
      Podfile
  2. 6
      Podfile.lock
  3. 18
      Session.xcodeproj/project.pbxproj
  4. 5
      Session/Calls/CallService.swift
  5. 319
      SessionUtilitiesKit/General/Atomics.swift
  6. 43
      SessionUtilitiesKit/General/UnfairLock.h
  7. 46
      SessionUtilitiesKit/General/UnfairLock.m
  8. 51
      SessionUtilitiesKit/General/UnfairLock.swift
  9. 1
      SessionUtilitiesKit/Meta/SessionUtilitiesKit.h

1
Podfile

@ -12,6 +12,7 @@ target 'Session' do
pod 'PureLayout', '~> 3.1.8', :inhibit_warnings => true
pod 'Reachability', :inhibit_warnings => true
pod 'Sodium', '~> 0.8.0', :inhibit_warnings => true
pod 'WebRTC', '~> 63.11', :inhibit_warnings => true
pod 'YapDatabase/SQLCipher', :git => 'https://github.com/loki-project/session-ios-yap-database.git', branch: 'signal-release', :inhibit_warnings => true
pod 'YYImage', git: 'https://github.com/signalapp/YYImage', :inhibit_warnings => true
pod 'ZXingObjC', :inhibit_warnings => true

6
Podfile.lock

@ -51,6 +51,7 @@ PODS:
- SQLCipher/standard (4.4.0):
- SQLCipher/common
- SwiftProtobuf (1.5.0)
- WebRTC (63.11.20455)
- YapDatabase/SQLCipher (3.1.1):
- YapDatabase/SQLCipher/Core (= 3.1.1)
- YapDatabase/SQLCipher/Extensions (= 3.1.1)
@ -135,6 +136,7 @@ DEPENDENCIES:
- SignalCoreKit (from `https://github.com/signalapp/SignalCoreKit.git`)
- Sodium (~> 0.8.0)
- SwiftProtobuf (~> 1.5.0)
- WebRTC (~> 63.11)
- YapDatabase/SQLCipher (from `https://github.com/loki-project/session-ios-yap-database.git`, branch `signal-release`)
- YYImage (from `https://github.com/signalapp/YYImage`)
- ZXingObjC
@ -154,6 +156,7 @@ SPEC REPOS:
- Sodium
- SQLCipher
- SwiftProtobuf
- WebRTC
- ZXingObjC
EXTERNAL SOURCES:
@ -204,10 +207,11 @@ SPEC CHECKSUMS:
Sodium: 63c0ca312a932e6da481689537d4b35568841bdc
SQLCipher: e434ed542b24f38ea7b36468a13f9765e1b5c072
SwiftProtobuf: 241400280f912735c1e1b9fe675fdd2c6c4d42e2
WebRTC: f2a6203584745fe53532633397557876b5d71640
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
YYImage: 6db68da66f20d9f169ceb94dfb9947c3867b9665
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: 50e6a35c838ba28d2ee02bc6018fdd297c04e55f
PODFILE CHECKSUM: 70c56fb65241e2064eb7999b6647a36be5031fe3
COCOAPODS: 1.10.1

18
Session.xcodeproj/project.pbxproj

@ -233,6 +233,10 @@
B882A79526AE878300B5AB69 /* IndividualCallService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77526AE878300B5AB69 /* IndividualCallService.swift */; };
B882A79626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift */; };
B882A79726AE878300B5AB69 /* IndividualCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77726AE878300B5AB69 /* IndividualCall.swift */; };
B882A79926AE897E00B5AB69 /* Atomics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A79826AE897E00B5AB69 /* Atomics.swift */; };
B882A79C26AE89F200B5AB69 /* UnfairLock.m in Sources */ = {isa = PBXBuildFile; fileRef = B882A79B26AE89F200B5AB69 /* UnfairLock.m */; };
B882A79D26AE8A1700B5AB69 /* UnfairLock.h in Headers */ = {isa = PBXBuildFile; fileRef = B882A79A26AE89E300B5AB69 /* UnfairLock.h */; settings = {ATTRIBUTES = (Public, ); }; };
B882A79F26AE8A2200B5AB69 /* UnfairLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A79E26AE8A2200B5AB69 /* UnfairLock.swift */; };
B8856CA8256F0F42001CE70E /* OWSBackupFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB07255A580700E217F9 /* OWSBackupFragment.m */; };
B8856CB1256F0F47001CE70E /* OWSBackupFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAEA255A580500E217F9 /* OWSBackupFragment.h */; settings = {ATTRIBUTES = (Public, ); }; };
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2F7255B6DBC007E1867 /* OWSAudioPlayer.m */; };
@ -1252,6 +1256,10 @@
B882A77526AE878300B5AB69 /* IndividualCallService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCallService.swift; sourceTree = "<group>"; };
B882A77626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutboundIndividualCallInitiator.swift; sourceTree = "<group>"; };
B882A77726AE878300B5AB69 /* IndividualCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCall.swift; sourceTree = "<group>"; };
B882A79826AE897E00B5AB69 /* Atomics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomics.swift; sourceTree = "<group>"; };
B882A79A26AE89E300B5AB69 /* UnfairLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnfairLock.h; sourceTree = "<group>"; };
B882A79B26AE89F200B5AB69 /* UnfairLock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnfairLock.m; sourceTree = "<group>"; };
B882A79E26AE8A2200B5AB69 /* UnfairLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnfairLock.swift; sourceTree = "<group>"; };
B8856D5F256F129B001CE70E /* OWSAlerts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAlerts.swift; sourceTree = "<group>"; };
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = "<group>"; };
B886B4A62398B23E00211ABE /* QRCodeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeVC.swift; sourceTree = "<group>"; };
@ -2409,6 +2417,7 @@
C33FDB8A255A581200E217F9 /* AppContext.h */,
C33FDB85255A581100E217F9 /* AppContext.m */,
C3C2A5D12553860800C340D1 /* Array+Description.swift */,
B882A79826AE897E00B5AB69 /* Atomics.swift */,
C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */,
B8F5F58225EC94A6003BF8D4 /* Collection+Subscripting.swift */,
B8AE75A325A6C6A6001A84D2 /* Data+Trimming.swift */,
@ -2433,6 +2442,9 @@
C33FDB14255A580800E217F9 /* OWSMath.h */,
C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */,
C33FDB3F255A580C00E217F9 /* String+SSK.swift */,
B882A79A26AE89E300B5AB69 /* UnfairLock.h */,
B882A79B26AE89F200B5AB69 /* UnfairLock.m */,
B882A79E26AE8A2200B5AB69 /* UnfairLock.swift */,
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
C38EF237255B6D65007E1867 /* UIDevice+featureSupport.swift */,
C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */,
@ -3785,6 +3797,7 @@
C352A3772557864000338F3E /* NSTimer+Proxying.h in Headers */,
C32C5B51256DC219003C73A2 /* NSNotificationCenter+OWS.h in Headers */,
C3C2A67D255388CC00C340D1 /* SessionUtilitiesKit.h in Headers */,
B882A79D26AE8A1700B5AB69 /* UnfairLock.h in Headers */,
C32C6018256E07F9003C73A2 /* NSUserDefaults+OWS.h in Headers */,
B8856D8D256F1502001CE70E /* UIView+OWS.h in Headers */,
);
@ -4361,6 +4374,7 @@
"${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework",
"${BUILT_PRODUCTS_DIR}/SQLCipher/SQLCipher.framework",
"${BUILT_PRODUCTS_DIR}/Sodium/Sodium.framework",
"${PODS_ROOT}/WebRTC/WebRTC.framework",
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
"${BUILT_PRODUCTS_DIR}/ZXingObjC/ZXingObjC.framework",
@ -4383,6 +4397,7 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SQLCipher.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sodium.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZXingObjC.framework",
@ -4720,6 +4735,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B882A79926AE897E00B5AB69 /* Atomics.swift in Sources */,
C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */,
C32C5A47256DB8F0003C73A2 /* ECKeyPair+Hexadecimal.swift in Sources */,
C3D9E41525676C320040E4F3 /* Storage.swift in Sources */,
@ -4737,6 +4753,7 @@
C32C5DD2256DD9E5003C73A2 /* LRUCache.swift in Sources */,
C3A7211A2558BCA10043A11F /* DiffieHellman.swift in Sources */,
C32C5FA1256DFED5003C73A2 /* NSArray+Functional.m in Sources */,
B882A79F26AE8A2200B5AB69 /* UnfairLock.swift in Sources */,
C3A7225E2558C38D0043A11F /* Promise+Retaining.swift in Sources */,
C3D9E4D12567777D0040E4F3 /* OWSMediaUtils.swift in Sources */,
C3BBE0AA2554D4DE0050F1E3 /* Dictionary+Description.swift in Sources */,
@ -4764,6 +4781,7 @@
C3D9E4F4256778AF0040E4F3 /* NSData+Image.m in Sources */,
C32C5E0C256DDAFA003C73A2 /* NSRegularExpression+SSK.swift in Sources */,
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,
B882A79C26AE89F200B5AB69 /* UnfairLock.m in Sources */,
B8856D23256F116B001CE70E /* Weak.swift in Sources */,
C32C5A48256DB8F0003C73A2 /* BuildConfiguration.swift in Sources */,
B87EF18126377A1D00124B3C /* Features.swift in Sources */,

5
Session/Calls/CallService.swift

@ -5,6 +5,7 @@
import Foundation
import SignalRingRTC
import PromiseKit
import SessionUtilitiesKit
// All Observer methods will be invoked from the main thread.
@objc(OWSCallServiceObserver)
@ -45,12 +46,12 @@ public final class CallService: NSObject {
// Prevent device from sleeping while we have an active call.
if oldValue != newValue {
if let oldValue = oldValue {
DeviceSleepManager.shared.removeBlock(blockObject: oldValue)
DeviceSleepManager.sharedInstance.removeBlock(blockObject: oldValue)
}
if let newValue = newValue {
assert(calls.contains(newValue))
DeviceSleepManager.shared.addBlock(blockObject: newValue)
DeviceSleepManager.sharedInstance.addBlock(blockObject: newValue)
if newValue.isIndividualCall { individualCallService.startCallTimer() }
} else {

319
SessionUtilitiesKit/General/Atomics.swift

@ -0,0 +1,319 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public enum AtomicError: Int, Error {
case invalidTransition
}
// MARK: -
private class Atomics {
fileprivate static let fairQueue = DispatchQueue(label: "Atomics")
fileprivate static let unfairLock = UnfairLock()
// Never instantiate this class.
private init() {}
class func perform<T>(isFair: Bool = false, _ block: () throws -> T) rethrows -> T {
if isFair {
return try fairQueue.sync(execute: block)
} else {
return try unfairLock.withLock(block)
}
}
}
// MARK: -
// Provides Objective-C compatibility for the most common atomic value type.
@objc
public class AtomicBool: NSObject {
private let value = AtomicValue<Bool>(false)
@objc(initWithValue:)
public required init(_ value: Bool) {
self.value.set(value)
}
@objc
public func get() -> Bool {
return value.get()
}
@objc
public func set(_ value: Bool) {
self.value.set(value)
}
// Sets value to "toValue" IFF it currently has "fromValue",
// otherwise throws.
private func transition(from fromValue: Bool, to toValue: Bool) throws {
return try value.transition(from: fromValue, to: toValue)
}
@objc
public func tryToSetFlag() -> Bool {
do {
try transition(from: false, to: true)
return true
} catch {
return false
}
}
@objc
public func tryToClearFlag() -> Bool {
do {
try transition(from: true, to: false)
return true
} catch {
return false
}
}
}
// MARK: -
@objc
public class AtomicUInt: NSObject {
private let value = AtomicValue<UInt>(0)
@objc
public required init(_ value: UInt = 0) {
self.value.set(value)
}
@objc
public func get() -> UInt {
return value.get()
}
@objc
public func set(_ value: UInt) {
self.value.set(value)
}
@discardableResult
@objc
public func increment() -> UInt {
return value.map { $0 + 1 }
}
@discardableResult
@objc
public func decrementOrZero() -> UInt {
return value.map { max($0, 1) - 1 }
}
@discardableResult
@objc
public func add(_ delta: UInt) -> UInt {
return value.map { $0 + delta }
}
}
// MARK: -
public final class AtomicValue<T> {
private var value: T
public required convenience init(_ value: T) {
self.init(value, allowOptionalType: false)
}
fileprivate init(_ value: T, allowOptionalType: Bool) {
self.value = value
}
public func get() -> T {
Atomics.perform {
return self.value
}
}
public func set(_ value: T) {
Atomics.perform {
self.value = value
}
}
// Transform the current value using a block.
@discardableResult
public func map(_ block: @escaping (T) -> T) -> T {
Atomics.perform {
let newValue = block(self.value)
self.value = newValue
return newValue
}
}
}
// MARK: -
extension AtomicValue: Codable where T: Codable {
public convenience init(from decoder: Decoder) throws {
let singleValueContainer = try decoder.singleValueContainer()
self.init(try singleValueContainer.decode(T.self))
}
public func encode(to encoder: Encoder) throws {
var singleValueContainer = encoder.singleValueContainer()
try singleValueContainer.encode(value)
}
}
// MARK: -
extension AtomicValue where T: Equatable {
// Sets value to "toValue" IFF it currently has "fromValue",
// otherwise throws.
public func transition(from fromValue: T, to toValue: T) throws {
try Atomics.perform {
guard self.value == fromValue else {
throw AtomicError.invalidTransition
}
self.value = toValue
}
}
}
// MARK: -
public final class AtomicOptional<T> {
fileprivate let value = AtomicValue<T?>(nil, allowOptionalType: true)
public required init(_ value: T?) {
self.value.set(value)
}
public func get() -> T? {
return value.get()
}
public func set(_ value: T?) {
self.value.set(value)
}
}
extension AtomicOptional: Codable where T: Codable {
public convenience init(from decoder: Decoder) throws {
let singleValueContainer = try decoder.singleValueContainer()
if singleValueContainer.decodeNil() {
self.init(nil)
} else {
self.init(try singleValueContainer.decode(T.self))
}
}
public func encode(to encoder: Encoder) throws {
var singleValueContainer = encoder.singleValueContainer()
try singleValueContainer.encode(value)
}
}
extension AtomicOptional where T: Equatable {
// Sets value to "toValue" IFF it currently has "fromValue",
// otherwise throws.
public func transition(from fromValue: T, to toValue: T) throws {
try value.transition(from: fromValue, to: toValue)
}
}
// MARK: -
public class AtomicArray<T> {
private var values: [T]
public required init(_ values: [T] = []) {
self.values = values
}
public func get() -> [T] {
Atomics.perform {
values
}
}
public func set(_ values: [T]) {
Atomics.perform {
self.values = values
}
}
public func append(_ value: T) {
Atomics.perform {
values.append(value)
}
}
public var first: T? {
Atomics.perform {
values.first
}
}
public var popHead: T? {
Atomics.perform {
values.removeFirst()
}
}
public func pushTail(_ value: T) {
append(value)
}
}
extension AtomicArray where T: Equatable {
public func remove(_ valueToRemove: T) {
Atomics.perform {
self.values = self.values.filter { (value: T) -> Bool in
valueToRemove != value
}
}
}
}
// MARK: -
public class AtomicDictionary<Key: Hashable, Value> {
private var values: [Key: Value]
public required init(_ values: [Key: Value] = [:]) {
self.values = values
}
public subscript(_ key: Key) -> Value? {
set { Atomics.perform { self.values[key] = newValue } }
get { Atomics.perform { self.values[key] } }
}
public func get() -> [Key: Value] {
Atomics.perform { self.values }
}
public func set(_ values: [Key: Value]) {
Atomics.perform { self.values = values }
}
}
// MARK: -
public class AtomicSet<T: Hashable> {
private var values = Set<T>()
public required init() {}
public func insert(_ value: T) {
Atomics.perform { _ = self.values.insert(value) }
}
public func contains(_ value: T) -> Bool {
Atomics.perform { self.values.contains(value) }
}
}

43
SessionUtilitiesKit/General/UnfairLock.h

@ -0,0 +1,43 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// An Objective-C wrapper around os_unfair_lock. This is a non-FIFO, priority preserving lock. See: os/lock.h
///
/// @discussion Why is this necessary? os_unfair_lock has some unexpected behavior in Swift. These problems arise
/// from Swift's handling of inout C structs. Passing the underlying struct as an inout parameter results in
/// surprising Law of Exclusivity violations. There are two ways to work around this: Manually allocate heap storage
/// in Swift or bridge to Objective-C. I figured bridging a simple struct is a bit easier to read.
///
/// Note: Errors with unfair lock are fatal and will terminate the process.
NS_SWIFT_NAME(UnfairLock)
@interface UnfairLock : NSObject <NSLocking>
/// Locks the lock. Blocks if the lock is held by another thread.
/// Forwards to os_unfair_lock_lock() defined in os/lock.h
- (void)lock;
/// Unlocks the lock. Fatal error if the lock is owned by another thread.
/// Forwards to os_unfair_lock_unlock() defined in os/lock.h
- (void)unlock;
/// Attempts to lock the lock. Returns YES if the lock was successfully acquired.
/// Forwards to os_unfair_lock_trylock() defined in os/lock.h
- (BOOL)tryLock NS_SWIFT_NAME(tryLock());
// Note: NS_SWIFT_NAME is required to prevent bridging from renaming to `try()`.
/// Fatal assert that the lock is owned by the current thread.
/// Forwards to os_unfair_lock_assert_owner defined in os/lock.h
- (void)assertOwner;
/// Fatal assert that the lock is not owned by the current thread.
/// Forwards to os_unfair_lock_assert_not_owner defined in os/lock.h
- (void)assertNotOwner;
@end
NS_ASSUME_NONNULL_END

46
SessionUtilitiesKit/General/UnfairLock.m

@ -0,0 +1,46 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import <SessionUtilitiesKit/UnfairLock.h>
#import <os/lock.h>
@implementation UnfairLock {
os_unfair_lock _lock;
}
- (instancetype)init
{
self = [super init];
if (self) {
_lock = OS_UNFAIR_LOCK_INIT;
}
return self;
}
- (void)lock
{
os_unfair_lock_lock(&_lock);
}
- (void)unlock
{
os_unfair_lock_unlock(&_lock);
}
- (BOOL)tryLock
{
return os_unfair_lock_trylock(&_lock);
}
- (void)assertOwner
{
os_unfair_lock_assert_owner(&_lock);
}
- (void)assertNotOwner
{
os_unfair_lock_assert_not_owner(&_lock);
}
@end

51
SessionUtilitiesKit/General/UnfairLock.swift

@ -0,0 +1,51 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
import Foundation
public extension UnfairLock {
/// Acquires and releases the lock around the provided closure. Blocks the current thread until the lock can be
/// acquired.
@objc
@available(swift, obsoleted: 1.0)
final func withLockObjc(_ criticalSection: () -> Void) {
withLock(criticalSection)
}
/// Acquires and releases the lock around the provided closure. Blocks the current thread until the lock can be
/// acquired.
final func withLock<T>(_ criticalSection: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try criticalSection()
}
/// Acquires and releases the lock around the provided closure. Returns without performing the closure if the lock
/// can not be acquired.
/// - Returns: `true` if the lock was acquired and the closure was invoked. `false` if the lock could not be
/// acquired.
@discardableResult
final func tryWithLock(_ criticalSection: () throws -> Void) rethrows -> Bool {
guard tryLock() else { return false }
defer { unlock() }
try criticalSection()
return true
}
/// Acquires and releases the lock around the provided closure. Returns without performing the closure if the lock
/// can not be acquired.
/// - Returns: nil if the lock could not be acquired. Otherwise, returns the returns the result of the provided
/// closure
@discardableResult
final func tryWithLock<T>(_ criticalSection: () throws -> T) rethrows -> T? {
guard tryLock() else { return nil }
defer { unlock() }
return try criticalSection()
}
}

1
SessionUtilitiesKit/Meta/SessionUtilitiesKit.h

@ -18,6 +18,7 @@ FOUNDATION_EXPORT const unsigned char SessionUtilitiesKitVersionString[];
#import <SessionUtilitiesKit/OWSMath.h>
#import <SessionUtilitiesKit/TSRequest.h>
#import <SessionUtilitiesKit/TSYapDatabaseObject.h>
#import <SessionUtilitiesKit/UnfairLock.h>
#import <SessionUtilitiesKit/UIImage+OWS.h>
#import <SessionUtilitiesKit/UIView+OWS.h>

Loading…
Cancel
Save