1 #import "keychain/ckks/CKKSListenerCollection.h"
2 #import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h"
4 @interface CKKSMockSOSPresentAdapter()
5 @property CKKSListenerCollection* peerChangeListeners;
8 @implementation CKKSMockSOSPresentAdapter
9 @synthesize essential = _essential;
10 @synthesize sosEnabled = _sosEnabled;
12 - (instancetype)initWithSelfPeer:(CKKSSOSSelfPeer*)selfPeer
13 trustedPeers:(NSSet<CKKSSOSPeer*>*)trustedPeers
14 essential:(BOOL)essential
16 if((self = [super init])) {
18 _essential = essential;
20 _circleStatus = kSOSCCInCircle;
22 _excludeSelfPeerFromTrustSet = false;
24 _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-mock-sos"];
27 _trustedPeers = [trustedPeers mutableCopy];
32 - (NSString*)providerID
34 return [NSString stringWithFormat:@"[CKKSMockSOSPresentAdapter: %@]", self.selfPeer.peerID];
37 - (SOSCCStatus)circleStatus:(NSError * _Nullable __autoreleasing * _Nullable)error
39 if(!self.sosEnabled || self.circleStatus == kSOSCCError) {
40 if(error && self.circleStatus == kSOSCCError) {
41 *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil];
46 return self.circleStatus;
49 // I currently don't understand when SOS returns a self or not. I've seen it return a self while not in kSOSCCInCircle,
50 // which seems wrong. So, always return a self, unless we're in an obvious error state.
51 - (id<CKKSSelfPeer> _Nullable)currentSOSSelf:(NSError * _Nullable __autoreleasing * _Nullable)error
53 if(self.selfPeerError) {
55 *error = self.selfPeerError;
60 if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) {
64 *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil];
70 - (CKKSSelves * _Nullable)fetchSelfPeers:(NSError *__autoreleasing _Nullable * _Nullable)error
72 id<CKKSSelfPeer> peer = [self currentSOSSelf:error];
77 return [[CKKSSelves alloc] initWithCurrent:peer allSelves:nil];
80 - (NSSet<id<CKKSRemotePeerProtocol>> * _Nullable)fetchTrustedPeers:(NSError * _Nullable __autoreleasing * _Nullable)error
82 if(self.trustedPeersError) {
84 *error = self.trustedPeersError;
89 // TODO: I'm actually not entirely sure what SOS does if it's not in circle?
90 if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) {
91 if(self.excludeSelfPeerFromTrustSet) {
92 return self.trustedPeers;
94 return [self allPeers];
98 *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSCCNotInCircle userInfo:nil];
104 - (void)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
105 if(self.updateOctagonKeySetListener) {
106 self.updateOctagonKeySetListener(currentSelfPeer);
111 - (void)registerForPeerChangeUpdates:(nonnull id<CKKSPeerUpdateListener>)listener {
112 [self.peerChangeListeners registerListener:listener];
115 - (void)sendSelfPeerChangedUpdate {
116 [self.peerChangeListeners iterateListeners: ^(id<CKKSPeerUpdateListener> listener) {
117 [listener selfPeerChanged:self];
121 - (void)sendTrustedPeerSetChangedUpdate {
122 [self.peerChangeListeners iterateListeners: ^(id<CKKSPeerUpdateListener> listener) {
123 [listener trustedPeerSetChanged:self];
127 - (nonnull CKKSPeerProviderState *)currentState {
128 return [CKKSPeerProviderState createFromProvider:self];
131 - (NSSet<id<CKKSRemotePeerProtocol>>*)allPeers
133 // include the self peer, but as a CKKSSOSPeer object instead of a self peer
134 CKKSSOSPeer* s = [[CKKSSOSPeer alloc] initWithSOSPeerID:self.selfPeer.peerID
135 encryptionPublicKey:self.selfPeer.publicEncryptionKey
136 signingPublicKey:self.selfPeer.publicSigningKey
137 viewList:self.selfPeer.viewList];
139 return [self.trustedPeers setByAddingObject: s];