2 #include <Security/SecureObjectSync/SOSInternal.h>
3 #include <Security/SecureObjectSync/SOSKVSKeys.h>
4 #include <Security/SecureObjectSync/SOSAccountPriv.h>
5 #include <Security/SecureObjectSync/SOSTransport.h>
6 #include <Security/SecureObjectSync/SOSTransportKeyParameterKVS.h>
7 #include <Security/SecureObjectSync/SOSTransportCircleKVS.h>
8 #include <Security/SecureObjectSync/SOSTransportMessageKVS.h>
9 #include <Security/SecureObjectSync/SOSTransportMessageIDS.h>
10 #include <Security/SecureObjectSync/SOSTransportMessage.h>
11 #include <Security/SecureObjectSync/SOSRing.h>
13 #include <SOSCloudKeychainClient.h>
14 #include <utilities/debugging.h>
15 #include <utilities/SecCFWrappers.h>
16 #include <CoreFoundation/CFBase.h>
18 CFStringRef kKeyParameter
= CFSTR("KeyParameter");
19 CFStringRef kCircle
= CFSTR("Circle");
20 CFStringRef kMessage
= CFSTR("Message");
21 CFStringRef kAlwaysKeys
= CFSTR("AlwaysKeys");
22 CFStringRef kFirstUnlocked
= CFSTR("FirstUnlockKeys");
23 CFStringRef kUnlocked
= CFSTR("UnlockedKeys");
24 extern CFStringRef kSOSAccountDebugScope
;
26 #define DATE_LENGTH 18
28 CFStringRef
SOSInterestListCopyDescription(CFArrayRef interests
)
30 CFMutableStringRef description
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
31 CFStringAppendFormat(description
, NULL
, CFSTR("<Interest: "));
34 CFArrayForEach(interests
, ^(const void* string
) {
37 CFStringAppendFormat(description
, NULL
, CFSTR(" '%@'"), string
);
40 CFStringAppend(description
, CFSTR(">"));
47 // MARK: Key Interest Processing
50 CFGiblisGetSingleton(CFMutableArrayRef
, SOSGetTransportMessages
, sTransportMessages
, ^{
51 *sTransportMessages
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, NULL
);
54 CFGiblisGetSingleton(CFMutableArrayRef
, SOSGetTransportKeyParameters
, sTransportKeyParameters
, ^{
55 *sTransportKeyParameters
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, NULL
);
58 CFGiblisGetSingleton(CFMutableArrayRef
, SOSGetTransportCircles
, sTransportCircles
, ^{
59 *sTransportCircles
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, NULL
);
63 void SOSRegisterTransportMessage(SOSTransportMessageRef additional
) {
64 CFArrayAppendValue(SOSGetTransportMessages(), additional
);
67 void SOSUnregisterTransportMessage(SOSTransportMessageRef removal
) {
68 CFArrayRemoveAllValue(SOSGetTransportMessages(), removal
);
71 void SOSUnregisterAllTransportMessages() {
72 CFArrayRemoveAllValues(SOSGetTransportMessages());
75 void SOSRegisterTransportCircle(SOSTransportCircleRef additional
) {
76 CFArrayAppendValue(SOSGetTransportCircles(), additional
);
79 void SOSUnregisterTransportCircle(SOSTransportCircleRef removal
) {
80 CFArrayRemoveAllValue(SOSGetTransportCircles(), removal
);
83 void SOSUnregisterAllTransportCircles() {
84 CFArrayRemoveAllValues(SOSGetTransportCircles());
87 void SOSRegisterTransportKeyParameter(SOSTransportKeyParameterRef additional
) {
88 CFArrayAppendValue(SOSGetTransportKeyParameters(), additional
);
91 void SOSUnregisterTransportKeyParameter(SOSTransportKeyParameterRef removal
) {
92 CFArrayRemoveAllValue(SOSGetTransportKeyParameters(), removal
);
95 void SOSUnregisterAllTransportKeyParameters() {
96 CFArrayRemoveAllValues(SOSGetTransportKeyParameters());
100 // Should we be dispatching back to our queue to handle later
102 void SOSUpdateKeyInterest(void)
104 CFMutableArrayRef alwaysKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
105 CFMutableArrayRef afterFirstUnlockKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
106 CFMutableArrayRef whenUnlockedKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
107 CFMutableDictionaryRef keyDict
= CFDictionaryCreateMutableForCFTypes (kCFAllocatorDefault
);
109 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value
) {
110 SOSTransportKeyParameterRef tKP
= (SOSTransportKeyParameterRef
) value
;
111 if (SOSTransportKeyParameterGetTransportType(tKP
, NULL
) == kKVS
) {
112 SOSTransportKeyParameterKVSRef tkvs
= (SOSTransportKeyParameterKVSRef
) value
;
113 CFErrorRef localError
= NULL
;
115 if (!SOSTransportKeyParameterKVSAppendKeyInterests(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)) {
116 secerror("Error getting key parameters interests %@", localError
);
118 CFReleaseNull(localError
);
121 CFMutableDictionaryRef keyParamsDict
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
122 CFDictionarySetValue(keyParamsDict
, kAlwaysKeys
, alwaysKeys
);
123 CFDictionarySetValue(keyParamsDict
, kFirstUnlocked
, afterFirstUnlockKeys
);
124 CFDictionarySetValue(keyParamsDict
, kUnlocked
, whenUnlockedKeys
);
125 CFDictionarySetValue(keyDict
, kKeyParameter
, keyParamsDict
);
127 CFReleaseNull(alwaysKeys
);
128 CFReleaseNull(afterFirstUnlockKeys
);
129 CFReleaseNull(whenUnlockedKeys
);
130 alwaysKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
131 afterFirstUnlockKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
132 whenUnlockedKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
134 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value
) {
135 if (SOSTransportCircleGetTransportType((SOSTransportCircleRef
)value
, NULL
) == kKVS
) {
136 SOSTransportCircleKVSRef tkvs
= (SOSTransportCircleKVSRef
) value
;
137 CFErrorRef localError
= NULL
;
139 if(!SOSTransportCircleKVSAppendKeyInterest(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)){
140 secerror("Error getting circle interests %@", localError
);
142 if(!SOSTransportCircleKVSAppendPeerInfoKeyInterest(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)){
143 secerror("Error getting peer info interests %@", localError
);
145 #if !ENABLE_V2_BACKUP
146 if(!SOSTransportCircleKVSAppendRingKeyInterest(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)){
147 secerror("Error getting ring interests %@", localError
);
150 if(!SOSTransportCircleKVSAppendDebugKeyInterest(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)){
151 secerror("Error getting debug key interests %@", localError
);
153 CFReleaseNull(localError
);
157 CFMutableDictionaryRef circleDict
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
158 CFDictionarySetValue(circleDict
, kAlwaysKeys
, alwaysKeys
);
159 CFDictionarySetValue(circleDict
, kFirstUnlocked
, afterFirstUnlockKeys
);
160 CFDictionarySetValue(circleDict
, kUnlocked
, whenUnlockedKeys
);
161 CFDictionarySetValue(keyDict
, kCircle
, circleDict
);
163 CFReleaseNull(alwaysKeys
);
164 CFReleaseNull(afterFirstUnlockKeys
);
165 CFReleaseNull(whenUnlockedKeys
);
166 alwaysKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
167 afterFirstUnlockKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
168 whenUnlockedKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
170 CFArrayForEach(SOSGetTransportMessages(), ^(const void *value
) {
171 if (SOSTransportMessageGetTransportType((SOSTransportMessageRef
) value
, NULL
) == kKVS
) {
172 SOSTransportMessageKVSRef tkvs
= (SOSTransportMessageKVSRef
) value
;
173 CFErrorRef localError
= NULL
;
175 if(!SOSTransportMessageKVSAppendKeyInterest(tkvs
, alwaysKeys
, afterFirstUnlockKeys
, whenUnlockedKeys
, &localError
)){
176 secerror("Error getting message interests %@", localError
);
178 CFReleaseNull(localError
);
182 CFMutableDictionaryRef messageDict
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
183 CFDictionarySetValue(messageDict
, kAlwaysKeys
, alwaysKeys
);
184 CFDictionarySetValue(messageDict
, kFirstUnlocked
, afterFirstUnlockKeys
);
185 CFDictionarySetValue(messageDict
, kUnlocked
, whenUnlockedKeys
);
186 CFDictionarySetValue(keyDict
, kMessage
, messageDict
);
189 // Log what we are about to do.
191 if (CFArrayGetCount(whenUnlockedKeys
) == 0) {
192 secnotice("sync", "Unlocked keys were empty!");
194 CFStringRef alwaysKeysDesc
= SOSInterestListCopyDescription(alwaysKeys
);
195 CFStringRef afterFirstUnlockKeysDesc
= SOSInterestListCopyDescription(afterFirstUnlockKeys
);
196 CFStringRef unlockedKeysDesc
= SOSInterestListCopyDescription(whenUnlockedKeys
);
197 secdebug("sync", "Updating interest: always: %@,\nfirstUnlock: %@,\nunlockedKeys: %@",
199 afterFirstUnlockKeysDesc
,
201 CFReleaseNull(alwaysKeysDesc
);
202 CFReleaseNull(afterFirstUnlockKeysDesc
);
203 CFReleaseNull(unlockedKeysDesc
);
209 SOSCloudKeychainUpdateKeys(keyDict
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(CFDictionaryRef returnedValues
, CFErrorRef error
) {
211 secerror("Error updating keys: %@", error
);
215 CFReleaseNull(alwaysKeys
);
216 CFReleaseNull(afterFirstUnlockKeys
);
217 CFReleaseNull(whenUnlockedKeys
);
218 CFReleaseNull(keyParamsDict
);
219 CFReleaseNull(circleDict
);
220 CFReleaseNull(messageDict
);
221 CFReleaseNull(keyDict
);
225 static void showWhatWasHandled(CFDictionaryRef updates
, CFMutableArrayRef handledKeys
) {
227 CFMutableStringRef updateStr
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
228 CFMutableStringRef handledKeysStr
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
230 CFDictionaryForEach(updates
, ^(const void *key
, const void *value
) {
232 CFStringAppendFormat(updateStr
, NULL
, CFSTR("%@ "), (CFStringRef
)key
);
235 CFArrayForEach(handledKeys
, ^(const void *value
) {
236 if (isString(value
)) {
237 CFStringAppendFormat(handledKeysStr
, NULL
, CFSTR("%@ "), (CFStringRef
)value
);
240 secinfo("updates", "Updates [%ld]: %@", CFDictionaryGetCount(updates
), updateStr
);
241 secinfo("updates", "Handled [%ld]: %@", CFArrayGetCount(handledKeys
), handledKeysStr
);
243 CFReleaseSafe(updateStr
);
244 CFReleaseSafe(handledKeysStr
);
248 CFMutableArrayRef
SOSTransportDispatchMessages(SOSAccountRef account
, CFDictionaryRef updates
, CFErrorRef
*error
){
250 CFMutableArrayRef handledKeys
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
252 if(CFDictionaryContainsKey(updates
, kSOSKVSAccountChangedKey
)){
253 secnotice("accountChange", "SOSTransportDispatchMessages received kSOSKVSAccountChangedKey");
254 // While changing accounts we may modify the key params array. To avoid stepping on ourselves we
255 // copy the list for iteration. Now modifying the transport outside of the list iteration.
256 __block SOSTransportKeyParameterRef tempTransport
= NULL
;
257 CFMutableArrayRef originalKeyParams
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, CFArrayGetCount(SOSGetTransportKeyParameters()), SOSGetTransportKeyParameters());
259 tempTransport
= NULL
;
260 CFArrayForEach(originalKeyParams
, ^(const void *value
) {
261 SOSTransportKeyParameterRef transport
= (SOSTransportKeyParameterRef
) value
;
262 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(transport
), account
)){
263 tempTransport
= transport
;
266 if(tempTransport
!= NULL
){
267 SOSTransportKeyParameterHandleNewAccount(tempTransport
, account
);
268 CFStringRef dsid
= NULL
;
269 if(CFDictionaryGetValueIfPresent(updates
, kSOSKVSAccountChangedKey
, (const void**)&dsid
)){
271 CFStringRef accountDSID
= (CFStringRef
)SOSAccountGetValue(account
, kSOSDSIDKey
, error
);
273 if(accountDSID
== NULL
){
274 SOSAccountSetValue(account
, kSOSDSIDKey
, dsid
, error
);
275 secdebug("dsid", "Assigning new DSID: %@", dsid
);
277 else if(accountDSID
!= NULL
&& CFStringCompare(accountDSID
, dsid
, 0) != 0 ){
278 SOSAccountSetValue(account
, kSOSDSIDKey
, dsid
, error
);
279 secdebug("dsid", "Assigning new DSID: %@", dsid
);
282 secdebug("dsid", "DSIDs are the same!");
285 CFArrayRemoveAllValue(originalKeyParams
, tempTransport
);
287 }while(tempTransport
!= NULL
);
288 CFArrayAppendValue(handledKeys
, kSOSKVSAccountChangedKey
);
289 CFReleaseNull(originalKeyParams
);
294 // Iterate through keys in updates. Perform circle change update.
295 // Then instantiate circles and engines and peers for all peers that
296 // are receiving a message in updates.
297 CFMutableDictionaryRef circle_peer_messages_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
298 CFMutableDictionaryRef circle_circle_messages_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
299 CFMutableDictionaryRef circle_retirement_messages_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
300 CFMutableDictionaryRef ring_update_message_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
301 CFMutableDictionaryRef peer_info_message_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
302 CFMutableDictionaryRef debug_info_message_table
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
304 __block CFDataRef newParameters
= NULL
;
305 __block
bool initial_sync
= false;
306 __block
bool new_account
= false;
308 CFDictionaryForEach(updates
, ^(const void *key
, const void *value
) {
309 CFErrorRef localError
= NULL
;
310 CFStringRef circle_name
= NULL
;
311 CFStringRef ring_name
= NULL
;
312 CFStringRef peer_info_name
= NULL
;
313 CFStringRef from_name
= NULL
;
314 CFStringRef to_name
= NULL
;
315 CFStringRef backup_name
= NULL
;
317 switch (SOSKVSKeyGetKeyTypeAndParse(key
, &circle_name
, &peer_info_name
, &ring_name
, &backup_name
, &from_name
, &to_name
)) {
319 CFDictionarySetValue(circle_circle_messages_table
, circle_name
, value
);
321 case kInitialSyncKey
:
326 newParameters
= (CFDataRef
) CFRetainSafe(value
);
330 CFMutableDictionaryRef circle_messages
= CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_peer_messages_table
, circle_name
);
331 CFDictionarySetValue(circle_messages
, from_name
, value
);
334 case kRetirementKey
: {
335 CFMutableDictionaryRef circle_retirements
= CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_retirement_messages_table
, circle_name
);
336 CFDictionarySetValue(circle_retirements
, from_name
, value
);
339 case kAccountChangedKey
:
343 CFDictionarySetValue(peer_info_message_table
, peer_info_name
, value
);
346 if(isString(ring_name
))
347 CFDictionarySetValue(ring_update_message_table
, ring_name
, value
);
350 CFDictionarySetValue(debug_info_message_table
, peer_info_name
, value
);
353 case kLastKeyParameterKey
:
355 secnotice("updates", "Unknown key '%@', ignoring", key
);
360 CFReleaseNull(circle_name
);
361 CFReleaseNull(from_name
);
362 CFReleaseNull(to_name
);
363 CFReleaseNull(ring_name
);
364 CFReleaseNull(peer_info_name
);
365 CFReleaseNull(backup_name
);
368 secerror("Peer message processing error for: %@ -> %@ (%@)", key
, value
, *error
);
370 secerror("Peer message local processing error for: %@ -> %@ (%@)", key
, value
, localError
);
372 CFReleaseNull(localError
);
377 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value
) {
378 SOSTransportKeyParameterRef tkvs
= (SOSTransportKeyParameterRef
) value
;
379 CFErrorRef localError
= NULL
;
380 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(tkvs
), account
)){
381 if(!SOSTransportKeyParameterHandleKeyParameterChanges(tkvs
, newParameters
, localError
))
382 secerror("Transport failed to handle new key parameters: %@", localError
);
385 CFArrayAppendValue(handledKeys
, kSOSKVSKeyParametersKey
);
387 CFReleaseNull(newParameters
);
390 CFArrayAppendValue(handledKeys
, kSOSKVSInitialSyncKey
);
393 if(CFDictionaryGetCount(debug_info_message_table
)) {
394 /* check for a newly set circle debug scope */
395 CFTypeRef debugScope
= CFDictionaryGetValue(debug_info_message_table
, kSOSAccountDebugScope
);
397 if(isString(debugScope
)){
398 ApplyScopeListForID(debugScope
, kScopeIDCircle
);
399 }else if(isDictionary(debugScope
)){
400 ApplyScopeDictionaryForID(debugScope
, kScopeIDCircle
);
404 CFArrayAppendValue(handledKeys
, SOSDebugInfoKeyCreateWithTypeName(kSOSAccountDebugScope
));
407 if(CFDictionaryGetCount(circle_retirement_messages_table
)) {
408 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value
) {
409 SOSTransportCircleRef tkvs
= (SOSTransportCircleRef
) value
;
410 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef
)value
), account
)){
411 CFErrorRef localError
= NULL
;
412 CFDictionaryRef handledRetirementKeys
= SOSTransportCircleHandleRetirementMessages(tkvs
, circle_retirement_messages_table
, error
);
413 if(handledRetirementKeys
== NULL
){
414 secerror("Transport failed to handle retirement messages: %@", localError
);
416 CFDictionaryForEach(handledRetirementKeys
, ^(const void *key
, const void *value
) {
417 CFStringRef circle_name
= (CFStringRef
)key
;
418 CFArrayRef handledPeerIDs
= (CFArrayRef
)value
;
419 CFArrayForEach(handledPeerIDs
, ^(const void *value
) {
420 CFStringRef peer_id
= (CFStringRef
)value
;
421 CFStringRef keyHandled
= SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name
, peer_id
);
422 CFArrayAppendValue(handledKeys
, keyHandled
);
423 CFReleaseNull(keyHandled
);
427 CFReleaseNull(handledRetirementKeys
);
428 CFReleaseNull(localError
);
432 if(CFDictionaryGetCount(peer_info_message_table
)){
433 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value
) {
434 SOSTransportCircleRef tkvs
= (SOSTransportCircleRef
) value
;
435 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef
)value
), account
)){
436 CFErrorRef localError
= NULL
;
437 CFArrayRef handledPeerInfoMessages
= SOSTransportCircleKVSHandlePeerInfoV2Messages(tkvs
, peer_info_message_table
, error
);
438 if(handledPeerInfoMessages
== NULL
){
439 secerror("Transport failed to handle peer info messages: %@", localError
);
441 CFArrayForEach(handledPeerInfoMessages
, ^(const void *value
) {
442 CFStringRef peer_id
= (CFStringRef
)value
;
443 CFStringRef keyHandled
= SOSPeerInfoV2KeyCreateWithPeerName(peer_id
);
444 CFArrayAppendValue(handledKeys
, keyHandled
);
445 CFReleaseNull(keyHandled
);
448 CFReleaseNull(handledPeerInfoMessages
);
449 CFReleaseNull(localError
);
453 if(CFDictionaryGetCount(circle_peer_messages_table
)) {
454 CFArrayForEach(SOSGetTransportMessages(), ^(const void *value
) {
455 SOSTransportMessageRef tkvs
= (SOSTransportMessageRef
) value
;
456 if(SOSTransportMessageGetTransportType(tkvs
, error
) != kIDS
){
457 if(CFEqualSafe(SOSTransportMessageGetAccount((SOSTransportMessageRef
)value
), account
)){
458 CFErrorRef handleMessagesError
= NULL
;
459 CFDictionaryRef handledPeers
= SOSTransportMessageHandleMessages(account
->kvs_message_transport
, circle_peer_messages_table
, &handleMessagesError
);
462 // We need to look for and send responses.
464 CFErrorRef syncError
= NULL
;
465 if (!SOSTransportMessageSyncWithPeers((SOSTransportMessageRef
)account
->kvs_message_transport
, handledPeers
, &syncError
)) {
466 secerror("Sync with peers failed: %@", syncError
);
469 CFDictionaryForEach(handledPeers
, ^(const void *key
, const void *value
) {
470 if (isString(key
) && isArray(value
)) {
471 CFArrayForEach(value
, ^(const void *value
) {
472 if (isString(value
)) {
473 CFStringRef peerID
= (CFStringRef
) value
;
475 CFStringRef kvsHandledKey
= SOSMessageKeyCreateFromPeerToTransport((SOSTransportMessageKVSRef
)account
->kvs_message_transport
, peerID
);
476 CFArrayAppendValue(handledKeys
, kvsHandledKey
);
477 CFReleaseSafe(kvsHandledKey
);
483 CFErrorRef flushError
= NULL
;
484 if (!SOSTransportMessageFlushChanges((SOSTransportMessageRef
)account
->kvs_message_transport
, &flushError
)) {
485 secerror("Flush failed: %@", flushError
);
489 secerror("Didn't handle? : %@", handleMessagesError
);
491 CFReleaseNull(handledPeers
);
492 CFReleaseNull(handleMessagesError
);
498 if(CFDictionaryGetCount(circle_circle_messages_table
)) {
499 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value
) {
500 SOSTransportCircleRef tkvs
= (SOSTransportCircleRef
) value
;
501 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef
)value
), account
)){
502 CFArrayRef handleCircleMessages
= SOSTransportCircleHandleCircleMessages(tkvs
, circle_circle_messages_table
, error
);
503 CFErrorRef localError
= NULL
;
504 if(handleCircleMessages
== NULL
){
505 secerror("Transport failed to handle circle messages: %@", localError
);
506 } else if(CFArrayGetCount(handleCircleMessages
) == 0) {
507 if(CFDictionaryGetCount(circle_circle_messages_table
) != 0) {
508 secerror("Transport failed to process all circle messages: (%ld/%ld) %@",
509 CFArrayGetCount(handleCircleMessages
),
510 CFDictionaryGetCount(circle_circle_messages_table
), localError
);
512 secnotice("circle", "Transport handled no circle messages");
515 CFArrayForEach(handleCircleMessages
, ^(const void *value
) {
516 CFStringRef keyHandled
= SOSCircleKeyCreateWithName((CFStringRef
)value
, error
);
517 CFArrayAppendValue(handledKeys
, keyHandled
);
518 CFReleaseNull(keyHandled
);
522 CFReleaseNull(localError
);
523 CFReleaseNull(handleCircleMessages
);
528 if(CFDictionaryGetCount(ring_update_message_table
)){
529 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value
) {
530 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef
)value
), account
)){
531 CFErrorRef localError
= NULL
;
532 CFMutableArrayRef handledRingMessages
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
534 CFDictionaryForEach(ring_update_message_table
, ^(const void *key
, const void *value
) {
535 CFDataRef ringData
= (CFDataRef
)value
;
536 SOSRingRef ring
= SOSRingCreateFromData(error
, ringData
);
538 if(SOSAccountUpdateRingFromRemote(account
, ring
, error
)){
539 CFArrayAppendValue(handledRingMessages
, key
);
543 if(CFArrayGetCount(handledRingMessages
) == 0){
544 secerror("Transport failed to handle ring messages: %@", localError
);
546 CFArrayForEach(handledRingMessages
, ^(const void *value
) {
547 CFStringRef ring_name
= (CFStringRef
)value
;
548 CFStringRef keyHandled
= SOSRingKeyCreateWithRingName(ring_name
);
549 CFArrayAppendValue(handledKeys
, keyHandled
);
550 CFReleaseNull(keyHandled
);
553 CFReleaseNull(handledRingMessages
);
554 CFReleaseNull(localError
);
559 CFReleaseNull(circle_retirement_messages_table
);
560 CFReleaseNull(circle_circle_messages_table
);
561 CFReleaseNull(circle_peer_messages_table
);
562 CFReleaseNull(debug_info_message_table
);
563 CFReleaseNull(ring_update_message_table
);
564 CFReleaseNull(peer_info_message_table
);
565 CFReleaseNull(debug_info_message_table
);
567 showWhatWasHandled(updates
, handledKeys
);