6 #include "SOSAccountPriv.h"
7 #include <SecureObjectSync/SOSTransport.h>
8 #include <SecureObjectSync/SOSTransportKeyParameterKVS.h>
9 #include <SecureObjectSync/SOSTransportCircleKVS.h>
10 #include <SecureObjectSync/SOSTransportMessageKVS.h>
12 void SOSAccountForEachCircle(SOSAccountRef account
, void (^process
)(SOSCircleRef circle
))
14 CFDictionaryForEach(account
->circles
, ^(const void* key
, const void* value
) {
16 process((SOSCircleRef
)value
);
21 void SOSAccountForEachKnownCircle(SOSAccountRef account
,
22 void (^handle_incompatible
)(CFStringRef name
),
23 void (^handle_no_peer
)(SOSCircleRef circle
),
24 void (^handle_peer
)(SOSCircleRef circle
, SOSFullPeerInfoRef full_peer
)) {
25 CFDictionaryForEach(account
->circles
, ^(const void *key
, const void *value
) {
27 if (handle_incompatible
)
28 handle_incompatible((CFStringRef
)key
);
30 SOSCircleRef circle
= (SOSCircleRef
) value
;
32 SOSFullPeerInfoRef fpi
= SOSAccountGetMyFullPeerInCircleNamedIfPresent(account
, SOSCircleGetName(circle
), NULL
);
35 handle_no_peer(circle
);
39 handle_peer(circle
, fpi
);
42 CFReleaseSafe(circle
);
48 // MARK: Circle management
51 int SOSAccountCountCircles(SOSAccountRef a
) {
53 assert(a
->circle_identities
);
55 return (int)CFDictionaryGetCount(a
->circles
);
60 SOSCircleRef
SOSAccountFindCircle(SOSAccountRef a
, CFStringRef name
, CFErrorRef
*error
)
62 CFTypeRef entry
= CFDictionaryGetValue(a
->circles
, name
);
64 require_action_quiet(!isNull(entry
), fail
,
65 SOSCreateError(kSOSErrorIncompatibleCircle
, CFSTR("Incompatible circle in KVS"), NULL
, error
));
67 require_action_quiet(entry
, fail
,
68 SOSCreateError(kSOSErrorNoCircle
, CFSTR("No circle found"), NULL
, error
));
71 return (SOSCircleRef
) entry
;
78 static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account
, CFStringRef circleName
, CFErrorRef
*error
){
80 SOSTransportKeyParameterRef tKey
= NULL
;
81 SOSTransportCircleRef tCircle
= NULL
;
82 SOSTransportMessageRef tMessage
= NULL
;
83 SOSFullPeerInfoRef fpi
= SOSAccountGetMyFullPeerInCircleNamed(account
, circleName
, error
);
84 require_quiet(fpi
, fail
);
85 SOSPeerInfoRef myPeer
= SOSFullPeerInfoGetPeerInfo(fpi
);
86 require_quiet(myPeer
, fail
);
87 CFStringRef type
= SOSPeerInfoGetTransportType(myPeer
);
88 if(CFStringCompare(type
, CFSTR("KVS"), 0) == kCFCompareEqualTo
){
89 tKey
= (SOSTransportKeyParameterRef
)SOSTransportKeyParameterKVSCreate(account
, error
);
90 tCircle
= (SOSTransportCircleRef
)SOSTransportCircleKVSCreate(account
, circleName
, error
);
91 tMessage
= (SOSTransportMessageRef
)SOSTransportMessageKVSCreate(account
, circleName
, error
);
92 require_quiet(tKey
, fail
);
93 require_quiet(tCircle
, fail
);
94 require_quiet(tMessage
, fail
);
96 CFRetainAssign(account
->key_transport
, (SOSTransportKeyParameterRef
)tKey
);
97 CFDictionarySetValue(account
->circle_transports
, circleName
, tCircle
);
98 CFDictionarySetValue(account
->message_transports
, circleName
, tMessage
);
104 CFReleaseNull(tCircle
);
105 CFReleaseNull(tMessage
);
109 SOSCircleRef
SOSAccountEnsureCircle(SOSAccountRef a
, CFStringRef name
, CFErrorRef
*error
)
111 CFErrorRef localError
= NULL
;
113 SOSCircleRef circle
= SOSAccountFindCircle(a
, name
, &localError
);
115 require_action_quiet(circle
|| !isSOSErrorCoded(localError
, kSOSErrorIncompatibleCircle
), fail
,
116 if (error
) { *error
= localError
; localError
= NULL
; });
119 circle
= SOSCircleCreate(NULL
, name
, NULL
);
121 CFDictionaryAddValue(a
->circles
, name
, circle
);
123 circle
= SOSAccountFindCircle(a
, name
, &localError
);
126 SOSUpdateKeyInterest();
129 require_quiet(SOSAccountInflateTransportsForCircle(a
, name
, error
), fail
);
132 CFReleaseNull(localError
);
137 bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account
, SOSCircleRef newCircle
, CFErrorRef
*error
)
139 return SOSAccountHandleUpdateCircle(account
, newCircle
, false, error
);
142 bool SOSAccountUpdateCircle(SOSAccountRef account
, SOSCircleRef newCircle
, CFErrorRef
*error
)
144 return SOSAccountHandleUpdateCircle(account
, newCircle
, true, error
);
147 bool SOSAccountModifyCircle(SOSAccountRef account
,
148 CFStringRef circleName
,
150 bool (^action
)(SOSCircleRef circle
))
152 bool success
= false;
154 SOSCircleRef circle
= NULL
;
155 SOSCircleRef accountCircle
= SOSAccountFindCircle(account
, circleName
, error
);
156 require_quiet(accountCircle
, fail
);
158 circle
= SOSCircleCopyCircle(kCFAllocatorDefault
, accountCircle
, error
);
159 require_quiet(circle
, fail
);
162 require_quiet(action(circle
), fail
);
164 success
= SOSAccountUpdateCircle(account
, circle
, error
);
167 CFReleaseSafe(circle
);