2 // SOSAccountTrustClassicRetirement.m
5 // Created by Michelle Auricchio on 12/27/16.
9 #import <Foundation/Foundation.h>
10 #import "Security/SecureObjectSync/SOSAccountTrustClassic.h"
11 #import "Security/SecureObjectSync/SOSAccountTrustClassic+Retirement.h"
12 #import "Security/SecureObjectSync/SOSPeerInfoCollections.h"
13 #import "Security/SecureObjectSync/SOSTransportMessageKVS.h"
15 @implementation SOSAccountTrustClassic (Retirement)
17 -(bool) cleanupRetirementTickets:(SOSAccount*)account circle:(SOSCircleRef)circle time:(size_t) seconds err:(CFErrorRef*) error
19 CFMutableSetRef retirees_to_remove = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault);
21 __block bool success = true;
23 CFSetForEach((__bridge CFSetRef)(self.retirees), ^(const void *value) {
24 SOSPeerInfoRef retiree = (SOSPeerInfoRef) value;
27 // Remove the entry if it's not a retired peer or if it's retirment ticket has expired AND he's no longer in the circle.
28 if (!SOSPeerInfoIsRetirementTicket(retiree) ||
29 (SOSPeerInfoRetireRetirementTicket(seconds, retiree) && !SOSCircleHasActivePeer(circle, retiree, NULL))) {
30 CFSetAddValue(retirees_to_remove, retiree);
35 CFMutableArrayRef retirees_to_cleanup = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
36 CFSetForEach(retirees_to_remove, ^(const void *value) {
37 CFArrayAppendValue(retirees_to_cleanup, value);
38 CFSetRemoveValue((__bridge CFMutableSetRef)self.retirees, value);
41 CFReleaseNull(retirees_to_remove);
43 CFDictionaryRef retirements_to_remove = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
44 SOSCircleGetName(circle), retirees_to_cleanup,
47 CFReleaseNull(retirees_to_cleanup);
49 success = [account.circle_transport expireRetirementRecords:retirements_to_remove err:error];
51 CFReleaseNull(retirements_to_remove);
56 static inline CFMutableArrayRef CFDictionaryEnsureCFArrayAndGetCurrentValue(CFMutableDictionaryRef dict, CFTypeRef key)
58 CFMutableArrayRef result = (CFMutableArrayRef) CFDictionaryGetValue(dict, key);
60 if (!isArray(result)) {
61 result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
62 CFDictionarySetValue(dict, key, result);
63 CFReleaseSafe(result);
70 -(bool) cleanupAfterPeer:(SOSMessageKVS*)kvsTransport circleTransport:(SOSCircleStorageTransport*)circleTransport seconds:(size_t) seconds circle:(SOSCircleRef) circle cleanupPeer:(SOSPeerInfoRef) cleanupPeer err:(CFErrorRef*) error
74 SOSPeerInfoRef myPeerInfo = self.peerInfo;
75 require_action_quiet(self.fullPeerInfo && myPeerInfo, xit, SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("I have no peer")));
76 require_quiet(SOSCircleHasActivePeer(circle, self.peerInfo, error), xit);
78 CFStringRef cleanupPeerID = SOSPeerInfoGetPeerID(cleanupPeer);
80 CFStringRef circle_name = SOSCircleGetName(circle);
82 CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
83 CFArrayAppendValue(CFDictionaryEnsureCFArrayAndGetCurrentValue(circleToPeerIDs, circle_name), cleanupPeerID);
85 CFErrorRef localError = NULL;
87 if (!(success &= [kvsTransport SOSTransportMessageCleanupAfterPeerMessages:kvsTransport peers:circleToPeerIDs err:&localError])) {
88 secnotice("account", "Failed to cleanup after peer %@ messages: %@", cleanupPeerID, localError);
91 CFReleaseNull(localError);
93 if((success &= SOSPeerInfoRetireRetirementTicket(seconds, cleanupPeer))) {
95 if (!(success &= [circleTransport expireRetirementRecords:circleToPeerIDs err:&localError])) {
96 secnotice("account", "Failed to cleanup after peer %@ retirement: %@", cleanupPeerID, localError);
99 CFReleaseNull(localError);
100 CFReleaseNull(circleToPeerIDs);