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
;
85 // Solve determining transport type without fullpeer
86 SOSFullPeerInfoRef fpi
= SOSAccountGetMyFullPeerInCircleNamed(account
, circleName
, error
);
87 require_quiet(fpi
, fail
);
88 SOSPeerInfoRef myPeer
= SOSFullPeerInfoGetPeerInfo(fpi
);
89 require_quiet(myPeer
, fail
);
90 CFStringRef type
= SOSPeerInfoGetTransportType(myPeer
);
91 if(CFStringCompare(type
, CFSTR("KVS"), 0) == kCFCompareEqualTo
){
93 tKey
= (SOSTransportKeyParameterRef
)SOSTransportKeyParameterKVSCreate(account
, error
);
94 tCircle
= (SOSTransportCircleRef
)SOSTransportCircleKVSCreate(account
, circleName
, error
);
95 tMessage
= (SOSTransportMessageRef
)SOSTransportMessageKVSCreate(account
, circleName
, error
);
96 require_quiet(tKey
, fail
);
97 require_quiet(tCircle
, fail
);
98 require_quiet(tMessage
, fail
);
100 CFRetainAssign(account
->key_transport
, (SOSTransportKeyParameterRef
)tKey
);
101 CFDictionarySetValue(account
->circle_transports
, circleName
, tCircle
);
102 CFDictionarySetValue(account
->message_transports
, circleName
, tMessage
);
110 CFReleaseNull(tCircle
);
111 CFReleaseNull(tMessage
);
115 SOSCircleRef
SOSAccountEnsureCircle(SOSAccountRef a
, CFStringRef name
, CFErrorRef
*error
)
117 CFErrorRef localError
= NULL
;
119 SOSCircleRef circle
= SOSAccountFindCircle(a
, name
, &localError
);
121 require_action_quiet(circle
|| !isSOSErrorCoded(localError
, kSOSErrorIncompatibleCircle
), fail
,
122 if (error
) { *error
= localError
; localError
= NULL
; });
125 circle
= SOSCircleCreate(NULL
, name
, NULL
);
127 CFDictionaryAddValue(a
->circles
, name
, circle
);
129 circle
= SOSAccountFindCircle(a
, name
, &localError
);
132 SOSUpdateKeyInterest();
135 require_quiet(SOSAccountInflateTransportsForCircle(a
, name
, error
), fail
);
138 CFReleaseNull(localError
);
143 bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account
, SOSCircleRef newCircle
, CFErrorRef
*error
)
145 return SOSAccountHandleUpdateCircle(account
, newCircle
, false, error
);
148 bool SOSAccountUpdateCircle(SOSAccountRef account
, SOSCircleRef newCircle
, CFErrorRef
*error
)
150 return SOSAccountHandleUpdateCircle(account
, newCircle
, true, error
);
153 bool SOSAccountModifyCircle(SOSAccountRef account
,
154 CFStringRef circleName
,
156 bool (^action
)(SOSCircleRef circle
))
158 bool success
= false;
160 SOSCircleRef circle
= NULL
;
161 SOSCircleRef accountCircle
= SOSAccountFindCircle(account
, circleName
, error
);
162 require_quiet(accountCircle
, fail
);
164 circle
= SOSCircleCopyCircle(kCFAllocatorDefault
, accountCircle
, error
);
165 require_quiet(circle
, fail
);
168 require_quiet(action(circle
), fail
);
170 success
= SOSAccountUpdateCircle(account
, circle
, error
);
173 CFReleaseSafe(circle
);